aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap3
-rw-r--r--CREDITS17
-rw-r--r--Documentation/ABI/stable/sysfs-block53
-rw-r--r--Documentation/ABI/testing/configfs-tsm63
-rw-r--r--Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu113
-rw-r--r--Documentation/ABI/testing/sysfs-devices-system-cpu18
-rw-r--r--Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Memory-Ordering.rst6
-rw-r--r--Documentation/RCU/Design/Requirements/Requirements.rst16
-rw-r--r--Documentation/RCU/whatisRCU.rst30
-rw-r--r--Documentation/admin-guide/cgroup-v1/pids.rst3
-rw-r--r--Documentation/admin-guide/cgroup-v2.rst47
-rw-r--r--Documentation/admin-guide/cifs/usage.rst36
-rw-r--r--Documentation/admin-guide/gpio/gpio-virtuser.rst177
-rw-r--r--Documentation/admin-guide/gpio/index.rst1
-rw-r--r--Documentation/admin-guide/hw-vuln/spectre.rst86
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt55
-rw-r--r--Documentation/arch/arm64/cpu-hotplug.rst79
-rw-r--r--Documentation/arch/arm64/index.rst1
-rw-r--r--Documentation/arch/arm64/memory.rst42
-rw-r--r--Documentation/arch/arm64/silicon-errata.rst16
-rw-r--r--Documentation/arch/riscv/cmodx.rst4
-rw-r--r--Documentation/arch/x86/amd-memory-encryption.rst29
-rw-r--r--Documentation/arch/x86/resctrl.rst27
-rw-r--r--Documentation/block/data-integrity.rst49
-rw-r--r--Documentation/block/writeback_cache_control.rst67
-rw-r--r--Documentation/dev-tools/gpio-sloppy-logic-analyzer.rst93
-rw-r--r--Documentation/dev-tools/index.rst1
-rw-r--r--Documentation/devicetree/bindings/arm/airoha.yaml4
-rw-r--r--Documentation/devicetree/bindings/arm/amlogic.yaml10
-rw-r--r--Documentation/devicetree/bindings/arm/arm,juno-fpga-apb-regs.yaml61
-rw-r--r--Documentation/devicetree/bindings/arm/bcm/bcm2835.yaml6
-rw-r--r--Documentation/devicetree/bindings/arm/fsl.yaml32
-rw-r--r--Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/marvell/armada-7k-8k.yaml18
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek.yaml24
-rw-r--r--Documentation/devicetree/bindings/arm/pmu.yaml6
-rw-r--r--Documentation/devicetree/bindings/arm/qcom.yaml27
-rw-r--r--Documentation/devicetree/bindings/arm/rockchip.yaml42
-rw-r--r--Documentation/devicetree/bindings/arm/rtsm-dcscb.txt19
-rw-r--r--Documentation/devicetree/bindings/arm/stm32/stm32.yaml6
-rw-r--r--Documentation/devicetree/bindings/arm/sunxi.yaml16
-rw-r--r--Documentation/devicetree/bindings/arm/ti/k3.yaml6
-rw-r--r--Documentation/devicetree/bindings/cache/qcom,llcc.yaml57
-rw-r--r--Documentation/devicetree/bindings/cache/starfive,jh8100-starlink-cache.yaml66
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml3
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml77
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml7
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml6
-rw-r--r--Documentation/devicetree/bindings/clock/ti,sci-clk.yaml2
-rw-r--r--Documentation/devicetree/bindings/firmware/arm,scmi.yaml12
-rw-r--r--Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml86
-rw-r--r--Documentation/devicetree/bindings/firmware/qcom,scm.yaml15
-rw-r--r--Documentation/devicetree/bindings/fuse/renesas,rcar-efuse.yaml55
-rw-r--r--Documentation/devicetree/bindings/fuse/renesas,rcar-otp.yaml38
-rw-r--r--Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml10
-rw-r--r--Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml81
-rw-r--r--Documentation/devicetree/bindings/gpio/fsl,qoriq-gpio.yaml87
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt53
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-pca95xx.yaml1
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-vf610.yaml4
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-zevio.txt16
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio_atmel.txt31
-rw-r--r--Documentation/devicetree/bindings/gpio/lsi,zevio-gpio.yaml43
-rw-r--r--Documentation/devicetree/bindings/hwmon/g762.txt47
-rw-r--r--Documentation/devicetree/bindings/hwmon/gmt,g762.yaml95
-rw-r--r--Documentation/devicetree/bindings/hwmon/maxim,max6639.yaml92
-rw-r--r--Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml9
-rw-r--r--Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml12
-rw-r--r--Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml4
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml3
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/fsl,ls-extirq.yaml1
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/marvell,armada-370-xp-mpic.txt38
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/marvell,mpic.yaml63
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,twl.yaml167
-rw-r--r--Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml3
-rw-r--r--Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml1
-rw-r--r--Documentation/devicetree/bindings/mmc/fsl,esdhc.yaml105
-rw-r--r--Documentation/devicetree/bindings/mmc/fsl-esdhc.txt52
-rw-r--r--Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml16
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-msm.yaml1
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-sprd.txt67
-rw-r--r--Documentation/devicetree/bindings/mmc/sprd,sdhci-r11.yaml112
-rw-r--r--Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml3
-rw-r--r--Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml2
-rw-r--r--Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml48
-rw-r--r--Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml4
-rw-r--r--Documentation/devicetree/bindings/pwm/fsl,vf610-ftm-pwm.yaml92
-rw-r--r--Documentation/devicetree/bindings/pwm/imx-pwm.yaml1
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt55
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-gpio.yaml46
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm.yaml6
-rw-r--r--Documentation/devicetree/bindings/regulator/mediatek,mt6873-dvfsrc-regulator.yaml43
-rw-r--r--Documentation/devicetree/bindings/regulator/mt6315-regulator.yaml6
-rw-r--r--Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml1
-rw-r--r--Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml185
-rw-r--r--Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml11
-rw-r--r--Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.txt43
-rw-r--r--Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml67
-rw-r--r--Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml7
-rw-r--r--Documentation/devicetree/bindings/regulator/ti,tps65132.yaml3
-rw-r--r--Documentation/devicetree/bindings/regulator/twl-regulator.txt80
-rw-r--r--Documentation/devicetree/bindings/reset/renesas,rzg2l-usbphy-ctrl.yaml10
-rw-r--r--Documentation/devicetree/bindings/reset/ti,sci-reset.yaml2
-rw-r--r--Documentation/devicetree/bindings/riscv/cpus.yaml1
-rw-r--r--Documentation/devicetree/bindings/riscv/microchip.yaml1
-rw-r--r--Documentation/devicetree/bindings/riscv/starfive.yaml1
-rw-r--r--Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt64
-rw-r--r--Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-dcfg.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-scfg.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/hisilicon/hisilicon,hi3660-usb3-otg-bc.yaml46
-rw-r--r--Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml3
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smsm.yaml30
-rw-r--r--Documentation/devicetree/bindings/soc/sti/st,sti-syscon.yaml9
-rw-r--r--Documentation/devicetree/bindings/soc/ti/sci-pm-domain.yaml2
-rw-r--r--Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml (renamed from Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml)4
-rw-r--r--Documentation/devicetree/bindings/spi/amlogic,a1-spifc.yaml3
-rw-r--r--Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml8
-rw-r--r--Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt23
-rw-r--r--Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml50
-rw-r--r--Documentation/devicetree/bindings/spi/fsl,dspi-peripheral-props.yaml30
-rw-r--r--Documentation/devicetree/bindings/spi/fsl,dspi.yaml116
-rw-r--r--Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml55
-rw-r--r--Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml35
-rw-r--r--Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml29
-rw-r--r--Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml4
-rw-r--r--Documentation/devicetree/bindings/spi/spi-cadence.yaml7
-rw-r--r--Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt65
-rw-r--r--Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml1
-rw-r--r--Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml28
-rw-r--r--Documentation/devicetree/bindings/sram/qcom,imem.yaml1
-rw-r--r--Documentation/devicetree/bindings/timer/realtek,otto-timer.yaml63
-rw-r--r--Documentation/devicetree/bindings/timer/renesas,tmu.yaml12
-rw-r--r--Documentation/devicetree/bindings/timer/sifive,clint.yaml1
-rw-r--r--Documentation/devicetree/bindings/trivial-devices.yaml10
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml10
-rw-r--r--Documentation/driver-api/cxl/memory-devices.rst15
-rw-r--r--Documentation/driver-api/driver-model/devres.rst3
-rw-r--r--Documentation/driver-api/gpio/board.rst6
-rw-r--r--Documentation/driver-api/gpio/consumer.rst4
-rw-r--r--Documentation/driver-api/gpio/driver.rst5
-rw-r--r--Documentation/driver-api/gpio/drivers-on-gpio.rst7
-rw-r--r--Documentation/driver-api/gpio/index.rst1
-rw-r--r--Documentation/driver-api/gpio/intro.rst12
-rw-r--r--Documentation/driver-api/gpio/legacy.rst679
-rw-r--r--Documentation/filesystems/index.rst1
-rw-r--r--Documentation/filesystems/iomap/design.rst441
-rw-r--r--Documentation/filesystems/iomap/index.rst13
-rw-r--r--Documentation/filesystems/iomap/operations.rst713
-rw-r--r--Documentation/filesystems/iomap/porting.rst120
-rw-r--r--Documentation/filesystems/mount_api.rst9
-rw-r--r--Documentation/hwmon/adm1021.rst153
-rw-r--r--Documentation/hwmon/amc6821.rst7
-rw-r--r--Documentation/hwmon/asus_ec_sensors.rst1
-rw-r--r--Documentation/hwmon/corsair-cpro.rst8
-rw-r--r--Documentation/hwmon/corsair-psu.rst6
-rw-r--r--Documentation/hwmon/cros_ec_hwmon.rst26
-rw-r--r--Documentation/hwmon/dell-smm-hwmon.rst2
-rw-r--r--Documentation/hwmon/index.rst8
-rw-r--r--Documentation/hwmon/max31827.rst13
-rw-r--r--Documentation/hwmon/max6642.rst27
-rw-r--r--Documentation/hwmon/mp2891.rst179
-rw-r--r--Documentation/hwmon/mp2993.rst150
-rw-r--r--Documentation/hwmon/mp5920.rst91
-rw-r--r--Documentation/hwmon/mp9941.rst92
-rw-r--r--Documentation/hwmon/spd5118.rst63
-rw-r--r--Documentation/networking/devlink/devlink-region.rst2
-rw-r--r--Documentation/power/regulator/consumer.rst6
-rw-r--r--Documentation/translations/zh_CN/driver-api/gpio/index.rst2
-rw-r--r--Documentation/translations/zh_CN/driver-api/gpio/legacy.rst618
-rw-r--r--Documentation/translations/zh_TW/gpio.txt574
-rw-r--r--Documentation/userspace-api/gpio/gpio-handle-get-line-values-ioctl.rst7
-rw-r--r--Documentation/userspace-api/gpio/gpio-handle-set-config-ioctl.rst5
-rw-r--r--Documentation/userspace-api/gpio/gpio-handle-set-line-values-ioctl.rst7
-rw-r--r--Documentation/userspace-api/gpio/gpio-lineevent-data-read.rst5
-rw-r--r--Documentation/userspace-api/gpio/gpio-v2-line-event-read.rst5
-rw-r--r--Documentation/userspace-api/gpio/gpio-v2-line-get-values-ioctl.rst7
-rw-r--r--Documentation/userspace-api/gpio/gpio-v2-line-set-config-ioctl.rst7
-rw-r--r--Documentation/userspace-api/gpio/gpio-v2-line-set-values-ioctl.rst7
-rw-r--r--Documentation/userspace-api/gpio/sysfs.rst7
-rw-r--r--Documentation/userspace-api/ioctl/ioctl-number.rst1
-rw-r--r--Documentation/virt/coco/sev-guest.rst11
-rw-r--r--MAINTAINERS219
-rw-r--r--Makefile4
-rw-r--r--arch/arc/include/asm/Kbuild2
-rw-r--r--arch/arc/include/asm/unistd.h14
-rw-r--r--arch/arc/include/uapi/asm/Kbuild2
-rw-r--r--arch/arc/include/uapi/asm/unistd.h44
-rw-r--r--arch/arc/kernel/Makefile.syscalls3
-rw-r--r--arch/arc/kernel/sys.c5
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/boot/dts/allwinner/Makefile62
-rw-r--r--arch/arm/boot/dts/arm/arm-realview-eb-bbrevd.dtsi2
-rw-r--r--arch/arm/boot/dts/arm/arm-realview-eb.dtsi48
-rw-r--r--arch/arm/boot/dts/arm/arm-realview-pb1176.dts38
-rw-r--r--arch/arm/boot/dts/arm/arm-realview-pb11mp.dts48
-rw-r--r--arch/arm/boot/dts/arm/arm-realview-pbx.dtsi48
-rw-r--r--arch/arm/boot/dts/arm/integratorap-im-pd1.dts4
-rw-r--r--arch/arm/boot/dts/arm/integratorap.dts14
-rw-r--r--arch/arm/boot/dts/arm/integratorcp.dts14
-rw-r--r--arch/arm/boot/dts/arm/mps2.dtsi48
-rw-r--r--arch/arm/boot/dts/arm/versatile-ab.dts8
-rw-r--r--arch/arm/boot/dts/arm/vexpress-v2m-rs1.dtsi8
-rw-r--r--arch/arm/boot/dts/arm/vexpress-v2m.dtsi16
-rw-r--r--arch/arm/boot/dts/arm/vexpress-v2p-ca15-tc1.dts14
-rw-r--r--arch/arm/boot/dts/arm/vexpress-v2p-ca15_a7.dts22
-rw-r--r--arch/arm/boot/dts/arm/vexpress-v2p-ca5s.dts12
-rw-r--r--arch/arm/boot/dts/arm/vexpress-v2p-ca9.dts18
-rw-r--r--arch/arm/boot/dts/aspeed/aspeed-g4.dtsi28
-rw-r--r--arch/arm/boot/dts/aspeed/aspeed-g5.dtsi28
-rw-r--r--arch/arm/boot/dts/aspeed/aspeed-g6.dtsi32
-rw-r--r--arch/arm/boot/dts/cirrus/ep7211-edb7211.dts2
-rw-r--r--arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts11
-rw-r--r--arch/arm/boot/dts/marvell/armada-370-xp.dtsi1
-rw-r--r--arch/arm/boot/dts/marvell/armada-375.dtsi1
-rw-r--r--arch/arm/boot/dts/marvell/armada-385-atl-x530.dts13
-rw-r--r--arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts35
-rw-r--r--arch/arm/boot/dts/marvell/armada-38x.dtsi1
-rw-r--r--arch/arm/boot/dts/marvell/armada-39x.dtsi1
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-blackarmor-nas220.dts6
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-c200-v1.dts8
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-cloudbox.dts8
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-d2net.dts2
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-dir665.dts22
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-dns320.dts10
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-dns325.dts10
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-dnskw.dtsi8
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-dockstar.dts4
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-dreamplug.dts6
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-goflexnet.dts20
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-guruplug-server-plus.dts8
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-ib62x0.dts12
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-iconnect.dts20
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-iomega_ix2_200.dts16
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-l-50.dts20
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-laplug.dts6
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-linkstation.dtsi2
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-linksys-viper.dts10
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-lsxl.dtsi18
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-mplcec4.dts12
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-mv88f6281gtw-ge.dts12
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-netxbig.dtsi8
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-ns2-common.dtsi6
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-ns2lite.dts2
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-nsa310.dts20
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-nsa310a.dts18
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-nsa310s.dts8
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-nsa320.dts18
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-nsa325.dts18
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-nsa3x0-common.dtsi8
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-openblocks_a6.dts4
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts2
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-pogo_e02.dts4
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-pogoplug-series-4.dts8
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-sheevaplug-esata.dts2
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-sheevaplug.dts4
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-synology.dtsi58
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-t5325.dts4
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-ts219-6281.dts6
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-ts219-6282.dts6
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-ts419.dtsi6
-rw-r--r--arch/arm/boot/dts/marvell/mvebu-linkstation-gpio-simple.dtsi2
-rw-r--r--arch/arm/boot/dts/marvell/orion5x-lacie-d2-network.dts9
-rw-r--r--arch/arm/boot/dts/marvell/orion5x-lacie-ethernet-disk-mini-v2.dts7
-rw-r--r--arch/arm/boot/dts/marvell/orion5x-linkstation-lschl.dts4
-rw-r--r--arch/arm/boot/dts/marvell/orion5x-lswsgl.dts25
-rw-r--r--arch/arm/boot/dts/marvell/orion5x-maxtor-shared-storage-2.dts7
-rw-r--r--arch/arm/boot/dts/marvell/orion5x-netgear-wnr854t.dts2
-rw-r--r--arch/arm/boot/dts/marvell/orion5x-rd88f5182-nas.dts2
-rw-r--r--arch/arm/boot/dts/mediatek/mt2701-evb.dts2
-rw-r--r--arch/arm/boot/dts/mediatek/mt7623.dtsi18
-rw-r--r--arch/arm/boot/dts/nspire/nspire-classic.dtsi2
-rw-r--r--arch/arm/boot/dts/nspire/nspire-cx.dts2
-rw-r--r--arch/arm/boot/dts/nspire/nspire.dtsi5
-rw-r--r--arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts22
-rw-r--r--arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts22
-rw-r--r--arch/arm/boot/dts/nxp/imx/Makefile2
-rw-r--r--arch/arm/boot/dts/nxp/imx/e60k02.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-babbage.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-ts4800.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts14
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-tx53-x13x.dts6
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos2_4.dts5
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_4.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_7.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i-ads2.dts12
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i-ads2.dts12
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i.dtsi25
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i-ads2.dtsi148
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i.dtsi58
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi12
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi12
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lcd.dtsi21
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lvds.dtsi20
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi14
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts6
-rw-r--r--arch/arm/boot/dts/qcom/Makefile5
-rw-r--r--arch/arm/boot/dts/qcom/msm8226-motorola-falcon.dts53
-rw-r--r--arch/arm/boot/dts/qcom/qcom-apq8026-samsung-milletwifi.dts573
-rw-r--r--arch/arm/boot/dts/qcom/qcom-apq8064.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/qcom-apq8084.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-common.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8226-samsung-ms013g.dts386
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8226.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8660.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8926-motorola-peregrine.dts121
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8960.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dts6
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8974-samsung-hlte.dts401
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8974.dtsi28
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8974pro-htc-m8.dts353
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-aries.dts44
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-common.dtsi2
-rw-r--r--arch/arm/boot/dts/renesas/r8a73a4.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a7742.dtsi1
-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.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a77470.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a7790.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a7791.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a7792.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a7793.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a7794.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r9a06g032.dtsi19
-rw-r--r--arch/arm/boot/dts/rockchip/rk3036.dtsi1
-rw-r--r--arch/arm/boot/dts/rockchip/rk3066a-mk808.dts8
-rw-r--r--arch/arm/boot/dts/rockchip/rk3066a.dtsi17
-rw-r--r--arch/arm/boot/dts/rockchip/rk3128.dtsi128
-rw-r--r--arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts3
-rw-r--r--arch/arm/boot/dts/st/Makefile1
-rw-r--r--arch/arm/boot/dts/st/stih407-family.dtsi6
-rw-r--r--arch/arm/boot/dts/st/stih410.dtsi1
-rw-r--r--arch/arm/boot/dts/st/stih418.dtsi42
-rw-r--r--arch/arm/boot/dts/st/stm32f429.dtsi1
-rw-r--r--arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi697
-rw-r--r--arch/arm/boot/dts/st/stm32mp131.dtsi38
-rw-r--r--arch/arm/boot/dts/st/stm32mp133.dtsi31
-rw-r--r--arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts377
-rw-r--r--arch/arm/boot/dts/st/stm32mp135f-dk.dts128
-rw-r--r--arch/arm/boot/dts/st/stm32mp13xx-dhcor-som.dtsi308
-rw-r--r--arch/arm/boot/dts/st/stm32mp151.dtsi1
-rw-r--r--arch/arm/boot/dts/st/stm32mp157a-dk1-scmi.dts5
-rw-r--r--arch/arm/boot/dts/st/stm32mp157c-dk2-scmi.dts5
-rw-r--r--arch/arm/boot/dts/st/stm32mp157c-ed1-scmi.dts5
-rw-r--r--arch/arm/boot/dts/st/stm32mp157c-ev1-scmi.dts5
-rw-r--r--arch/arm/boot/dts/st/stm32mp157c-osd32mp1-red.dts13
-rw-r--r--arch/arm/boot/dts/st/stm32mp15xc-lxa-tac.dtsi13
-rw-r--r--arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi13
-rw-r--r--arch/arm/boot/dts/ti/davinci/da850-evm.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am335x-guardian.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am335x-pdu001.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am335x-pepper.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts1
-rw-r--r--arch/arm/boot/dts/vt8500/vt8500-bv07.dts2
-rw-r--r--arch/arm/boot/dts/vt8500/vt8500.dtsi2
-rw-r--r--arch/arm/boot/dts/vt8500/wm8505-ref.dts2
-rw-r--r--arch/arm/boot/dts/vt8500/wm8505.dtsi2
-rw-r--r--arch/arm/boot/dts/vt8500/wm8650-mid.dts2
-rw-r--r--arch/arm/boot/dts/vt8500/wm8650.dtsi2
-rw-r--r--arch/arm/boot/dts/vt8500/wm8750.dtsi4
-rw-r--r--arch/arm/boot/dts/vt8500/wm8850-w70v2.dts2
-rw-r--r--arch/arm/boot/dts/vt8500/wm8850.dtsi4
-rw-r--r--arch/arm/configs/at91_dt_defconfig1
-rw-r--r--arch/arm/configs/imx_v6_v7_defconfig7
-rw-r--r--arch/arm/configs/multi_v7_defconfig1
-rw-r--r--arch/arm/configs/vexpress_defconfig1
-rw-r--r--arch/arm/include/asm/cmpxchg.h7
-rw-r--r--arch/arm/include/asm/unistd.h1
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/mach-davinci/pm.c2
-rw-r--r--arch/arm/mach-pxa/devices.c55
-rw-r--r--arch/arm/mach-pxa/devices.h5
-rw-r--r--arch/arm/mach-pxa/gumstix.c24
-rw-r--r--arch/arm/mach-pxa/pxa25x.c8
-rw-r--r--arch/arm/mach-pxa/pxa27x.c9
-rw-r--r--arch/arm/mach-pxa/spitz.c284
-rw-r--r--arch/arm/mach-tegra/board-paz00.c50
-rw-r--r--arch/arm/mach-versatile/Kconfig9
-rw-r--r--arch/arm/mach-versatile/Makefile3
-rw-r--r--arch/arm/mach-versatile/dcscb.c173
-rw-r--r--arch/arm/mach-versatile/dcscb_setup.S33
-rw-r--r--arch/arm/tools/syscall.tbl1
-rw-r--r--arch/arm64/Kconfig40
-rw-r--r--arch/arm64/Kconfig.platforms3
-rw-r--r--arch/arm64/boot/dts/Makefile1
-rw-r--r--arch/arm64/boot/dts/airoha/Makefile2
-rw-r--r--arch/arm64/boot/dts/airoha/en7581-evb.dts26
-rw-r--r--arch/arm64/boot/dts/airoha/en7581.dtsi154
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-early-adopter.dts2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi37
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi37
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi25
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi77
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h64-remix-mini-pc.dts2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts4
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-h.dts79
-rw-r--r--arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi10
-rw-r--r--arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts2
-rw-r--r--arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts2
-rw-r--r--arch/arm64/boot/dts/amlogic/Makefile4
-rw-r--r--arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi10
-rw-r--r--arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi3
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts45
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-a1.dtsi16
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-axg.dtsi24
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi438
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12.dtsi4
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts2
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-bananapi.dtsi14
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-one.dts17
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-two.dts20
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi154
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts24
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts2
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi10
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts199
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl.dtsi10
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxlx-s905l-p271.dts51
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-s4.dtsi199
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-sm1.dtsi44
-rw-r--r--arch/arm64/boot/dts/apm/apm-merlin.dts2
-rw-r--r--arch/arm64/boot/dts/apm/apm-mustang.dts2
-rw-r--r--arch/arm64/boot/dts/arm/corstone1000-fvp.dts2
-rw-r--r--arch/arm64/boot/dts/arm/corstone1000.dtsi6
-rw-r--r--arch/arm64/boot/dts/arm/foundation-v8.dtsi6
-rw-r--r--arch/arm64/boot/dts/arm/juno-base.dtsi1
-rw-r--r--arch/arm64/boot/dts/arm/juno-clocks.dtsi10
-rw-r--r--arch/arm64/boot/dts/arm/juno-motherboard.dtsi13
-rw-r--r--arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi10
-rw-r--r--arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts6
-rw-r--r--arch/arm64/boot/dts/exynos/exynos850.dtsi8
-rw-r--r--arch/arm64/boot/dts/exynos/google/gs101-oriole.dts9
-rw-r--r--arch/arm64/boot/dts/exynos/google/gs101.dtsi22
-rw-r--r--arch/arm64/boot/dts/freescale/Makefile15
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi79
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts31
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi55
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts20
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi138
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi49
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi72
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi186
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi56
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-cm41.dtsi68
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi69
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-evk.dts277
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi78
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi11
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-iot-gateway.dts218
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs232.dtso72
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs485.dtso76
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rts-cts.dtso41
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts10
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi8
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-ucm-som.dtsi679
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi20
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi20
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi8
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts12
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-beacon-som.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts47
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts39
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts39
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi13
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-evk-mx8-dlvds-lcd1.dtso77
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-evk.dts91
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-msc-sm2s-ep1.dts27
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314.dts906
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts5
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi8
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi20
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts24
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi37
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi37
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin-mallow.dtsi37
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi.dtsi3
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi3
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi37
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi18
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp.dtsi120
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi8
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-mek.dts344
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-ss-audio.dtsi473
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm.dtsi103
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-mek.dts1
-rw-r--r--arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts309
-rw-r--r--arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts492
-rw-r--r--arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts73
-rw-r--r--arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts61
-rw-r--r--arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts289
-rw-r--r--arch/arm64/boot/dts/freescale/imx95-clock.h187
-rw-r--r--arch/arm64/boot/dts/freescale/imx95-pinfunc.h865
-rw-r--r--arch/arm64/boot/dts/freescale/imx95-power.h47
-rw-r--r--arch/arm64/boot/dts/freescale/imx95.dtsi1192
-rw-r--r--arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/tqma8xx.dtsi8
-rw-r--r--arch/arm64/boot/dts/hisilicon/hi3660.dtsi2
-rw-r--r--arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts2
-rw-r--r--arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts2
-rw-r--r--arch/arm64/boot/dts/marvell/Makefile4
-rw-r--r--arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts8
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-cf-base.dts178
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-cf-pro.dts375
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-cf.dtsi197
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-sr-som.dtsi160
-rw-r--r--arch/arm64/boot/dts/marvell/cn9131-cf-solidwan.dts637
-rw-r--r--arch/arm64/boot/dts/marvell/cn9132-clearfog.dts673
-rw-r--r--arch/arm64/boot/dts/marvell/cn9132-sr-cex7.dtsi712
-rw-r--r--arch/arm64/boot/dts/mediatek/Makefile12
-rw-r--r--arch/arm64/boot/dts/mediatek/mt2712-evb.dts4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts8
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts8
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7981b-cudy-wr3000-v1.dts74
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7981b-openwrt-one.dts15
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7981b.dtsi78
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso28
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-mini.dts493
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso74
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso90
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso16
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7988a.dtsi90
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi9
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi6
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173-evb.dts12
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-evb.dts6
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-audio-da7219.dtsi2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku1.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku6.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku7.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14-sku2.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kappa.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kenzo.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-makomo-sku0.dts2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-makomo-sku1.dts2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-pico6.dts14
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku0.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku1.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi25
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi18
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts10
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183.dtsi136
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589824.dts13
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589825.dts25
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtsi103
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi42
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8188.dtsi480
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r5-sku2.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r4.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192.dtsi2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195-cherry-dojo-r1.dts114
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi50
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195-demo.dts26
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195-evb.dts4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195.dtsi2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8365-evk.dts4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8365.dtsi3
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts880
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts34
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8395-kontron-3-5-sbc-i1200.dts1127
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts88
-rw-r--r--arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi372
-rw-r--r--arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi95
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts77
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0005.dts31
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi (renamed from arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi)28
-rw-r--r--arch/arm64/boot/dts/qcom/Makefile19
-rw-r--r--arch/arm64/boot/dts/qcom/apq8016-schneider-hmibsc.dts491
-rw-r--r--arch/arm64/boot/dts/qcom/ipq5018-tplink-archer-ax55-v1.dts128
-rw-r--r--arch/arm64/boot/dts/qcom/ipq5018.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/ipq5332.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/ipq6018.dtsi28
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/ipq9574.dtsi39
-rw-r--r--arch/arm64/boot/dts/qcom/msm8216-samsung-fortuna3g.dts14
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts26
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts47
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-lg-c50.dts140
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-lg-m216.dts251
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-motorola-common.dtsi161
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-motorola-harpia.dts147
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-motorola-osprey.dts105
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-motorola-surnia.dts83
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi53
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts6
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts6
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-e5.dts6
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-e7.dts7
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-fortuna-common.dtsi197
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-gprimeltecan.dts70
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts6
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-grandprimelte.dts14
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-rossa-common.dtsi18
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-rossa.dts6
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916.dtsi18
-rw-r--r--arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts56
-rw-r--r--arch/arm64/boot/dts/qcom/msm8939.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/msm8953-motorola-potter.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/msm8953-xiaomi-daisy.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/msm8953-xiaomi-mido.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/msm8953-xiaomi-tissot.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/msm8953-xiaomi-vince.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/msm8953.dtsi30
-rw-r--r--arch/arm64/boot/dts/qcom/msm8956.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/msm8976.dtsi579
-rw-r--r--arch/arm64/boot/dts/qcom/msm8994.dtsi14
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996.dtsi104
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998.dtsi70
-rw-r--r--arch/arm64/boot/dts/qcom/pm6125.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm6150.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/pm6150l.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/pm6350.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm660.dtsi26
-rw-r--r--arch/arm64/boot/dts/qcom/pm660l.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm7250b.dtsi47
-rw-r--r--arch/arm64/boot/dts/qcom/pm7325.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm7550ba.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm8010.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150b.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150l.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm8350.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm8350b.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm8350c.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm8450.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm8550.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm8550b.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm8550ve.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm8550vs.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/pm8916.dtsi31
-rw-r--r--arch/arm64/boot/dts/qcom/pm8953.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/pm8994.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm8998.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pmi632.dtsi7
-rw-r--r--arch/arm64/boot/dts/qcom/pmi8950.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/pmm8155au_1.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pmm8155au_2.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pmr735a.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pmr735b.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pmr735d_a.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pmr735d_b.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pms405.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pmx75.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/qcm2290.dtsi184
-rw-r--r--arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts157
-rw-r--r--arch/arm64/boot/dts/qcom/qcm6490-idp.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts961
-rw-r--r--arch/arm64/boot/dts/qcom/qcs404.dtsi20
-rw-r--r--arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts111
-rw-r--r--arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dts315
-rw-r--r--arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi405
-rw-r--r--arch/arm64/boot/dts/qcom/qcs8550.dtsi162
-rw-r--r--arch/arm64/boot/dts/qcom/qdu1000-idp.dts23
-rw-r--r--arch/arm64/boot/dts/qcom/qdu1000.dtsi153
-rw-r--r--arch/arm64/boot/dts/qcom/qrb2210-rb1.dts21
-rw-r--r--arch/arm64/boot/dts/qcom/qrb4210-rb2.dts17
-rw-r--r--arch/arm64/boot/dts/qcom/qrb5165-rb5.dts122
-rw-r--r--arch/arm64/boot/dts/qcom/qru1000-idp.dts23
-rw-r--r--arch/arm64/boot/dts/qcom/sa8155p.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sa8775p-ride-r3.dts47
-rw-r--r--arch/arm64/boot/dts/qcom/sa8775p-ride.dts834
-rw-r--r--arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi814
-rw-r--r--arch/arm64/boot/dts/qcom/sa8775p.dtsi1146
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-clamshell.dtsi9
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-detachable.dtsi13
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi10
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1-kb.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1-lte.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-kb.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-lte.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-kb.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-lte.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-kb.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-lte.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel.dtsi5
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi15
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180.dtsi29
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-idp.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280.dtsi226
-rw-r--r--arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts16
-rw-r--r--arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sc8180x-primus.dts20
-rw-r--r--arch/arm64/boot/dts/qcom/sc8180x.dtsi263
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp-crd.dts23
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts160
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp.dtsi84
-rw-r--r--arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts15
-rw-r--r--arch/arm64/boot/dts/qcom/sdm450-lenovo-tbx605f.dts276
-rw-r--r--arch/arm64/boot/dts/qcom/sdm450-motorola-ali.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630.dtsi30
-rw-r--r--arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sdm632-motorola-ocean.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670.dtsi18
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-mtp.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845.dtsi179
-rw-r--r--arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts77
-rw-r--r--arch/arm64/boot/dts/qcom/sdx75-idp.dts45
-rw-r--r--arch/arm64/boot/dts/qcom/sdx75.dtsi583
-rw-r--r--arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sm4450.dtsi48
-rw-r--r--arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sm6115.dtsi46
-rw-r--r--arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts8
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts6
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sm6350-sony-xperia-lena-pdx213.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/sm6350.dtsi148
-rw-r--r--arch/arm64/boot/dts/qcom/sm6375-sony-xperia-murray-pdx225.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sm6375.dtsi78
-rw-r--r--arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts417
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-hdk.dts17
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150.dtsi74
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250-mtp.dts14
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250.dtsi83
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350-hdk.dts27
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350.dtsi82
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-hdk.dts43
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450.dtsi225
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550-hdk.dts26
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550-mtp.dts26
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550-qrd.dts134
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550-samsung-q5q.dts593
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550-sony-xperia-yodo-pdx234.dts14
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550.dtsi335
-rw-r--r--arch/arm64/boot/dts/qcom/sm8650-hdk-display-card.dtso141
-rw-r--r--arch/arm64/boot/dts/qcom/sm8650-hdk.dts1355
-rw-r--r--arch/arm64/boot/dts/qcom/sm8650-mtp.dts34
-rw-r--r--arch/arm64/boot/dts/qcom/sm8650-qrd.dts128
-rw-r--r--arch/arm64/boot/dts/qcom/sm8650.dtsi327
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts616
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-crd.dts213
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts929
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi482
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-qcp.dts365
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100.dtsi1844
-rw-r--r--arch/arm64/boot/dts/renesas/condor-common.dtsi6
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774a1.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774b1.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774c0.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774e1.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77951.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77960.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77961.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77980-condor.dts8
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77980.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77990.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77995.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779a0.dtsi5
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi6
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0.dtsi5
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts6
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779g0-white-hawk-ard-audio-da7212.dtso4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779g0.dtsi28
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779h0.dtsi737
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g043.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g043u.dtsi5
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g044.dtsi9
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g054.dtsi9
-rw-r--r--arch/arm64/boot/dts/renesas/r9a08g045.dtsi11
-rw-r--r--arch/arm64/boot/dts/renesas/r9a09g011.dtsi7
-rw-r--r--arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi11
-rw-r--r--arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi29
-rw-r--r--arch/arm64/boot/dts/renesas/white-hawk-ethernet.dtsi103
-rw-r--r--arch/arm64/boot/dts/rockchip/Makefile11
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts99
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3308-rock-s0.dts293
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3308.dtsi31
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-rock64.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328.dtsi4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368-lba3368.dts659
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368.dtsi3
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts74
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399pro.dtsi22
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts29
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v2.1.dts70
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi678
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi1
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts1
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts3
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi531
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3e.dts52
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3w.dts92
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi1
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi48
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts16
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts781
-rw-r--r--arch/arm64/boot/dts/rockchip/rk356x.dtsi13
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi (renamed from arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi)0
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-base.dtsi2799
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts16
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi (renamed from arch/arm64/boot/dts/rockchip/rk3588-pinctrl.dtsi)0
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi448
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dts778
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588.dtsi653
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts10
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-opp.dtsi190
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts1
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts13
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts1177
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-rock-5b-pcie-ep.dtso25
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-rock-5b-pcie-srns.dtso16
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts58
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi5
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi7
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588.dtsi413
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588j.dtsi143
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts19
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s.dtsi2670
-rw-r--r--arch/arm64/boot/dts/sprd/ums512.dtsi14
-rw-r--r--arch/arm64/boot/dts/sprd/ums9620.dtsi14
-rw-r--r--arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi100
-rw-r--r--arch/arm64/boot/dts/st/stm32mp251.dtsi246
-rw-r--r--arch/arm64/boot/dts/st/stm32mp253.dtsi64
-rw-r--r--arch/arm64/boot/dts/st/stm32mp257f-ev1.dts77
-rw-r--r--arch/arm64/boot/dts/ti/Makefile56
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-lp-sk-nand.dtso116
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts4
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-main.dtsi39
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi4
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi4
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi5
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts2
-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-phyboard-lyra-rdk.dts467
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a-main.dtsi32
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi330
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi11
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a7-phyboard-lyra-rdk.dts18
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a7-sk.dts11
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi1062
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi (renamed from arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi)11
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-j722s-common-thermal.dtsi (renamed from arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi)0
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-j722s-common-wakeup.dtsi (renamed from arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi)8
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-main.dtsi1083
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p.dtsi9
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p5-sk.dts20
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi475
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi32
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-main.dtsi24
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi46
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-tqma64xxl-mbax4xxl-sdcard.dtso4
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-tqma64xxl-mbax4xxl-wlan.dtso4
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac-mii.dtso101
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso148
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-evm.dts15
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-hummingboard-t.dts1
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-pcie-usb2.dtso87
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts12
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-sk.dts12
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts4
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi4
-rw-r--r--arch/arm64/boot/dts/ti/k3-am65-main.dtsi36
-rw-r--r--arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi12
-rw-r--r--arch/arm64/boot/dts/ti/k3-am654-base-board.dts1
-rw-r--r--arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts76
-rw-r--r--arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi86
-rw-r--r--arch/arm64/boot/dts/ti/k3-am69-sk.dts87
-rw-r--r--arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-eth-phy.dtso19
-rw-r--r--arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-rtc.dtso15
-rw-r--r--arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-spi-nor.dtso15
-rw-r--r--arch/arm64/boot/dts/ti/k3-am6xx-phycore-qspi-nor.dtso15
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi14
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi5
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-common-proc-board-infotainment.dtso164
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi12
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-sk.dts117
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi1
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi12
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi5
-rw-r--r--arch/arm64/boot/dts/ti/k3-j722s-evm.dts182
-rw-r--r--arch/arm64/boot/dts/ti/k3-j722s-main.dtsi217
-rw-r--r--arch/arm64/boot/dts/ti/k3-j722s.dtsi165
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-evm-pcie0-pcie1-ep.dtso79
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-evm-quad-port-eth-exp1.dtso147
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-evm-usxgmii-exp1-exp2.dtso81
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-evm.dts383
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi527
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi14
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4.dtsi10
-rw-r--r--arch/arm64/boot/dts/ti/k3-pinctrl.h3
-rw-r--r--arch/arm64/boot/dts/ti/k3-serdes.h8
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi16
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso19
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso41
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts19
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-smk-k26-revA.dts8
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts8
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp.dtsi186
-rw-r--r--arch/arm64/configs/defconfig23
-rw-r--r--arch/arm64/include/asm/Kbuild8
-rw-r--r--arch/arm64/include/asm/acpi.h12
-rw-r--r--arch/arm64/include/asm/arch_gicv3.h15
-rw-r--r--arch/arm64/include/asm/arch_timer.h2
-rw-r--r--arch/arm64/include/asm/arm_pmuv3.h2
-rw-r--r--arch/arm64/include/asm/asm-extable.h3
-rw-r--r--arch/arm64/include/asm/cpucaps.h2
-rw-r--r--arch/arm64/include/asm/cpufeature.h4
-rw-r--r--arch/arm64/include/asm/cputype.h6
-rw-r--r--arch/arm64/include/asm/esr.h33
-rw-r--r--arch/arm64/include/asm/mmu_context.h4
-rw-r--r--arch/arm64/include/asm/mte.h4
-rw-r--r--arch/arm64/include/asm/ptrace.h35
-rw-r--r--arch/arm64/include/asm/runtime-const.h88
-rw-r--r--arch/arm64/include/asm/seccomp.h13
-rw-r--r--arch/arm64/include/asm/smp.h13
-rw-r--r--arch/arm64/include/asm/sysreg.h4
-rw-r--r--arch/arm64/include/asm/uaccess.h169
-rw-r--r--arch/arm64/include/asm/unistd.h22
-rw-r--r--arch/arm64/include/asm/unistd32.h939
-rw-r--r--arch/arm64/include/asm/vdso/compat_gettimeofday.h12
-rw-r--r--arch/arm64/include/asm/word-at-a-time.h11
-rw-r--r--arch/arm64/include/uapi/asm/Kbuild1
-rw-r--r--arch/arm64/include/uapi/asm/unistd.h25
-rw-r--r--arch/arm64/kernel/Makefile1
-rw-r--r--arch/arm64/kernel/Makefile.syscalls6
-rw-r--r--arch/arm64/kernel/acpi.c129
-rw-r--r--arch/arm64/kernel/acpi_numa.c11
-rw-r--r--arch/arm64/kernel/cpu_errata.c17
-rw-r--r--arch/arm64/kernel/cpufeature.c5
-rw-r--r--arch/arm64/kernel/image-vars.h5
-rw-r--r--arch/arm64/kernel/mte.c12
-rw-r--r--arch/arm64/kernel/proton-pack.c2
-rw-r--r--arch/arm64/kernel/psci.c2
-rw-r--r--arch/arm64/kernel/reloc_test_core.c1
-rw-r--r--arch/arm64/kernel/signal32.c4
-rw-r--r--arch/arm64/kernel/sigreturn32.S18
-rw-r--r--arch/arm64/kernel/smp.c74
-rw-r--r--arch/arm64/kernel/sys.c6
-rw-r--r--arch/arm64/kernel/sys32.c17
-rw-r--r--arch/arm64/kernel/syscall.c3
-rw-r--r--arch/arm64/kernel/vmlinux.lds.S3
-rw-r--r--arch/arm64/kvm/hyp/include/nvhe/fixed_config.h10
-rw-r--r--arch/arm64/kvm/hyp/nvhe/pkvm.c4
-rw-r--r--arch/arm64/kvm/hyp/nvhe/sys_regs.c2
-rw-r--r--arch/arm64/kvm/pmu-emul.c1
-rw-r--r--arch/arm64/tools/Makefile6
-rw-r--r--arch/arm64/tools/syscall_32.tbl476
l---------arch/arm64/tools/syscall_64.tbl1
-rw-r--r--arch/csky/include/asm/Kbuild3
-rw-r--r--arch/csky/include/asm/unistd.h3
-rw-r--r--arch/csky/include/uapi/asm/Kbuild2
-rw-r--r--arch/csky/include/uapi/asm/unistd.h15
-rw-r--r--arch/csky/kernel/Makefile.syscalls4
-rw-r--r--arch/csky/kernel/syscall_table.c4
-rw-r--r--arch/hexagon/include/asm/Kbuild2
-rw-r--r--arch/hexagon/include/asm/unistd.h10
-rw-r--r--arch/hexagon/include/uapi/asm/Kbuild2
-rw-r--r--arch/hexagon/include/uapi/asm/unistd.h14
-rw-r--r--arch/hexagon/kernel/Makefile.syscalls3
-rw-r--r--arch/hexagon/kernel/syscalltab.c8
-rw-r--r--arch/loongarch/include/asm/Kbuild17
-rw-r--r--arch/loongarch/include/asm/unistd.h2
-rw-r--r--arch/loongarch/include/uapi/asm/Kbuild2
-rw-r--r--arch/loongarch/include/uapi/asm/unistd.h4
-rw-r--r--arch/loongarch/kernel/Makefile.syscalls4
-rw-r--r--arch/loongarch/kernel/syscall.c3
-rw-r--r--arch/m68k/amiga/config.c9
-rw-r--r--arch/m68k/atari/ataints.c6
-rw-r--r--arch/m68k/configs/amiga_defconfig1
-rw-r--r--arch/m68k/configs/apollo_defconfig1
-rw-r--r--arch/m68k/configs/atari_defconfig1
-rw-r--r--arch/m68k/configs/bvme6000_defconfig1
-rw-r--r--arch/m68k/configs/hp300_defconfig1
-rw-r--r--arch/m68k/configs/mac_defconfig1
-rw-r--r--arch/m68k/configs/multi_defconfig1
-rw-r--r--arch/m68k/configs/mvme147_defconfig1
-rw-r--r--arch/m68k/configs/mvme16x_defconfig1
-rw-r--r--arch/m68k/configs/q40_defconfig1
-rw-r--r--arch/m68k/configs/sun3_defconfig1
-rw-r--r--arch/m68k/configs/sun3x_defconfig1
-rw-r--r--arch/m68k/emu/nfblock.c4
-rw-r--r--arch/m68k/emu/nfcon.c1
-rw-r--r--arch/m68k/include/asm/cmpxchg.h2
-rw-r--r--arch/m68k/include/asm/unistd.h1
-rw-r--r--arch/mips/include/asm/unistd.h1
-rw-r--r--arch/nios2/include/asm/Kbuild2
-rw-r--r--arch/nios2/include/asm/unistd.h12
-rw-r--r--arch/nios2/include/uapi/asm/Kbuild2
-rw-r--r--arch/nios2/include/uapi/asm/unistd.h14
-rw-r--r--arch/nios2/kernel/Makefile.syscalls3
-rw-r--r--arch/nios2/kernel/syscall_table.c6
-rw-r--r--arch/openrisc/include/asm/Kbuild2
-rw-r--r--arch/openrisc/include/asm/syscalls.h4
-rw-r--r--arch/openrisc/include/asm/unistd.h8
-rw-r--r--arch/openrisc/include/uapi/asm/Kbuild2
-rw-r--r--arch/openrisc/include/uapi/asm/unistd.h15
-rw-r--r--arch/openrisc/kernel/Makefile.syscalls3
-rw-r--r--arch/openrisc/kernel/sys_call_table.c9
-rw-r--r--arch/parisc/include/asm/unistd.h1
-rw-r--r--arch/powerpc/include/asm/unistd.h1
-rw-r--r--arch/powerpc/kernel/eeh_pe.c7
-rw-r--r--arch/powerpc/kernel/head_64.S5
-rw-r--r--arch/powerpc/kexec/core_64.c11
-rw-r--r--arch/powerpc/platforms/pseries/kexec.c8
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h1
-rw-r--r--arch/powerpc/platforms/pseries/setup.c5
-rw-r--r--arch/riscv/boot/dts/allwinner/Makefile2
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts252
-rw-r--r--arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts36
-rw-r--r--arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi11
-rw-r--r--arch/riscv/boot/dts/canaan/canaan_kd233.dts7
-rw-r--r--arch/riscv/boot/dts/canaan/k210.dtsi23
-rw-r--r--arch/riscv/boot/dts/canaan/k210_generic.dts5
-rw-r--r--arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts9
-rw-r--r--arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts7
-rw-r--r--arch/riscv/boot/dts/canaan/sipeed_maix_go.dts9
-rw-r--r--arch/riscv/boot/dts/canaan/sipeed_maixduino.dts10
-rw-r--r--arch/riscv/boot/dts/microchip/Makefile1
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-beaglev-fire-fabric.dtsi82
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-beaglev-fire.dts223
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts12
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2042.dtsi55
-rw-r--r--arch/riscv/boot/dts/starfive/Makefile1
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-common.dtsi71
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-milkv-mars.dts7
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts65
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi8
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110.dtsi86
-rw-r--r--arch/riscv/boot/dts/thead/th1520.dtsi81
-rw-r--r--arch/riscv/configs/defconfig26
-rw-r--r--arch/riscv/include/asm/Kbuild3
-rw-r--r--arch/riscv/include/asm/syscall_table.h7
-rw-r--r--arch/riscv/include/asm/unistd.h13
-rw-r--r--arch/riscv/include/uapi/asm/Kbuild2
-rw-r--r--arch/riscv/include/uapi/asm/unistd.h41
-rw-r--r--arch/riscv/kernel/Makefile.syscalls4
-rw-r--r--arch/riscv/kernel/compat_syscall_table.c6
-rw-r--r--arch/riscv/kernel/machine_kexec.c10
-rw-r--r--arch/riscv/kernel/stacktrace.c3
-rw-r--r--arch/riscv/kernel/syscall_table.c6
-rw-r--r--arch/riscv/kvm/vcpu_pmu.c2
-rw-r--r--arch/s390/configs/debug_defconfig5
-rw-r--r--arch/s390/configs/defconfig5
-rw-r--r--arch/s390/include/asm/kvm_host.h1
-rw-r--r--arch/s390/include/asm/unistd.h1
-rw-r--r--arch/s390/kvm/kvm-s390.c1
-rw-r--r--arch/s390/kvm/kvm-s390.h15
-rw-r--r--arch/s390/kvm/priv.c32
-rw-r--r--arch/s390/mm/pgalloc.c4
-rw-r--r--arch/sh/include/asm/unistd.h2
-rw-r--r--arch/sparc/include/asm/unistd.h2
-rw-r--r--arch/um/drivers/ubd_kern.c53
-rw-r--r--arch/um/include/asm/Kbuild1
-rw-r--r--arch/um/include/asm/bpf_perf_event.h9
-rw-r--r--arch/x86/Kconfig27
-rw-r--r--arch/x86/Kconfig.assembler2
-rw-r--r--arch/x86/boot/compressed/kaslr.c43
-rw-r--r--arch/x86/boot/compressed/misc.c5
-rw-r--r--arch/x86/boot/compressed/sev.c86
-rw-r--r--arch/x86/boot/cpucheck.c2
-rw-r--r--arch/x86/boot/main.c42
-rw-r--r--arch/x86/coco/Makefile1
-rw-r--r--arch/x86/coco/core.c1
-rw-r--r--arch/x86/coco/sev/Makefile15
-rw-r--r--arch/x86/coco/sev/core.c (renamed from arch/x86/kernel/sev.c)449
-rw-r--r--arch/x86/coco/sev/shared.c (renamed from arch/x86/kernel/sev-shared.c)460
-rw-r--r--arch/x86/coco/tdx/tdx.c121
-rw-r--r--arch/x86/entry/entry_64_compat.S14
-rw-r--r--arch/x86/entry/syscall_32.c10
-rw-r--r--arch/x86/entry/syscall_64.c9
-rw-r--r--arch/x86/entry/syscall_x32.c7
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl7
-rw-r--r--arch/x86/entry/syscalls/syscall_64.tbl7
-rw-r--r--arch/x86/events/intel/core.c212
-rw-r--r--arch/x86/events/rapl.c90
-rw-r--r--arch/x86/hyperv/ivm.c22
-rw-r--r--arch/x86/include/asm/acpi.h7
-rw-r--r--arch/x86/include/asm/alternative.h241
-rw-r--r--arch/x86/include/asm/amd_nb.h4
-rw-r--r--arch/x86/include/asm/cpu_device_id.h8
-rw-r--r--arch/x86/include/asm/cpufeatures.h801
-rw-r--r--arch/x86/include/asm/efi.h22
-rw-r--r--arch/x86/include/asm/init.h3
-rw-r--r--arch/x86/include/asm/intel_pconfig.h65
-rw-r--r--arch/x86/include/asm/irqflags.h20
-rw-r--r--arch/x86/include/asm/mce.h3
-rw-r--r--arch/x86/include/asm/msr-index.h3
-rw-r--r--arch/x86/include/asm/page_64.h2
-rw-r--r--arch/x86/include/asm/pgtable.h5
-rw-r--r--arch/x86/include/asm/pgtable_types.h1
-rw-r--r--arch/x86/include/asm/processor.h12
-rw-r--r--arch/x86/include/asm/runtime-const.h61
-rw-r--r--arch/x86/include/asm/set_memory.h3
-rw-r--r--arch/x86/include/asm/setup.h8
-rw-r--r--arch/x86/include/asm/sev-common.h18
-rw-r--r--arch/x86/include/asm/sev.h135
-rw-r--r--arch/x86/include/asm/smp.h1
-rw-r--r--arch/x86/include/asm/tsc.h3
-rw-r--r--arch/x86/include/asm/unistd.h1
-rw-r--r--arch/x86/include/asm/vdso/gettimeofday.h5
-rw-r--r--arch/x86/include/asm/vdso/vsyscall.h1
-rw-r--r--arch/x86/include/asm/vgtod.h5
-rw-r--r--arch/x86/include/asm/vmware.h336
-rw-r--r--arch/x86/include/asm/vmxfeatures.h110
-rw-r--r--arch/x86/include/asm/word-at-a-time.h57
-rw-r--r--arch/x86/include/asm/x86_init.h14
-rw-r--r--arch/x86/include/uapi/asm/svm.h1
-rw-r--r--arch/x86/kernel/Makefile6
-rw-r--r--arch/x86/kernel/acpi/Makefile1
-rw-r--r--arch/x86/kernel/acpi/boot.c86
-rw-r--r--arch/x86/kernel/acpi/madt_playdead.S28
-rw-r--r--arch/x86/kernel/acpi/madt_wakeup.c292
-rw-r--r--arch/x86/kernel/alternative.c22
-rw-r--r--arch/x86/kernel/amd_nb.c44
-rw-r--r--arch/x86/kernel/cpu/Makefile2
-rw-r--r--arch/x86/kernel/cpu/amd.c11
-rw-r--r--arch/x86/kernel/cpu/bugs.c16
-rw-r--r--arch/x86/kernel/cpu/intel.c188
-rw-r--r--arch/x86/kernel/cpu/intel_pconfig.c84
-rw-r--r--arch/x86/kernel/cpu/mce/core.c7
-rw-r--r--arch/x86/kernel/cpu/mce/inject.c9
-rw-r--r--arch/x86/kernel/cpu/mkcapflags.sh3
-rw-r--r--arch/x86/kernel/cpu/resctrl/core.c312
-rw-r--r--arch/x86/kernel/cpu/resctrl/ctrlmondata.c89
-rw-r--r--arch/x86/kernel/cpu/resctrl/internal.h108
-rw-r--r--arch/x86/kernel/cpu/resctrl/monitor.c250
-rw-r--r--arch/x86/kernel/cpu/resctrl/pseudo_lock.c42
-rw-r--r--arch/x86/kernel/cpu/resctrl/rdtgroup.c288
-rw-r--r--arch/x86/kernel/cpu/vmware.c225
-rw-r--r--arch/x86/kernel/crash.c12
-rw-r--r--arch/x86/kernel/devicetree.c2
-rw-r--r--arch/x86/kernel/e820.c9
-rw-r--r--arch/x86/kernel/fpu/xstate.h14
-rw-r--r--arch/x86/kernel/process.c7
-rw-r--r--arch/x86/kernel/reboot.c18
-rw-r--r--arch/x86/kernel/relocate_kernel_64.S27
-rw-r--r--arch/x86/kernel/setup.c3
-rw-r--r--arch/x86/kernel/tsc.c92
-rw-r--r--arch/x86/kernel/vmlinux.lds.S3
-rw-r--r--arch/x86/kernel/x86_init.c8
-rw-r--r--arch/x86/kvm/emulate.c2
-rw-r--r--arch/x86/lib/cmdline.c8
-rw-r--r--arch/x86/lib/getuser.S69
-rw-r--r--arch/x86/lib/iomem.c5
-rw-r--r--arch/x86/mm/ident_map.c73
-rw-r--r--arch/x86/mm/init_64.c16
-rw-r--r--arch/x86/mm/mem_encrypt_amd.c16
-rw-r--r--arch/x86/mm/pat/set_memory.c75
-rw-r--r--arch/x86/pci/intel_mid_pci.c8
-rw-r--r--arch/x86/pci/xen.c4
-rw-r--r--arch/x86/platform/efi/Makefile1
-rw-r--r--arch/x86/platform/efi/efi.c2
-rw-r--r--arch/x86/platform/efi/fake_mem.c197
-rw-r--r--arch/x86/platform/efi/memmap.c1
-rw-r--r--arch/x86/platform/intel-mid/intel-mid.c6
-rw-r--r--arch/x86/platform/intel/iosf_mbi.c4
-rw-r--r--arch/x86/um/sys_call_table_32.c10
-rw-r--r--arch/x86/um/sys_call_table_64.c11
-rw-r--r--arch/x86/virt/svm/sev.c44
-rw-r--r--arch/x86/virt/vmx/tdx/tdx.c8
-rw-r--r--arch/xtensa/include/asm/current.h2
-rw-r--r--arch/xtensa/include/asm/thread_info.h2
-rw-r--r--arch/xtensa/include/asm/unistd.h1
-rw-r--r--arch/xtensa/platforms/iss/simdisk.c5
-rw-r--r--block/Kconfig8
-rw-r--r--block/Makefile3
-rw-r--r--block/bdev.c41
-rw-r--r--block/bfq-cgroup.c51
-rw-r--r--block/bfq-iosched.c38
-rw-r--r--block/bfq-iosched.h3
-rw-r--r--block/bio-integrity.c135
-rw-r--r--block/bio.c2
-rw-r--r--block/blk-cgroup.h13
-rw-r--r--block/blk-core.c45
-rw-r--r--block/blk-flush.c36
-rw-r--r--block/blk-integrity.c228
-rw-r--r--block/blk-lib.c210
-rw-r--r--block/blk-map.c2
-rw-r--r--block/blk-merge.c92
-rw-r--r--block/blk-mq-debugfs.c13
-rw-r--r--block/blk-mq.c89
-rw-r--r--block/blk-settings.c549
-rw-r--r--block/blk-sysfs.c434
-rw-r--r--block/blk-throttle.c3
-rw-r--r--block/blk-wbt.c22
-rw-r--r--block/blk-zoned.c126
-rw-r--r--block/blk.h22
-rw-r--r--block/elevator.c9
-rw-r--r--block/elevator.h4
-rw-r--r--block/fops.c25
-rw-r--r--block/genhd.c2
-rw-r--r--block/ioctl.c2
-rw-r--r--block/mq-deadline.c20
-rw-r--r--block/t10-pi.c302
-rw-r--r--drivers/acpi/acpi_processor.c141
-rw-r--r--drivers/acpi/arm64/Makefile6
-rw-r--r--drivers/acpi/arm64/amba.c6
-rw-r--r--drivers/acpi/arm64/cpuidle.c (renamed from arch/arm64/kernel/cpuidle.c)4
-rw-r--r--drivers/acpi/arm64/ffh.c107
-rw-r--r--drivers/acpi/battery.c15
-rw-r--r--drivers/acpi/processor_core.c3
-rw-r--r--drivers/acpi/processor_driver.c43
-rw-r--r--drivers/acpi/processor_idle.c37
-rw-r--r--drivers/acpi/scan.c47
-rw-r--r--drivers/acpi/tables.c14
-rw-r--r--drivers/ata/libata-scsi.c3
-rw-r--r--drivers/ata/pata_macio.c4
-rw-r--r--drivers/base/cpu.c12
-rw-r--r--drivers/base/regmap/regcache-maple.c13
-rw-r--r--drivers/base/regmap/regcache.c6
-rw-r--r--drivers/base/regmap/regmap-ac97.c1
-rw-r--r--drivers/base/regmap/regmap-i2c.c1
-rw-r--r--drivers/base/regmap/regmap-irq.c2
-rw-r--r--drivers/base/regmap/regmap-kunit.c158
-rw-r--r--drivers/base/regmap/regmap-ram.c1
-rw-r--r--drivers/base/regmap/regmap-raw-ram.c1
-rw-r--r--drivers/base/regmap/regmap-sccb.c1
-rw-r--r--drivers/base/regmap/regmap-slimbus.c1
-rw-r--r--drivers/base/regmap/regmap-spi-avmm.c1
-rw-r--r--drivers/base/regmap/regmap-spi.c3
-rw-r--r--drivers/base/regmap/regmap-spmi.c1
-rw-r--r--drivers/base/regmap/regmap-w1.c1
-rw-r--r--drivers/base/regmap/regmap.c105
-rw-r--r--drivers/block/Kconfig9
-rw-r--r--drivers/block/Makefile3
-rw-r--r--drivers/block/amiflop.c6
-rw-r--r--drivers/block/aoe/aoeblk.c1
-rw-r--r--drivers/block/ataflop.c6
-rw-r--r--drivers/block/brd.c7
-rw-r--r--drivers/block/drbd/drbd_main.c6
-rw-r--r--drivers/block/floppy.c4
-rw-r--r--drivers/block/loop.c184
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c2
-rw-r--r--drivers/block/n64cart.c2
-rw-r--r--drivers/block/nbd.c26
-rw-r--r--drivers/block/null_blk/main.c29
-rw-r--r--drivers/block/null_blk/null_blk.h1
-rw-r--r--drivers/block/null_blk/zoned.c15
-rw-r--r--drivers/block/pktcdvd.c1
-rw-r--r--drivers/block/ps3disk.c8
-rw-r--r--drivers/block/rbd.c15
-rw-r--r--drivers/block/rnbd/rnbd-clt-sysfs.c2
-rw-r--r--drivers/block/rnbd/rnbd-clt.c16
-rw-r--r--drivers/block/rnbd/rnbd-srv-sysfs.c4
-rw-r--r--drivers/block/rnull.rs73
-rw-r--r--drivers/block/sunvdc.c1
-rw-r--r--drivers/block/swim.c5
-rw-r--r--drivers/block/swim3.c5
-rw-r--r--drivers/block/ublk_drv.c22
-rw-r--r--drivers/block/virtio_blk.c68
-rw-r--r--drivers/block/xen-blkback/blkback.c1
-rw-r--r--drivers/block/xen-blkfront.c73
-rw-r--r--drivers/block/z2ram.c1
-rw-r--r--drivers/block/zram/zram_drv.c6
-rw-r--r--drivers/bluetooth/btintel_pcie.c2
-rw-r--r--drivers/bluetooth/btnxpuart.c2
-rw-r--r--drivers/bluetooth/hci_bcm4377.c10
-rw-r--r--drivers/bluetooth/hci_qca.c18
-rw-r--r--drivers/bus/sunxi-rsb.c2
-rw-r--r--drivers/bus/ts-nbus.c2
-rw-r--r--drivers/bus/vexpress-config.c1
-rw-r--r--drivers/cache/Kconfig9
-rw-r--r--drivers/cache/Makefile5
-rw-r--r--drivers/cache/starfive_starlink_cache.c130
-rw-r--r--drivers/cdrom/cdrom.c1
-rw-r--r--drivers/cdrom/gdrom.c1
-rw-r--r--drivers/char/hpet.c34
-rw-r--r--drivers/char/tpm/Makefile2
-rw-r--r--drivers/char/tpm/eventlog/common.c2
-rw-r--r--drivers/char/tpm/tpm2-sessions.c419
-rw-r--r--drivers/char/tpm/tpm_tis_spi_main.c1
-rw-r--r--drivers/clk/mediatek/clk-mt8183-mfgcfg.c1
-rw-r--r--drivers/clk/mediatek/clk-mtk.c24
-rw-r--r--drivers/clk/mediatek/clk-mtk.h2
-rw-r--r--drivers/clk/qcom/Kconfig8
-rw-r--r--drivers/clk/qcom/Makefile1
-rw-r--r--drivers/clk/qcom/apss-ipq-pll.c2
-rw-r--r--drivers/clk/qcom/camcc-sm8650.c3591
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c3
-rw-r--r--drivers/clk/qcom/gcc-ipq9574.c10
-rw-r--r--drivers/clk/qcom/gcc-sm6350.c10
-rw-r--r--drivers/clk/qcom/gdsc.c41
-rw-r--r--drivers/clk/qcom/gdsc.h1
-rw-r--r--drivers/clk/qcom/videocc-sc7280.c2
-rw-r--r--drivers/clk/qcom/videocc-sm8250.c4
-rw-r--r--drivers/clk/qcom/videocc-sm8550.c156
-rw-r--r--drivers/clk/sunxi-ng/ccu_common.c18
-rw-r--r--drivers/clocksource/Kconfig10
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/arm_arch_timer.c2
-rw-r--r--drivers/clocksource/arm_global_timer.c2
-rw-r--r--drivers/clocksource/mips-gic-timer.c20
-rw-r--r--drivers/clocksource/sh_cmt.c13
-rw-r--r--drivers/clocksource/timer-rtl-otto.c291
-rw-r--r--drivers/counter/stm32-timer-cnt.c4
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c4
-rw-r--r--drivers/cpufreq/cpufreq.c3
-rw-r--r--drivers/cpufreq/qcom-cpufreq-nvmem.c1
-rw-r--r--drivers/cxl/core/hdm.c13
-rw-r--r--drivers/cxl/core/pmem.c16
-rw-r--r--drivers/cxl/core/region.c103
-rw-r--r--drivers/cxl/cxl.h6
-rw-r--r--drivers/cxl/cxlmem.h21
-rw-r--r--drivers/cxl/mem.c17
-rw-r--r--drivers/edac/Makefile10
-rw-r--r--drivers/edac/amd64_edac.c69
-rw-r--r--drivers/edac/amd64_edac.h4
-rw-r--r--drivers/edac/dmc520_edac.c4
-rw-r--r--drivers/edac/ghes_edac.c2
-rw-r--r--drivers/edac/i10nm_base.c20
-rw-r--r--drivers/edac/igen6_edac.c8
-rw-r--r--drivers/edac/layerscape_edac.c1
-rw-r--r--drivers/edac/mpc85xx_edac.c1
-rw-r--r--drivers/edac/octeon_edac-l2c.c1
-rw-r--r--drivers/edac/octeon_edac-lmc.c1
-rw-r--r--drivers/edac/octeon_edac-pc.c1
-rw-r--r--drivers/edac/octeon_edac-pci.c1
-rw-r--r--drivers/edac/pnd2_edac.c4
-rw-r--r--drivers/edac/sb_edac.c14
-rw-r--r--drivers/edac/skx_base.c2
-rw-r--r--drivers/edac/skx_common.c21
-rw-r--r--drivers/edac/skx_common.h4
-rw-r--r--drivers/edac/thunderx_edac.c6
-rw-r--r--drivers/firmware/arm_ffa/Makefile6
-rw-r--r--drivers/firmware/arm_ffa/bus.c22
-rw-r--r--drivers/firmware/arm_ffa/common.h2
-rw-r--r--drivers/firmware/arm_ffa/driver.c57
-rw-r--r--drivers/firmware/arm_scmi/common.h1
-rw-r--r--drivers/firmware/arm_scmi/mailbox.c57
-rw-r--r--drivers/firmware/arm_scmi/scmi_power_control.c21
-rw-r--r--drivers/firmware/arm_scmi/shmem.c5
-rw-r--r--drivers/firmware/cirrus/cs_dsp.c227
-rw-r--r--drivers/firmware/efi/libstub/Makefile2
-rw-r--r--drivers/firmware/efi/libstub/arm64-stub.c13
-rw-r--r--drivers/firmware/efi/libstub/arm64.c3
-rw-r--r--drivers/firmware/efi/libstub/efistub.h9
-rw-r--r--drivers/firmware/efi/libstub/kaslr.c20
-rw-r--r--drivers/firmware/efi/libstub/relocate.c2
-rw-r--r--drivers/firmware/efi/libstub/smbios.c43
-rw-r--r--drivers/firmware/efi/libstub/unaccepted_memory.c2
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.c83
-rw-r--r--drivers/firmware/efi/memattr.c2
-rw-r--r--drivers/firmware/google/cbmem.c1
-rw-r--r--drivers/firmware/google/coreboot_table.c1
-rw-r--r--drivers/firmware/google/framebuffer-coreboot.c1
-rw-r--r--drivers/firmware/google/gsmi.c1
-rw-r--r--drivers/firmware/google/memconsole-coreboot.c1
-rw-r--r--drivers/firmware/google/memconsole-x86-legacy.c1
-rw-r--r--drivers/firmware/google/memconsole.c1
-rw-r--r--drivers/firmware/google/vpd.c1
-rw-r--r--drivers/firmware/meson/meson_sm.c1
-rw-r--r--drivers/firmware/microchip/mpfs-auto-update.c136
-rw-r--r--drivers/firmware/qcom/Kconfig31
-rw-r--r--drivers/firmware/qcom/Makefile1
-rw-r--r--drivers/firmware/qcom/qcom_qseecom_uefisecapp.c256
-rw-r--r--drivers/firmware/qcom/qcom_scm-smc.c30
-rw-r--r--drivers/firmware/qcom/qcom_scm.c197
-rw-r--r--drivers/firmware/qcom/qcom_scm.h9
-rw-r--r--drivers/firmware/qcom/qcom_tzmem.c469
-rw-r--r--drivers/firmware/qcom/qcom_tzmem.h13
-rw-r--r--drivers/firmware/sysfb.c12
-rw-r--r--drivers/firmware/ti_sci.h2
-rw-r--r--drivers/firmware/turris-mox-rwtm.c23
-rw-r--r--drivers/firmware/xilinx/zynqmp.c3
-rw-r--r--drivers/gpio/Kconfig33
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/gpio-amd8111.c4
-rw-r--r--drivers/gpio/gpio-ath79.c2
-rw-r--r--drivers/gpio/gpio-mc33880.c2
-rw-r--r--drivers/gpio/gpio-mmio.c2
-rw-r--r--drivers/gpio/gpio-pca953x.c1
-rw-r--r--drivers/gpio/gpio-rdc321x.c6
-rw-r--r--drivers/gpio/gpio-sim.c60
-rw-r--r--drivers/gpio/gpio-sloppy-logic-analyzer.c344
-rw-r--r--drivers/gpio/gpio-syscon.c27
-rw-r--r--drivers/gpio/gpio-virtuser.c1807
-rw-r--r--drivers/gpio/gpiolib-acpi.c4
-rw-r--r--drivers/gpio/gpiolib-cdev.c80
-rw-r--r--drivers/gpio/gpiolib-of.c26
-rw-r--r--drivers/gpio/gpiolib.c36
-rw-r--r--drivers/gpio/gpiolib.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c52
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c2
-rw-r--r--drivers/gpu/drm/amd/include/atomfirmware.h2
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511.h2
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_cec.c13
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c22
-rw-r--r--drivers/gpu/drm/drm_fbdev_generic.c3
-rw-r--r--drivers/gpu/drm/drm_panel_orientation_quirks.c9
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_lvds.c3
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_lvds.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c3
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c37
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c3
-rw-r--r--drivers/gpu/drm/panthor/panthor_drv.c6
-rw-r--r--drivers/gpu/drm/panthor/panthor_sched.c44
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg.c173
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h196
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h185
-rw-r--r--drivers/gpu/drm/xe/display/xe_hdcp_gsc.c12
-rw-r--r--drivers/gpu/drm/xe/xe_bo.c47
-rw-r--r--drivers/gpu/drm/xe/xe_bo_types.h3
-rw-r--r--drivers/gpu/drm/xe/xe_gt_mcr.c6
-rw-r--r--drivers/gpu/drm/xe/xe_migrate.c8
-rw-r--r--drivers/hwmon/Kconfig67
-rw-r--r--drivers/hwmon/Makefile4
-rw-r--r--drivers/hwmon/ad7418.c7
-rw-r--r--drivers/hwmon/adc128d818.c4
-rw-r--r--drivers/hwmon/adm1021.c505
-rw-r--r--drivers/hwmon/adm1031.c4
-rw-r--r--drivers/hwmon/ads7828.c7
-rw-r--r--drivers/hwmon/adt7475.c18
-rw-r--r--drivers/hwmon/aht10.c3
-rw-r--r--drivers/hwmon/amc6821.c1356
-rw-r--r--drivers/hwmon/asus-ec-sensors.c10
-rw-r--r--drivers/hwmon/asus_atk0110.c1
-rw-r--r--drivers/hwmon/corsair-cpro.c89
-rw-r--r--drivers/hwmon/corsair-psu.c7
-rw-r--r--drivers/hwmon/cros_ec_hwmon.c283
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c7
-rw-r--r--drivers/hwmon/dme1737.c4
-rw-r--r--drivers/hwmon/ds1621.c4
-rw-r--r--drivers/hwmon/f75375s.c46
-rw-r--r--drivers/hwmon/fschmd.c2
-rw-r--r--drivers/hwmon/g762.c43
-rw-r--r--drivers/hwmon/gsc-hwmon.c9
-rw-r--r--drivers/hwmon/hwmon.c149
-rw-r--r--drivers/hwmon/iio_hwmon.c11
-rw-r--r--drivers/hwmon/ina238.c2
-rw-r--r--drivers/hwmon/ina2xx.c39
-rw-r--r--drivers/hwmon/jc42.c49
-rw-r--r--drivers/hwmon/k10temp.c62
-rw-r--r--drivers/hwmon/lm63.c5
-rw-r--r--drivers/hwmon/lm70.c6
-rw-r--r--drivers/hwmon/lm75.c10
-rw-r--r--drivers/hwmon/lm78.c4
-rw-r--r--drivers/hwmon/lm83.c16
-rw-r--r--drivers/hwmon/lm85.c7
-rw-r--r--drivers/hwmon/lm90.c61
-rw-r--r--drivers/hwmon/lm95234.c14
-rw-r--r--drivers/hwmon/ltc2991.c15
-rw-r--r--drivers/hwmon/max16065.c10
-rw-r--r--drivers/hwmon/max1668.c4
-rw-r--r--drivers/hwmon/max31827.c23
-rw-r--r--drivers/hwmon/max6639.c534
-rw-r--r--drivers/hwmon/max6642.c314
-rw-r--r--drivers/hwmon/max6697.c12
-rw-r--r--drivers/hwmon/mcp3021.c6
-rw-r--r--drivers/hwmon/mr75203.c1
-rw-r--r--drivers/hwmon/nct6683.c2
-rw-r--r--drivers/hwmon/nct6775-core.c2
-rw-r--r--drivers/hwmon/nct6775.h2
-rw-r--r--drivers/hwmon/nzxt-smart2.c1
-rw-r--r--drivers/hwmon/pmbus/Kconfig36
-rw-r--r--drivers/hwmon/pmbus/Makefile4
-rw-r--r--drivers/hwmon/pmbus/lm25066.c2
-rw-r--r--drivers/hwmon/pmbus/ltc4286.c4
-rw-r--r--drivers/hwmon/pmbus/mp2856.c8
-rw-r--r--drivers/hwmon/pmbus/mp2891.c600
-rw-r--r--drivers/hwmon/pmbus/mp2993.c261
-rw-r--r--drivers/hwmon/pmbus/mp5920.c90
-rw-r--r--drivers/hwmon/pmbus/mp9941.c319
-rw-r--r--drivers/hwmon/powr1220.c6
-rw-r--r--drivers/hwmon/sht3x.c20
-rw-r--r--drivers/hwmon/shtc1.c4
-rw-r--r--drivers/hwmon/spd5118.c703
-rw-r--r--drivers/hwmon/thmc50.c4
-rw-r--r--drivers/hwmon/tmp401.c2
-rw-r--r--drivers/hwmon/tmp421.c6
-rw-r--r--drivers/hwmon/tmp464.c5
-rw-r--r--drivers/hwmon/tmp513.c2
-rw-r--r--drivers/hwmon/tps23861.c2
-rw-r--r--drivers/hwmon/w83627ehf.c4
-rw-r--r--drivers/hwmon/w83781d.c4
-rw-r--r--drivers/hwmon/w83795.c4
-rw-r--r--drivers/i2c/Kconfig2
-rw-r--r--drivers/i2c/busses/i2c-pnx.c48
-rw-r--r--drivers/i2c/busses/i2c-rcar.c27
-rw-r--r--drivers/i2c/i2c-core-base.c1
-rw-r--r--drivers/i2c/i2c-slave-testunit.c7
-rw-r--r--drivers/i2c/i2c-smbus.c6
-rw-r--r--drivers/iio/industrialio-trigger.c2
-rw-r--r--drivers/iio/light/apds9306.c4
-rw-r--r--drivers/input/mouse/vmmouse.c76
-rw-r--r--drivers/irqchip/irq-gic-common.c22
-rw-r--r--drivers/irqchip/irq-gic-common.h7
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c11
-rw-r--r--drivers/irqchip/irq-gic-v3.c282
-rw-r--r--drivers/irqchip/irq-gic.c10
-rw-r--r--drivers/irqchip/irq-hip04.c6
-rw-r--r--drivers/md/bcache/super.c13
-rw-r--r--drivers/md/dm-cache-target.c1
-rw-r--r--drivers/md/dm-clone-target.c1
-rw-r--r--drivers/md/dm-core.h1
-rw-r--r--drivers/md/dm-crypt.c4
-rw-r--r--drivers/md/dm-integrity.c47
-rw-r--r--drivers/md/dm-raid.c2
-rw-r--r--drivers/md/dm-table.c351
-rw-r--r--drivers/md/dm-vdo/dm-vdo-target.c2
-rw-r--r--drivers/md/dm-zone.c254
-rw-r--r--drivers/md/dm-zoned-target.c2
-rw-r--r--drivers/md/dm.c174
-rw-r--r--drivers/md/dm.h4
-rw-r--r--drivers/md/md-bitmap.c6
-rw-r--r--drivers/md/md-cluster.c2
-rw-r--r--drivers/md/md.c630
-rw-r--r--drivers/md/md.h136
-rw-r--r--drivers/md/raid0.c30
-rw-r--r--drivers/md/raid1.c34
-rw-r--r--drivers/md/raid10.c23
-rw-r--r--drivers/md/raid5.c114
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-isys-video.c2
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-isys.c2
-rw-r--r--drivers/media/pci/intel/ivsc/Kconfig1
-rw-r--r--drivers/media/platform/qcom/venus/pm_helpers.c39
-rw-r--r--drivers/memory/Kconfig2
-rw-r--r--drivers/memstick/host/Kconfig10
-rw-r--r--drivers/memstick/host/Makefile1
-rw-r--r--drivers/memstick/host/rtsx_pci_ms.c638
-rw-r--r--drivers/misc/fastrpc.c41
-rw-r--r--drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_otpe2p.c4
-rw-r--r--drivers/misc/mei/platform-vsc.c4
-rw-r--r--drivers/misc/mei/vsc-fw-loader.c2
-rw-r--r--drivers/misc/mei/vsc-tp.c18
-rw-r--r--drivers/mmc/core/block.c42
-rw-r--r--drivers/mmc/core/core.c1
-rw-r--r--drivers/mmc/core/pwrseq_emmc.c1
-rw-r--r--drivers/mmc/core/pwrseq_sd8787.c1
-rw-r--r--drivers/mmc/core/pwrseq_simple.c1
-rw-r--r--drivers/mmc/core/queue.c20
-rw-r--r--drivers/mmc/core/queue.h3
-rw-r--r--drivers/mmc/core/sdio_uart.c1
-rw-r--r--drivers/mmc/host/Kconfig2
-rw-r--r--drivers/mmc/host/atmel-mci.c35
-rw-r--r--drivers/mmc/host/au1xmmc.c37
-rw-r--r--drivers/mmc/host/cb710-mmc.c14
-rw-r--r--drivers/mmc/host/cb710-mmc.h3
-rw-r--r--drivers/mmc/host/davinci_mmc.c14
-rw-r--r--drivers/mmc/host/dw_mmc-bluefield.c18
-rw-r--r--drivers/mmc/host/dw_mmc.c30
-rw-r--r--drivers/mmc/host/dw_mmc.h11
-rw-r--r--drivers/mmc/host/mmc_spi.c5
-rw-r--r--drivers/mmc/host/of_mmc_spi.c1
-rw-r--r--drivers/mmc/host/omap.c17
-rw-r--r--drivers/mmc/host/renesas_sdhi.h4
-rw-r--r--drivers/mmc/host/renesas_sdhi_core.c3
-rw-r--r--drivers/mmc/host/renesas_sdhi_internal_dmac.c26
-rw-r--r--drivers/mmc/host/renesas_sdhi_sys_dmac.c9
-rw-r--r--drivers/mmc/host/sdhci-bcm-kona.c2
-rw-r--r--drivers/mmc/host/sdhci-brcmstb.c60
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c16
-rw-r--r--drivers/mmc/host/sdhci-of-dwcmshc.c1
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c27
-rw-r--r--drivers/mmc/host/sdhci.c46
-rw-r--r--drivers/mmc/host/sdhci.h3
-rw-r--r--drivers/mmc/host/sdhci_am654.c2
-rw-r--r--drivers/mmc/host/tifm_sd.c15
-rw-r--r--drivers/mmc/host/tmio_mmc.h6
-rw-r--r--drivers/mmc/host/tmio_mmc_core.c13
-rw-r--r--drivers/mmc/host/uniphier-sd.c12
-rw-r--r--drivers/mmc/host/via-sdmmc.c25
-rw-r--r--drivers/mmc/host/wbsd.c74
-rw-r--r--drivers/mmc/host/wbsd.h10
-rw-r--r--drivers/mtd/mtd_blkdevs.c9
-rw-r--r--drivers/mtd/nand/raw/Kconfig3
-rw-r--r--drivers/mtd/nand/raw/nand_base.c66
-rw-r--r--drivers/mtd/nand/raw/rockchip-nand-controller.c6
-rw-r--r--drivers/net/bonding/bond_options.c6
-rw-r--r--drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c1
-rw-r--r--drivers/net/dsa/lan9303-core.c23
-rw-r--r--drivers/net/ethernet/broadcom/asp2/bcmasp.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c24
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h1
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c6
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c73
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c132
-rw-r--r--drivers/net/ethernet/intel/e1000e/ptp.c3
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.h4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_hwmon.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.c134
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.h9
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ptp.c6
-rw-r--r--drivers/net/ethernet/lantiq_etop.c4
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mbox.h2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/npc.h8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.c2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c23
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c12
-rw-r--r--drivers/net/ethernet/mediatek/mtk_star_emac.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c48
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eq.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c37
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_linecards.c1
-rw-r--r--drivers/net/ethernet/micrel/ks8851_common.c10
-rw-r--r--drivers/net/ethernet/micrel/ks8851_spi.c4
-rw-r--r--drivers/net/ethernet/renesas/rswitch.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c7
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_hw.c1
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_lib.c10
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_type.h1
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_main.c2
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c124
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_irq.h2
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_main.c9
-rw-r--r--drivers/net/ntb_netdev.c2
-rw-r--r--drivers/net/phy/aquantia/aquantia.h5
-rw-r--r--drivers/net/phy/microchip_t1.c2
-rw-r--r--drivers/net/ppp/ppp_generic.c15
-rw-r--r--drivers/net/wireguard/allowedips.c4
-rw-r--r--drivers/net/wireguard/queueing.h4
-rw-r--r--drivers/net/wireguard/send.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c15
-rw-r--r--drivers/net/wireless/microchip/wilc1000/hif.c3
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c7
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c17
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c7
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h6
-rw-r--r--drivers/nvdimm/btt.c17
-rw-r--r--drivers/nvdimm/pmem.c14
-rw-r--r--drivers/nvme/host/Kconfig1
-rw-r--r--drivers/nvme/host/apple.c32
-rw-r--r--drivers/nvme/host/constants.c2
-rw-r--r--drivers/nvme/host/core.c286
-rw-r--r--drivers/nvme/host/fabrics.c25
-rw-r--r--drivers/nvme/host/fabrics.h1
-rw-r--r--drivers/nvme/host/fault_inject.c2
-rw-r--r--drivers/nvme/host/fc.c55
-rw-r--r--drivers/nvme/host/multipath.c144
-rw-r--r--drivers/nvme/host/nvme.h28
-rw-r--r--drivers/nvme/host/pci.c47
-rw-r--r--drivers/nvme/host/pr.c10
-rw-r--r--drivers/nvme/host/rdma.c34
-rw-r--r--drivers/nvme/host/tcp.c31
-rw-r--r--drivers/nvme/host/zns.c3
-rw-r--r--drivers/nvme/target/Kconfig10
-rw-r--r--drivers/nvme/target/Makefile1
-rw-r--r--drivers/nvme/target/admin-cmd.c24
-rw-r--r--drivers/nvme/target/auth.c14
-rw-r--r--drivers/nvme/target/core.c76
-rw-r--r--drivers/nvme/target/debugfs.c202
-rw-r--r--drivers/nvme/target/debugfs.h42
-rw-r--r--drivers/nvme/target/discovery.c14
-rw-r--r--drivers/nvme/target/fabrics-cmd-auth.c16
-rw-r--r--drivers/nvme/target/fabrics-cmd.c36
-rw-r--r--drivers/nvme/target/fc.c33
-rw-r--r--drivers/nvme/target/fcloop.c11
-rw-r--r--drivers/nvme/target/io-cmd-bdev.c28
-rw-r--r--drivers/nvme/target/loop.c5
-rw-r--r--drivers/nvme/target/nvmet.h12
-rw-r--r--drivers/nvme/target/passthru.c10
-rw-r--r--drivers/nvme/target/rdma.c22
-rw-r--r--drivers/nvme/target/tcp.c18
-rw-r--r--drivers/nvme/target/zns.c30
-rw-r--r--drivers/nvmem/core.c7
-rw-r--r--drivers/nvmem/meson-efuse.c14
-rw-r--r--drivers/nvmem/rmem.c5
-rw-r--r--drivers/of/irq.c18
-rw-r--r--drivers/pci/Kconfig1
-rw-r--r--drivers/pci/Makefile1
-rw-r--r--drivers/pci/bus.c9
-rw-r--r--drivers/pci/of.c14
-rw-r--r--drivers/pci/probe.c2
-rw-r--r--drivers/pci/pwrctl/Kconfig17
-rw-r--r--drivers/pci/pwrctl/Makefile6
-rw-r--r--drivers/pci/pwrctl/core.c137
-rw-r--r--drivers/pci/pwrctl/pci-pwrctl-pwrseq.c89
-rw-r--r--drivers/pci/remove.c3
-rw-r--r--drivers/perf/Kconfig12
-rw-r--r--drivers/perf/Makefile3
-rw-r--r--drivers/perf/arm-ccn.c1
-rw-r--r--drivers/perf/arm-cmn.c116
-rw-r--r--drivers/perf/arm_cspmu/ampere_cspmu.c1
-rw-r--r--drivers/perf/arm_cspmu/arm_cspmu.c1
-rw-r--r--drivers/perf/arm_cspmu/nvidia_cspmu.c1
-rw-r--r--drivers/perf/arm_pmuv3.c26
-rw-r--r--drivers/perf/arm_v6_pmu.c (renamed from arch/arm/kernel/perf_event_v6.c)20
-rw-r--r--drivers/perf/arm_v7_pmu.c (renamed from arch/arm/kernel/perf_event_v7.c)13
-rw-r--r--drivers/perf/arm_xscale_pmu.c (renamed from arch/arm/kernel/perf_event_xscale.c)3
-rw-r--r--drivers/perf/cxl_pmu.c1
-rw-r--r--drivers/perf/fsl_imx8_ddr_perf.c1
-rw-r--r--drivers/perf/fsl_imx9_ddr_perf.c352
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_pmu.c1
-rw-r--r--drivers/perf/marvell_cn10k_ddr_pmu.c1
-rw-r--r--drivers/perf/riscv_pmu.c2
-rw-r--r--drivers/perf/riscv_pmu_sbi.c44
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb2.c8
-rw-r--r--drivers/pinctrl/pinctrl-da9062.c2
-rw-r--r--drivers/platform/Kconfig2
-rw-r--r--drivers/platform/Makefile1
-rw-r--r--drivers/platform/chrome/cros_ec.c4
-rw-r--r--drivers/platform/chrome/cros_ec_debugfs.c9
-rw-r--r--drivers/platform/chrome/cros_ec_lpc.c210
-rw-r--r--drivers/platform/chrome/cros_ec_lpc_mec.c91
-rw-r--r--drivers/platform/chrome/cros_ec_lpc_mec.h18
-rw-r--r--drivers/platform/chrome/cros_ec_proto.c95
-rw-r--r--drivers/platform/chrome/cros_ec_proto_test.c9
-rw-r--r--drivers/platform/chrome/wilco_ec/mailbox.c22
-rw-r--r--drivers/platform/cznic/Kconfig50
-rw-r--r--drivers/platform/cznic/Makefile8
-rw-r--r--drivers/platform/cznic/turris-omnia-mcu-base.c408
-rw-r--r--drivers/platform/cznic/turris-omnia-mcu-gpio.c1095
-rw-r--r--drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c260
-rw-r--r--drivers/platform/cznic/turris-omnia-mcu-trng.c103
-rw-r--r--drivers/platform/cznic/turris-omnia-mcu-watchdog.c130
-rw-r--r--drivers/platform/cznic/turris-omnia-mcu.h194
-rw-r--r--drivers/platform/x86/toshiba_acpi.c32
-rw-r--r--drivers/pmdomain/amlogic/meson-ee-pwrc.c1
-rw-r--r--drivers/pmdomain/amlogic/meson-gx-pwrc-vpu.c1
-rw-r--r--drivers/pmdomain/amlogic/meson-secure-pwrc.c65
-rw-r--r--drivers/pmdomain/arm/scmi_pm_domain.c1
-rw-r--r--drivers/pmdomain/core.c80
-rw-r--r--drivers/pmdomain/qcom/rpmhpd.c7
-rw-r--r--drivers/pmdomain/renesas/rmobile-sysc.c8
-rw-r--r--drivers/power/Kconfig1
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/sequencing/Kconfig29
-rw-r--r--drivers/power/sequencing/Makefile6
-rw-r--r--drivers/power/sequencing/core.c1105
-rw-r--r--drivers/power/sequencing/pwrseq-qcom-wcn.c336
-rw-r--r--drivers/power/supply/Kconfig12
-rw-r--r--drivers/power/supply/Makefile1
-rw-r--r--drivers/power/supply/cros_charge-control.c352
-rw-r--r--drivers/ptp/ptp_vmw.c12
-rw-r--r--drivers/pwm/Kconfig24
-rw-r--r--drivers/pwm/Makefile2
-rw-r--r--drivers/pwm/core.c181
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c113
-rw-r--r--drivers/pwm/pwm-axi-pwmgen.c242
-rw-r--r--drivers/pwm/pwm-cros-ec.c64
-rw-r--r--drivers/pwm/pwm-gpio.c241
-rw-r--r--drivers/pwm/pwm-imx-tpm.c16
-rw-r--r--drivers/pwm/pwm-imx1.c1
-rw-r--r--drivers/pwm/pwm-imx27.c1
-rw-r--r--drivers/pwm/pwm-intel-lgm.c1
-rw-r--r--drivers/pwm/pwm-jz4740.c9
-rw-r--r--drivers/pwm/pwm-lpss-pci.c22
-rw-r--r--drivers/pwm/pwm-lpss-platform.c10
-rw-r--r--drivers/pwm/pwm-mediatek.c1
-rw-r--r--drivers/pwm/pwm-meson.c39
-rw-r--r--drivers/pwm/pwm-pxa.c1
-rw-r--r--drivers/pwm/pwm-samsung.c1
-rw-r--r--drivers/pwm/pwm-spear.c1
-rw-r--r--drivers/pwm/pwm-stm32.c27
-rw-r--r--drivers/pwm/pwm-visconti.c1
-rw-r--r--drivers/pwm/pwm-xilinx.c27
-rw-r--r--drivers/ras/amd/atl/core.c52
-rw-r--r--drivers/ras/amd/atl/dehash.c43
-rw-r--r--drivers/ras/amd/atl/denormalize.c561
-rw-r--r--drivers/ras/amd/atl/internal.h48
-rw-r--r--drivers/ras/amd/atl/map.c97
-rw-r--r--drivers/ras/amd/atl/system.c21
-rw-r--r--drivers/ras/amd/fmpm.c4
-rw-r--r--drivers/regulator/Kconfig9
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/core.c28
-rw-r--r--drivers/regulator/da9121-regulator.c7
-rw-r--r--drivers/regulator/da9210-regulator.c4
-rw-r--r--drivers/regulator/lp3971.c2
-rw-r--r--drivers/regulator/lp3972.c2
-rw-r--r--drivers/regulator/lp8755.c2
-rw-r--r--drivers/regulator/max1586.c2
-rw-r--r--drivers/regulator/max20411-regulator.c5
-rw-r--r--drivers/regulator/max77503-regulator.c8
-rw-r--r--drivers/regulator/max77857-regulator.c2
-rw-r--r--drivers/regulator/max8649.c2
-rw-r--r--drivers/regulator/max8893.c4
-rw-r--r--drivers/regulator/max8952.c4
-rw-r--r--drivers/regulator/mcp16502.c2
-rw-r--r--drivers/regulator/mt6311-regulator.c4
-rw-r--r--drivers/regulator/mtk-dvfsrc-regulator.c248
-rw-r--r--drivers/regulator/pca9450-regulator.c41
-rw-r--r--drivers/regulator/pf8x00-regulator.c8
-rw-r--r--drivers/regulator/pv88060-regulator.c4
-rw-r--r--drivers/regulator/pv88090-regulator.c4
-rw-r--r--drivers/regulator/renesas-usb-vbus-regulator.c74
-rw-r--r--drivers/regulator/rt4831-regulator.c1
-rw-r--r--drivers/regulator/rtq2208-regulator.c44
-rw-r--r--drivers/regulator/slg51000-regulator.c4
-rw-r--r--drivers/regulator/stm32-pwr.c1
-rw-r--r--drivers/regulator/sy8106a-regulator.c4
-rw-r--r--drivers/regulator/tps6286x-regulator.c11
-rw-r--r--drivers/regulator/tps6287x-regulator.c10
-rw-r--r--drivers/regulator/userspace-consumer.c6
-rw-r--r--drivers/reset/Kconfig15
-rw-r--r--drivers/reset/Makefile7
-rw-r--r--drivers/reset/hisilicon/hi6220_reset.c1
-rw-r--r--drivers/reset/reset-imx8mp-audiomix.c128
-rw-r--r--drivers/reset/reset-meson-audio-arb.c9
-rw-r--r--drivers/reset/reset-rzg2l-usbphy-ctrl.c63
-rw-r--r--drivers/reset/sti/Kconfig4
-rw-r--r--drivers/reset/tegra/Kconfig3
-rw-r--r--drivers/s390/block/dasd_eckd.c4
-rw-r--r--drivers/s390/block/dasd_fba.c2
-rw-r--r--drivers/s390/block/dasd_genhd.c1
-rw-r--r--drivers/s390/block/dcssblk.c2
-rw-r--r--drivers/s390/block/scm_blk.c5
-rw-r--r--drivers/s390/cio/vfio_ccw_cp.c9
-rw-r--r--drivers/scsi/Kconfig1
-rw-r--r--drivers/scsi/iscsi_tcp.c8
-rw-r--r--drivers/scsi/libsas/sas_internal.h14
-rw-r--r--drivers/scsi/lpfc/lpfc_nvmet.c11
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c2
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c6
-rw-r--r--drivers/scsi/scsi_debug.c594
-rw-r--r--drivers/scsi/scsi_lib.c9
-rw-r--r--drivers/scsi/scsi_trace.c22
-rw-r--r--drivers/scsi/sd.c378
-rw-r--r--drivers/scsi/sd.h31
-rw-r--r--drivers/scsi/sd_dif.c45
-rw-r--r--drivers/scsi/sd_zbc.c52
-rw-r--r--drivers/scsi/sr.c42
-rw-r--r--drivers/soc/amlogic/meson-clk-measure.c1
-rw-r--r--drivers/soc/amlogic/meson-gx-socinfo.c2
-rw-r--r--drivers/soc/imx/soc-imx8m.c1
-rw-r--r--drivers/soc/ixp4xx/ixp4xx-npe.c1
-rw-r--r--drivers/soc/ixp4xx/ixp4xx-qmgr.c1
-rw-r--r--drivers/soc/litex/Kconfig2
-rw-r--r--drivers/soc/litex/litex_soc_ctrl.c4
-rw-r--r--drivers/soc/mediatek/mtk-cmdq-helper.c35
-rw-r--r--drivers/soc/mediatek/mtk-mmsys.c1
-rw-r--r--drivers/soc/mediatek/mtk-mutex.c1
-rw-r--r--drivers/soc/qcom/Kconfig18
-rw-r--r--drivers/soc/qcom/Makefile2
-rw-r--r--drivers/soc/qcom/icc-bwmon.c16
-rw-r--r--drivers/soc/qcom/llcc-qcom.c57
-rw-r--r--drivers/soc/qcom/mdt_loader.c6
-rw-r--r--drivers/soc/qcom/ocmem.c10
-rw-r--r--drivers/soc/qcom/pdr_interface.c46
-rw-r--r--drivers/soc/qcom/pdr_internal.h318
-rw-r--r--drivers/soc/qcom/pmic_glink.c17
-rw-r--r--drivers/soc/qcom/pmic_glink_altmode.c2
-rw-r--r--drivers/soc/qcom/qcom_pd_mapper.c677
-rw-r--r--drivers/soc/qcom/qcom_pdr_msg.c353
-rw-r--r--drivers/soc/qcom/rpmh-rsc.c7
-rw-r--r--drivers/soc/qcom/rpmh.c1
-rw-r--r--drivers/soc/qcom/smem.c33
-rw-r--r--drivers/soc/qcom/smp2p.c11
-rw-r--r--drivers/soc/qcom/smsm.c51
-rw-r--r--drivers/soc/qcom/socinfo.c14
-rw-r--r--drivers/soc/qcom/spm.c1
-rw-r--r--drivers/soc/qcom/wcnss_ctrl.c11
-rw-r--r--drivers/soc/samsung/exynos-pmu.c22
-rw-r--r--drivers/soc/sunxi/sunxi_sram.c4
-rw-r--r--drivers/soc/tegra/pmc.c8
-rw-r--r--drivers/soc/ti/k3-socinfo.c2
-rw-r--r--drivers/soc/ti/knav_qmss.h2
-rw-r--r--drivers/soc/ti/knav_qmss_acc.c2
-rw-r--r--drivers/soc/ti/knav_qmss_queue.c2
-rw-r--r--drivers/soc/ti/pm33xx.c4
-rw-r--r--drivers/soc/xilinx/xlnx_event_manager.c16
-rw-r--r--drivers/soc/xilinx/zynqmp_power.c155
-rw-r--r--drivers/spi/Kconfig6
-rw-r--r--drivers/spi/Makefile4
-rw-r--r--drivers/spi/atmel-quadspi.c11
-rw-r--r--drivers/spi/internals.h8
-rw-r--r--drivers/spi/spi-altera-core.c1
-rw-r--r--drivers/spi/spi-axi-spi-engine.c68
-rw-r--r--drivers/spi/spi-bitbang.c73
-rw-r--r--drivers/spi/spi-cadence.c27
-rw-r--r--drivers/spi/spi-ch341.c241
-rw-r--r--drivers/spi/spi-cs42l43.c95
-rw-r--r--drivers/spi/spi-davinci.c6
-rw-r--r--drivers/spi/spi-dw-bt1.c10
-rw-r--r--drivers/spi/spi-dw-core.c4
-rw-r--r--drivers/spi/spi-fsl-cpm.c1
-rw-r--r--drivers/spi/spi-fsl-dspi.c19
-rw-r--r--drivers/spi/spi-fsl-lib.c1
-rw-r--r--drivers/spi/spi-fsl-lpspi.c8
-rw-r--r--drivers/spi/spi-gpio.c66
-rw-r--r--drivers/spi/spi-imx.c22
-rw-r--r--drivers/spi/spi-ingenic.c4
-rw-r--r--drivers/spi/spi-meson-spicc.c22
-rw-r--r--drivers/spi/spi-microchip-core.c6
-rw-r--r--drivers/spi/spi-mux.c2
-rw-r--r--drivers/spi/spi-mxic.c2
-rw-r--r--drivers/spi/spi-omap-uwire.c1
-rw-r--r--drivers/spi/spi-omap2-mcspi.c24
-rw-r--r--drivers/spi/spi-pci1xxxx.c5
-rw-r--r--drivers/spi/spi-pxa2xx-pci.c39
-rw-r--r--drivers/spi/spi-pxa2xx-platform.c214
-rw-r--r--drivers/spi/spi-pxa2xx.c259
-rw-r--r--drivers/spi/spi-pxa2xx.h6
-rw-r--r--drivers/spi/spi-qup.c10
-rw-r--r--drivers/spi/spi-rpc-if.c12
-rw-r--r--drivers/spi/spi-wpcm-fiu.c6
-rw-r--r--drivers/spi/spi-xcomm.c75
-rw-r--r--drivers/spi/spi.c154
-rw-r--r--drivers/staging/greybus/gpio.c2
-rw-r--r--drivers/target/target_core_iblock.c49
-rw-r--r--drivers/tee/optee/ffa_abi.c12
-rw-r--r--drivers/tee/optee/notif.c9
-rw-r--r--drivers/tee/optee/optee_private.h5
-rw-r--r--drivers/tee/optee/optee_rpc_cmd.h1
-rw-r--r--drivers/tee/optee/rpc.c10
-rw-r--r--drivers/thermal/gov_power_allocator.c3
-rw-r--r--drivers/thermal/thermal_core.c15
-rw-r--r--drivers/thermal/thermal_core.h6
-rw-r--r--drivers/tty/serial/8250/8250_omap.c3
-rw-r--r--drivers/tty/serial/imx.c59
-rw-r--r--drivers/tty/serial/ma35d1_serial.c13
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c51
-rw-r--r--drivers/ufs/core/ufs-mcq.c11
-rw-r--r--drivers/ufs/core/ufshcd.c12
-rw-r--r--drivers/usb/core/config.c18
-rw-r--r--drivers/usb/core/of.c7
-rw-r--r--drivers/usb/core/quirks.c3
-rw-r--r--drivers/usb/dwc3/dwc3-pci.c8
-rw-r--r--drivers/usb/gadget/configfs.c3
-rw-r--r--drivers/usb/host/xhci.c16
-rw-r--r--drivers/usb/serial/mos7840.c45
-rw-r--r--drivers/usb/serial/option.c38
-rw-r--r--drivers/vfio/pci/vfio_pci_core.c2
-rw-r--r--drivers/virt/coco/sev-guest/sev-guest.c211
-rw-r--r--drivers/virt/coco/tdx-guest/tdx-guest.c26
-rw-r--r--drivers/virt/coco/tsm.c177
-rw-r--r--drivers/zorro/zorro.c3
-rw-r--r--fs/afs/inode.c4
-rw-r--r--fs/aio.c8
-rw-r--r--fs/attr.c2
-rw-r--r--fs/autofs/init.c1
-rw-r--r--fs/autofs/inode.c16
-rw-r--r--fs/bcachefs/alloc_background.c48
-rw-r--r--fs/bcachefs/alloc_foreground.c2
-rw-r--r--fs/bcachefs/backpointers.c70
-rw-r--r--fs/bcachefs/bkey.c5
-rw-r--r--fs/bcachefs/bkey.h7
-rw-r--r--fs/bcachefs/btree_gc.c54
-rw-r--r--fs/bcachefs/btree_iter.c7
-rw-r--r--fs/bcachefs/btree_locking.c10
-rw-r--r--fs/bcachefs/btree_locking.h22
-rw-r--r--fs/bcachefs/btree_types.h1
-rw-r--r--fs/bcachefs/btree_write_buffer.c37
-rw-r--r--fs/bcachefs/btree_write_buffer.h3
-rw-r--r--fs/bcachefs/buckets.c2
-rw-r--r--fs/bcachefs/buckets.h8
-rw-r--r--fs/bcachefs/clock.c7
-rw-r--r--fs/bcachefs/data_update.c44
-rw-r--r--fs/bcachefs/data_update.h5
-rw-r--r--fs/bcachefs/debug.c12
-rw-r--r--fs/bcachefs/eytzinger.h6
-rw-r--r--fs/bcachefs/fs.c9
-rw-r--r--fs/bcachefs/io_misc.c2
-rw-r--r--fs/bcachefs/io_read.c4
-rw-r--r--fs/bcachefs/journal.c18
-rw-r--r--fs/bcachefs/journal.h2
-rw-r--r--fs/bcachefs/journal_io.c12
-rw-r--r--fs/bcachefs/lru.c39
-rw-r--r--fs/bcachefs/lru.h3
-rw-r--r--fs/bcachefs/move.c25
-rw-r--r--fs/bcachefs/sb-errors_format.h3
-rw-r--r--fs/bcachefs/super.c11
-rw-r--r--fs/bcachefs/util.c25
-rw-r--r--fs/bcachefs/util.h1
-rw-r--r--fs/befs/linuxvfs.c10
-rw-r--r--fs/binfmt_elf.c2
-rw-r--r--fs/binfmt_elf_fdpic.c5
-rw-r--r--fs/binfmt_misc.c8
-rw-r--r--fs/binfmt_script.c1
-rw-r--r--fs/btrfs/block-group.c13
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/extent_io.c2
-rw-r--r--fs/btrfs/extent_map.c123
-rw-r--r--fs/btrfs/fs.h1
-rw-r--r--fs/btrfs/inode.c4
-rw-r--r--fs/btrfs/ioctl.c2
-rw-r--r--fs/btrfs/qgroup.c10
-rw-r--r--fs/btrfs/ref-verify.c9
-rw-r--r--fs/btrfs/space-info.c24
-rw-r--r--fs/buffer.c7
-rw-r--r--fs/cachefiles/cache.c45
-rw-r--r--fs/cachefiles/daemon.c4
-rw-r--r--fs/cachefiles/internal.h3
-rw-r--r--fs/cachefiles/ondemand.c52
-rw-r--r--fs/cachefiles/volume.c1
-rw-r--r--fs/cachefiles/xattr.c5
-rw-r--r--fs/coda/symlink.c10
-rw-r--r--fs/configfs/dir.c10
-rw-r--r--fs/cramfs/inode.c26
-rw-r--r--fs/dcache.c90
-rw-r--r--fs/debugfs/inode.c16
-rw-r--r--fs/efivarfs/super.c12
-rw-r--r--fs/efs/inode.c1
-rw-r--r--fs/efs/symlink.c14
-rw-r--r--fs/erofs/super.c2
-rw-r--r--fs/erofs/zmap.c2
-rw-r--r--fs/erofs/zutil.c8
-rw-r--r--fs/exec.c14
-rw-r--r--fs/exfat/super.c8
-rw-r--r--fs/exportfs/expfs.c9
-rw-r--r--fs/ext4/crypto.c10
-rw-r--r--fs/ext4/ext4.h35
-rw-r--r--fs/ext4/namei.c122
-rw-r--r--fs/ext4/super.c26
-rw-r--r--fs/f2fs/acl.c3
-rw-r--r--fs/f2fs/dir.c105
-rw-r--r--fs/f2fs/f2fs.h16
-rw-r--r--fs/f2fs/file.c6
-rw-r--r--fs/f2fs/namei.c10
-rw-r--r--fs/f2fs/recovery.c9
-rw-r--r--fs/f2fs/super.c8
-rw-r--r--fs/fat/fat.h18
-rw-r--r--fs/fat/fat_test.c1
-rw-r--r--fs/fat/inode.c675
-rw-r--r--fs/fat/namei_msdos.c38
-rw-r--r--fs/fat/namei_vfat.c38
-rw-r--r--fs/fhandle.c178
-rw-r--r--fs/fs_parser.c34
-rw-r--r--fs/fsopen.c7
-rw-r--r--fs/fuse/acl.c4
-rw-r--r--fs/fuse/inode.c24
-rw-r--r--fs/hfs/inode.c3
-rw-r--r--fs/hfs/super.c1
-rw-r--r--fs/hfsplus/bfind.c15
-rw-r--r--fs/hfsplus/extents.c9
-rw-r--r--fs/hfsplus/hfsplus_fs.h21
-rw-r--r--fs/hfsplus/ioctl.c4
-rw-r--r--fs/hfsplus/xattr.c2
-rw-r--r--fs/hostfs/hostfs_kern.c106
-rw-r--r--fs/hpfs/namei.c15
-rw-r--r--fs/hpfs/super.c1
-rw-r--r--fs/hugetlbfs/inode.c12
-rw-r--r--fs/inode.c109
-rw-r--r--fs/internal.h16
-rw-r--r--fs/iomap/buffered-io.c81
-rw-r--r--fs/isofs/inode.c16
-rw-r--r--fs/isofs/rock.c17
-rw-r--r--fs/jffs2/file.c14
-rw-r--r--fs/libfs.c74
-rw-r--r--fs/locks.c11
-rw-r--r--fs/minix/inode.c1
-rw-r--r--fs/minix/namei.c3
-rw-r--r--fs/mount.h3
-rw-r--r--fs/mpage.c13
-rw-r--r--fs/namei.c249
-rw-r--r--fs/namespace.c524
-rw-r--r--fs/netfs/buffered_read.c14
-rw-r--r--fs/netfs/buffered_write.c24
-rw-r--r--fs/netfs/direct_read.c2
-rw-r--r--fs/netfs/direct_write.c11
-rw-r--r--fs/netfs/fscache_cache.c4
-rw-r--r--fs/netfs/fscache_cookie.c28
-rw-r--r--fs/netfs/fscache_io.c12
-rw-r--r--fs/netfs/fscache_main.c2
-rw-r--r--fs/netfs/fscache_volume.c18
-rw-r--r--fs/netfs/internal.h44
-rw-r--r--fs/netfs/io.c12
-rw-r--r--fs/netfs/main.c4
-rw-r--r--fs/netfs/misc.c85
-rw-r--r--fs/netfs/write_collect.c16
-rw-r--r--fs/netfs/write_issue.c38
-rw-r--r--fs/nfs/read.c2
-rw-r--r--fs/nfs/symlink.c10
-rw-r--r--fs/nfs/write.c1
-rw-r--r--fs/nfsd/nfsfh.c2
-rw-r--r--fs/nilfs2/alloc.c19
-rw-r--r--fs/nilfs2/alloc.h4
-rw-r--r--fs/nilfs2/dat.c2
-rw-r--r--fs/nilfs2/dir.c38
-rw-r--r--fs/nilfs2/ifile.c7
-rw-r--r--fs/nilfs2/nilfs.h10
-rw-r--r--fs/nilfs2/the_nilfs.c6
-rw-r--r--fs/nilfs2/the_nilfs.h2
-rw-r--r--fs/nls/mac-celtic.c1
-rw-r--r--fs/nls/mac-centeuro.c1
-rw-r--r--fs/nls/mac-croatian.c1
-rw-r--r--fs/nls/mac-cyrillic.c1
-rw-r--r--fs/nls/mac-gaelic.c1
-rw-r--r--fs/nls/mac-greek.c1
-rw-r--r--fs/nls/mac-iceland.c1
-rw-r--r--fs/nls/mac-inuit.c1
-rw-r--r--fs/nls/mac-roman.c1
-rw-r--r--fs/nls/mac-romanian.c1
-rw-r--r--fs/nls/mac-turkish.c1
-rw-r--r--fs/nls/nls_ascii.c1
-rw-r--r--fs/nls/nls_base.c1
-rw-r--r--fs/nls/nls_cp1250.c1
-rw-r--r--fs/nls/nls_cp1251.c1
-rw-r--r--fs/nls/nls_cp1255.c1
-rw-r--r--fs/nls/nls_cp437.c1
-rw-r--r--fs/nls/nls_cp737.c1
-rw-r--r--fs/nls/nls_cp775.c1
-rw-r--r--fs/nls/nls_cp850.c1
-rw-r--r--fs/nls/nls_cp852.c1
-rw-r--r--fs/nls/nls_cp855.c1
-rw-r--r--fs/nls/nls_cp857.c1
-rw-r--r--fs/nls/nls_cp860.c1
-rw-r--r--fs/nls/nls_cp861.c1
-rw-r--r--fs/nls/nls_cp862.c1
-rw-r--r--fs/nls/nls_cp863.c1
-rw-r--r--fs/nls/nls_cp864.c1
-rw-r--r--fs/nls/nls_cp865.c1
-rw-r--r--fs/nls/nls_cp866.c1
-rw-r--r--fs/nls/nls_cp869.c1
-rw-r--r--fs/nls/nls_cp874.c1
-rw-r--r--fs/nls/nls_cp932.c1
-rw-r--r--fs/nls/nls_cp936.c1
-rw-r--r--fs/nls/nls_cp949.c1
-rw-r--r--fs/nls/nls_cp950.c1
-rw-r--r--fs/nls/nls_euc-jp.c1
-rw-r--r--fs/nls/nls_iso8859-1.c1
-rw-r--r--fs/nls/nls_iso8859-13.c1
-rw-r--r--fs/nls/nls_iso8859-14.c1
-rw-r--r--fs/nls/nls_iso8859-15.c1
-rw-r--r--fs/nls/nls_iso8859-2.c1
-rw-r--r--fs/nls/nls_iso8859-3.c1
-rw-r--r--fs/nls/nls_iso8859-4.c1
-rw-r--r--fs/nls/nls_iso8859-5.c1
-rw-r--r--fs/nls/nls_iso8859-6.c1
-rw-r--r--fs/nls/nls_iso8859-7.c1
-rw-r--r--fs/nls/nls_iso8859-9.c1
-rw-r--r--fs/nls/nls_koi8-r.c1
-rw-r--r--fs/nls/nls_koi8-ru.c1
-rw-r--r--fs/nls/nls_koi8-u.c1
-rw-r--r--fs/nls/nls_ucs2_utils.c1
-rw-r--r--fs/nls/nls_utf8.c1
-rw-r--r--fs/nsfs.c122
-rw-r--r--fs/ntfs3/super.c12
-rw-r--r--fs/open.c39
-rw-r--r--fs/openpromfs/inode.c1
-rw-r--r--fs/orangefs/inode.c13
-rw-r--r--fs/orangefs/orangefs-bufmap.c4
-rw-r--r--fs/pidfs.c90
-rw-r--r--fs/proc/generic.c6
-rw-r--r--fs/proc_namespace.c6
-rw-r--r--fs/qnx4/inode.c1
-rw-r--r--fs/qnx6/inode.c1
-rw-r--r--fs/quota/dquot.c8
-rw-r--r--fs/read_write.c18
-rw-r--r--fs/readdir.c4
-rw-r--r--fs/reiserfs/inode.c1
-rw-r--r--fs/romfs/super.c22
-rw-r--r--fs/smb/client/cifsglob.h4
-rw-r--r--fs/smb/client/file.c30
-rw-r--r--fs/smb/client/fs_context.c39
-rw-r--r--fs/smb/common/smb2pdu.h34
-rw-r--r--fs/smb/server/smb2pdu.c22
-rw-r--r--fs/stat.c206
-rw-r--r--fs/super.c11
-rw-r--r--fs/sysv/super.c1
-rw-r--r--fs/tracefs/inode.c16
-rw-r--r--fs/ufs/dir.c1
-rw-r--r--fs/userfaultfd.c7
-rw-r--r--fs/vboxsf/file.c18
-rw-r--r--fs/vboxsf/super.c16
-rw-r--r--fs/xfs/xfs_icache.c5
-rw-r--r--fs/xfs/xfs_iops.c15
-rw-r--r--include/acpi/acpi_bus.h1
-rw-r--r--include/acpi/actbl2.h19
-rw-r--r--include/acpi/battery.h2
-rw-r--r--include/acpi/processor.h2
-rw-r--r--include/asm-generic/Kbuild2
-rw-r--r--include/asm-generic/fixmap.h3
-rw-r--r--include/asm-generic/runtime-const.h15
-rw-r--r--include/asm-generic/vmlinux.lds.h10
-rw-r--r--include/clocksource/timer-xilinx.h2
-rw-r--r--include/dt-bindings/arm/qcom,ids.h2
-rw-r--r--include/dt-bindings/clock/qcom,qcm2290-gpucc.h32
-rw-r--r--include/dt-bindings/clock/qcom,sm8650-camcc.h195
-rw-r--r--include/dt-bindings/clock/qcom,sm8650-videocc.h23
-rw-r--r--include/dt-bindings/clock/rk3128-cru.h1
-rw-r--r--include/dt-bindings/clock/sun50i-h616-ccu.h1
-rw-r--r--include/dt-bindings/input/cros-ec-keyboard.h104
-rw-r--r--include/dt-bindings/interconnect/qcom,ipq9574.h59
-rw-r--r--include/dt-bindings/power/amlogic,a4-pwrc.h21
-rw-r--r--include/dt-bindings/power/amlogic,a5-pwrc.h21
-rw-r--r--include/dt-bindings/regulator/st,stm32mp25-regulator.h48
-rw-r--r--include/dt-bindings/reset/sun50i-h616-ccu.h1
-rw-r--r--include/linux/acpi.h12
-rw-r--r--include/linux/blk-integrity.h87
-rw-r--r--include/linux/blk_types.h8
-rw-r--r--include/linux/blkdev.h348
-rw-r--r--include/linux/bvec.h14
-rw-r--r--include/linux/cacheinfo.h25
-rw-r--r--include/linux/cc_platform.h10
-rw-r--r--include/linux/cgroup-defs.h7
-rw-r--r--include/linux/cleanup.h13
-rw-r--r--include/linux/clocksource.h27
-rw-r--r--include/linux/clocksource_ids.h1
-rw-r--r--include/linux/closure.h7
-rw-r--r--include/linux/compiler.h10
-rw-r--r--include/linux/configfs.h3
-rw-r--r--include/linux/cpu.h33
-rw-r--r--include/linux/cpuhotplug.h3
-rw-r--r--include/linux/cpuhplock.h49
-rw-r--r--include/linux/cpumask.h25
-rw-r--r--include/linux/dcache.h11
-rw-r--r--include/linux/device-mapper.h7
-rw-r--r--include/linux/efi.h15
-rw-r--r--include/linux/exportfs.h2
-rw-r--r--include/linux/file.h20
-rw-r--r--include/linux/firmware/qcom/qcom_qseecom.h8
-rw-r--r--include/linux/firmware/qcom/qcom_scm.h37
-rw-r--r--include/linux/firmware/qcom/qcom_tzmem.h56
-rw-r--r--include/linux/firmware/xlnx-event-manager.h10
-rw-r--r--include/linux/firmware/xlnx-zynqmp.h3
-rw-r--r--include/linux/fs.h116
-rw-r--r--include/linux/fs_parser.h6
-rw-r--r--include/linux/fscache-cache.h6
-rw-r--r--include/linux/fsnotify.h8
-rw-r--r--include/linux/gpio.h6
-rw-r--r--include/linux/gpio/driver.h5
-rw-r--r--include/linux/hwmon.h2
-rw-r--r--include/linux/io_uring_types.h14
-rw-r--r--include/linux/irq_sim.h17
-rw-r--r--include/linux/irqchip/arm-gic-common.h4
-rw-r--r--include/linux/irqchip/arm-gic-v3-prio.h52
-rw-r--r--include/linux/irqchip/arm-gic-v3.h2
-rw-r--r--include/linux/mfd/stm32-timers.h179
-rw-r--r--include/linux/mfd/tmio.h2
-rw-r--r--include/linux/misc_cgroup.h12
-rw-r--r--include/linux/mlx5/mlx5_ifc.h6
-rw-r--r--include/linux/mmzone.h3
-rw-r--r--include/linux/namei.h8
-rw-r--r--include/linux/nsproxy.h13
-rw-r--r--include/linux/nvme-fc-driver.h4
-rw-r--r--include/linux/nvme.h19
-rw-r--r--include/linux/page_ref.h57
-rw-r--r--include/linux/pagemap.h11
-rw-r--r--include/linux/path.h9
-rw-r--r--include/linux/pci-pwrctl.h51
-rw-r--r--include/linux/perf/arm_pmuv3.h2
-rw-r--r--include/linux/phy.h2
-rw-r--r--include/linux/platform_data/cros_ec_commands.h83
-rw-r--r--include/linux/platform_data/cros_ec_proto.h6
-rw-r--r--include/linux/platform_data/mmc-pxamci.h4
-rw-r--r--include/linux/pm_domain.h17
-rw-r--r--include/linux/pwm.h26
-rw-r--r--include/linux/pwrseq/consumer.h56
-rw-r--r--include/linux/pwrseq/provider.h75
-rw-r--r--include/linux/rcu_segcblist.h88
-rw-r--r--include/linux/rcupdate.h62
-rw-r--r--include/linux/regmap.h4
-rw-r--r--include/linux/regulator/consumer.h13
-rw-r--r--include/linux/resctrl.h88
-rw-r--r--include/linux/sched.h4
-rw-r--r--include/linux/soc/mediatek/mtk-cmdq.h42
-rw-r--r--include/linux/soc/qcom/llcc-qcom.h4
-rw-r--r--include/linux/soc/qcom/smem.h1
-rw-r--r--include/linux/soc/qcom/socinfo.h34
-rw-r--r--include/linux/soc/samsung/exynos-regs-pmu.h4
-rw-r--r--include/linux/socket.h3
-rw-r--r--include/linux/spi/spi.h17
-rw-r--r--include/linux/spi/spi_bitbang.h7
-rw-r--r--include/linux/srcu.h35
-rw-r--r--include/linux/stat.h3
-rw-r--r--include/linux/swap.h3
-rw-r--r--include/linux/syscalls.h6
-rw-r--r--include/linux/t10-pi.h22
-rw-r--r--include/linux/tick.h1
-rw-r--r--include/linux/timekeeping.h6
-rw-r--r--include/linux/tpm.h81
-rw-r--r--include/linux/tsm.h59
-rw-r--r--include/linux/turris-omnia-mcu-interface.h249
-rw-r--r--include/linux/wordpart.h8
-rw-r--r--include/net/bluetooth/hci.h11
-rw-r--r--include/net/bluetooth/hci_sync.h2
-rw-r--r--include/net/mac80211.h2
-rw-r--r--include/net/tcx.h13
-rw-r--r--include/scsi/scsi_proto.h1
-rw-r--r--include/trace/events/block.h41
-rw-r--r--include/trace/events/btrfs.h18
-rw-r--r--include/trace/events/fscache.h4
-rw-r--r--include/trace/events/scsi.h1
-rw-r--r--include/uapi/asm-generic/unistd.h4
-rw-r--r--include/uapi/drm/panthor_drm.h5
-rw-r--r--include/uapi/drm/xe_drm.h8
-rw-r--r--include/uapi/linux/fs.h5
-rw-r--r--include/uapi/linux/io_uring.h2
-rw-r--r--include/uapi/linux/mount.h10
-rw-r--r--include/uapi/linux/nsfs.h10
-rw-r--r--include/uapi/linux/pidfd.h14
-rw-r--r--include/uapi/linux/stat.h10
-rw-r--r--include/uapi/linux/trace_mmap.h2
-rw-r--r--include/uapi/linux/zorro_ids.h3
-rw-r--r--include/uapi/misc/fastrpc.h3
-rw-r--r--include/vdso/datapage.h4
-rw-r--r--io_uring/Makefile6
-rw-r--r--io_uring/advise.c16
-rw-r--r--io_uring/eventfd.c160
-rw-r--r--io_uring/eventfd.h8
-rw-r--r--io_uring/io-wq.c29
-rw-r--r--io_uring/io-wq.h2
-rw-r--r--io_uring/io_uring.c150
-rw-r--r--io_uring/io_uring.h9
-rw-r--r--io_uring/msg_ring.c122
-rw-r--r--io_uring/msg_ring.h1
-rw-r--r--io_uring/napi.c2
-rw-r--r--io_uring/net.c104
-rw-r--r--io_uring/net.h6
-rw-r--r--io_uring/opdef.c34
-rw-r--r--io_uring/opdef.h4
-rw-r--r--io_uring/register.c65
-rw-r--r--io_uring/rsrc.c63
-rw-r--r--io_uring/rw.c9
-rw-r--r--io_uring/statx.c3
-rw-r--r--io_uring/xattr.c4
-rw-r--r--ipc/mqueue.c3
-rw-r--r--kernel/bpf/bpf_local_storage.c4
-rw-r--r--kernel/bpf/helpers.c99
-rw-r--r--kernel/cgroup/cgroup.c36
-rw-r--r--kernel/cgroup/cpuset.c197
-rw-r--r--kernel/cgroup/misc.c80
-rw-r--r--kernel/cgroup/pids.c129
-rw-r--r--kernel/cgroup/rstat.c37
-rw-r--r--kernel/cpu.c19
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/fork.c34
-rw-r--r--kernel/irq/irq_sim.c60
-rw-r--r--kernel/kcsan/kcsan_test.c1
-rw-r--r--kernel/locking/locktorture.c1
-rw-r--r--kernel/pid_namespace.c17
-rw-r--r--kernel/rcu/rcuscale.c1
-rw-r--r--kernel/rcu/rcutorture.c49
-rw-r--r--kernel/rcu/refscale.c1
-rw-r--r--kernel/rcu/srcutiny.c3
-rw-r--r--kernel/rcu/srcutree.c13
-rw-r--r--kernel/rcu/sync.c12
-rw-r--r--kernel/rcu/tasks.h26
-rw-r--r--kernel/rcu/tree.c92
-rw-r--r--kernel/rcu/tree.h2
-rw-r--r--kernel/rcu/tree_exp.h24
-rw-r--r--kernel/rcu/tree_nocb.h147
-rw-r--r--kernel/rcu/tree_plugin.h14
-rw-r--r--kernel/rcu/tree_stall.h4
-rw-r--r--kernel/scftorture.c3
-rw-r--r--kernel/sched/core.c21
-rw-r--r--kernel/sched/deadline.c7
-rw-r--r--kernel/sched/fair.c12
-rw-r--r--kernel/sched/psi.c21
-rw-r--r--kernel/sched/sched.h1
-rw-r--r--kernel/sched/stats.h11
-rw-r--r--kernel/signal.c8
-rw-r--r--kernel/smp.c5
-rw-r--r--kernel/sys_ni.c2
-rw-r--r--kernel/time/clocksource-wdtest.c1
-rw-r--r--kernel/time/test_udelay.c1
-rw-r--r--kernel/time/tick-broadcast.c23
-rw-r--r--kernel/time/tick-sched.c22
-rw-r--r--kernel/time/time_test.c1
-rw-r--r--kernel/time/timekeeping.c131
-rw-r--r--kernel/torture.c1
-rw-r--r--kernel/workqueue.c352
-rw-r--r--lib/Makefile4
-rwxr-xr-xlib/build_OID_registry4
-rw-r--r--lib/closure.c3
-rw-r--r--lib/debugobjects.c21
-rw-r--r--lib/vdso/gettimeofday.c20
-rw-r--r--mm/damon/core.c23
-rw-r--r--mm/filemap.c20
-rw-r--r--mm/gup.c291
-rw-r--r--mm/huge_memory.c2
-rw-r--r--mm/hugetlb.c70
-rw-r--r--mm/hugetlb_vmemmap.c16
-rw-r--r--mm/internal.h4
-rw-r--r--mm/khugepaged.c10
-rw-r--r--mm/memcontrol.c11
-rw-r--r--mm/migrate.c13
-rw-r--r--mm/page-writeback.c32
-rw-r--r--mm/readahead.c8
-rw-r--r--mm/shmem.c36
-rw-r--r--mm/vmalloc.c10
-rw-r--r--mm/workingset.c14
-rw-r--r--net/bluetooth/hci_conn.c15
-rw-r--r--net/bluetooth/hci_core.c76
-rw-r--r--net/bluetooth/hci_event.c33
-rw-r--r--net/bluetooth/hci_sync.c13
-rw-r--r--net/bluetooth/iso.c3
-rw-r--r--net/bluetooth/l2cap_core.c3
-rw-r--r--net/bluetooth/l2cap_sock.c14
-rw-r--r--net/ceph/crush/mapper.c7
-rw-r--r--net/ceph/mon_client.c14
-rw-r--r--net/core/datagram.c20
-rw-r--r--net/core/skmsg.c3
-rw-r--r--net/ethtool/ioctl.c3
-rw-r--r--net/ethtool/linkstate.c41
-rw-r--r--net/ipv4/inet_diag.c2
-rw-r--r--net/ipv4/tcp_input.c20
-rw-r--r--net/ipv4/tcp_metrics.c1
-rw-r--r--net/ipv4/tcp_timer.c17
-rw-r--r--net/ipv4/udp.c4
-rw-r--r--net/mac80211/main.c1
-rw-r--r--net/mac80211/util.c2
-rw-r--r--net/mac802154/main.c14
-rw-r--r--net/mac802154/tx.c8
-rw-r--r--net/netfilter/nf_tables_api.c161
-rw-r--r--net/netfilter/nfnetlink_queue.c2
-rw-r--r--net/sched/act_ct.c8
-rw-r--r--net/sched/sch_ingress.c12
-rw-r--r--net/socket.c48
-rw-r--r--net/sunrpc/xprtsock.c7
-rw-r--r--net/unix/garbage.c9
-rw-r--r--net/wireless/nl80211.c6
-rw-r--r--rust/bindings/bindings_helper.h5
-rw-r--r--rust/helpers.c16
-rw-r--r--rust/kernel/block.rs5
-rw-r--r--rust/kernel/block/mq.rs98
-rw-r--r--rust/kernel/block/mq/gen_disk.rs198
-rw-r--r--rust/kernel/block/mq/operations.rs245
-rw-r--r--rust/kernel/block/mq/raw_writer.rs55
-rw-r--r--rust/kernel/block/mq/request.rs253
-rw-r--r--rust/kernel/block/mq/tag_set.rs86
-rw-r--r--rust/kernel/error.rs6
-rw-r--r--rust/kernel/lib.rs2
-rw-r--r--scripts/Kconfig.include3
-rw-r--r--scripts/Makefile.asm-generic58
-rw-r--r--scripts/Makefile.asm-headers98
-rw-r--r--scripts/const_structs.checkpatch10
-rwxr-xr-xscripts/ld-version.sh8
-rw-r--r--scripts/package/kernel.spec1
-rw-r--r--scripts/syscall.tbl404
-rwxr-xr-xscripts/syscalltbl.sh18
-rw-r--r--security/integrity/ima/ima_fs.c3
-rw-r--r--security/keys/encrypted-keys/encrypted.c1
-rw-r--r--security/keys/trusted-keys/trusted_core.c1
-rw-r--r--sound/pci/hda/cs35l41_hda_property.c4
-rw-r--r--sound/pci/hda/hda_controller.c3
-rw-r--r--sound/pci/hda/patch_realtek.c4
-rw-r--r--sound/soc/codecs/rt711-sdw.c2
-rw-r--r--sound/soc/sof/intel/hda-dai.c12
-rw-r--r--sound/soc/sof/intel/hda-pcm.c6
-rw-r--r--tools/arch/arm64/include/uapi/asm/unistd.h1
-rw-r--r--tools/arch/loongarch/include/uapi/asm/unistd.h1
-rw-r--r--tools/arch/x86/kcpuid/Makefile4
-rwxr-xr-xtools/gpio/gpio-sloppy-logic-analyzer.sh246
-rw-r--r--tools/include/nolibc/stdint.h19
-rw-r--r--tools/include/nolibc/stdio.h10
-rw-r--r--tools/include/nolibc/stdlib.h109
-rw-r--r--tools/include/uapi/asm-generic/unistd.h4
-rw-r--r--tools/memory-model/Documentation/README4
-rw-r--r--tools/memory-model/Documentation/access-marking.txt34
-rw-r--r--tools/memory-model/lock.cat62
-rw-r--r--tools/objtool/Documentation/objtool.txt19
-rw-r--r--tools/objtool/arch/x86/special.c23
-rw-r--r--tools/objtool/noreturns.h4
-rw-r--r--tools/objtool/special.c16
-rw-r--r--tools/perf/util/comm.c29
-rw-r--r--tools/perf/util/dsos.c26
-rwxr-xr-xtools/rcu/rcu-updaters.sh52
-rw-r--r--tools/testing/cxl/test/cxl.c4
-rw-r--r--tools/testing/selftests/arm64/abi/ptrace.c2
-rw-r--r--tools/testing/selftests/arm64/fp/.gitignore1
-rw-r--r--tools/testing/selftests/arm64/fp/Makefile1
-rw-r--r--tools/testing/selftests/arm64/fp/fp-stress.c26
-rw-r--r--tools/testing/selftests/arm64/fp/kernel-test.c324
-rw-r--r--tools/testing/selftests/arm64/tags/Makefile1
-rwxr-xr-xtools/testing/selftests/arm64/tags/run_tags_test.sh12
-rw-r--r--tools/testing/selftests/arm64/tags/tags_test.c10
-rw-r--r--tools/testing/selftests/bpf/config3
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tc_links.c61
-rw-r--r--tools/testing/selftests/bpf/prog_tests/timer_lockup.c91
-rw-r--r--tools/testing/selftests/bpf/progs/timer_lockup.c87
-rw-r--r--tools/testing/selftests/cgroup/.gitignore11
-rw-r--r--tools/testing/selftests/cgroup/Makefile25
-rwxr-xr-xtools/testing/selftests/cgroup/test_cpuset_prs.sh75
-rw-r--r--tools/testing/selftests/cgroup/test_pids.c178
-rw-r--r--tools/testing/selftests/filesystems/statmount/Makefile2
-rw-r--r--tools/testing/selftests/filesystems/statmount/statmount.h46
-rw-r--r--tools/testing/selftests/filesystems/statmount/statmount_test.c144
-rw-r--r--tools/testing/selftests/filesystems/statmount/statmount_test_ns.c364
-rw-r--r--tools/testing/selftests/kselftest.h8
-rw-r--r--tools/testing/selftests/kselftest_harness.h43
-rw-r--r--tools/testing/selftests/net/af_unix/scm_rights.c25
-rw-r--r--tools/testing/selftests/net/msg_zerocopy.c14
-rw-r--r--tools/testing/selftests/nolibc/Makefile2
-rw-r--r--tools/testing/selftests/nolibc/nolibc-test.c109
-rwxr-xr-xtools/testing/selftests/nolibc/run-tests.sh9
-rw-r--r--tools/testing/selftests/powerpc/flags.mk5
-rw-r--r--tools/testing/selftests/resctrl/cat_test.c32
-rw-r--r--tools/testing/selftests/riscv/sigreturn/sigreturn.c2
-rw-r--r--tools/testing/selftests/timens/exec.c6
-rw-r--r--tools/testing/selftests/timens/timer.c2
-rw-r--r--tools/testing/selftests/timens/timerfd.c2
-rw-r--r--tools/testing/selftests/timens/vfork_exec.c4
-rw-r--r--tools/testing/selftests/vDSO/Makefile29
-rw-r--r--tools/testing/selftests/vDSO/parse_vdso.c16
-rw-r--r--tools/testing/selftests/vDSO/vdso_standalone_test_x86.c18
-rw-r--r--tools/testing/selftests/wireguard/qemu/Makefile8
2569 files changed, 108610 insertions, 32352 deletions
diff --git a/.mailmap b/.mailmap
index a6c619e22efc..38f8bed507a2 100644
--- a/.mailmap
+++ b/.mailmap
@@ -384,7 +384,9 @@ Li Yang <[email protected]> <[email protected]>
Lorenzo Pieralisi <[email protected]> <[email protected]>
Maciej W. Rozycki <[email protected]> <[email protected]>
@@ -689,6 +691,7 @@ Vivien Didelot <[email protected]> <[email protected]>
diff --git a/CREDITS b/CREDITS
index 0107047f807b..1a762cf46b49 100644
--- a/CREDITS
+++ b/CREDITS
@@ -796,6 +796,11 @@ E: [email protected]
D: Ralink rt2x00 WLAN driver
S: Belas, Portugal
+N: Benoît Cousson
+D: TI OMAP Devicetree platforms
+D: TI OMAP HWMOD boards
+
N: Alan Cox
W: http://www.linux.org.uk/diary/
D: Linux Networking (0.99.10->2.0.29)
@@ -1214,6 +1219,10 @@ D: UDF filesystem
S: (ask for current address)
S: USA
+N: Larry Finger
+D: Maintainer of wireless drivers, too many to list here
+
N: Jürgen Fischer
D: Author of Adaptec AHA-152x SCSI driver
@@ -3146,9 +3155,11 @@ S: Triftstra=DFe 55
S: 13353 Berlin
S: Germany
-N: Gustavo Pimental
+N: Gustavo Pimentel
D: PCI driver for Synopsys DesignWare
+D: Synopsys DesignWare eDMA driver
+D: Synopsys DesignWare xData traffic generator
N: Emanuel Pirker
@@ -4362,6 +4373,10 @@ N: Haojian Zhuang
D: MMP support
+N: Tsahee Zidenberg
+D: Annapurna Labs Alpine Architecture
+
N: Richard Zidlicky
W: http://www.geocities.com/rdzidlic
diff --git a/Documentation/ABI/stable/sysfs-block b/Documentation/ABI/stable/sysfs-block
index 831f19a32e08..cea8856f798d 100644
--- a/Documentation/ABI/stable/sysfs-block
+++ b/Documentation/ABI/stable/sysfs-block
@@ -21,6 +21,59 @@ Description:
device is offset from the internal allocation unit's
natural alignment.
+What: /sys/block/<disk>/atomic_write_max_bytes
+Date: February 2024
+Contact: Himanshu Madhani <[email protected]>
+Description:
+ [RO] This parameter specifies the maximum atomic write
+ size reported by the device. This parameter is relevant
+ for merging of writes, where a merged atomic write
+ operation must not exceed this number of bytes.
+ This parameter may be greater than the value in
+ atomic_write_unit_max_bytes as
+ atomic_write_unit_max_bytes will be rounded down to a
+ power-of-two and atomic_write_unit_max_bytes may also be
+ limited by some other queue limits, such as max_segments.
+ This parameter - along with atomic_write_unit_min_bytes
+ and atomic_write_unit_max_bytes - will not be larger than
+ max_hw_sectors_kb, but may be larger than max_sectors_kb.
+
+
+What: /sys/block/<disk>/atomic_write_unit_min_bytes
+Date: February 2024
+Contact: Himanshu Madhani <[email protected]>
+Description:
+ [RO] This parameter specifies the smallest block which can
+ be written atomically with an atomic write operation. All
+ atomic write operations must begin at a
+ atomic_write_unit_min boundary and must be multiples of
+ atomic_write_unit_min. This value must be a power-of-two.
+
+
+What: /sys/block/<disk>/atomic_write_unit_max_bytes
+Date: February 2024
+Contact: Himanshu Madhani <[email protected]>
+Description:
+ [RO] This parameter defines the largest block which can be
+ written atomically with an atomic write operation. This
+ value must be a multiple of atomic_write_unit_min and must
+ be a power-of-two. This value will not be larger than
+ atomic_write_max_bytes.
+
+
+What: /sys/block/<disk>/atomic_write_boundary_bytes
+Date: February 2024
+Contact: Himanshu Madhani <[email protected]>
+Description:
+ [RO] A device may need to internally split an atomic write I/O
+ which straddles a given logical block address boundary. This
+ parameter specifies the size in bytes of the atomic boundary if
+ one is reported by the device. This value must be a
+ power-of-two and at least the size as in
+ atomic_write_unit_max_bytes.
+ Any attempt to merge atomic write I/Os must not result in a
+ merged I/O which crosses this boundary (if any).
+
What: /sys/block/<disk>/diskseq
Date: February 2021
diff --git a/Documentation/ABI/testing/configfs-tsm b/Documentation/ABI/testing/configfs-tsm
index dd24202b5ba5..534408bc1408 100644
--- a/Documentation/ABI/testing/configfs-tsm
+++ b/Documentation/ABI/testing/configfs-tsm
@@ -31,6 +31,18 @@ Description:
Standardization v2.03 Section 4.1.8.1 MSG_REPORT_REQ.
https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56421.pdf
+What: /sys/kernel/config/tsm/report/$name/manifestblob
+Date: January, 2024
+KernelVersion: v6.10
+Description:
+ (RO) Optional supplemental data that a TSM may emit, visibility
+ of this attribute depends on TSM, and may be empty if no
+ manifest data is available.
+
+ See 'service_provider' for information on the format of the
+ manifest blob.
+
What: /sys/kernel/config/tsm/report/$name/provider
Date: September, 2023
KernelVersion: v6.7
@@ -80,3 +92,54 @@ Contact: [email protected]
Description:
(RO) Indicates the minimum permissible value that can be written
to @privlevel.
+
+What: /sys/kernel/config/tsm/report/$name/service_provider
+Date: January, 2024
+KernelVersion: v6.10
+Description:
+ (WO) Attribute is visible if a TSM implementation provider
+ supports the concept of attestation reports from a service
+ provider for TVMs, like SEV-SNP running under an SVSM.
+ Specifying the service provider via this attribute will create
+ an attestation report as specified by the service provider.
+ The only currently supported service provider is "svsm".
+
+ For the "svsm" service provider, see the Secure VM Service Module
+ for SEV-SNP Guests v1.00 Section 7. For the doc, search for
+ "site:amd.com "Secure VM Service Module for SEV-SNP
+ Guests", docID: 58019"
+
+What: /sys/kernel/config/tsm/report/$name/service_guid
+Date: January, 2024
+KernelVersion: v6.10
+Description:
+ (WO) Attribute is visible if a TSM implementation provider
+ supports the concept of attestation reports from a service
+ provider for TVMs, like SEV-SNP running under an SVSM.
+ Specifying an empty/null GUID (00000000-0000-0000-0000-000000)
+ requests all active services within the service provider be
+ part of the attestation report. Specifying a GUID request
+ an attestation report of just the specified service using the
+ manifest form specified by the service_manifest_version
+ attribute.
+
+ See 'service_provider' for information on the format of the
+ service guid.
+
+What: /sys/kernel/config/tsm/report/$name/service_manifest_version
+Date: January, 2024
+KernelVersion: v6.10
+Description:
+ (WO) Attribute is visible if a TSM implementation provider
+ supports the concept of attestation reports from a service
+ provider for TVMs, like SEV-SNP running under an SVSM.
+ Indicates the service manifest version requested for the
+ attestation report (default 0). If this field is not set by
+ the user, the default manifest version of the service (the
+ service's initial/first manifest version) is returned.
+
+ See 'service_provider' for information on the format of the
+ service manifest version.
diff --git a/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu
new file mode 100644
index 000000000000..307a55f599cb
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu
@@ -0,0 +1,113 @@
+What: /sys/bus/i2c/devices/<mcu_device>/board_revision
+Date: September 2024
+KernelVersion: 6.11
+Contact: Marek Behún <[email protected]>
+Description: (RO) Contains board revision number.
+
+ Only available if board information is burned in the MCU (older
+ revisions have board information burned in the ATSHA204-A chip).
+
+ Format: %u.
+
+What: /sys/bus/i2c/devices/<mcu_device>/first_mac_address
+Date: September 2024
+KernelVersion: 6.11
+Contact: Marek Behún <[email protected]>
+Description: (RO) Contains device first MAC address. Each Turris Omnia is
+ allocated 3 MAC addresses. The two additional addresses are
+ computed from the first one by incrementing it.
+
+ Only available if board information is burned in the MCU (older
+ revisions have board information burned in the ATSHA204-A chip).
+
+ Format: %pM.
+
+What: /sys/bus/i2c/devices/<mcu_device>/front_button_mode
+Date: September 2024
+KernelVersion: 6.11
+Contact: Marek Behún <[email protected]>
+Description: (RW) The front button on the Turris Omnia router can be
+ configured either to change the intensity of all the LEDs on the
+ front panel, or to send the press event to the CPU as an
+ interrupt.
+
+ This file switches between these two modes:
+ - "mcu" makes the button press event be handled by the MCU to
+ change the LEDs panel intensity.
+ - "cpu" makes the button press event be handled by the CPU.
+
+ Format: %s.
+
+What: /sys/bus/i2c/devices/<mcu_device>/front_button_poweron
+Date: September 2024
+KernelVersion: 6.11
+Contact: Marek Behún <[email protected]>
+Description: (RW) Newer versions of the microcontroller firmware of the
+ Turris Omnia router support powering off the router into true
+ low power mode. The router can be powered on by pressing the
+ front button.
+
+ This file configures whether front button power on is enabled.
+
+ This file is present only if the power off feature is supported
+ by the firmware.
+
+ Format: %i.
+
+What: /sys/bus/i2c/devices/<mcu_device>/fw_features
+Date: September 2024
+KernelVersion: 6.11
+Contact: Marek Behún <[email protected]>
+Description: (RO) Newer versions of the microcontroller firmware report the
+ features they support. These can be read from this file. If the
+ MCU firmware is too old, this file reads 0x0.
+
+ Format: 0x%x.
+
+What: /sys/bus/i2c/devices/<mcu_device>/fw_version_hash_application
+Date: September 2024
+KernelVersion: 6.11
+Contact: Marek Behún <[email protected]>
+Description: (RO) Contains the version hash (commit hash) of the application
+ part of the microcontroller firmware.
+
+ Format: %s.
+
+What: /sys/bus/i2c/devices/<mcu_device>/fw_version_hash_bootloader
+Date: September 2024
+KernelVersion: 6.11
+Contact: Marek Behún <[email protected]>
+Description: (RO) Contains the version hash (commit hash) of the bootloader
+ part of the microcontroller firmware.
+
+ Format: %s.
+
+What: /sys/bus/i2c/devices/<mcu_device>/mcu_type
+Date: September 2024
+KernelVersion: 6.11
+Contact: Marek Behún <[email protected]>
+Description: (RO) Contains the microcontroller type (STM32, GD32, MKL).
+
+ Format: %s.
+
+What: /sys/bus/i2c/devices/<mcu_device>/reset_selector
+Date: September 2024
+KernelVersion: 6.11
+Contact: Marek Behún <[email protected]>
+Description: (RO) Contains the selected factory reset level, determined by
+ how long the rear reset button was held by the user during board
+ reset.
+
+ Format: %i.
+
+What: /sys/bus/i2c/devices/<mcu_device>/serial_number
+Date: September 2024
+KernelVersion: 6.11
+Contact: Marek Behún <[email protected]>
+Description: (RO) Contains the 64-bit board serial number in hexadecimal
+ format.
+
+ Only available if board information is burned in the MCU (older
+ revisions have board information burned in the ATSHA204-A chip).
+
+ Format: %016X.
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index e7e160954e79..325873385b71 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -605,6 +605,18 @@ Description: Umwait control
Note that a value of zero means there is no limit.
Low order two bits must be zero.
+What: /sys/devices/system/cpu/sev
+ /sys/devices/system/cpu/sev/vmpl
+Date: May 2024
+Contact: Linux kernel mailing list <[email protected]>
+Description: Secure Encrypted Virtualization (SEV) information
+
+ This directory is only present when running as an SEV-SNP guest.
+
+ vmpl: Reports the Virtual Machine Privilege Level (VMPL) at which
+ the SEV-SNP guest is running.
+
+
What: /sys/devices/system/cpu/svm
Date: August 2019
Contact: Linux kernel mailing list <[email protected]>
@@ -694,3 +706,9 @@ Description:
(RO) indicates whether or not the kernel directly supports
modifying the crash elfcorehdr for CPU hot un/plug and/or
on/offline changes.
+
+What: /sys/devices/system/cpu/enabled
+Date: Nov 2022
+Contact: Linux kernel mailing list <[email protected]>
+Description:
+ (RO) the list of CPUs that can be brought online.
diff --git a/Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Memory-Ordering.rst b/Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Memory-Ordering.rst
index 5750f125361b..728b1e690c64 100644
--- a/Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Memory-Ordering.rst
+++ b/Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Memory-Ordering.rst
@@ -149,9 +149,9 @@ This case is handled by calls to the strongly ordered
``atomic_add_return()`` read-modify-write atomic operation that
is invoked within ``rcu_dynticks_eqs_enter()`` at idle-entry
time and within ``rcu_dynticks_eqs_exit()`` at idle-exit time.
-The grace-period kthread invokes ``rcu_dynticks_snap()`` and
-``rcu_dynticks_in_eqs_since()`` (both of which invoke
-an ``atomic_add_return()`` of zero) to detect idle CPUs.
+The grace-period kthread invokes first ``ct_dynticks_cpu_acquire()``
+(preceded by a full memory barrier) and ``rcu_dynticks_in_eqs_since()``
+(both of which rely on acquire semantics) to detect idle CPUs.
+-----------------------------------------------------------------------+
| **Quick Quiz**: |
diff --git a/Documentation/RCU/Design/Requirements/Requirements.rst b/Documentation/RCU/Design/Requirements/Requirements.rst
index cccafdaa1f84..f511476b4550 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.rst
+++ b/Documentation/RCU/Design/Requirements/Requirements.rst
@@ -2357,6 +2357,7 @@ section.
#. `Sched Flavor (Historical)`_
#. `Sleepable RCU`_
#. `Tasks RCU`_
+#. `Tasks Trace RCU`_
Bottom-Half Flavor (Historical)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2610,6 +2611,16 @@ critical sections that are delimited by voluntary context switches, that
is, calls to schedule(), cond_resched(), and
synchronize_rcu_tasks(). In addition, transitions to and from
userspace execution also delimit tasks-RCU read-side critical sections.
+Idle tasks are ignored by Tasks RCU, and Tasks Rude RCU may be used to
+interact with them.
+
+Note well that involuntary context switches are *not* Tasks-RCU quiescent
+states. After all, in preemptible kernels, a task executing code in a
+trampoline might be preempted. In this case, the Tasks-RCU grace period
+clearly cannot end until that task resumes and its execution leaves that
+trampoline. This means, among other things, that cond_resched() does
+not provide a Tasks RCU quiescent state. (Instead, use rcu_softirq_qs()
+from softirq or rcu_tasks_classic_qs() otherwise.)
The tasks-RCU API is quite compact, consisting only of
call_rcu_tasks(), synchronize_rcu_tasks(), and
@@ -2632,6 +2643,11 @@ moniker. And this operation is considered to be quite rude by real-time
workloads that don't want their ``nohz_full`` CPUs receiving IPIs and
by battery-powered systems that don't want their idle CPUs to be awakened.
+Once kernel entry/exit and deep-idle functions have been properly tagged
+``noinstr``, Tasks RCU can start paying attention to idle tasks (except
+those that are idle from RCU's perspective) and then Tasks Rude RCU can
+be removed from the kernel.
+
The tasks-rude-RCU API is also reader-marking-free and thus quite compact,
consisting of call_rcu_tasks_rude(), synchronize_rcu_tasks_rude(),
and rcu_barrier_tasks_rude().
diff --git a/Documentation/RCU/whatisRCU.rst b/Documentation/RCU/whatisRCU.rst
index 94838c65c7d9..d585a5490aee 100644
--- a/Documentation/RCU/whatisRCU.rst
+++ b/Documentation/RCU/whatisRCU.rst
@@ -250,21 +250,25 @@ rcu_assign_pointer()
^^^^^^^^^^^^^^^^^^^^
void rcu_assign_pointer(p, typeof(p) v);
- Yes, rcu_assign_pointer() **is** implemented as a macro, though it
- would be cool to be able to declare a function in this manner.
- (Compiler experts will no doubt disagree.)
+ Yes, rcu_assign_pointer() **is** implemented as a macro, though
+ it would be cool to be able to declare a function in this manner.
+ (And there has been some discussion of adding overloaded functions
+ to the C language, so who knows?)
The updater uses this spatial macro to assign a new value to an
RCU-protected pointer, in order to safely communicate the change
in value from the updater to the reader. This is a spatial (as
opposed to temporal) macro. It does not evaluate to an rvalue,
- but it does execute any memory-barrier instructions required
- for a given CPU architecture. Its ordering properties are that
- of a store-release operation.
-
- Perhaps just as important, it serves to document (1) which
- pointers are protected by RCU and (2) the point at which a
- given structure becomes accessible to other CPUs. That said,
+ but it does provide any compiler directives and memory-barrier
+ instructions required for a given compile or CPU architecture.
+ Its ordering properties are that of a store-release operation,
+ that is, any prior loads and stores required to initialize the
+ structure are ordered before the store that publishes the pointer
+ to that structure.
+
+ Perhaps just as important, rcu_assign_pointer() serves to document
+ (1) which pointers are protected by RCU and (2) the point at which
+ a given structure becomes accessible to other CPUs. That said,
rcu_assign_pointer() is most frequently used indirectly, via
the _rcu list-manipulation primitives such as list_add_rcu().
@@ -283,7 +287,11 @@ rcu_dereference()
executes any needed memory-barrier instructions for a given
CPU architecture. Currently, only Alpha needs memory barriers
within rcu_dereference() -- on other CPUs, it compiles to a
- volatile load.
+ volatile load. However, no mainstream C compilers respect
+ address dependencies, so rcu_dereference() uses volatile casts,
+ which, in combination with the coding guidelines listed in
+ rcu_dereference.rst, prevent current compilers from breaking
+ these dependencies.
Common coding practice uses rcu_dereference() to copy an
RCU-protected pointer to a local variable, then dereferences
diff --git a/Documentation/admin-guide/cgroup-v1/pids.rst b/Documentation/admin-guide/cgroup-v1/pids.rst
index 6acebd9e72c8..0f9f9a7b1f6c 100644
--- a/Documentation/admin-guide/cgroup-v1/pids.rst
+++ b/Documentation/admin-guide/cgroup-v1/pids.rst
@@ -36,7 +36,8 @@ superset of parent/child/pids.current.
The pids.events file contains event counters:
- - max: Number of times fork failed because limit was hit.
+ - max: Number of times fork failed in the cgroup because limit was hit in
+ self or ancestors.
Example
-------
diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index 8fbb0519d556..05862f06ed26 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -239,6 +239,13 @@ cgroup v2 currently supports the following mount options.
will not be tracked by the memory controller (even if cgroup
v2 is remounted later on).
+ pids_localevents
+ The option restores v1-like behavior of pids.events:max, that is only
+ local (inside cgroup proper) fork failures are counted. Without this
+ option pids.events.max represents any pids.max enforcemnt across
+ cgroup's subtree.
+
+
Organizing Processes and Threads
--------------------------------
@@ -2205,12 +2212,18 @@ PID Interface Files
descendants has ever reached.
pids.events
- A read-only flat-keyed file which exists on non-root cgroups. The
- following entries are defined. Unless specified otherwise, a value
- change in this file generates a file modified event.
+ A read-only flat-keyed file which exists on non-root cgroups. Unless
+ specified otherwise, a value change in this file generates a file
+ modified event. The following entries are defined.
max
- Number of times fork failed because limit was hit.
+ The number of times the cgroup's total number of processes hit the pids.max
+ limit (see also pids_localevents).
+
+ pids.events.local
+ Similar to pids.events but the fields in the file are local
+ to the cgroup i.e. not hierarchical. The file modified event
+ generated on this file reflects only the local events.
Organisational operations are not blocked by cgroup policies, so it is
possible to have pids.current > pids.max. This can be done by either
@@ -2346,8 +2359,12 @@ Cpuset Interface Files
is always a subset of it.
Users can manually set it to a value that is different from
- "cpuset.cpus". The only constraint in setting it is that the
- list of CPUs must be exclusive with respect to its sibling.
+ "cpuset.cpus". One constraint in setting it is that the list of
+ CPUs must be exclusive with respect to "cpuset.cpus.exclusive"
+ of its sibling. If "cpuset.cpus.exclusive" of a sibling cgroup
+ isn't set, its "cpuset.cpus" value, if set, cannot be a subset
+ of it to leave at least one CPU available when the exclusive
+ CPUs are taken away.
For a parent cgroup, any one of its exclusive CPUs can only
be distributed to at most one of its child cgroups. Having an
@@ -2363,8 +2380,8 @@ Cpuset Interface Files
cpuset-enabled cgroups.
This file shows the effective set of exclusive CPUs that
- can be used to create a partition root. The content of this
- file will always be a subset of "cpuset.cpus" and its parent's
+ can be used to create a partition root. The content
+ of this file will always be a subset of its parent's
"cpuset.cpus.exclusive.effective" if its parent is not the root
cgroup. It will also be a subset of "cpuset.cpus.exclusive"
if it is set. If "cpuset.cpus.exclusive" is not set, it is
@@ -2625,6 +2642,15 @@ Miscellaneous controller provides 3 interface files. If two misc resources (res_
res_a 3
res_b 0
+ misc.peak
+ A read-only flat-keyed file shown in all cgroups. It shows the
+ historical maximum usage of the resources in the cgroup and its
+ children.::
+
+ $ cat misc.peak
+ res_a 10
+ res_b 8
+
misc.max
A read-write flat-keyed file shown in the non root cgroups. Allowed
maximum usage of the resources in the cgroup and its children.::
@@ -2654,6 +2680,11 @@ Miscellaneous controller provides 3 interface files. If two misc resources (res_
The number of times the cgroup's resource usage was
about to go over the max boundary.
+ misc.events.local
+ Similar to misc.events but the fields in the file are local to the
+ cgroup i.e. not hierarchical. The file modified event generated on
+ this file reflects only the local events.
+
Migration and Ownership
~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/admin-guide/cifs/usage.rst b/Documentation/admin-guide/cifs/usage.rst
index aa8290a29dc8..fd4b56c0996f 100644
--- a/Documentation/admin-guide/cifs/usage.rst
+++ b/Documentation/admin-guide/cifs/usage.rst
@@ -723,40 +723,26 @@ Configuration pseudo-files:
======================= =======================================================
SecurityFlags Flags which control security negotiation and
also packet signing. Authentication (may/must)
- flags (e.g. for NTLM and/or NTLMv2) may be combined with
+ flags (e.g. for NTLMv2) may be combined with
the signing flags. Specifying two different password
hashing mechanisms (as "must use") on the other hand
does not make much sense. Default flags are::
- 0x07007
-
- (NTLM, NTLMv2 and packet signing allowed). The maximum
- allowable flags if you want to allow mounts to servers
- using weaker password hashes is 0x37037 (lanman,
- plaintext, ntlm, ntlmv2, signing allowed). Some
- SecurityFlags require the corresponding menuconfig
- options to be enabled. Enabling plaintext
- authentication currently requires also enabling
- lanman authentication in the security flags
- because the cifs module only supports sending
- laintext passwords using the older lanman dialect
- form of the session setup SMB. (e.g. for authentication
- using plain text passwords, set the SecurityFlags
- to 0x30030)::
+ 0x00C5
+
+ (NTLMv2 and packet signing allowed). Some SecurityFlags
+ may require enabling a corresponding menuconfig option.
may use packet signing 0x00001
must use packet signing 0x01001
- may use NTLM (most common password hash) 0x00002
- must use NTLM 0x02002
may use NTLMv2 0x00004
must use NTLMv2 0x04004
- may use Kerberos security 0x00008
- must use Kerberos 0x08008
- may use lanman (weak) password hash 0x00010
- must use lanman password hash 0x10010
- may use plaintext passwords 0x00020
- must use plaintext passwords 0x20020
- (reserved for future packet encryption) 0x00040
+ may use Kerberos security (krb5) 0x00008
+ must use Kerberos 0x08008
+ may use NTLMSSP 0x00080
+ must use NTLMSSP 0x80080
+ seal (packet encryption) 0x00040
+ must seal (not implemented yet) 0x40040
cifsFYI If set to non-zero value, additional debug information
will be logged to the system error log. This field
diff --git a/Documentation/admin-guide/gpio/gpio-virtuser.rst b/Documentation/admin-guide/gpio/gpio-virtuser.rst
new file mode 100644
index 000000000000..2aca70db9f3b
--- /dev/null
+++ b/Documentation/admin-guide/gpio/gpio-virtuser.rst
@@ -0,0 +1,177 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+Virtual GPIO Consumer
+=====================
+
+The virtual GPIO Consumer module allows users to instantiate virtual devices
+that request GPIOs and then control their behavior over debugfs. Virtual
+consumer devices can be instantiated from device-tree or over configfs.
+
+A virtual consumer uses the driver-facing GPIO APIs and allows to cover it with
+automated tests driven by user-space. The GPIOs are requested using
+``gpiod_get_array()`` and so we support multiple GPIOs per connector ID.
+
+Creating GPIO consumers
+-----------------------
+
+The gpio-consumer module registers a configfs subsystem called
+``'gpio-virtuser'``. For details of the configfs filesystem, please refer to
+the configfs documentation.
+
+The user can create a hierarchy of configfs groups and items as well as modify
+values of exposed attributes. Once the consumer is instantiated, this hierarchy
+will be translated to appropriate device properties. The general structure is:
+
+**Group:** ``/config/gpio-virtuser``
+
+This is the top directory of the gpio-consumer configfs tree.
+
+**Group:** ``/config/gpio-consumer/example-name``
+
+**Attribute:** ``/config/gpio-consumer/example-name/live``
+
+**Attribute:** ``/config/gpio-consumer/example-name/dev_name``
+
+This is a directory representing a GPIO consumer device.
+
+The read-only ``dev_name`` attribute exposes the name of the device as it will
+appear in the system on the platform bus. This is useful for locating the
+associated debugfs directory under
+``/sys/kernel/debug/gpio-virtuser/$dev_name``.
+
+The ``'live'`` attribute allows to trigger the actual creation of the device
+once it's fully configured. The accepted values are: ``'1'`` to enable the
+virtual device and ``'0'`` to disable and tear it down.
+
+Creating GPIO lookup tables
+---------------------------
+
+Users can create a number of configfs groups under the device group:
+
+**Group:** ``/config/gpio-consumer/example-name/con_id``
+
+The ``'con_id'`` directory represents a single GPIO lookup and its value maps
+to the ``'con_id'`` argument of the ``gpiod_get()`` function. For example:
+``con_id`` == ``'reset'`` maps to the ``reset-gpios`` device property.
+
+Users can assign a number of GPIOs to each lookup. Each GPIO is a sub-directory
+with a user-defined name under the ``'con_id'`` group.
+
+**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/key``
+
+**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/offset``
+
+**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/drive``
+
+**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/pull``
+
+**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/active_low``
+
+**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/transitory``
+
+This is a group describing a single GPIO in the ``con_id-gpios`` property.
+
+For virtual consumers created using configfs we use machine lookup tables so
+this group can be considered as a mapping between the filesystem and the fields
+of a single entry in ``'struct gpiod_lookup'``.
+
+The ``'key'`` attribute represents either the name of the chip this GPIO
+belongs to or the GPIO line name. This depends on the value of the ``'offset'``
+attribute: if its value is >= 0, then ``'key'`` represents the label of the
+chip to lookup while ``'offset'`` represents the offset of the line in that
+chip. If ``'offset'`` is < 0, then ``'key'`` represents the name of the line.
+
+The remaining attributes map to the ``'flags'`` field of the GPIO lookup
+struct. The first two take string values as arguments:
+
+**``'drive'``:** ``'push-pull'``, ``'open-drain'``, ``'open-source'``
+**``'pull'``:** ``'pull-up'``, ``'pull-down'``, ``'pull-disabled'``, ``'as-is'``
+
+``'active_low'`` and ``'transitory'`` are boolean attributes.
+
+Activating GPIO consumers
+-------------------------
+
+Once the confiuration is complete, the ``'live'`` attribute must be set to 1 in
+order to instantiate the consumer. It can be set back to 0 to destroy the
+virtual device. The module will synchronously wait for the new simulated device
+to be successfully probed and if this doesn't happen, writing to ``'live'`` will
+result in an error.
+
+Device-tree
+-----------
+
+Virtual GPIO consumers can also be defined in device-tree. The compatible string
+must be: ``"gpio-virtuser"`` with at least one property following the
+standardized GPIO pattern.
+
+An example device-tree code defining a virtual GPIO consumer:
+
+.. code-block :: none
+
+ gpio-virt-consumer {
+ compatible = "gpio-virtuser";
+
+ foo-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>, <&gpio1 2 0>;
+ bar-gpios = <&gpio0 6 0>;
+ };
+
+Controlling virtual GPIO consumers
+----------------------------------
+
+Once active, the device will export debugfs attributes for controlling GPIO
+arrays as well as each requested GPIO line separately. Let's consider the
+following device property: ``foo-gpios = <&gpio0 0 0>, <&gpio0 4 0>;``.
+
+The following debugfs attribute groups will be created:
+
+**Group:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/``
+
+This is the group that will contain the attributes for the entire GPIO array.
+
+**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/values``
+
+**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/values_atomic``
+
+Both attributes allow to read and set arrays of GPIO values. User must pass
+exactly the number of values that the array contains in the form of a string
+containing zeroes and ones representing inactive and active GPIO states
+respectively. In this example: ``echo 11 > values``.
+
+The ``values_atomic`` attribute works the same as ``values`` but the kernel
+will execute the GPIO driver callbacks in interrupt context.
+
+**Group:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/``
+
+This is a group that represents a single GPIO with ``$index`` being its offset
+in the array.
+
+**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/consumer``
+
+Allows to set and read the consumer label of the GPIO line.
+
+**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/debounce``
+
+Allows to set and read the debounce period of the GPIO line.
+
+**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/direction``
+
+**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/direction_atomic``
+
+These two attributes allow to set the direction of the GPIO line. They accept
+"input" and "output" as values. The atomic variant executes the driver callback
+in interrupt context.
+
+**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/interrupts``
+
+If the line is requested in input mode, writing ``1`` to this attribute will
+make the module listen for edge interrupts on the GPIO. Writing ``0`` disables
+the monitoring. Reading this attribute returns the current number of registered
+interrupts (both edges).
+
+**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/value``
+
+**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/value_atomic``
+
+Both attributes allow to read and set values of individual requested GPIO lines.
+They accept the following values: ``1`` and ``0``.
diff --git a/Documentation/admin-guide/gpio/index.rst b/Documentation/admin-guide/gpio/index.rst
index 460afd29617e..712f379731cb 100644
--- a/Documentation/admin-guide/gpio/index.rst
+++ b/Documentation/admin-guide/gpio/index.rst
@@ -10,6 +10,7 @@ GPIO
Character Device Userspace API <../../userspace-api/gpio/chardev>
gpio-aggregator
gpio-sim
+ gpio-virtuser
Obsolete APIs <obsolete>
.. only:: subproject and html
diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst
index 25a04cda4c2c..132e0bc6007e 100644
--- a/Documentation/admin-guide/hw-vuln/spectre.rst
+++ b/Documentation/admin-guide/hw-vuln/spectre.rst
@@ -592,85 +592,19 @@ Spectre variant 2
Mitigation control on the kernel command line
---------------------------------------------
-Spectre variant 2 mitigation can be disabled or force enabled at the
-kernel command line.
+In general the kernel selects reasonable default mitigations for the
+current CPU.
- nospectre_v1
+Spectre default mitigations can be disabled or changed at the kernel
+command line with the following options:
- [X86,PPC] Disable mitigations for Spectre Variant 1
- (bounds check bypass). With this option data leaks are
- possible in the system.
+ - nospectre_v1
+ - nospectre_v2
+ - spectre_v2={option}
+ - spectre_v2_user={option}
+ - spectre_bhi={option}
- nospectre_v2
-
- [X86] Disable all mitigations for the Spectre variant 2
- (indirect branch prediction) vulnerability. System may
- allow data leaks with this option, which is equivalent
- to spectre_v2=off.
-
-
- spectre_v2=
-
- [X86] Control mitigation of Spectre variant 2
- (indirect branch speculation) vulnerability.
- The default operation protects the kernel from
- user space attacks.
-
- on
- unconditionally enable, implies
- spectre_v2_user=on
- off
- unconditionally disable, implies
- spectre_v2_user=off
- auto
- kernel detects whether your CPU model is
- vulnerable
-
- Selecting 'on' will, and 'auto' may, choose a
- mitigation method at run time according to the
- CPU, the available microcode, the setting of the
- CONFIG_MITIGATION_RETPOLINE configuration option,
- and the compiler with which the kernel was built.
-
- Selecting 'on' will also enable the mitigation
- against user space to user space task attacks.
-
- Selecting 'off' will disable both the kernel and
- the user space protections.
-
- Specific mitigations can also be selected manually:
-
- retpoline auto pick between generic,lfence
- retpoline,generic Retpolines
- retpoline,lfence LFENCE; indirect branch
- retpoline,amd alias for retpoline,lfence
- eibrs Enhanced/Auto IBRS
- eibrs,retpoline Enhanced/Auto IBRS + Retpolines
- eibrs,lfence Enhanced/Auto IBRS + LFENCE
- ibrs use IBRS to protect kernel
-
- Not specifying this option is equivalent to
- spectre_v2=auto.
-
- In general the kernel by default selects
- reasonable mitigations for the current CPU. To
- disable Spectre variant 2 mitigations, boot with
- spectre_v2=off. Spectre variant 1 mitigations
- cannot be disabled.
-
- spectre_bhi=
-
- [X86] Control mitigation of Branch History Injection
- (BHI) vulnerability. This setting affects the deployment
- of the HW BHI control and the SW BHB clearing sequence.
-
- on
- (default) Enable the HW or SW mitigation as
- needed.
- off
- Disable the mitigation.
-
-For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt
+For more details on the available options, refer to Documentation/admin-guide/kernel-parameters.txt
Mitigation selection guide
--------------------------
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 2074ba03f2e3..1bd225eca34c 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -12,7 +12,7 @@
acpi= [HW,ACPI,X86,ARM64,RISCV64,EARLY]
Advanced Configuration and Power Interface
Format: { force | on | off | strict | noirq | rsdt |
- copy_dsdt }
+ copy_dsdt | nospcr }
force -- enable ACPI if default was off
on -- enable ACPI but allow fallback to DT [arm64,riscv64]
off -- disable ACPI if default was on
@@ -21,8 +21,12 @@
strictly ACPI specification compliant.
rsdt -- prefer RSDT over (default) XSDT
copy_dsdt -- copy DSDT to memory
- For ARM64 and RISCV64, ONLY "acpi=off", "acpi=on" or
- "acpi=force" are available
+ nospcr -- disable console in ACPI SPCR table as
+ default _serial_ console on ARM64
+ For ARM64, ONLY "acpi=off", "acpi=on", "acpi=force" or
+ "acpi=nospcr" are available
+ For RISCV64, ONLY "acpi=off", "acpi=on" or "acpi=force"
+ are available
See also Documentation/power/runtime_pm.rst, pci=noacpi
@@ -1431,27 +1435,6 @@
you are really sure that your UEFI does sane gc and
fulfills the spec otherwise your board may brick.
- efi_fake_mem= nn[KMG]@ss[KMG]:aa[,nn[KMG]@ss[KMG]:aa,..] [EFI,X86,EARLY]
- Add arbitrary attribute to specific memory range by
- updating original EFI memory map.
- Region of memory which aa attribute is added to is
- from ss to ss+nn.
-
- If efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000
- is specified, EFI_MEMORY_MORE_RELIABLE(0x10000)
- attribute is added to range 0x100000000-0x180000000 and
- 0x10a0000000-0x1120000000.
-
- If efi_fake_mem=8G@9G:0x40000 is specified, the
- EFI_MEMORY_SP(0x40000) attribute is added to
- range 0x240000000-0x43fffffff.
-
- Using this parameter you can do debugging of EFI memmap
- related features. For example, you can do debugging of
- Address Range Mirroring feature even if your box
- doesn't support it, or mark specific memory as
- "soft reserved".
-
efivar_ssdt= [EFI; X86] Name of an EFI variable that contains an SSDT
that is to be dynamically loaded by Linux. If there are
multiple variables with the same name but with different
@@ -3404,10 +3387,6 @@
deep - Suspend-To-RAM or equivalent (if supported)
See Documentation/admin-guide/pm/sleep-states.rst.
- mfgpt_irq= [IA-32] Specify the IRQ to use for the
- Multi-Function General Purpose Timers on AMD Geode
- platforms.
-
mfgptfix [X86-32] Fix MFGPT timers on AMD Geode platforms when
the BIOS has incorrectly applied a workaround. TinyBIOS
version 0.98 is known to be affected, 0.99 fixes the
@@ -5015,6 +4994,14 @@
the ->nocb_bypass queue. The definition of "too
many" is supplied by this kernel boot parameter.
+ rcutree.nohz_full_patience_delay= [KNL]
+ On callback-offloaded (rcu_nocbs) CPUs, avoid
+ disturbing RCU unless the grace period has
+ reached the specified age in milliseconds.
+ Defaults to zero. Large values will be capped
+ at five seconds. All values will be rounded down
+ to the nearest value representable by jiffies.
+
rcutree.qhimark= [KNL]
Set threshold of queued RCU callbacks beyond which
batch limiting is disabled.
@@ -6117,9 +6104,15 @@
deployment of the HW BHI control and the SW BHB
clearing sequence.
- on - (default) Enable the HW or SW mitigation
- as needed.
- off - Disable the mitigation.
+ on - (default) Enable the HW or SW mitigation as
+ needed. This protects the kernel from
+ both syscalls and VMs.
+ vmexit - On systems which don't have the HW mitigation
+ available, enable the SW mitigation on vmexit
+ ONLY. On such systems, the host kernel is
+ protected from VM-originated BHI attacks, but
+ may still be vulnerable to syscall attacks.
+ off - Disable the mitigation.
spectre_v2= [X86,EARLY] Control mitigation of Spectre variant 2
(indirect branch speculation) vulnerability.
diff --git a/Documentation/arch/arm64/cpu-hotplug.rst b/Documentation/arch/arm64/cpu-hotplug.rst
new file mode 100644
index 000000000000..76ba8d932c72
--- /dev/null
+++ b/Documentation/arch/arm64/cpu-hotplug.rst
@@ -0,0 +1,79 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. _cpuhp_index:
+
+====================
+CPU Hotplug and ACPI
+====================
+
+CPU hotplug in the arm64 world is commonly used to describe the kernel taking
+CPUs online/offline using PSCI. This document is about ACPI firmware allowing
+CPUs that were not available during boot to be added to the system later.
+
+``possible`` and ``present`` refer to the state of the CPU as seen by linux.
+
+
+CPU Hotplug on physical systems - CPUs not present at boot
+----------------------------------------------------------
+
+Physical systems need to mark a CPU that is ``possible`` but not ``present`` as
+being ``present``. An example would be a dual socket machine, where the package
+in one of the sockets can be replaced while the system is running.
+
+This is not supported.
+
+In the arm64 world CPUs are not a single device but a slice of the system.
+There are no systems that support the physical addition (or removal) of CPUs
+while the system is running, and ACPI is not able to sufficiently describe
+them.
+
+e.g. New CPUs come with new caches, but the platform's cache toplogy is
+described in a static table, the PPTT. How caches are shared between CPUs is
+not discoverable, and must be described by firmware.
+
+e.g. The GIC redistributor for each CPU must be accessed by the driver during
+boot to discover the system wide supported features. ACPI's MADT GICC
+structures can describe a redistributor associated with a disabled CPU, but
+can't describe whether the redistributor is accessible, only that it is not
+'always on'.
+
+arm64's ACPI tables assume that everything described is ``present``.
+
+
+CPU Hotplug on virtual systems - CPUs not enabled at boot
+---------------------------------------------------------
+
+Virtual systems have the advantage that all the properties the system will
+ever have can be described at boot. There are no power-domain considerations
+as such devices are emulated.
+
+CPU Hotplug on virtual systems is supported. It is distinct from physical
+CPU Hotplug as all resources are described as ``present``, but CPUs may be
+marked as disabled by firmware. Only the CPU's online/offline behaviour is
+influenced by firmware. An example is where a virtual machine boots with a
+single CPU, and additional CPUs are added once a cloud orchestrator deploys
+the workload.
+
+For a virtual machine, the VMM (e.g. Qemu) plays the part of firmware.
+
+Virtual hotplug is implemented as a firmware policy affecting which CPUs can be
+brought online. Firmware can enforce its policy via PSCI's return codes. e.g.
+``DENIED``.
+
+The ACPI tables must describe all the resources of the virtual machine. CPUs
+that firmware wishes to disable either from boot (or later) should not be
+``enabled`` in the MADT GICC structures, but should have the ``online capable``
+bit set, to indicate they can be enabled later. The boot CPU must be marked as
+``enabled``. The 'always on' GICR structure must be used to describe the
+redistributors.
+
+CPUs described as ``online capable`` but not ``enabled`` can be set to enabled
+by the DSDT's Processor object's _STA method. On virtual systems the _STA method
+must always report the CPU as ``present``. Changes to the firmware policy can
+be notified to the OS via device-check or eject-request.
+
+CPUs described as ``enabled`` in the static table, should not have their _STA
+modified dynamically by firmware. Soft-restart features such as kexec will
+re-read the static properties of the system from these static tables, and
+may malfunction if these no longer describe the running system. Linux will
+re-discover the dynamic properties of the system from the _STA method later
+during boot.
diff --git a/Documentation/arch/arm64/index.rst b/Documentation/arch/arm64/index.rst
index d08e924204bf..78544de0a8a9 100644
--- a/Documentation/arch/arm64/index.rst
+++ b/Documentation/arch/arm64/index.rst
@@ -13,6 +13,7 @@ ARM64 Architecture
asymmetric-32bit
booting
cpu-feature-registers
+ cpu-hotplug
elf_hwcaps
hugetlbpage
kdump
diff --git a/Documentation/arch/arm64/memory.rst b/Documentation/arch/arm64/memory.rst
index 55a55f30eed8..8a658984b8bb 100644
--- a/Documentation/arch/arm64/memory.rst
+++ b/Documentation/arch/arm64/memory.rst
@@ -18,12 +18,10 @@ ARMv8.2 adds optional support for Large Virtual Address space. This is
only available when running with a 64KB page size and expands the
number of descriptors in the first level of translation.
-User addresses have bits 63:48 set to 0 while the kernel addresses have
-the same bits set to 1. TTBRx selection is given by bit 63 of the
-virtual address. The swapper_pg_dir contains only kernel (global)
-mappings while the user pgd contains only user (non-global) mappings.
-The swapper_pg_dir address is written to TTBR1 and never written to
-TTBR0.
+TTBRx selection is given by bit 55 of the virtual address. The
+swapper_pg_dir contains only kernel (global) mappings while the user pgd
+contains only user (non-global) mappings. The swapper_pg_dir address is
+written to TTBR1 and never written to TTBR0.
AArch64 Linux memory layout with 4KB pages + 4 levels (48-bit)::
@@ -65,14 +63,14 @@ Translation table lookup with 4KB pages::
+--------+--------+--------+--------+--------+--------+--------+--------+
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0|
+--------+--------+--------+--------+--------+--------+--------+--------+
- | | | | | |
- | | | | | v
- | | | | | [11:0] in-page offset
- | | | | +-> [20:12] L3 index
- | | | +-----------> [29:21] L2 index
- | | +---------------------> [38:30] L1 index
- | +-------------------------------> [47:39] L0 index
- +-------------------------------------------------> [63] TTBR0/1
+ | | | | | |
+ | | | | | v
+ | | | | | [11:0] in-page offset
+ | | | | +-> [20:12] L3 index
+ | | | +-----------> [29:21] L2 index
+ | | +---------------------> [38:30] L1 index
+ | +-------------------------------> [47:39] L0 index
+ +----------------------------------------> [55] TTBR0/1
Translation table lookup with 64KB pages::
@@ -80,14 +78,14 @@ Translation table lookup with 64KB pages::
+--------+--------+--------+--------+--------+--------+--------+--------+
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0|
+--------+--------+--------+--------+--------+--------+--------+--------+
- | | | | |
- | | | | v
- | | | | [15:0] in-page offset
- | | | +----------> [28:16] L3 index
- | | +--------------------------> [41:29] L2 index
- | +-------------------------------> [47:42] L1 index (48-bit)
- | [51:42] L1 index (52-bit)
- +-------------------------------------------------> [63] TTBR0/1
+ | | | | |
+ | | | | v
+ | | | | [15:0] in-page offset
+ | | | +----------> [28:16] L3 index
+ | | +--------------------------> [41:29] L2 index
+ | +-------------------------------> [47:42] L1 index (48-bit)
+ | [51:42] L1 index (52-bit)
+ +----------------------------------------> [55] TTBR0/1
When using KVM without the Virtualization Host Extensions, the
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index eb8af8032c31..bb83c5d8c675 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -132,16 +132,26 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A710 | #2224489 | ARM64_ERRATUM_2224489 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-A710 | #3324338 | ARM64_ERRATUM_3194386 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A715 | #2645198 | ARM64_ERRATUM_2645198 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-A720 | #3456091 | ARM64_ERRATUM_3194386 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X1 | #1502854 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X2 | #2119858 | ARM64_ERRATUM_2119858 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X2 | #2224489 | ARM64_ERRATUM_2224489 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-X2 | #3324338 | ARM64_ERRATUM_3194386 |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-X3 | #3324335 | ARM64_ERRATUM_3194386 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X4 | #3194386 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-X925 | #3324334 | ARM64_ERRATUM_3194386 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N1 | #1188873,1418040| ARM64_ERRATUM_1418040 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N1 | #1349291 | N/A |
@@ -156,9 +166,13 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N2 | #2253138 | ARM64_ERRATUM_2253138 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Neoverse-N2 | #3324339 | ARM64_ERRATUM_3194386 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-V1 | #1619801 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
-| ARM | Neoverse-V3 | #3312417 | ARM64_ERRATUM_3312417 |
+| ARM | Neoverse-V2 | #3324336 | ARM64_ERRATUM_3194386 |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM | Neoverse-V3 | #3312417 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | MMU-500 | #841119,826419 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
diff --git a/Documentation/arch/riscv/cmodx.rst b/Documentation/arch/riscv/cmodx.rst
index 1c0ca06b6c97..8c48bcff3df9 100644
--- a/Documentation/arch/riscv/cmodx.rst
+++ b/Documentation/arch/riscv/cmodx.rst
@@ -62,10 +62,10 @@ cmodx.c::
printf("Value before cmodx: %d\n", value);
// Call prctl before first fence.i is called inside modify_instruction
- prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX_ON, PR_RISCV_CTX_SW_FENCEI, PR_RISCV_SCOPE_PER_PROCESS);
+ prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX, PR_RISCV_CTX_SW_FENCEI_ON, PR_RISCV_SCOPE_PER_PROCESS);
modify_instruction();
// Call prctl after final fence.i is called in process
- prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX_OFF, PR_RISCV_CTX_SW_FENCEI, PR_RISCV_SCOPE_PER_PROCESS);
+ prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX, PR_RISCV_CTX_SW_FENCEI_OFF, PR_RISCV_SCOPE_PER_PROCESS);
value = get_value();
printf("Value after cmodx: %d\n", value);
diff --git a/Documentation/arch/x86/amd-memory-encryption.rst b/Documentation/arch/x86/amd-memory-encryption.rst
index 414bc7402ae7..6df3264f23b9 100644
--- a/Documentation/arch/x86/amd-memory-encryption.rst
+++ b/Documentation/arch/x86/amd-memory-encryption.rst
@@ -130,4 +130,31 @@ SNP feature support.
More details in AMD64 APM[1] Vol 2: 15.34.10 SEV_STATUS MSR
-[1] https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24593.pdf
+Secure VM Service Module (SVSM)
+===============================
+SNP provides a feature called Virtual Machine Privilege Levels (VMPL) which
+defines four privilege levels at which guest software can run. The most
+privileged level is 0 and numerically higher numbers have lesser privileges.
+More details in the AMD64 APM Vol 2, section "15.35.7 Virtual Machine
+Privilege Levels", docID: 24593.
+
+When using that feature, different services can run at different protection
+levels, apart from the guest OS but still within the secure SNP environment.
+They can provide services to the guest, like a vTPM, for example.
+
+When a guest is not running at VMPL0, it needs to communicate with the software
+running at VMPL0 to perform privileged operations or to interact with secure
+services. An example fur such a privileged operation is PVALIDATE which is
+*required* to be executed at VMPL0.
+
+In this scenario, the software running at VMPL0 is usually called a Secure VM
+Service Module (SVSM). Discovery of an SVSM and the API used to communicate
+with it is documented in "Secure VM Service Module for SEV-SNP Guests", docID:
+58019.
+
+(Latest versions of the above-mentioned documents can be found by using
+a search engine like duckduckgo.com and typing in:
+
+ site:amd.com "Secure VM Service Module for SEV-SNP Guests", docID: 58019
+
+for example.)
diff --git a/Documentation/arch/x86/resctrl.rst b/Documentation/arch/x86/resctrl.rst
index 627e23869bca..a824affd741d 100644
--- a/Documentation/arch/x86/resctrl.rst
+++ b/Documentation/arch/x86/resctrl.rst
@@ -375,6 +375,10 @@ When monitoring is enabled all MON groups will also contain:
all tasks in the group. In CTRL_MON groups these files provide
the sum for all tasks in the CTRL_MON group and all tasks in
MON groups. Please see example section for more details on usage.
+ On systems with Sub-NUMA Cluster (SNC) enabled there are extra
+ directories for each node (located within the "mon_L3_XX" directory
+ for the L3 cache they occupy). These are named "mon_sub_L3_YY"
+ where "YY" is the node number.
"mon_hw_id":
Available only with debug option. The identifier used by hardware
@@ -484,6 +488,29 @@ if non-contiguous 1s value is supported. On a system with a 20-bit mask
each bit represents 5% of the capacity of the cache. You could partition
the cache into four equal parts with masks: 0x1f, 0x3e0, 0x7c00, 0xf8000.
+Notes on Sub-NUMA Cluster mode
+==============================
+When SNC mode is enabled, Linux may load balance tasks between Sub-NUMA
+nodes much more readily than between regular NUMA nodes since the CPUs
+on Sub-NUMA nodes share the same L3 cache and the system may report
+the NUMA distance between Sub-NUMA nodes with a lower value than used
+for regular NUMA nodes.
+
+The top-level monitoring files in each "mon_L3_XX" directory provide
+the sum of data across all SNC nodes sharing an L3 cache instance.
+Users who bind tasks to the CPUs of a specific Sub-NUMA node can read
+the "llc_occupancy", "mbm_total_bytes", and "mbm_local_bytes" in the
+"mon_sub_L3_YY" directories to get node local data.
+
+Memory bandwidth allocation is still performed at the L3 cache
+level. I.e. throttling controls are applied to all SNC nodes.
+
+L3 cache allocation bitmaps also apply to all SNC nodes. But note that
+the amount of L3 cache represented by each bit is divided by the number
+of SNC nodes per L3 cache. E.g. with a 100MB cache on a system with 10-bit
+allocation masks each bit normally represents 10MB. With SNC mode enabled
+with two SNC nodes per L3 cache, each bit only represents 5MB.
+
Memory bandwidth Allocation and monitoring
==========================================
diff --git a/Documentation/block/data-integrity.rst b/Documentation/block/data-integrity.rst
index 6a760c0eb192..99905e880a0e 100644
--- a/Documentation/block/data-integrity.rst
+++ b/Documentation/block/data-integrity.rst
@@ -153,18 +153,11 @@ bio_free() will automatically free the bip.
4.2 Block Device
----------------
-Because the format of the protection data is tied to the physical
-disk, each block device has been extended with a block integrity
-profile (struct blk_integrity). This optional profile is registered
-with the block layer using blk_integrity_register().
-
-The profile contains callback functions for generating and verifying
-the protection data, as well as getting and setting application tags.
-The profile also contains a few constants to aid in completing,
-merging and splitting the integrity metadata.
+Block devices can set up the integrity information in the integrity
+sub-struture of the queue_limits structure.
Layered block devices will need to pick a profile that's appropriate
-for all subdevices. blk_integrity_compare() can help with that. DM
+for all subdevices. queue_limits_stack_integrity() can help with that. DM
and MD linear, RAID0 and RAID1 are currently supported. RAID4/5/6
will require extra work due to the application tag.
@@ -250,42 +243,6 @@ will require extra work due to the application tag.
integrity upon completion.
-5.4 Registering A Block Device As Capable Of Exchanging Integrity Metadata
---------------------------------------------------------------------------
-
- To enable integrity exchange on a block device the gendisk must be
- registered as capable:
-
- `int blk_integrity_register(gendisk, blk_integrity);`
-
- The blk_integrity struct is a template and should contain the
- following::
-
- static struct blk_integrity my_profile = {
- .name = "STANDARDSBODY-TYPE-VARIANT-CSUM",
- .generate_fn = my_generate_fn,
- .verify_fn = my_verify_fn,
- .tuple_size = sizeof(struct my_tuple_size),
- .tag_size = <tag bytes per hw sector>,
- };
-
- 'name' is a text string which will be visible in sysfs. This is
- part of the userland API so chose it carefully and never change
- it. The format is standards body-type-variant.
- E.g. T10-DIF-TYPE1-IP or T13-EPP-0-CRC.
-
- 'generate_fn' generates appropriate integrity metadata (for WRITE).
-
- 'verify_fn' verifies that the data buffer matches the integrity
- metadata.
-
- 'tuple_size' must be set to match the size of the integrity
- metadata per sector. I.e. 8 for DIF and EPP.
-
- 'tag_size' must be set to identify how many bytes of tag space
- are available per hardware sector. For DIF this is either 2 or
- 0 depending on the value of the Control Mode Page ATO bit.
-
----------------------------------------------------------------------
2007-12-24 Martin K. Petersen <[email protected]>
diff --git a/Documentation/block/writeback_cache_control.rst b/Documentation/block/writeback_cache_control.rst
index b208488d0aae..c3707d071780 100644
--- a/Documentation/block/writeback_cache_control.rst
+++ b/Documentation/block/writeback_cache_control.rst
@@ -46,41 +46,50 @@ worry if the underlying devices need any explicit cache flushing and how
the Forced Unit Access is implemented. The REQ_PREFLUSH and REQ_FUA flags
may both be set on a single bio.
+Feature settings for block drivers
+----------------------------------
-Implementation details for bio based block drivers
---------------------------------------------------------------
+For devices that do not support volatile write caches there is no driver
+support required, the block layer completes empty REQ_PREFLUSH requests before
+entering the driver and strips off the REQ_PREFLUSH and REQ_FUA bits from
+requests that have a payload.
-These drivers will always see the REQ_PREFLUSH and REQ_FUA bits as they sit
-directly below the submit_bio interface. For remapping drivers the REQ_FUA
-bits need to be propagated to underlying devices, and a global flush needs
-to be implemented for bios with the REQ_PREFLUSH bit set. For real device
-drivers that do not have a volatile cache the REQ_PREFLUSH and REQ_FUA bits
-on non-empty bios can simply be ignored, and REQ_PREFLUSH requests without
-data can be completed successfully without doing any work. Drivers for
-devices with volatile caches need to implement the support for these
-flags themselves without any help from the block layer.
+For devices with volatile write caches the driver needs to tell the block layer
+that it supports flushing caches by setting the
+ BLK_FEAT_WRITE_CACHE
-Implementation details for request_fn based block drivers
----------------------------------------------------------
+flag in the queue_limits feature field. For devices that also support the FUA
+bit the block layer needs to be told to pass on the REQ_FUA bit by also setting
+the
-For devices that do not support volatile write caches there is no driver
-support required, the block layer completes empty REQ_PREFLUSH requests before
-entering the driver and strips off the REQ_PREFLUSH and REQ_FUA bits from
-requests that have a payload. For devices with volatile write caches the
-driver needs to tell the block layer that it supports flushing caches by
-doing::
+ BLK_FEAT_FUA
+
+flag in the features field of the queue_limits structure.
+
+Implementation details for bio based block drivers
+--------------------------------------------------
+
+For bio based drivers the REQ_PREFLUSH and REQ_FUA bit are simply passed on to
+the driver if the driver sets the BLK_FEAT_WRITE_CACHE flag and the driver
+needs to handle them.
+
+*NOTE*: The REQ_FUA bit also gets passed on when the BLK_FEAT_FUA flags is
+_not_ set. Any bio based driver that sets BLK_FEAT_WRITE_CACHE also needs to
+handle REQ_FUA.
- blk_queue_write_cache(sdkp->disk->queue, true, false);
+For remapping drivers the REQ_FUA bits need to be propagated to underlying
+devices, and a global flush needs to be implemented for bios with the
+REQ_PREFLUSH bit set.
-and handle empty REQ_OP_FLUSH requests in its prep_fn/request_fn. Note that
-REQ_PREFLUSH requests with a payload are automatically turned into a sequence
-of an empty REQ_OP_FLUSH request followed by the actual write by the block
-layer. For devices that also support the FUA bit the block layer needs
-to be told to pass through the REQ_FUA bit using::
+Implementation details for blk-mq drivers
+-----------------------------------------
- blk_queue_write_cache(sdkp->disk->queue, true, true);
+When the BLK_FEAT_WRITE_CACHE flag is set, REQ_OP_WRITE | REQ_PREFLUSH requests
+with a payload are automatically turned into a sequence of a REQ_OP_FLUSH
+request followed by the actual write by the block layer.
-and the driver must handle write requests that have the REQ_FUA bit set
-in prep_fn/request_fn. If the FUA bit is not natively supported the block
-layer turns it into an empty REQ_OP_FLUSH request after the actual write.
+When the BLK_FEAT_FUA flags is set, the REQ_FUA bit is simply passed on for the
+REQ_OP_WRITE request, else a REQ_OP_FLUSH request is sent by the block layer
+after the completion of the write request for bio submissions with the REQ_FUA
+bit set.
diff --git a/Documentation/dev-tools/gpio-sloppy-logic-analyzer.rst b/Documentation/dev-tools/gpio-sloppy-logic-analyzer.rst
new file mode 100644
index 000000000000..d69f24c0d9e1
--- /dev/null
+++ b/Documentation/dev-tools/gpio-sloppy-logic-analyzer.rst
@@ -0,0 +1,93 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============================================
+Linux Kernel GPIO based sloppy logic analyzer
+=============================================
+
+:Author: Wolfram Sang
+
+Introduction
+============
+
+This document briefly describes how to run the GPIO based in-kernel sloppy
+logic analyzer running on an isolated CPU.
+
+The sloppy logic analyzer will utilize a few GPIO lines in input mode on a
+system to rapidly sample these digital lines, which will, if the Nyquist
+criteria is met, result in a time series log with approximate waveforms as they
+appeared on these lines. One way to use it is to analyze external traffic
+connected to these GPIO lines with wires (i.e. digital probes), acting as a
+common logic analyzer.
+
+Another feature is to snoop on on-chip peripherals if the I/O cells of these
+peripherals can be used in GPIO input mode at the same time as they are being
+used as inputs or outputs for the peripheral. That means you could e.g. snoop
+I2C traffic without any wiring (if your hardware supports it). In the pin
+control subsystem such pin controllers are called "non-strict": a certain pin
+can be used with a certain peripheral and as a GPIO input line at the same
+time.
+
+Note that this is a last resort analyzer which can be affected by latencies,
+non-deterministic code paths and non-maskable interrupts. It is called 'sloppy'
+for a reason. However, for e.g. remote development, it may be useful to get a
+first view and aid further debugging.
+
+Setup
+=====
+
+Your kernel must have CONFIG_DEBUG_FS and CONFIG_CPUSETS enabled. Ideally, your
+runtime environment does not utilize cpusets otherwise, then isolation of a CPU
+core is easiest. If you do need cpusets, check that helper script for the
+sloppy logic analyzer does not interfere with your other settings.
+
+Tell the kernel which GPIOs are used as probes. For a Device Tree based system,
+you need to use the following bindings. Because these bindings are only for
+debugging, there is no official schema::
+
+ i2c-analyzer {
+ compatible = "gpio-sloppy-logic-analyzer";
+ probe-gpios = <&gpio6 21 GPIO_OPEN_DRAIN>, <&gpio6 4 GPIO_OPEN_DRAIN>;
+ probe-names = "SCL", "SDA";
+ };
+
+Note that you must provide a name for every GPIO specified. Currently a
+maximum of 8 probes are supported. 32 are likely possible but are not
+implemented yet.
+
+Usage
+=====
+
+The logic analyzer is configurable via files in debugfs. However, it is
+strongly recommended to not use them directly, but to use the script
+``tools/gpio/gpio-sloppy-logic-analyzer``. Besides checking parameters more
+extensively, it will isolate the CPU core so you will have the least
+disturbance while measuring.
+
+The script has a help option explaining the parameters. For the above DT
+snippet which analyzes an I2C bus at 400kHz on a Renesas Salvator-XS board, the
+following settings are used: The isolated CPU shall be CPU1 because it is a big
+core in a big.LITTLE setup. Because CPU1 is the default, we don't need a
+parameter. The bus speed is 400kHz. So, the sampling theorem says we need to
+sample at least at 800kHz. However, falling edges of both signals in an I2C
+start condition happen faster, so we need a higher sampling frequency, e.g.
+``-s 1500000`` for 1.5MHz. Also, we don't want to sample right away but wait
+for a start condition on an idle bus. So, we need to set a trigger to a falling
+edge on SDA while SCL stays high, i.e. ``-t 1H+2F``. Last is the duration, let
+us assume 15ms here which results in the parameter ``-d 15000``. So,
+altogether::
+
+ gpio-sloppy-logic-analyzer -s 1500000 -t 1H+2F -d 15000
+
+Note that the process will return you back to the prompt but a sub-process is
+still sampling in the background. Unless this has finished, you will not find a
+result file in the current or specified directory. For the above example, we
+will then need to trigger I2C communication::
+
+ i2cdetect -y -r <your bus number>
+
+Result is a .sr file to be consumed with PulseView or sigrok-cli from the free
+`sigrok`_ project. It is a zip file which also contains the binary sample data
+which may be consumed by other software. The filename is the logic analyzer
+instance name plus a since-epoch timestamp.
+
+.. _sigrok: https://sigrok.org/
diff --git a/Documentation/dev-tools/index.rst b/Documentation/dev-tools/index.rst
index efa49cdc8e2e..6971ed581c08 100644
--- a/Documentation/dev-tools/index.rst
+++ b/Documentation/dev-tools/index.rst
@@ -32,6 +32,7 @@ Documentation/dev-tools/testing-overview.rst
kunit/index
ktap
checkuapi
+ gpio-sloppy-logic-analyzer
.. only:: subproject and html
diff --git a/Documentation/devicetree/bindings/arm/airoha.yaml b/Documentation/devicetree/bindings/arm/airoha.yaml
index 3292c669ee11..7c38c08dbf3f 100644
--- a/Documentation/devicetree/bindings/arm/airoha.yaml
+++ b/Documentation/devicetree/bindings/arm/airoha.yaml
@@ -22,6 +22,10 @@ properties:
- enum:
- airoha,en7523-evb
- const: airoha,en7523
+ - items:
+ - enum:
+ - airoha,en7581-evb
+ - const: airoha,en7581
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index a374b98080fe..0647851ae1f5 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -91,6 +91,7 @@ properties:
- libretech,aml-s905x-cc
- libretech,aml-s905x-cc-v2
- nexbox,a95x
+ - osmc,vero4k
- const: amlogic,s905x
- const: amlogic,meson-gxl
@@ -107,6 +108,13 @@ properties:
- const: amlogic,s905d
- const: amlogic,meson-gxl
+ - description: Boards with the Amlogic Meson GXLX S905L SoC
+ items:
+ - enum:
+ - amlogic,p271
+ - const: amlogic,s905l
+ - const: amlogic,meson-gxlx
+
- description: Boards with the Amlogic Meson GXM S912 SoC
items:
- enum:
@@ -169,6 +177,8 @@ properties:
- azw,gtking
- azw,gtking-pro
- bananapi,bpi-m2s
+ - dream,dreambox-one
+ - dream,dreambox-two
- hardkernel,odroid-go-ultra
- hardkernel,odroid-n2
- hardkernel,odroid-n2l
diff --git a/Documentation/devicetree/bindings/arm/arm,juno-fpga-apb-regs.yaml b/Documentation/devicetree/bindings/arm/arm,juno-fpga-apb-regs.yaml
new file mode 100644
index 000000000000..ce5f2e1ec1ea
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,juno-fpga-apb-regs.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/arm,juno-fpga-apb-regs.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ARM Juno FPGA APB Registers
+
+maintainers:
+ - Sudeep Holla <[email protected]>
+
+properties:
+ compatible:
+ items:
+ - const: arm,juno-fpga-apb-regs
+ - const: syscon
+ - const: simple-mfd
+
+ reg:
+ maxItems: 1
+
+ ranges: true
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+patternProperties:
+ "^led@[0-9a-f]+,[0-9a-f]$":
+ $ref: /schemas/leds/register-bit-led.yaml#
+
+required:
+ - compatible
+ - reg
+ - ranges
+ - "#address-cells"
+ - "#size-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ syscon@10000 {
+ compatible = "arm,juno-fpga-apb-regs", "syscon", "simple-mfd";
+ reg = <0x010000 0x1000>;
+ ranges = <0x0 0x10000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ led@8,0 {
+ compatible = "register-bit-led";
+ reg = <0x08 0x04>;
+ offset = <0x08>;
+ mask = <0x01>;
+ label = "vexpress:0";
+ linux,default-trigger = "heartbeat";
+ default-state = "on";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/arm/bcm/bcm2835.yaml b/Documentation/devicetree/bindings/arm/bcm/bcm2835.yaml
index 162a39dab218..e4ff71f006b8 100644
--- a/Documentation/devicetree/bindings/arm/bcm/bcm2835.yaml
+++ b/Documentation/devicetree/bindings/arm/bcm/bcm2835.yaml
@@ -23,6 +23,12 @@ properties:
- raspberrypi,4-model-b
- const: brcm,bcm2711
+ - description: BCM2712 based Boards
+ items:
+ - enum:
+ - raspberrypi,5-model-b
+ - const: brcm,bcm2712
+
- description: BCM2835 based Boards
items:
- enum:
diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 6d185d09cb6a..80747d79418a 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -8,7 +8,6 @@ title: Freescale i.MX Platforms
maintainers:
- Shawn Guo <[email protected]>
- - Li Yang <[email protected]>
properties:
$nodename:
@@ -363,6 +362,12 @@ properties:
- const: gw,ventana
- const: fsl,imx6q
+ - description: i.MX6Q Kontron SMARC-sAMX6i on SMARC Eval Carrier 2.0
+ items:
+ - const: kontron,imx6q-samx6i-ads2
+ - const: kontron,imx6q-samx6i
+ - const: fsl,imx6q
+
- description: i.MX6Q PHYTEC phyBOARD-Mira
items:
- enum:
@@ -544,6 +549,12 @@ properties:
- const: gw,ventana
- const: fsl,imx6dl
+ - description: i.MX6DL Kontron SMARC-sAMX6i on SMARC Eval Carrier 2.0
+ items:
+ - const: kontron,imx6dl-samx6i-ads2
+ - const: kontron,imx6dl-samx6i
+ - const: fsl,imx6dl
+
- description: i.MX6DL PHYTEC phyBOARD-Mira
items:
- enum:
@@ -946,6 +957,13 @@ properties:
- prt,prt8mm # i.MX8MM Protonic PRT8MM Board
- const: fsl,imx8mm
+ - description: Compulab i.MX8MM UCM SoM based boards
+ items:
+ - enum:
+ - compulab,imx8mm-iot-gateway # i.MX8MM Compulab IoT-Gateway
+ - const: compulab,imx8mm-ucm-som # i.MX8MM Compulab UCM SoM
+ - const: fsl,imx8mm
+
- description: Emtop i.MX8MM based Boards
items:
- const: ees,imx8mm-emtop-baseboard # i.MX8MM Emtop SoM on i.MX8M Mini Baseboard V1
@@ -1145,8 +1163,9 @@ properties:
version as an industrial computing device.
items:
- enum:
- - tq,imx8mp-tqma8mpql-mba8mpxl # TQ-Systems GmbH i.MX8MP TQMa8MPQL SOM on MBa8MPxL
- - const: tq,imx8mp-tqma8mpql # TQ-Systems GmbH i.MX8MP TQMa8MPQL SOM
+ - tq,imx8mp-tqma8mpql-mba8mpxl # TQ-Systems GmbH i.MX8MP TQMa8MPQL SOM on MBa8MPxL
+ - tq,imx8mp-tqma8mpql-mba8mp-ras314 # TQ-Systems GmbH i.MX8MP TQMa8MPQL SOM on MBa8MP-RAS314
+ - const: tq,imx8mp-tqma8mpql # TQ-Systems GmbH i.MX8MP TQMa8MPQL SOM
- const: fsl,imx8mp
- description: i.MX8MQ based Boards
@@ -1272,9 +1291,16 @@ properties:
- description: i.MX93 based Boards
items:
- enum:
+ - fsl,imx93-9x9-qsb # i.MX93 9x9 QSB Board
- fsl,imx93-11x11-evk # i.MX93 11x11 EVK Board
- const: fsl,imx93
+ - description: i.MX95 based Boards
+ items:
+ - enum:
+ - fsl,imx95-19x19-evk # i.MX95 19x19 EVK Board
+ - const: fsl,imx95
+
- description: i.MXRT1050 based Boards
items:
- enum:
diff --git a/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml b/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml
index 7f06b1080244..25a2b42105e5 100644
--- a/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml
+++ b/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml
@@ -20,7 +20,7 @@ description: |
initialized early into boot process and provides services to Operating Systems
on multiple processors including ones running Linux.
- See http://processors.wiki.ti.com/index.php/TISCI for protocol definition.
+ See https://software-dl.ti.com/tisci/esd/latest/index.html for protocol definition.
The TI-SCI node describes the Texas Instrument's System Controller entity node.
This parent node may optionally have additional children nodes which describe
diff --git a/Documentation/devicetree/bindings/arm/marvell/armada-7k-8k.yaml b/Documentation/devicetree/bindings/arm/marvell/armada-7k-8k.yaml
index 16d2e132d3d1..538d91be8857 100644
--- a/Documentation/devicetree/bindings/arm/marvell/armada-7k-8k.yaml
+++ b/Documentation/devicetree/bindings/arm/marvell/armada-7k-8k.yaml
@@ -82,4 +82,22 @@ properties:
- const: marvell,armada-ap807-quad
- const: marvell,armada-ap807
+ - description:
+ SolidRun CN9130 SoM based single-board computers
+ items:
+ - enum:
+ - solidrun,cn9130-clearfog-base
+ - solidrun,cn9130-clearfog-pro
+ - solidrun,cn9131-solidwan
+ - const: solidrun,cn9130-sr-som
+ - const: marvell,cn9130
+
+ - description:
+ SolidRun CN9132 COM-Express Type 7 based single-board computers
+ items:
+ - enum:
+ - solidrun,cn9132-clearfog
+ - const: solidrun,cn9132-sr-cex7
+ - const: marvell,cn9130
+
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/arm/mediatek.yaml b/Documentation/devicetree/bindings/arm/mediatek.yaml
index 09f9ffd3ff7b..1d4bb50fcd8d 100644
--- a/Documentation/devicetree/bindings/arm/mediatek.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek.yaml
@@ -85,12 +85,15 @@ properties:
- const: mediatek,mt7629
- items:
- enum:
+ - cudy,wr3000-v1
+ - openwrt,one
- xiaomi,ax3000t
- const: mediatek,mt7981b
- items:
- enum:
- acelink,ew-7886cax
- bananapi,bpi-r3
+ - bananapi,bpi-r3mini
- mediatek,mt7986a-rfb
- const: mediatek,mt7986a
- items:
@@ -293,6 +296,13 @@ properties:
- const: google,tentacruel-sku327683
- const: google,tentacruel
- const: mediatek,mt8186
+ - description: Google Voltorb (Acer Chromebook 311 C723/C732T)
+ items:
+ - enum:
+ - google,voltorb-sku589824
+ - google,voltorb-sku589825
+ - const: google,voltorb
+ - const: mediatek,mt8186
- items:
- enum:
- mediatek,mt8186-evb
@@ -342,6 +352,14 @@ properties:
- const: google,tomato-rev3
- const: google,tomato
- const: mediatek,mt8195
+ - description: HP Dojo sku1, 3, 5, 7 (HP Chromebook x360 13b-ca0002sa)
+ items:
+ - const: google,dojo-sku7
+ - const: google,dojo-sku5
+ - const: google,dojo-sku3
+ - const: google,dojo-sku1
+ - const: google,dojo
+ - const: mediatek,mt8195
- items:
- enum:
- mediatek,mt8195-demo
@@ -353,6 +371,12 @@ properties:
- const: mediatek,mt8365
- items:
- enum:
+ - mediatek,mt8390-evk
+ - const: mediatek,mt8390
+ - const: mediatek,mt8188
+ - items:
+ - enum:
+ - kontron,3-5-sbc-i1200
- mediatek,mt8395-evk
- radxa,nio-12l
- const: mediatek,mt8395
diff --git a/Documentation/devicetree/bindings/arm/pmu.yaml b/Documentation/devicetree/bindings/arm/pmu.yaml
index 99b5e9530707..528544d0a161 100644
--- a/Documentation/devicetree/bindings/arm/pmu.yaml
+++ b/Documentation/devicetree/bindings/arm/pmu.yaml
@@ -53,14 +53,20 @@ properties:
- arm,cortex-a710-pmu
- arm,cortex-a715-pmu
- arm,cortex-a720-pmu
+ - arm,cortex-a725-pmu
- arm,cortex-x1-pmu
- arm,cortex-x2-pmu
- arm,cortex-x3-pmu
- arm,cortex-x4-pmu
+ - arm,cortex-x925-pmu
- arm,neoverse-e1-pmu
- arm,neoverse-n1-pmu
- arm,neoverse-n2-pmu
+ - arm,neoverse-n3-pmu
- arm,neoverse-v1-pmu
+ - arm,neoverse-v2-pmu
+ - arm,neoverse-v3-pmu
+ - arm,neoverse-v3ae-pmu
- brcm,vulcan-pmu
- cavium,thunder-pmu
- nvidia,denver-pmu
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index ae885414b181..f08e13b61172 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -42,6 +42,7 @@ description: |
msm8996
msm8998
qcs404
+ qcs8550
qcm2290
qcm6490
qdu1000
@@ -96,6 +97,7 @@ properties:
- items:
- enum:
- qcom,apq8016-sbc
+ - schneider,apq8016-hmibsc
- const: qcom,apq8016
- items:
@@ -104,6 +106,7 @@ properties:
- huawei,sturgeon
- lg,lenok
- samsung,matisse-wifi
+ - samsung,milletwifi
- const: qcom,apq8026
- items:
@@ -138,6 +141,7 @@ properties:
- microsoft,makepeace
- microsoft,moneypenny
- motorola,falcon
+ - samsung,ms013g
- samsung,s3ve3g
- const: qcom,msm8226
@@ -175,6 +179,7 @@ properties:
- items:
- enum:
- lge,hammerhead
+ - samsung,hlte
- sony,xperia-amami
- sony,xperia-honami
- const: qcom,msm8974
@@ -182,8 +187,10 @@ properties:
- items:
- enum:
- fairphone,fp2
+ - htc,m8
- oneplus,bacon
- samsung,klte
+ - sony,xperia-aries
- sony,xperia-castor
- sony,xperia-leo
- const: qcom,msm8974pro
@@ -203,8 +210,13 @@ properties:
- asus,z00l
- gplus,fl8005a
- huawei,g7
+ - lg,c50
+ - lg,m216
- longcheer,l8910
- longcheer,l8150
+ - motorola,harpia
+ - motorola,osprey
+ - motorola,surnia
- qcom,msm8916-mtp
- samsung,a3u-eur
- samsung,a5u-eur
@@ -316,6 +328,7 @@ properties:
- items:
- enum:
- qcom,ipq5018-rdp432-c2
+ - tplink,archer-ax55-v1
- const: qcom,ipq5018
- items:
@@ -366,6 +379,7 @@ properties:
- fairphone,fp5
- qcom,qcm6490-idp
- qcom,qcs6490-rb3gen2
+ - shift,otter
- const: qcom,qcm6490
- description: Qualcomm Technologies, Inc. Distributed Unit 1000 platform
@@ -802,6 +816,7 @@ properties:
- items:
- enum:
+ - lenovo,tbx605f
- motorola,ali
- const: qcom,sdm450
@@ -883,6 +898,7 @@ properties:
- items:
- enum:
- qcom,sa8775p-ride
+ - qcom,sa8775p-ride-r3
- const: qcom,sa8775p
- items:
@@ -1004,17 +1020,28 @@ properties:
- qcom,sm8550-hdk
- qcom,sm8550-mtp
- qcom,sm8550-qrd
+ - samsung,q5q
- sony,pdx234
- const: qcom,sm8550
- items:
- enum:
+ - qcom,qcs8550-aim300-aiot
+ - const: qcom,qcs8550-aim300
+ - const: qcom,qcs8550
+ - const: qcom,sm8550
+
+ - items:
+ - enum:
+ - qcom,sm8650-hdk
- qcom,sm8650-mtp
- qcom,sm8650-qrd
- const: qcom,sm8650
- items:
- enum:
+ - asus,vivobook-s15
+ - lenovo,yoga-slim7x
- qcom,x1e80100-crd
- qcom,x1e80100-qcp
- const: qcom,x1e80100
diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
index e04c213a0dee..1ef09fbfdfaf 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
+++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
@@ -248,6 +248,13 @@ properties:
- const: friendlyarm,nanopc-t6
- const: rockchip,rk3588
+ - description: FriendlyElec CM3588-based boards
+ items:
+ - enum:
+ - friendlyarm,cm3588-nas
+ - const: friendlyarm,cm3588
+ - const: rockchip,rk3588
+
- description: GameForce Chi
items:
- const: gameforce,chi
@@ -627,6 +634,11 @@ properties:
- const: mqmaker,miqi
- const: rockchip,rk3288
+ - description: Neardi LBA3368
+ items:
+ - const: neardi,lba3368
+ - const: rockchip,rk3368
+
- description: Netxeon R89 board
items:
- const: netxeon,r89
@@ -799,11 +811,21 @@ properties:
- const: radxa,rock3a
- const: rockchip,rk3568
+ - description: Radxa ROCK 3B
+ items:
+ - const: radxa,rock-3b
+ - const: rockchip,rk3568
+
- description: Radxa ROCK 3C
items:
- const: radxa,rock-3c
- const: rockchip,rk3566
+ - description: Radxa ROCK 5 ITX
+ items:
+ - const: radxa,rock-5-itx
+ - const: rockchip,rk3588
+
- description: Radxa ROCK 5A
items:
- const: radxa,rock-5a
@@ -814,6 +836,18 @@ properties:
- const: radxa,rock-5b
- const: rockchip,rk3588
+ - description: Radxa ROCK S0
+ items:
+ - const: radxa,rock-s0
+ - const: rockchip,rk3308
+
+ - description: Radxa ZERO 3W/3E
+ items:
+ - enum:
+ - radxa,zero-3e
+ - radxa,zero-3w
+ - const: rockchip,rk3566
+
- description: Rikomagic MK808 v1
items:
- const: rikomagic,mk808
@@ -959,6 +993,14 @@ properties:
- const: wolfvision,rk3568-pf5
- const: rockchip,rk3568
+ - description: Xunlong Orange Pi 3B
+ items:
+ - enum:
+ - xunlong,orangepi-3b-v1.1
+ - xunlong,orangepi-3b-v2.1
+ - const: xunlong,orangepi-3b
+ - const: rockchip,rk3566
+
- description: Xunlong Orange Pi 5 Plus
items:
- const: xunlong,orangepi-5-plus
diff --git a/Documentation/devicetree/bindings/arm/rtsm-dcscb.txt b/Documentation/devicetree/bindings/arm/rtsm-dcscb.txt
deleted file mode 100644
index 3b8fbf3c00c5..000000000000
--- a/Documentation/devicetree/bindings/arm/rtsm-dcscb.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-ARM Dual Cluster System Configuration Block
--------------------------------------------
-
-The Dual Cluster System Configuration Block (DCSCB) provides basic
-functionality for controlling clocks, resets and configuration pins in
-the Dual Cluster System implemented by the Real-Time System Model (RTSM).
-
-Required properties:
-
-- compatible : should be "arm,rtsm,dcscb"
-
-- reg : physical base address and the size of the registers window
-
-Example:
-
- dcscb@60000000 {
- compatible = "arm,rtsm,dcscb";
- reg = <0x60000000 0x1000>;
- };
diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
index bc2f43330ae4..58099949e8f3 100644
--- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
@@ -59,6 +59,12 @@ properties:
- prt,prtt1s # Protonic PRTT1S
- const: st,stm32mp151
+ - description: DH STM32MP135 DHCOR SoM based Boards
+ items:
+ - const: dh,stm32mp135f-dhcor-dhsbc
+ - const: dh,stm32mp135f-dhcor-som
+ - const: st,stm32mp135
+
- description: DH STM32MP151 DHCOR SoM based Boards
items:
- const: dh,stm32mp151a-dhcor-testbench
diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index c2a158b75e49..09dc6f424986 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -708,12 +708,12 @@ properties:
- const: olimex,a64-teres-i
- const: allwinner,sun50i-a64
- - description: Pine64
+ - description: Pine64 PINE A64
items:
- const: pine64,pine64
- const: allwinner,sun50i-a64
- - description: Pine64+
+ - description: Pine64 PINE A64+
items:
- const: pine64,pine64-plus
- const: allwinner,sun50i-a64
@@ -724,17 +724,17 @@ properties:
- const: sochip,s3
- const: allwinner,sun8i-v3
- - description: Pine64 PineH64 model A
+ - description: Pine64 PINE H64 Model A
items:
- const: pine64,pine-h64
- const: allwinner,sun50i-h6
- - description: Pine64 PineH64 model B
+ - description: Pine64 PINE H64 Model B
items:
- const: pine64,pine-h64-model-b
- const: allwinner,sun50i-h6
- - description: Pine64 LTS
+ - description: Pine64 PINE A64 LTS
items:
- const: pine64,pine64-lts
- const: allwinner,sun50i-r18
@@ -763,17 +763,17 @@ properties:
- const: pine64,pinephone
- const: allwinner,sun50i-a64
- - description: Pine64 PineTab, Development Sample
+ - description: Pine64 PineTab Developer Sample
items:
- const: pine64,pinetab
- const: allwinner,sun50i-a64
- - description: Pine64 PineTab, Early Adopter's batch (and maybe later ones)
+ - description: Pine64 PineTab Early Adopter
items:
- const: pine64,pinetab-early-adopter
- const: allwinner,sun50i-a64
- - description: Pine64 SoPine Baseboard
+ - description: Pine64 SOPINE
items:
- const: pine64,sopine-baseboard
- const: pine64,sopine
diff --git a/Documentation/devicetree/bindings/arm/ti/k3.yaml b/Documentation/devicetree/bindings/arm/ti/k3.yaml
index 52b51fd7044e..4d9c5fbb4c26 100644
--- a/Documentation/devicetree/bindings/arm/ti/k3.yaml
+++ b/Documentation/devicetree/bindings/arm/ti/k3.yaml
@@ -25,6 +25,12 @@ properties:
- ti,am62a7-sk
- const: ti,am62a7
+ - description: K3 AM62A7 SoC PHYTEC phyBOARD-Lyra
+ items:
+ - const: phytec,am62a7-phyboard-lyra-rdk
+ - const: phytec,am62a-phycore-som
+ - const: ti,am62a7
+
- description: K3 AM62P5 SoC and Boards
items:
- enum:
diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml
index 07ccbda4a0ab..68ea5f70b75f 100644
--- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml
+++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml
@@ -21,6 +21,7 @@ properties:
compatible:
enum:
- qcom,qdu1000-llcc
+ - qcom,sa8775p-llcc
- qcom,sc7180-llcc
- qcom,sc7280-llcc
- qcom,sc8180x-llcc
@@ -66,7 +67,6 @@ allOf:
compatible:
contains:
enum:
- - qcom,qdu1000-llcc
- qcom,sc7180-llcc
- qcom,sm6350-llcc
then:
@@ -85,6 +85,33 @@ allOf:
compatible:
contains:
enum:
+ - qcom,sa8775p-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: 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: llcc_broadcast_base
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,sc7280-llcc
then:
properties:
@@ -104,6 +131,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,qdu1000-llcc
- qcom,sc8180x-llcc
- qcom,sc8280xp-llcc
- qcom,x1e80100-llcc
@@ -141,8 +169,31 @@ allOf:
- qcom,sm8150-llcc
- qcom,sm8250-llcc
- qcom,sm8350-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: LLCC broadcast base register region
+ reg-names:
+ items:
+ - const: llcc0_base
+ - const: llcc1_base
+ - const: llcc2_base
+ - const: llcc3_base
+ - const: llcc_broadcast_base
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,sm8450-llcc
- qcom,sm8550-llcc
+ - qcom,sm8650-llcc
then:
properties:
reg:
@@ -151,7 +202,8 @@ allOf:
- description: LLCC1 base register region
- description: LLCC2 base register region
- description: LLCC3 base register region
- - description: LLCC broadcast base register region
+ - description: LLCC broadcast OR register region
+ - description: LLCC broadcast AND register region
reg-names:
items:
- const: llcc0_base
@@ -159,6 +211,7 @@ allOf:
- const: llcc2_base
- const: llcc3_base
- const: llcc_broadcast_base
+ - const: llcc_broadcast_and_base
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/cache/starfive,jh8100-starlink-cache.yaml b/Documentation/devicetree/bindings/cache/starfive,jh8100-starlink-cache.yaml
new file mode 100644
index 000000000000..6d61098e388b
--- /dev/null
+++ b/Documentation/devicetree/bindings/cache/starfive,jh8100-starlink-cache.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/cache/starfive,jh8100-starlink-cache.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive StarLink Cache Controller
+
+maintainers:
+ - Joshua Yeong <[email protected]>
+
+description:
+ StarFive's StarLink Cache Controller manages the L3 cache shared between
+ clusters of CPU cores. The cache driver enables RISC-V non-standard cache
+ management as an alternative to instructions in the RISC-V Zicbom extension.
+
+allOf:
+ - $ref: /schemas/cache-controller.yaml#
+
+# We need a select here so we don't match all nodes with 'cache'
+select:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - starfive,jh8100-starlink-cache
+
+ required:
+ - compatible
+
+properties:
+ compatible:
+ items:
+ - const: starfive,jh8100-starlink-cache
+ - const: cache
+
+ reg:
+ maxItems: 1
+
+unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - cache-block-size
+ - cache-level
+ - cache-sets
+ - cache-size
+ - cache-unified
+
+examples:
+ - |
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cache-controller@15000000 {
+ compatible = "starfive,jh8100-starlink-cache", "cache";
+ reg = <0x0 0x15000000 0x0 0x278>;
+ cache-block-size = <64>;
+ cache-level = <3>;
+ cache-sets = <8192>;
+ cache-size = <0x400000>;
+ cache-unified;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml
index 944a0ea79cd6..824781cbdf34 100644
--- a/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml
@@ -33,6 +33,9 @@ properties:
- description: PCIE30 PHY3 pipe clock source
- description: USB3 PHY pipe clock source
+ '#interconnect-cells':
+ const: 1
+
required:
- compatible
- clocks
diff --git a/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml
new file mode 100644
index 000000000000..734880805c1b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,qcm2290-gpucc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Graphics Clock & Reset Controller on QCM2290
+
+maintainers:
+ - Konrad Dybcio <[email protected]>
+
+description: |
+ Qualcomm graphics clock control module provides the clocks, resets and power
+ domains on Qualcomm SoCs.
+
+ See also::
+ include/dt-bindings/clock/qcom,qcm2290-gpucc.h
+
+properties:
+ compatible:
+ const: qcom,qcm2290-gpucc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: AHB interface clock,
+ - description: SoC CXO clock
+ - description: GPLL0 main branch source
+ - description: GPLL0 div branch source
+
+ power-domains:
+ description:
+ A phandle and PM domain specifier for the CX power domain.
+ maxItems: 1
+
+ required-opps:
+ description:
+ A phandle to an OPP node describing required CX performance point.
+ maxItems: 1
+
+required:
+ - compatible
+ - clocks
+ - power-domains
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-qcm2290.h>
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clock-controller@5990000 {
+ compatible = "qcom,qcm2290-gpucc";
+ reg = <0x0 0x05990000 0x0 0x9000>;
+ clocks = <&gcc GCC_GPU_CFG_AHB_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>;
+ power-domains = <&rpmpd QCM2290_VDDCX>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ #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 fa0e5b6b02b8..f58edfc10f4c 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
@@ -8,15 +8,17 @@ title: Qualcomm Camera Clock & Reset Controller on SM8450
maintainers:
- Vladimir Zapolskiy <[email protected]>
+ - Jagadeesh Kona <[email protected]>
description: |
Qualcomm camera clock control module provides the clocks, resets and power
domains on SM8450.
- See also::
+ See also:
+ include/dt-bindings/clock/qcom,sc8280xp-camcc.h
include/dt-bindings/clock/qcom,sm8450-camcc.h
include/dt-bindings/clock/qcom,sm8550-camcc.h
- include/dt-bindings/clock/qcom,sc8280xp-camcc.h
+ include/dt-bindings/clock/qcom,sm8650-camcc.h
include/dt-bindings/clock/qcom,x1e80100-camcc.h
allOf:
@@ -28,6 +30,7 @@ properties:
- qcom,sc8280xp-camcc
- qcom,sm8450-camcc
- qcom,sm8550-camcc
+ - qcom,sm8650-camcc
- qcom,x1e80100-camcc
clocks:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml
index bad8f019a8d3..8ce5972a65d5 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml
@@ -8,18 +8,22 @@ title: Qualcomm Video Clock & Reset Controller on SM8450
maintainers:
- Taniya Das <[email protected]>
+ - Jagadeesh Kona <[email protected]>
description: |
Qualcomm video clock control module provides the clocks, resets and power
domains on SM8450.
- See also:: include/dt-bindings/clock/qcom,videocc-sm8450.h
+ See also:
+ include/dt-bindings/clock/qcom,sm8450-videocc.h
+ include/dt-bindings/clock/qcom,sm8650-videocc.h
properties:
compatible:
enum:
- qcom,sm8450-videocc
- qcom,sm8550-videocc
+ - qcom,sm8650-videocc
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/clock/ti,sci-clk.yaml b/Documentation/devicetree/bindings/clock/ti,sci-clk.yaml
index 0a9d6a4c4b66..66e8e66ca175 100644
--- a/Documentation/devicetree/bindings/clock/ti,sci-clk.yaml
+++ b/Documentation/devicetree/bindings/clock/ti,sci-clk.yaml
@@ -36,7 +36,7 @@ properties:
The second cell should contain the clock ID.
- Please see http://processors.wiki.ti.com/index.php/TISCI for
+ Please see https://software-dl.ti.com/tisci/esd/latest/index.html for
protocol documentation for the values to be used for different devices.
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
index 7de2c29606e5..308af58180d1 100644
--- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
+++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
@@ -72,14 +72,17 @@ properties:
- const: tx
- const: tx_reply
- const: rx
+ - const: rx_reply
minItems: 2
mboxes:
description:
List of phandle and mailbox channel specifiers. It should contain
- exactly one, two or three mailboxes; the first one or two for transmitting
- messages ("tx") and another optional ("rx") for receiving notifications
- and delayed responses, if supported by the platform.
+ exactly one, two, three or four mailboxes; the first one or two for
+ transmitting messages ("tx") and another optional ("rx") for receiving
+ notifications and delayed responses, if supported by the platform.
+ The optional ("rx_reply") is for notifications completion interrupt,
+ if supported by the platform.
The number of mailboxes needed for transmitting messages depends on the
type of channels exposed by the specific underlying mailbox controller;
one single channel descriptor is enough if such channel is bidirectional,
@@ -92,9 +95,10 @@ properties:
2 mbox / 2 shmem => SCMI TX and RX over 2 mailbox bidirectional channels
2 mbox / 1 shmem => SCMI TX over 2 mailbox unidirectional channels
3 mbox / 2 shmem => SCMI TX and RX over 3 mailbox unidirectional channels
+ 4 mbox / 2 shmem => SCMI TX and RX over 4 mailbox unidirectional channels
Any other combination of mboxes and shmem is invalid.
minItems: 1
- maxItems: 3
+ maxItems: 4
shmem:
description:
diff --git a/Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml b/Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml
new file mode 100644
index 000000000000..af9249695ef5
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/firmware/cznic,turris-omnia-mcu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: CZ.NIC's Turris Omnia MCU
+
+maintainers:
+ - Marek Behún <[email protected]>
+
+description:
+ The MCU on Turris Omnia acts as a system controller providing additional
+ GPIOs, interrupts, watchdog, system power off and wakeup configuration.
+
+properties:
+ compatible:
+ const: cznic,turris-omnia-mcu
+
+ reg:
+ description: MCU I2C slave address
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+ description: |
+ The first cell specifies the interrupt number (0 to 63), the second cell
+ specifies interrupt type (which can be one of IRQ_TYPE_EDGE_RISING,
+ IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH).
+ The interrupt numbers correspond sequentially to GPIO numbers, taking the
+ GPIO banks into account:
+ IRQ number GPIO bank GPIO pin within bank
+ 0 - 15 0 0 - 15
+ 16 - 47 1 0 - 31
+ 48 - 63 2 0 - 15
+ There are several exceptions:
+ IRQ number meaning
+ 11 LED panel brightness changed by button press
+ 13 TRNG entropy ready
+ 14 ECDSA message signature computation done
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 3
+ description:
+ The first cell is bank number (0, 1 or 2), the second cell is pin number
+ within the bank (0 to 15 for banks 0 and 2, 0 to 31 for bank 1), and the
+ third cell specifies consumer flags.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-controller
+ - gpio-controller
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ system-controller@2a {
+ compatible = "cznic,turris-omnia-mcu";
+ reg = <0x2a>;
+
+ interrupt-parent = <&gpio1>;
+ interrupts = <11 IRQ_TYPE_NONE>;
+
+ gpio-controller;
+ #gpio-cells = <3>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
index 47d3d2d52acd..2cc83771d8e7 100644
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
@@ -93,6 +93,11 @@ properties:
protocol to handle sleeping SCM calls.
maxItems: 1
+ memory-region:
+ description:
+ Phandle to the memory region reserved for the shared memory bridge to TZ.
+ maxItems: 1
+
qcom,sdi-enabled:
description:
Indicates that the SDI (Secure Debug Image) has been enabled by TZ
@@ -193,6 +198,16 @@ allOf:
then:
properties:
interrupts: false
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,scm-sa8775p
+ then:
+ properties:
+ memory-region: false
required:
- compatible
diff --git a/Documentation/devicetree/bindings/fuse/renesas,rcar-efuse.yaml b/Documentation/devicetree/bindings/fuse/renesas,rcar-efuse.yaml
new file mode 100644
index 000000000000..d7e289244e72
--- /dev/null
+++ b/Documentation/devicetree/bindings/fuse/renesas,rcar-efuse.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/fuse/renesas,rcar-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: R-Car E-FUSE connected to PFC
+
+maintainers:
+ - Geert Uytterhoeven <[email protected]>
+
+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.
+
+properties:
+ compatible:
+ enum:
+ - renesas,r8a779a0-efuse # R-Car V3U
+ - renesas,r8a779f0-efuse # R-Car S4-8
+
+ reg:
+ maxItems: 1
+ description: PFC System Group Fuse Control and Monitor register block
+
+ clocks:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - power-domains
+ - resets
+
+additionalProperties: 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>;
+ };
diff --git a/Documentation/devicetree/bindings/fuse/renesas,rcar-otp.yaml b/Documentation/devicetree/bindings/fuse/renesas,rcar-otp.yaml
new file mode 100644
index 000000000000..d74872ae9ff3
--- /dev/null
+++ b/Documentation/devicetree/bindings/fuse/renesas,rcar-otp.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/fuse/renesas,rcar-otp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: R-Car E-FUSE connected to OTP_MEM
+
+maintainers:
+ - Geert Uytterhoeven <[email protected]>
+
+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.
+
+properties:
+ compatible:
+ enum:
+ - renesas,r8a779g0-otp # R-CarV4H
+ - renesas,r8a779h0-otp # R-CarV4M
+
+ reg:
+ items:
+ - description: OTP_MEM_0
+ - description: OTP_MEM_1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ otp: otp@e61be000 {
+ compatible = "renesas,r8a779g0-otp";
+ reg = <0xe61be000 0x1000>, <0xe61bf000 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml b/Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml
index 46bb121360dc..1046f0331c09 100644
--- a/Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml
@@ -33,6 +33,11 @@ properties:
gpio-controller: true
+ # Each SGPIO is represented as a pair of input and output GPIOs
+ gpio-line-names:
+ minItems: 160
+ maxItems: 256
+
'#gpio-cells':
const: 2
@@ -41,6 +46,9 @@ properties:
interrupt-controller: true
+ '#interrupt-cells':
+ const: 2
+
clocks:
maxItems: 1
@@ -55,6 +63,7 @@ required:
- '#gpio-cells'
- interrupts
- interrupt-controller
+ - '#interrupt-cells'
- ngpios
- clocks
- bus-frequency
@@ -72,6 +81,7 @@ examples:
reg = <0x1e780200 0x0100>;
clocks = <&syscon ASPEED_CLK_APB>;
interrupt-controller;
+ #interrupt-cells = <2>;
ngpios = <80>;
bus-frequency = <12000000>;
};
diff --git a/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml b/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml
new file mode 100644
index 000000000000..3dd70933ed8e
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/atmel,at91rm9200-gpio.yaml
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/atmel,at91rm9200-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip GPIO controller (PIO)
+
+maintainers:
+ - Manikandan Muralidharan <[email protected]>
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - atmel,at91sam9x5-gpio
+ - microchip,sam9x60-gpio
+ - const: atmel,at91rm9200-gpio
+ - items:
+ - enum:
+ - microchip,sam9x7-gpio
+ - const: microchip,sam9x60-gpio
+ - const: atmel,at91rm9200-gpio
+ - items:
+ - const: atmel,at91rm9200-gpio
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 2
+
+ gpio-controller: true
+ gpio-line-names: true
+
+ "#gpio-cells":
+ const: 2
+
+ clocks:
+ maxItems: 1
+
+ "#gpio-lines":
+ description:
+ Number of gpio, 32 by default if absent
+ maxItems: 1
+ default: 32
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-controller
+ - "#interrupt-cells"
+ - gpio-controller
+ - "#gpio-cells"
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/at91.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ gpio@fffff400 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x200>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 2>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/gpio/fsl,qoriq-gpio.yaml b/Documentation/devicetree/bindings/gpio/fsl,qoriq-gpio.yaml
new file mode 100644
index 000000000000..84fd82291ee4
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/fsl,qoriq-gpio.yaml
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/fsl,qoriq-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale MPC512x/MPC8xxx/QorIQ/Layerscape GPIO controller
+
+maintainers:
+ - Frank Li <[email protected]>
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - fsl,mpc5121-gpio
+ - fsl,mpc5125-gpio
+ - fsl,mpc8349-gpio
+ - fsl,mpc8572-gpio
+ - fsl,mpc8610-gpio
+ - fsl,pq3-gpio
+ - items:
+ - enum:
+ - fsl,ls1021a-gpio
+ - fsl,ls1028a-gpio
+ - fsl,ls1043a-gpio
+ - fsl,ls1046a-gpio
+ - fsl,ls1088a-gpio
+ - fsl,ls2080a-gpio
+ - const: fsl,qoriq-gpio
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ "#gpio-cells":
+ const: 2
+
+ gpio-controller: true
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 2
+
+ gpio-line-names:
+ minItems: 1
+ maxItems: 32
+
+ little-endian:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ GPIO registers are used as little endian. If not
+ present registers are used as big endian by default.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - "#gpio-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ gpio@1100 {
+ compatible = "fsl,mpc5125-gpio";
+ reg = <0x1100 0x080>;
+ interrupts = <78 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ gpio@2300000 {
+ compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
+ reg = <0x2300000 0x10000>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ little-endian;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
deleted file mode 100644
index cd28e932bf50..000000000000
--- a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-* Freescale MPC512x/MPC8xxx/QorIQ/Layerscape GPIO controller
-
-Required properties:
-- compatible : Should be "fsl,<soc>-gpio"
- The following <soc>s are known to be supported:
- mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq,
- ls1021a, ls1043a, ls2080a, ls1028a, ls1088a.
-- reg : Address and length of the register set for the device
-- interrupts : Should be the port interrupt shared by all 32 pins.
-- #gpio-cells : Should be two. The first cell is the pin number and
- the second cell is used to specify the gpio polarity:
- 0 = active high
- 1 = active low
-
-Optional properties:
-- little-endian : GPIO registers are used as little endian. If not
- present registers are used as big endian by default.
-
-Example of gpio-controller node for a mpc5125 SoC:
-
-gpio0: gpio@1100 {
- compatible = "fsl,mpc5125-gpio";
- #gpio-cells = <2>;
- reg = <0x1100 0x080>;
- interrupts = <78 0x8>;
-};
-
-Example of gpio-controller node for a ls2080a SoC:
-
-gpio0: gpio@2300000 {
- compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
- reg = <0x0 0x2300000 0x0 0x10000>;
- interrupts = <0 36 0x4>; /* Level high type */
- gpio-controller;
- little-endian;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
-};
-
-
-Example of gpio-controller node for a ls1028a/ls1088a SoC:
-
-gpio1: gpio@2300000 {
- compatible = "fsl,ls1028a-gpio", "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
- reg = <0x0 0x2300000 0x0 0x10000>;
- interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- little-endian;
-};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca95xx.yaml b/Documentation/devicetree/bindings/gpio/gpio-pca95xx.yaml
index 99febb8ea1b6..51e8390d6b32 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-pca95xx.yaml
+++ b/Documentation/devicetree/bindings/gpio/gpio-pca95xx.yaml
@@ -66,6 +66,7 @@ properties:
- ti,tca6408
- ti,tca6416
- ti,tca6424
+ - ti,tca9535
- ti,tca9538
- ti,tca9539
- ti,tca9554
diff --git a/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml b/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml
index a27f92950257..cabda2eab4a2 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml
+++ b/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml
@@ -51,6 +51,10 @@ properties:
gpio-controller: true
+ gpio-line-names:
+ minItems: 1
+ maxItems: 32
+
clocks:
items:
- description: SoC GPIO clock
diff --git a/Documentation/devicetree/bindings/gpio/gpio-zevio.txt b/Documentation/devicetree/bindings/gpio/gpio-zevio.txt
deleted file mode 100644
index a37bd9ae2730..000000000000
--- a/Documentation/devicetree/bindings/gpio/gpio-zevio.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-Zevio GPIO controller
-
-Required properties:
-- compatible: Should be "lsi,zevio-gpio"
-- reg: Address and length of the register set for the device
-- #gpio-cells: Should be two. The first cell is the pin number and the
- second cell is used to specify optional parameters (currently unused).
-- gpio-controller: Marks the device node as a GPIO controller.
-
-Example:
- gpio: gpio@90000000 {
- compatible = "lsi,zevio-gpio";
- reg = <0x90000000 0x1000>;
- gpio-controller;
- #gpio-cells = <2>;
- };
diff --git a/Documentation/devicetree/bindings/gpio/gpio_atmel.txt b/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
deleted file mode 100644
index 29416f9c3220..000000000000
--- a/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-* Atmel GPIO controller (PIO)
-
-Required properties:
-- compatible: "atmel,<chip>-gpio", where <chip> is at91rm9200 or at91sam9x5.
-- reg: Should contain GPIO controller registers location and length
-- interrupts: Should be the port interrupt shared by all the pins.
-- #gpio-cells: Should be two. The first cell is the pin number and
- the second cell is used to specify optional parameters to declare if the GPIO
- is active high or low. See gpio.txt.
-- gpio-controller: Marks the device node as a GPIO controller.
-- interrupt-controller: Marks the device node as an interrupt controller.
-- #interrupt-cells: Should be two. The first cell is the pin number and the
- second cell is used to specify irq type flags, see the two cell description
- in interrupt-controller/interrupts.txt for details.
-
-optional properties:
-- #gpio-lines: Number of gpio if absent 32.
-
-
-Example:
- pioA: gpio@fffff200 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff200 0x100>;
- interrupts = <2 4>;
- #gpio-cells = <2>;
- gpio-controller;
- #gpio-lines = <19>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-
diff --git a/Documentation/devicetree/bindings/gpio/lsi,zevio-gpio.yaml b/Documentation/devicetree/bindings/gpio/lsi,zevio-gpio.yaml
new file mode 100644
index 000000000000..e9e201a489e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/lsi,zevio-gpio.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/lsi,zevio-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zevio GPIO controller
+
+maintainers:
+ - Pratik Farkase <[email protected]>
+
+properties:
+ compatible:
+ items:
+ - const: lsi,zevio-gpio
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ "#gpio-cells":
+ const: 2
+
+ gpio-controller: true
+
+required:
+ - compatible
+ - reg
+ - "#gpio-cells"
+ - gpio-controller
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ gpio@90000000 {
+ compatible = "lsi,zevio-gpio";
+ reg = <0x90000000 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/hwmon/g762.txt b/Documentation/devicetree/bindings/hwmon/g762.txt
deleted file mode 100644
index 6d154c4923de..000000000000
--- a/Documentation/devicetree/bindings/hwmon/g762.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-GMT G762/G763 PWM Fan controller
-
-Required node properties:
-
- - "compatible": must be either "gmt,g762" or "gmt,g763"
- - "reg": I2C bus address of the device
- - "clocks": a fixed clock providing input clock frequency
- on CLK pin of the chip.
-
-Optional properties:
-
- - "fan_startv": fan startup voltage. Accepted values are 0, 1, 2 and 3.
- The higher the more.
-
- - "pwm_polarity": pwm polarity. Accepted values are 0 (positive duty)
- and 1 (negative duty).
-
- - "fan_gear_mode": fan gear mode. Supported values are 0, 1 and 2.
-
-If an optional property is not set in .dts file, then current value is kept
-unmodified (e.g. u-boot installed value).
-
-Additional information on operational parameters for the device is available
-in Documentation/hwmon/g762.rst. A detailed datasheet for the device is available
-at http://natisbad.org/NAS/refs/GMT_EDS-762_763-080710-0.2.pdf.
-
-Example g762 node:
-
- clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
- g762_clk: fixedclk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <8192>;
- }
- }
-
- g762: g762@3e {
- compatible = "gmt,g762";
- reg = <0x3e>;
- clocks = <&g762_clk>
- fan_gear_mode = <0>; /* chip default */
- fan_startv = <1>; /* chip default */
- pwm_polarity = <0>; /* chip default */
- };
diff --git a/Documentation/devicetree/bindings/hwmon/gmt,g762.yaml b/Documentation/devicetree/bindings/hwmon/gmt,g762.yaml
new file mode 100644
index 000000000000..8e1bffd252e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/gmt,g762.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/gmt,g762.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GMT G761/G762/G763 PWM Fan controller
+
+maintainers:
+ - Christian Marangi <[email protected]>
+
+description: |
+ GMT G761/G762/G763 PWM Fan controller.
+
+ G761 supports an internal-clock hence the clocks property is optional.
+ If not defined, internal-clock will be used. (31KHz is the clock of
+ the internal crystal oscillator)
+
+ If an optional property is not set in DT, then current value is kept
+ unmodified (e.g. bootloader installed value).
+
+ Additional information on operational parameters for the device is available
+ in Documentation/hwmon/g762.rst. A detailed datasheet for the device is available
+ at http://natisbad.org/NAS/refs/GMT_EDS-762_763-080710-0.2.pdf.
+
+properties:
+ compatible:
+ enum:
+ - gmt,g761
+ - gmt,g762
+ - gmt,g763
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ description: a fixed clock providing input clock frequency on CLK
+ pin of the chip.
+ maxItems: 1
+
+ fan_startv:
+ description: Fan startup voltage step
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2, 3]
+
+ pwm_polarity:
+ description: PWM polarity (positive or negative duty)
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+ fan_gear_mode:
+ description: FAN gear mode. Configure High speed fan setting factor
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2]
+
+required:
+ - compatible
+ - reg
+
+if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - gmt,g762
+ - gmt,g763
+then:
+ required:
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ g762@3e {
+ compatible = "gmt,g762";
+ reg = <0x3e>;
+ clocks = <&g762_clk>;
+ fan_gear_mode = <0>;
+ fan_startv = <1>;
+ pwm_polarity = <0>;
+ };
+
+ g761@1e {
+ compatible = "gmt,g761";
+ reg = <0x1e>;
+ fan_gear_mode = <0>;
+ fan_startv = <1>;
+ pwm_polarity = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/hwmon/maxim,max6639.yaml b/Documentation/devicetree/bindings/hwmon/maxim,max6639.yaml
new file mode 100644
index 000000000000..4f5837a30773
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/maxim,max6639.yaml
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/maxim,max6639.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim max6639
+
+maintainers:
+ - Naresh Solanki <[email protected]>
+
+description: |
+ The MAX6639 is a 2-channel temperature monitor with dual, automatic, PWM
+ fan-speed controller. It monitors its own temperature and one external
+ diode-connected transistor or the temperatures of two external diode-connected
+ transistors, typically available in CPUs, FPGAs, or GPUs.
+
+ Datasheets:
+ https://datasheets.maximintegrated.com/en/ds/MAX6639-MAX6639F.pdf
+
+properties:
+ compatible:
+ enum:
+ - maxim,max6639
+
+ reg:
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ '#pwm-cells':
+ const: 3
+
+required:
+ - compatible
+ - reg
+
+patternProperties:
+ "^fan@[0-1]$":
+ type: object
+ description:
+ Represents the two fans and their specific configuration.
+
+ $ref: fan-common.yaml#
+
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ description:
+ The fan number.
+
+ required:
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fan1: fan-controller@10 {
+ compatible = "maxim,max6639";
+ reg = <0x10>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #pwm-cells = <3>;
+
+ fan@0 {
+ reg = <0x0>;
+ pulses-per-revolution = <2>;
+ max-rpm = <4000>;
+ target-rpm = <1000>;
+ pwms = <&fan1 0 25000 0>;
+ };
+
+ fan@1 {
+ reg = <0x1>;
+ pulses-per-revolution = <2>;
+ max-rpm = <8000>;
+ pwms = <&fan1 1 25000 0>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml b/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
index df86c2c92037..6ae961732e6b 100644
--- a/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
@@ -66,6 +66,14 @@ properties:
description: phandle to the regulator that provides the VS supply typically
in range from 2.7 V to 5.5 V.
+ ti,alert-polarity-active-high:
+ description: Alert pin is asserted based on the value of Alert polarity Bit
+ of Mask/Enable register. Default value is Normal (0 which maps to
+ active-low open collector). The other value is Inverted
+ (1 which maps to active-high open collector). Specify this property to set
+ the alert polarity to active-high.
+ $ref: /schemas/types.yaml#/definitions/flag
+
required:
- compatible
- reg
@@ -88,5 +96,6 @@ examples:
label = "vdd_3v0";
shunt-resistor = <1000>;
vs-supply = <&vdd_3v0>;
+ ti,alert-polarity-active-high;
};
};
diff --git a/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml b/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
index 8b5307c875ff..0ad10d43fac0 100644
--- a/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
@@ -9,6 +9,14 @@ title: TMP108 temperature sensor
maintainers:
- Krzysztof Kozlowski <[email protected]>
+description: |
+ The TMP108 is a digital-output temperature sensor with a
+ dynamically-programmable limit window, and under- and overtemperature
+ alert functions.
+
+ Datasheets:
+ https://www.ti.com/product/TMP108
+
properties:
compatible:
enum:
@@ -24,6 +32,9 @@ properties:
"#thermal-sensor-cells":
const: 0
+ vcc-supply:
+ description: phandle to the regulator that provides the V+ supply
+
required:
- compatible
- reg
@@ -45,6 +56,7 @@ examples:
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&tmp_alrt>;
+ vcc-supply = <&supply>;
#thermal-sensor-cells = <0>;
};
};
diff --git a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
index c384bf0bb25d..6bdb8040be65 100644
--- a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
+++ b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
@@ -22,7 +22,9 @@ properties:
- const: allwinner,sun8i-a83t-r-lradc
- const: allwinner,sun50i-r329-lradc
- items:
- - const: allwinner,sun20i-d1-lradc
+ - enum:
+ - allwinner,sun50i-h616-lradc
+ - allwinner,sun20i-d1-lradc
- const: allwinner,sun50i-r329-lradc
reg:
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
index 05067e197abe..2cd1f5590fd9 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
@@ -35,6 +35,7 @@ properties:
- qcom,sm8250-cpu-bwmon
- qcom,sm8550-cpu-bwmon
- qcom,sm8650-cpu-bwmon
+ - qcom,x1e80100-cpu-bwmon
- const: qcom,sdm845-bwmon # BWMON v4, unified register space
- items:
- enum:
@@ -44,6 +45,7 @@ properties:
- qcom,sm8250-llcc-bwmon
- qcom,sm8550-llcc-bwmon
- qcom,sm8650-llcc-bwmon
+ - qcom,x1e80100-llcc-bwmon
- const: qcom,sc7280-llcc-bwmon
- const: qcom,sc7280-llcc-bwmon # BWMON v5
- const: qcom,sdm845-llcc-bwmon # BWMON v5
@@ -72,7 +74,6 @@ required:
- interconnects
- interrupts
- operating-points-v2
- - opp-table
- reg
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-extirq.yaml b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-extirq.yaml
index 887e565b9573..199b34fdbefc 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-extirq.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-extirq.yaml
@@ -8,7 +8,6 @@ title: Freescale Layerscape External Interrupt Controller
maintainers:
- Shawn Guo <[email protected]>
- - Li Yang <[email protected]>
description: |
Some Layerscape SOCs (LS1021A, LS1043A, LS1046A LS1088A, LS208xA,
diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/interrupt-controller/marvell,armada-370-xp-mpic.txt
deleted file mode 100644
index 5fc03134a999..000000000000
--- a/Documentation/devicetree/bindings/interrupt-controller/marvell,armada-370-xp-mpic.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-Marvell Armada 370, 375, 38x, XP Interrupt Controller
------------------------------------------------------
-
-Required properties:
-- compatible: Should be "marvell,mpic"
-- interrupt-controller: Identifies the node as an interrupt controller.
-- msi-controller: Identifies the node as an PCI Message Signaled
- Interrupt controller.
-- #interrupt-cells: The number of cells to define the interrupts. Should be 1.
- The cell is the IRQ number
-
-- reg: Should contain PMIC registers location and length. First pair
- for the main interrupt registers, second pair for the per-CPU
- interrupt registers. For this last pair, to be compliant with SMP
- support, the "virtual" must be use (For the record, these registers
- automatically map to the interrupt controller registers of the
- current CPU)
-
-Optional properties:
-
-- interrupts: If defined, then it indicates that this MPIC is
- connected as a slave to another interrupt controller. This is
- typically the case on Armada 375 and Armada 38x, where the MPIC is
- connected as a slave to the Cortex-A9 GIC. The provided interrupt
- indicate to which GIC interrupt the MPIC output is connected.
-
-Example:
-
- mpic: interrupt-controller@d0020000 {
- compatible = "marvell,mpic";
- #interrupt-cells = <1>;
- #address-cells = <1>;
- #size-cells = <1>;
- interrupt-controller;
- msi-controller;
- reg = <0xd0020a00 0x1d0>,
- <0xd0021070 0x58>;
- };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,mpic.yaml b/Documentation/devicetree/bindings/interrupt-controller/marvell,mpic.yaml
new file mode 100644
index 000000000000..616a41c87352
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/marvell,mpic.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/marvell,mpic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell Armada 370, 375, 38x, 39x, XP Interrupt Controller
+
+maintainers:
+ - Marek Behún <[email protected]>
+
+description: |
+ The top-level interrupt controller on Marvell Armada 370 and XP. On these
+ platforms it also provides inter-processor interrupts.
+
+ On Marvell Armada 375, 38x and 39x this controller is wired under ARM GIC.
+
+ Provides MSI handling for the PCIe controllers.
+
+properties:
+ compatible:
+ const: marvell,mpic
+
+ reg:
+ items:
+ - description: main registers
+ - description: per-cpu registers
+
+ interrupts:
+ items:
+ - description: |
+ Parent interrupt on platforms where MPIC is not the top-level
+ interrupt controller.
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 1
+
+ msi-controller: true
+
+required:
+ - compatible
+ - reg
+ - interrupt-controller
+ - '#interrupt-cells'
+ - msi-controller
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ interrupt-controller@20a00 {
+ compatible = "marvell,mpic";
+ reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+ interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ msi-controller;
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml b/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml
index 3be1db30bf41..d1c3421bee10 100644
--- a/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: FSL/NXP Integrated Flash Controller
maintainers:
- - Li Yang <[email protected]>
+ - Shawn Guo <[email protected]>
description: |
NXP's integrated flash controller (IFC) is an advanced version of the
diff --git a/Documentation/devicetree/bindings/mfd/ti,twl.yaml b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
index c2357fecb56c..e94b0fd7af0f 100644
--- a/Documentation/devicetree/bindings/mfd/ti,twl.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
@@ -22,6 +22,32 @@ allOf:
contains:
const: ti,twl4030
then:
+ patternProperties:
+ "^regulator-":
+ properties:
+ compatible:
+ enum:
+ - ti,twl4030-vaux1
+ - ti,twl4030-vaux2
+ - ti,twl4030-vaux3
+ - ti,twl4030-vaux4
+ - ti,twl4030-vmmc1
+ - ti,twl4030-vmmc2
+ - ti,twl4030-vpll1
+ - ti,twl4030-vpll2
+ - ti,twl4030-vsim
+ - ti,twl4030-vdac
+ - ti,twl4030-vintana2
+ - ti,twl4030-vio
+ - ti,twl4030-vdd1
+ - ti,twl4030-vdd2
+ - ti,twl4030-vintana1
+ - ti,twl4030-vintdig
+ - ti,twl4030-vusb1v5
+ - ti,twl4030-vusb1v8
+ - ti,twl4030-vusb3v1
+ ti,retain-on-reset: false
+
properties:
madc:
type: object
@@ -50,13 +76,34 @@ allOf:
properties:
compatible:
const: ti,twl4030-wdt
-
- if:
properties:
compatible:
contains:
const: ti,twl6030
then:
+ patternProperties:
+ "^regulator-":
+ properties:
+ compatible:
+ enum:
+ - ti,twl6030-vaux1
+ - ti,twl6030-vaux2
+ - ti,twl6030-vaux3
+ - ti,twl6030-vmmc
+ - ti,twl6030-vpp
+ - ti,twl6030-vusim
+ - ti,twl6030-vana
+ - ti,twl6030-vcxio
+ - ti,twl6030-vdac
+ - ti,twl6030-vusb
+ - ti,twl6030-v1v8
+ - ti,twl6030-v2v1
+ - ti,twl6030-vdd1
+ - ti,twl6030-vdd2
+ - ti,twl6030-vdd3
+ regulator-initial-mode: false
+
properties:
gpadc:
type: object
@@ -69,6 +116,25 @@ allOf:
contains:
const: ti,twl6032
then:
+ patternProperties:
+ "^regulator-":
+ properties:
+ compatible:
+ enum:
+ - ti,twl6032-ldo1
+ - ti,twl6032-ldo2
+ - ti,twl6032-ldo3
+ - ti,twl6032-ldo4
+ - ti,twl6032-ldo5
+ - ti,twl6032-ldo6
+ - ti,twl6032-ldo7
+ - ti,twl6032-ldoln
+ - ti,twl6032-ldousb
+ - ti,twl6032-smps3
+ - ti,twl6032-smps4
+ - ti,twl6032-vio
+ regulator-initial-mode: false
+
properties:
gpadc:
type: object
@@ -112,6 +178,27 @@ properties:
interrupts:
maxItems: 1
+patternProperties:
+ "^regulator-":
+ type: object
+ unevaluatedProperties: false
+ $ref: /schemas/regulator/regulator.yaml
+ properties:
+ compatible: true
+ regulator-initial-mode:
+ enum:
+ - 0x08 # Sleep mode, the nominal output voltage is maintained
+ # with low power consumption with low load current capability
+ - 0x0e # Active mode, the regulator can deliver its nominal output
+ # voltage with full-load current capability
+ ti,retain-on-reset:
+ description:
+ Does not turn off the supplies during warm
+ reset. Could be needed for VMMC, as TWL6030
+ reset sequence for this signal does not comply
+ with the SD specification.
+ type: boolean
+
unevaluatedProperties: false
required:
@@ -131,9 +218,85 @@ examples:
compatible = "ti,twl6030";
reg = <0x48>;
interrupts = <39>; /* IRQ_SYS_1N cascaded to gic */
+ interrupt-parent = <&gic>;
interrupt-controller;
#interrupt-cells = <1>;
- interrupt-parent = <&gic>;
+
+ gpadc {
+ compatible = "ti,twl6030-gpadc";
+ interrupts = <6>;
+ #io-channel-cells = <1>;
+ };
+
+ rtc {
+ compatible = "ti,twl4030-rtc";
+ interrupts = <8>;
+ };
+
+ regulator-vaux1 {
+ compatible = "ti,twl6030-vaux1";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ regulator-vmmc1 {
+ compatible = "ti,twl6030-vmmc";
+ ti,retain-on-reset;
+ };
};
};
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@48 {
+ compatible = "ti,twl4030";
+ reg = <0x48>;
+ interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+ interrupt-parent = <&intc>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ bci {
+ compatible = "ti,twl4030-bci";
+ interrupts = <9>, <2>;
+ bci3v1-supply = <&vusb3v1>;
+ io-channels = <&twl_madc 11>;
+ io-channel-names = "vac";
+ };
+
+ twl_madc: madc {
+ compatible = "ti,twl4030-madc";
+ interrupts = <3>;
+ #io-channel-cells = <1>;
+ };
+
+ pwrbutton {
+ compatible = "ti,twl4030-pwrbutton";
+ interrupts = <8>;
+ };
+
+ rtc {
+ compatible = "ti,twl4030-rtc";
+ interrupts = <11>;
+ };
+
+ regulator-vaux1 {
+ compatible = "ti,twl4030-vaux1";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <0xe>;
+ };
+
+ vusb3v1: regulator-vusb3v1 {
+ compatible = "ti,twl4030-vusb3v1";
+ };
+
+ watchdog {
+ compatible = "ti,twl4030-wdt";
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml
index bc403ae9e5d9..57646575a13f 100644
--- a/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml
@@ -51,6 +51,9 @@ properties:
set when controller's internal DMA engine cannot access the DRAM memory,
like on the G12A dedicated SDIO controller.
+ power-domains:
+ maxItems: 1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
index cbd3d6c6c77f..eee6be7a7867 100644
--- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
+++ b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
@@ -20,6 +20,7 @@ properties:
- const: brcm,sdhci-brcmstb
- items:
- enum:
+ - brcm,bcm2712-sdhci
- brcm,bcm74165b0-sdhci
- brcm,bcm7445-sdhci
- brcm,bcm7425-sdhci
diff --git a/Documentation/devicetree/bindings/mmc/fsl,esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl,esdhc.yaml
new file mode 100644
index 000000000000..b86ffb53b18b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/fsl,esdhc.yaml
@@ -0,0 +1,105 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/fsl,esdhc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale Enhanced Secure Digital Host Controller (eSDHC)
+
+description:
+ The Enhanced Secure Digital Host Controller provides an interface
+ for MMC, SD, and SDIO types of memory cards.
+
+maintainers:
+ - Frank Li <[email protected]>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - fsl,mpc8536-esdhc
+ - fsl,mpc8378-esdhc
+ - fsl,p2020-esdhc
+ - fsl,p4080-esdhc
+ - fsl,t1040-esdhc
+ - fsl,t4240-esdhc
+ - fsl,ls1012a-esdhc
+ - fsl,ls1028a-esdhc
+ - fsl,ls1088a-esdhc
+ - fsl,ls1043a-esdhc
+ - fsl,ls1046a-esdhc
+ - fsl,ls2080a-esdhc
+ - const: fsl,esdhc
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-frequency:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: specifies eSDHC base clock frequency.
+
+ sdhci,wp-inverted:
+ $ref: /schemas/types.yaml#/definitions/flag
+ deprecated: true
+ description:
+ specifies that eSDHC controller reports
+ inverted write-protect state; New devices should use the generic
+ "wp-inverted" property.
+
+ sdhci,1-bit-only:
+ $ref: /schemas/types.yaml#/definitions/flag
+ deprecated: true
+ description:
+ specifies that a controller can only handle
+ 1-bit data transfers. New devices should use the generic
+ "bus-width = <1>" property.
+
+ sdhci,auto-cmd12:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ specifies that a controller can only handle auto CMD12.
+
+ voltage-ranges:
+ $ref: /schemas/types.yaml#/definitions/uint32-matrix
+ items:
+ items:
+ - description: specifies minimum slot voltage (mV).
+ - description: specifies maximum slot voltage (mV).
+ minItems: 1
+ maxItems: 8
+
+ dma-coherent: true
+
+ little-endian:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ If the host controller is little-endian mode, specify
+ this property. The default endian mode is big-endian.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+allOf:
+ - $ref: sdhci-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ mmc@2e000 {
+ compatible = "fsl,mpc8378-esdhc", "fsl,esdhc";
+ reg = <0x2e000 0x1000>;
+ interrupts = <42 0x8>;
+ interrupt-parent = <&ipic>;
+ /* Filled in by U-Boot */
+ clock-frequency = <100000000>;
+ voltage-ranges = <3300 3300>;
+ };
diff --git a/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt
deleted file mode 100644
index edb8cadb9541..000000000000
--- a/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-* Freescale Enhanced Secure Digital Host Controller (eSDHC)
-
-The Enhanced Secure Digital Host Controller provides an interface
-for MMC, SD, and SDIO types of memory cards.
-
-This file documents differences between the core properties described
-by mmc.txt and the properties used by the sdhci-esdhc driver.
-
-Required properties:
- - compatible : should be "fsl,esdhc", or "fsl,<chip>-esdhc".
- Possible compatibles for PowerPC:
- "fsl,mpc8536-esdhc"
- "fsl,mpc8378-esdhc"
- "fsl,p2020-esdhc"
- "fsl,p4080-esdhc"
- "fsl,t1040-esdhc"
- "fsl,t4240-esdhc"
- Possible compatibles for ARM:
- "fsl,ls1012a-esdhc"
- "fsl,ls1028a-esdhc"
- "fsl,ls1088a-esdhc"
- "fsl,ls1043a-esdhc"
- "fsl,ls1046a-esdhc"
- "fsl,ls2080a-esdhc"
- - clock-frequency : specifies eSDHC base clock frequency.
-
-Optional properties:
- - sdhci,wp-inverted : specifies that eSDHC controller reports
- inverted write-protect state; New devices should use the generic
- "wp-inverted" property.
- - sdhci,1-bit-only : specifies that a controller can only handle
- 1-bit data transfers. New devices should use the generic
- "bus-width = <1>" property.
- - sdhci,auto-cmd12: specifies that a controller can only handle auto
- CMD12.
- - voltage-ranges : two cells are required, first cell specifies minimum
- slot voltage (mV), second cell specifies maximum slot voltage (mV).
- Several ranges could be specified.
- - little-endian : If the host controller is little-endian mode, specify
- this property. The default endian mode is big-endian.
-
-Example:
-
-sdhci@2e000 {
- compatible = "fsl,mpc8378-esdhc", "fsl,esdhc";
- reg = <0x2e000 0x1000>;
- interrupts = <42 0x8>;
- interrupt-parent = <&ipic>;
- /* Filled in by U-Boot */
- clock-frequency = <0>;
- voltage-ranges = <3300 3300>;
-};
diff --git a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml
index 36acc40c7d18..6e2cdac6a85d 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml
+++ b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml
@@ -27,17 +27,19 @@ properties:
maxItems: 1
voltage-ranges:
- $ref: /schemas/types.yaml#/definitions/uint32-array
+ $ref: /schemas/types.yaml#/definitions/uint32-matrix
description: |
Two cells are required, first cell specifies minimum slot voltage (mV),
second cell specifies maximum slot voltage (mV).
items:
- - description: |
- value for minimum slot voltage in mV
- default: 3200
- - description: |
- value for maximum slot voltage in mV
- default: 3400
+ items:
+ - description: |
+ value for minimum slot voltage in mV
+ default: 3200
+ - description: |
+ value for maximum slot voltage in mV
+ default: 3400
+ maxItems: 1
gpios:
description: |
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
index c24c537f62b1..11979b026d21 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
@@ -51,6 +51,7 @@ properties:
- qcom,sdm845-sdhci
- qcom,sdx55-sdhci
- qcom,sdx65-sdhci
+ - qcom,sdx75-sdhci
- qcom,sm6115-sdhci
- qcom,sm6125-sdhci
- qcom,sm6350-sdhci
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt b/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt
deleted file mode 100644
index eb7eb1b529f0..000000000000
--- a/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt
+++ /dev/null
@@ -1,67 +0,0 @@
-* Spreadtrum SDHCI controller (sdhci-sprd)
-
-The Secure Digital (SD) Host controller on Spreadtrum SoCs provides an interface
-for MMC, SD and SDIO types of cards.
-
-This file documents differences between the core properties in mmc.txt
-and the properties used by the sdhci-sprd driver.
-
-Required properties:
-- compatible: Should contain "sprd,sdhci-r11".
-- reg: physical base address of the controller and length.
-- interrupts: Interrupts used by the SDHCI controller.
-- clocks: Should contain phandle for the clock feeding the SDHCI controller
-- clock-names: Should contain the following:
- "sdio" - SDIO source clock (required)
- "enable" - gate clock which used for enabling/disabling the device (required)
- "2x_enable" - gate clock controlling the device for some special platforms (optional)
-
-Optional properties:
-- assigned-clocks: the same with "sdio" clock
-- assigned-clock-parents: the default parent of "sdio" clock
-- pinctrl-names: should be "default", "state_uhs"
-- pinctrl-0: should contain default/high speed pin control
-- pinctrl-1: should contain uhs mode pin control
-
-PHY DLL delays are used to delay the data valid window, and align the window
-to sampling clock. PHY DLL delays can be configured by following properties,
-and each property contains 4 cells which are used to configure the clock data
-write line delay value, clock read command line delay value, clock read data
-positive edge delay value and clock read data negative edge delay value.
-Each cell's delay value unit is cycle of the PHY clock.
-
-- sprd,phy-delay-legacy: Delay value for legacy timing.
-- sprd,phy-delay-sd-highspeed: Delay value for SD high-speed timing.
-- sprd,phy-delay-sd-uhs-sdr50: Delay value for SD UHS SDR50 timing.
-- sprd,phy-delay-sd-uhs-sdr104: Delay value for SD UHS SDR50 timing.
-- sprd,phy-delay-mmc-highspeed: Delay value for MMC high-speed timing.
-- sprd,phy-delay-mmc-ddr52: Delay value for MMC DDR52 timing.
-- sprd,phy-delay-mmc-hs200: Delay value for MMC HS200 timing.
-- sprd,phy-delay-mmc-hs400: Delay value for MMC HS400 timing.
-- sprd,phy-delay-mmc-hs400es: Delay value for MMC HS400 enhanced strobe timing.
-
-Examples:
-
-sdio0: sdio@20600000 {
- compatible = "sprd,sdhci-r11";
- reg = <0 0x20600000 0 0x1000>;
- interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
-
- clock-names = "sdio", "enable";
- clocks = <&ap_clk CLK_EMMC_2X>,
- <&apahb_gate CLK_EMMC_EB>;
- assigned-clocks = <&ap_clk CLK_EMMC_2X>;
- assigned-clock-parents = <&rpll CLK_RPLL_390M>;
-
- pinctrl-names = "default", "state_uhs";
- pinctrl-0 = <&sd0_pins_default>;
- pinctrl-1 = <&sd0_pins_uhs>;
-
- sprd,phy-delay-sd-uhs-sdr104 = <0x3f 0x7f 0x2e 0x2e>;
- bus-width = <8>;
- non-removable;
- no-sdio;
- no-sd;
- cap-mmc-hw-reset;
- status = "okay";
-};
diff --git a/Documentation/devicetree/bindings/mmc/sprd,sdhci-r11.yaml b/Documentation/devicetree/bindings/mmc/sprd,sdhci-r11.yaml
new file mode 100644
index 000000000000..b08081bc018b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sprd,sdhci-r11.yaml
@@ -0,0 +1,112 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/sprd,sdhci-r11.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spreadtrum SDHCI controller
+
+maintainers:
+ - Orson Zhai <[email protected]>
+ - Baolin Wang <[email protected]>
+ - Chunyan Zhang <[email protected]>
+
+properties:
+ compatible:
+ const: sprd,sdhci-r11
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ minItems: 2
+ items:
+ - description: SDIO source clock
+ - description: gate clock for enabling/disabling the device
+ - description: gate clock controlling the device for some special platforms (optional)
+
+ clock-names:
+ minItems: 2
+ items:
+ - const: sdio
+ - const: enable
+ - const: 2x_enable
+
+ pinctrl-0:
+ description: default/high speed pin control
+ maxItems: 1
+
+ pinctrl-1:
+ description: UHS mode pin control
+ maxItems: 1
+
+ pinctrl-names:
+ minItems: 1
+ items:
+ - const: default
+ - const: state_uhs
+
+patternProperties:
+ "^sprd,phy-delay-(legacy|mmc-(ddr52|highspeed|hs[24]00|hs400es)|sd-(highspeed|uhs-sdr(50|104)))$":
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ items:
+ - description: clock data write line delay value
+ - description: clock read command line delay value
+ - description: clock read data positive edge delay value
+ - description: clock read data negative edge delay value
+ description:
+ PHY DLL delays are used to delay the data valid window, and align
+ the window to the sampling clock. Each cell's delay value unit is
+ cycle of the PHY clock.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+
+allOf:
+ - $ref: sdhci-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/sprd,sc9860-clk.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ mmc@50430000 {
+ compatible = "sprd,sdhci-r11";
+ reg = <0x50430000 0x1000>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&aon_prediv CLK_EMMC_2X>,
+ <&apahb_gate CLK_EMMC_EB>,
+ <&aon_gate CLK_EMMC_2X_EN>;
+ clock-names = "sdio", "enable", "2x_enable";
+
+ pinctrl-0 = <&sd0_pins_default>;
+ pinctrl-1 = <&sd0_pins_uhs>;
+ pinctrl-names = "default", "state_uhs";
+
+ bus-width = <8>;
+ cap-mmc-hw-reset;
+ mmc-hs400-enhanced-strobe;
+ mmc-hs400-1_8v;
+ mmc-hs200-1_8v;
+ mmc-ddr-1_8v;
+ non-removable;
+ no-sdio;
+ no-sd;
+
+ sprd,phy-delay-mmc-ddr52 = <0x3f 0x75 0x14 0x14>;
+ sprd,phy-delay-mmc-hs200 = <0x0 0x8c 0x8c 0x8c>;
+ sprd,phy-delay-mmc-hs400 = <0x44 0x7f 0x2e 0x2e>;
+ sprd,phy-delay-mmc-hs400es = <0x3f 0x3f 0x2e 0x2e>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml b/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml
index 6c96a4204e5d..37e8b98f2cdc 100644
--- a/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml
+++ b/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml
@@ -30,6 +30,9 @@ properties:
- items:
- const: fsl,imx8dxl-ddr-pmu
- const: fsl,imx8-ddr-pmu
+ - items:
+ - const: fsl,imx95-ddr-pmu
+ - const: fsl,imx93-ddr-pmu
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml b/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml
index dab3d92bc273..15d74138baa3 100644
--- a/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml
+++ b/Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml
@@ -20,6 +20,8 @@ properties:
enum:
- amlogic,meson-a1-pwrc
- amlogic,meson-s4-pwrc
+ - amlogic,a4-pwrc
+ - amlogic,a5-pwrc
- amlogic,c3-pwrc
- amlogic,t7-pwrc
diff --git a/Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml b/Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml
new file mode 100644
index 000000000000..ec6115d3796b
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/adi,axi-pwmgen.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AXI PWM generator
+
+maintainers:
+ - Michael Hennerich <[email protected]>
+ - Nuno Sá <[email protected]>
+
+description:
+ The Analog Devices AXI PWM generator can generate PWM signals
+ with variable pulse width and period.
+
+ https://wiki.analog.com/resources/fpga/docs/axi_pwm_gen
+
+allOf:
+ - $ref: pwm.yaml#
+
+properties:
+ compatible:
+ const: adi,axi-pwmgen-2.00.a
+
+ reg:
+ maxItems: 1
+
+ "#pwm-cells":
+ const: 2
+
+ clocks:
+ maxItems: 1
+
+required:
+ - reg
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ pwm@44b00000 {
+ compatible = "adi,axi-pwmgen-2.00.a";
+ reg = <0x44b00000 0x1000>;
+ clocks = <&spi_clk>;
+ #pwm-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml b/Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml
index 96cd6f3c3546..d20ad27657aa 100644
--- a/Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml
@@ -23,7 +23,9 @@ properties:
- atmel,sama5d2-pwm
- microchip,sam9x60-pwm
- items:
- - const: microchip,sama7g5-pwm
+ - enum:
+ - microchip,sama7d65-pwm
+ - microchip,sama7g5-pwm
- const: atmel,sama5d2-pwm
- items:
- const: microchip,sam9x7-pwm
diff --git a/Documentation/devicetree/bindings/pwm/fsl,vf610-ftm-pwm.yaml b/Documentation/devicetree/bindings/pwm/fsl,vf610-ftm-pwm.yaml
new file mode 100644
index 000000000000..7f9f72d95e7a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/fsl,vf610-ftm-pwm.yaml
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/fsl,vf610-ftm-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale FlexTimer Module (FTM) PWM controller
+
+description: |
+ The same FTM PWM device can have a different endianness on different SoCs. The
+ device tree provides a property to describing this so that an operating system
+ device driver can handle all variants of the device. Refer to the table below
+ for the endianness of the FTM PWM block as integrated into the existing SoCs:
+
+ SoC | FTM-PWM endianness
+ --------+-------------------
+ Vybrid | LE
+ LS1 | BE
+ LS2 | LE
+
+ Please see ../regmap/regmap.txt for more detail about how to specify endian
+ modes in device tree.
+
+maintainers:
+ - Frank Li <[email protected]>
+
+properties:
+ compatible:
+ enum:
+ - fsl,vf610-ftm-pwm
+ - fsl,imx8qm-ftm-pwm
+
+ reg:
+ maxItems: 1
+
+ "#pwm-cells":
+ const: 3
+
+ clocks:
+ minItems: 4
+ maxItems: 4
+
+ clock-names:
+ items:
+ - const: ftm_sys
+ - const: ftm_ext
+ - const: ftm_fix
+ - const: ftm_cnt_clk_en
+
+ pinctrl-0: true
+ pinctrl-1: true
+
+ pinctrl-names:
+ minItems: 1
+ items:
+ - const: default
+ - const: sleep
+
+ big-endian:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Boolean property, required if the FTM PWM registers use a big-
+ endian rather than little-endian layout.
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+
+allOf:
+ - $ref: pwm.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/vf610-clock.h>
+
+ pwm@40038000 {
+ compatible = "fsl,vf610-ftm-pwm";
+ reg = <0x40038000 0x1000>;
+ #pwm-cells = <3>;
+ clocks = <&clks VF610_CLK_FTM0>,
+ <&clks VF610_CLK_FTM0_EXT_SEL>,
+ <&clks VF610_CLK_FTM0_FIX_SEL>,
+ <&clks VF610_CLK_FTM0_EXT_FIX_EN>;
+ clock-names = "ftm_sys", "ftm_ext", "ftm_fix", "ftm_cnt_clk_en";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0_1>;
+ big-endian;
+ };
diff --git a/Documentation/devicetree/bindings/pwm/imx-pwm.yaml b/Documentation/devicetree/bindings/pwm/imx-pwm.yaml
index a84a240a61dc..04148198e34d 100644
--- a/Documentation/devicetree/bindings/pwm/imx-pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/imx-pwm.yaml
@@ -68,7 +68,6 @@ required:
- reg
- clocks
- clock-names
- - interrupts
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt b/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
deleted file mode 100644
index 36532cd5ab25..000000000000
--- a/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-Freescale FlexTimer Module (FTM) PWM controller
-
-The same FTM PWM device can have a different endianness on different SoCs. The
-device tree provides a property to describing this so that an operating system
-device driver can handle all variants of the device. Refer to the table below
-for the endianness of the FTM PWM block as integrated into the existing SoCs:
-
- SoC | FTM-PWM endianness
- --------+-------------------
- Vybrid | LE
- LS1 | BE
- LS2 | LE
-
-Please see ../regmap/regmap.txt for more detail about how to specify endian
-modes in device tree.
-
-
-Required properties:
-- compatible : should be "fsl,<soc>-ftm-pwm" and one of the following
- compatible strings:
- - "fsl,vf610-ftm-pwm" for PWM compatible with the one integrated on VF610
- - "fsl,imx8qm-ftm-pwm" for PWM compatible with the one integrated on i.MX8QM
-- reg: Physical base address and length of the controller's registers
-- #pwm-cells: Should be 3. See pwm.yaml in this directory for a description of
- the cells format.
-- clock-names: Should include the following module clock source entries:
- "ftm_sys" (module clock, also can be used as counter clock),
- "ftm_ext" (external counter clock),
- "ftm_fix" (fixed counter clock),
- "ftm_cnt_clk_en" (external and fixed counter clock enable/disable).
-- clocks: Must contain a phandle and clock specifier for each entry in
- clock-names, please see clock/clock-bindings.txt for details of the property
- values.
-- pinctrl-names: Must contain a "default" entry.
-- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
- See pinctrl/pinctrl-bindings.txt for details of the property values.
-- big-endian: Boolean property, required if the FTM PWM registers use a big-
- endian rather than little-endian layout.
-
-Example:
-
-pwm0: pwm@40038000 {
- compatible = "fsl,vf610-ftm-pwm";
- reg = <0x40038000 0x1000>;
- #pwm-cells = <3>;
- clock-names = "ftm_sys", "ftm_ext",
- "ftm_fix", "ftm_cnt_clk_en";
- clocks = <&clks VF610_CLK_FTM0>,
- <&clks VF610_CLK_FTM0_EXT_SEL>,
- <&clks VF610_CLK_FTM0_FIX_SEL>,
- <&clks VF610_CLK_FTM0_EXT_FIX_EN>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_pwm0_1>;
- big-endian;
-};
diff --git a/Documentation/devicetree/bindings/pwm/pwm-gpio.yaml b/Documentation/devicetree/bindings/pwm/pwm-gpio.yaml
new file mode 100644
index 000000000000..1576c193f2ab
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-gpio.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/pwm-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Generic software PWM for modulating GPIOs
+
+maintainers:
+ - Stefan Wahren <[email protected]>
+
+allOf:
+ - $ref: pwm.yaml#
+
+properties:
+ compatible:
+ const: pwm-gpio
+
+ "#pwm-cells":
+ const: 3
+ description:
+ See pwm.yaml in this directory for a description of the cells format.
+ The first cell which represents the PWM instance number must always
+ be zero.
+
+ gpios:
+ description:
+ GPIO to be modulated
+ maxItems: 1
+
+required:
+ - compatible
+ - "#pwm-cells"
+ - gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ pwm {
+ #pwm-cells = <3>;
+ compatible = "pwm-gpio";
+ gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
+ };
diff --git a/Documentation/devicetree/bindings/pwm/pwm.yaml b/Documentation/devicetree/bindings/pwm/pwm.yaml
index abd9fa873354..f2206ec3c7c4 100644
--- a/Documentation/devicetree/bindings/pwm/pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/pwm.yaml
@@ -16,8 +16,10 @@ properties:
pattern: "^pwm(@.*|-([0-9]|[1-9][0-9]+))?$"
"#pwm-cells":
- description:
- Number of cells in a PWM specifier.
+ description: |
+ Number of cells in a PWM specifier. Typically the cells represent, in
+ order: the chip-relative PWM number, the PWM period in nanoseconds and
+ optionally a number of flags (defined in <dt-bindings/pwm/pwm.h>).
required:
- "#pwm-cells"
diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6873-dvfsrc-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6873-dvfsrc-regulator.yaml
new file mode 100644
index 000000000000..704828687970
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6873-dvfsrc-regulator.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/mediatek,mt6873-dvfsrc-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek DVFSRC-controlled Regulators
+
+description:
+ The Dynamic Voltage and Frequency Scaling Resource Collector Regulators
+ are controlled with votes to the DVFSRC hardware.
+
+maintainers:
+ - AngeloGioacchino Del Regno <[email protected]>
+
+properties:
+ compatible:
+ enum:
+ - mediatek,mt6873-dvfsrc-regulator
+ - mediatek,mt8183-dvfsrc-regulator
+ - mediatek,mt8192-dvfsrc-regulator
+ - mediatek,mt8195-dvfsrc-regulator
+
+ dvfsrc-vcore:
+ description: DVFSRC-controlled SoC Vcore regulator
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ dvfsrc-vscp:
+ description: DVFSRC-controlled System Control Processor regulator
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+required:
+ - compatible
+
+anyOf:
+ - required:
+ - dvfsrc-vcore
+ - required:
+ - dvfsrc-vscp
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/regulator/mt6315-regulator.yaml b/Documentation/devicetree/bindings/regulator/mt6315-regulator.yaml
index 6317daf76d1f..cd4aa27218a1 100644
--- a/Documentation/devicetree/bindings/regulator/mt6315-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/mt6315-regulator.yaml
@@ -16,7 +16,11 @@ description: |
properties:
compatible:
- const: mediatek,mt6315-regulator
+ oneOf:
+ - items:
+ - const: mediatek,mt6319-regulator
+ - const: mediatek,mt6315-regulator
+ - const: mediatek,mt6315-regulator
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml b/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml
index 849bfa50bdba..f8057bba747a 100644
--- a/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml
@@ -96,7 +96,6 @@ properties:
required:
- compatible
- reg
- - interrupts
- regulators
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml b/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
new file mode 100644
index 000000000000..3aaa9653419a
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
@@ -0,0 +1,185 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/qcom,qca6390-pmu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. QCA6390 PMU Regulators
+
+maintainers:
+ - Bartosz Golaszewski <[email protected]>
+
+description:
+ The QCA6390 package contains discrete modules for WLAN and Bluetooth. They
+ are powered by the Power Management Unit (PMU) that takes inputs from the
+ host and provides LDO outputs. This document describes this module.
+
+properties:
+ compatible:
+ enum:
+ - qcom,qca6390-pmu
+ - qcom,wcn7850-pmu
+
+ vdd-supply:
+ description: VDD supply regulator handle
+
+ vddaon-supply:
+ description: VDD_AON supply regulator handle
+
+ vdddig-supply:
+ description: VDD_DIG supply regulator handle
+
+ vddpmu-supply:
+ description: VDD_PMU supply regulator handle
+
+ vddio1p2-supply:
+ description: VDD_IO_1P2 supply regulator handle
+
+ vddrfa0p95-supply:
+ description: VDD_RFA_0P95 supply regulator handle
+
+ vddrfa1p2-supply:
+ description: VDD_RFA_1P2 supply regulator handle
+
+ vddrfa1p3-supply:
+ description: VDD_RFA_1P3 supply regulator handle
+
+ vddrfa1p8-supply:
+ description: VDD_RFA_1P8 supply regulator handle
+
+ vddrfa1p9-supply:
+ description: VDD_RFA_1P9 supply regulator handle
+
+ vddpcie1p3-supply:
+ description: VDD_PCIE_1P3 supply regulator handle
+
+ vddpcie1p9-supply:
+ description: VDD_PCIE_1P9 supply regulator handle
+
+ vddio-supply:
+ description: VDD_IO supply regulator handle
+
+ wlan-enable-gpios:
+ maxItems: 1
+ description: GPIO line enabling the ATH11K WLAN module supplied by the PMU
+
+ bt-enable-gpios:
+ maxItems: 1
+ description: GPIO line enabling the ATH11K Bluetooth module supplied by the PMU
+
+ clocks:
+ maxItems: 1
+ description: Reference clock handle
+
+ regulators:
+ type: object
+ description:
+ LDO outputs of the PMU
+
+ patternProperties:
+ "^ldo[0-9]$":
+ $ref: regulator.yaml#
+ type: object
+ unevaluatedProperties: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - regulators
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: qcom,qca6390-pmu
+ then:
+ required:
+ - vddaon-supply
+ - vddpmu-supply
+ - vddrfa0p95-supply
+ - vddrfa1p3-supply
+ - vddrfa1p9-supply
+ - vddpcie1p3-supply
+ - vddpcie1p9-supply
+ - vddio-supply
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: qcom,wcn7850-pmu
+ then:
+ required:
+ - vdd-supply
+ - vddio-supply
+ - vddaon-supply
+ - vdddig-supply
+ - vddrfa1p2-supply
+ - vddrfa1p8-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ pmu {
+ compatible = "qcom,qca6390-pmu";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_en_state>, <&wlan_en_state>;
+
+ vddaon-supply = <&vreg_s6a_0p95>;
+ vddpmu-supply = <&vreg_s2f_0p95>;
+ vddrfa0p95-supply = <&vreg_s2f_0p95>;
+ vddrfa1p3-supply = <&vreg_s8c_1p3>;
+ vddrfa1p9-supply = <&vreg_s5a_1p9>;
+ vddpcie1p3-supply = <&vreg_s8c_1p3>;
+ vddpcie1p9-supply = <&vreg_s5a_1p9>;
+ vddio-supply = <&vreg_s4a_1p8>;
+
+ wlan-enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>;
+ bt-enable-gpios = <&tlmm 21 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";
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml b/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml
index 609c06615bdc..87accc6f13b8 100644
--- a/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml
+++ b/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml
@@ -75,6 +75,12 @@ properties:
description:
regulator description for ldo[1-2].
+ properties:
+ richtek,fixed-microvolt:
+ description: |
+ This property can be used to set a fixed operating voltage that lies outside
+ the range of the regulator's adjustable mode.
+
required:
- compatible
- reg
@@ -177,6 +183,8 @@ examples:
};
};
ldo1 {
+ /* Fixed LDO VOUT */
+ richtek,fixed-microvolt = <1200000>;
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-always-on;
@@ -185,7 +193,8 @@ examples:
};
};
ldo2 {
- regulator-min-microvolt = <3300000>;
+ /* Adjustable LDO VOUT */
+ regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-state-mem {
diff --git a/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.txt b/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.txt
deleted file mode 100644
index 63dc07877cd6..000000000000
--- a/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-Spreadtrum SC2731 Voltage regulators
-
-The SC2731 integrates low-voltage and low quiescent current DCDC/LDO.
-14 LDO and 3 DCDCs are designed for external use. All DCDCs/LDOs have
-their own bypass (power-down) control signals. External tantalum or MLCC
-ceramic capacitors are recommended to use with these LDOs.
-
-Required properties:
- - compatible: should be "sprd,sc27xx-regulator".
-
-List of regulators provided by this controller. It is named according to
-its regulator type, BUCK_<name> and LDO_<name>. The definition for each
-of these nodes is defined using the standard binding for regulators at
-Documentation/devicetree/bindings/regulator/regulator.txt.
-
-The valid names for regulators are:
-BUCK:
- BUCK_CPU0, BUCK_CPU1, BUCK_RF
-LDO:
- LDO_CAMA0, LDO_CAMA1, LDO_CAMMOT, LDO_VLDO, LDO_EMMCCORE, LDO_SDCORE,
- LDO_SDIO, LDO_WIFIPA, LDO_USB33, LDO_CAMD0, LDO_CAMD1, LDO_CON,
- LDO_CAMIO, LDO_SRAM
-
-Example:
- regulators {
- compatible = "sprd,sc27xx-regulator";
-
- vddarm0: BUCK_CPU0 {
- regulator-name = "vddarm0";
- regulator-min-microvolt = <400000>;
- regulator-max-microvolt = <1996875>;
- regulator-ramp-delay = <25000>;
- regulator-always-on;
- };
-
- vddcama0: 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/sprd,sc2731-regulator.yaml b/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml
new file mode 100644
index 000000000000..ffb2924dde36
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/sprd,sc2731-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spreadtrum SC2731 Power Management IC regulators
+
+maintainers:
+ - Orson Zhai <[email protected]>
+ - Baolin Wang <[email protected]>
+ - Chunyan Zhang <[email protected]>
+
+description: |
+ The SC2731 integrates low-voltage and low quiescent current DCDC/LDO.
+ 14 LDO and 3 DCDCs are designed for external use. All DCDCs/LDOs have
+ their own bypass (power-down) control signals. It is recommended to use
+ external tantalum or MLCC ceramic capacitors with these LDOs.
+ Valid names for the regulators are:
+ BUCK:
+ BUCK_CPU0, BUCK_CPU1, BUCK_RF
+ LDO:
+ LDO_CAMA0, LDO_CAMA1, LDO_CAMD0, LDO_CAMD1, LDO_CAMIO, LDO_CAMMOT,
+ LDO_CON, LDO_EMMCCORE, LDO_SDCORE, LDO_SDIO, LDO_SRAM, LDO_USB33,
+ LDO_VLDO, LDO_WIFIPA
+
+properties:
+ compatible:
+ const: sprd,sc2731-regulator
+
+patternProperties:
+ "^BUCK_(CPU[0-1]|RF)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+ "^LDO_(CAM(A0|A1|D0|D1|IO|MOT)|CON|EMMCCORE|SD(CORE|IO)|SRAM|USB33|VLDO|WIFIPA)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+
+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/st,stm32mp1-pwr-reg.yaml b/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml
index c9586d277f41..3cb2dad18781 100644
--- a/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml
+++ b/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml
@@ -11,7 +11,12 @@ maintainers:
properties:
compatible:
- const: st,stm32mp1,pwr-reg
+ oneOf:
+ - items:
+ - const: st,stm32mp1,pwr-reg
+ - items:
+ - const: st,stm32mp13-pwr-reg
+ - const: st,stm32mp1,pwr-reg
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/regulator/ti,tps65132.yaml b/Documentation/devicetree/bindings/regulator/ti,tps65132.yaml
index 6a6d1a3d6fa7..873d92738eb0 100644
--- a/Documentation/devicetree/bindings/regulator/ti,tps65132.yaml
+++ b/Documentation/devicetree/bindings/regulator/ti,tps65132.yaml
@@ -23,6 +23,8 @@ properties:
reg:
maxItems: 1
+ vin-supply: true
+
patternProperties:
"^out[pn]$":
type: object
@@ -65,6 +67,7 @@ examples:
regulator@3e {
compatible = "ti,tps65132";
reg = <0x3e>;
+ vin-supply = <&supply>;
outp {
regulator-name = "outp";
diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt
deleted file mode 100644
index 549f80436deb..000000000000
--- a/Documentation/devicetree/bindings/regulator/twl-regulator.txt
+++ /dev/null
@@ -1,80 +0,0 @@
-TWL family of regulators
-
-Required properties:
-For twl6030 regulators/LDOs
-- compatible:
- - "ti,twl6030-vaux1" for VAUX1 LDO
- - "ti,twl6030-vaux2" for VAUX2 LDO
- - "ti,twl6030-vaux3" for VAUX3 LDO
- - "ti,twl6030-vmmc" for VMMC LDO
- - "ti,twl6030-vpp" for VPP LDO
- - "ti,twl6030-vusim" for VUSIM LDO
- - "ti,twl6030-vana" for VANA LDO
- - "ti,twl6030-vcxio" for VCXIO LDO
- - "ti,twl6030-vdac" for VDAC LDO
- - "ti,twl6030-vusb" for VUSB LDO
- - "ti,twl6030-v1v8" for V1V8 LDO
- - "ti,twl6030-v2v1" for V2V1 LDO
- - "ti,twl6030-vdd1" for VDD1 SMPS
- - "ti,twl6030-vdd2" for VDD2 SMPS
- - "ti,twl6030-vdd3" for VDD3 SMPS
-For twl6032 regulators/LDOs
-- compatible:
- - "ti,twl6032-ldo1" for LDO1 LDO
- - "ti,twl6032-ldo2" for LDO2 LDO
- - "ti,twl6032-ldo3" for LDO3 LDO
- - "ti,twl6032-ldo4" for LDO4 LDO
- - "ti,twl6032-ldo5" for LDO5 LDO
- - "ti,twl6032-ldo6" for LDO6 LDO
- - "ti,twl6032-ldo7" for LDO7 LDO
- - "ti,twl6032-ldoln" for LDOLN LDO
- - "ti,twl6032-ldousb" for LDOUSB LDO
- - "ti,twl6032-smps3" for SMPS3 SMPS
- - "ti,twl6032-smps4" for SMPS4 SMPS
- - "ti,twl6032-vio" for VIO SMPS
-For twl4030 regulators/LDOs
-- compatible:
- - "ti,twl4030-vaux1" for VAUX1 LDO
- - "ti,twl4030-vaux2" for VAUX2 LDO
- - "ti,twl5030-vaux2" for VAUX2 LDO
- - "ti,twl4030-vaux3" for VAUX3 LDO
- - "ti,twl4030-vaux4" for VAUX4 LDO
- - "ti,twl4030-vmmc1" for VMMC1 LDO
- - "ti,twl4030-vmmc2" for VMMC2 LDO
- - "ti,twl4030-vpll1" for VPLL1 LDO
- - "ti,twl4030-vpll2" for VPLL2 LDO
- - "ti,twl4030-vsim" for VSIM LDO
- - "ti,twl4030-vdac" for VDAC LDO
- - "ti,twl4030-vintana2" for VINTANA2 LDO
- - "ti,twl4030-vio" for VIO LDO
- - "ti,twl4030-vdd1" for VDD1 SMPS
- - "ti,twl4030-vdd2" for VDD2 SMPS
- - "ti,twl4030-vintana1" for VINTANA1 LDO
- - "ti,twl4030-vintdig" for VINTDIG LDO
- - "ti,twl4030-vusb1v5" for VUSB1V5 LDO
- - "ti,twl4030-vusb1v8" for VUSB1V8 LDO
- - "ti,twl4030-vusb3v1" for VUSB3V1 LDO
-
-Optional properties:
-- Any optional property defined in bindings/regulator/regulator.txt
-For twl4030 regulators/LDOs:
- - regulator-initial-mode:
- - 0x08 - Sleep mode, the nominal output voltage is maintained with low power
- consumption with low load current capability.
- - 0x0e - Active mode, the regulator can deliver its nominal output voltage
- with full-load current capability.
-
-Example:
-
- xyz: regulator@0 {
- compatible = "ti,twl6030-vaux1";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <3000000>;
- };
-
-For twl6030 regulators/LDOs:
-
- - ti,retain-on-reset: Does not turn off the supplies during warm
- reset. Could be needed for VMMC, as TWL6030
- reset sequence for this signal does not comply
- with the SD specification.
diff --git a/Documentation/devicetree/bindings/reset/renesas,rzg2l-usbphy-ctrl.yaml b/Documentation/devicetree/bindings/reset/renesas,rzg2l-usbphy-ctrl.yaml
index 03c18611e42d..b0b20af15313 100644
--- a/Documentation/devicetree/bindings/reset/renesas,rzg2l-usbphy-ctrl.yaml
+++ b/Documentation/devicetree/bindings/reset/renesas,rzg2l-usbphy-ctrl.yaml
@@ -42,6 +42,12 @@ properties:
0 = Port 1 Phy reset
1 = Port 2 Phy reset
+ regulator-vbus:
+ type: object
+ description: USB VBUS regulator
+ $ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
+
required:
- compatible
- reg
@@ -49,6 +55,7 @@ required:
- resets
- power-domains
- '#reset-cells'
+ - regulator-vbus
additionalProperties: false
@@ -64,4 +71,7 @@ examples:
resets = <&cpg R9A07G044_USB_PRESETN>;
power-domains = <&cpg>;
#reset-cells = <1>;
+ regulator-vbus {
+ regulator-name = "vbus";
+ };
};
diff --git a/Documentation/devicetree/bindings/reset/ti,sci-reset.yaml b/Documentation/devicetree/bindings/reset/ti,sci-reset.yaml
index e10eb98eddad..1db08ce9ae27 100644
--- a/Documentation/devicetree/bindings/reset/ti,sci-reset.yaml
+++ b/Documentation/devicetree/bindings/reset/ti,sci-reset.yaml
@@ -37,7 +37,7 @@ properties:
The second cell should contain the reset mask corresponding to the device
used by system controller.
- Please see http://processors.wiki.ti.com/index.php/TISCI for
+ Please see https://software-dl.ti.com/tisci/esd/latest/index.html for
protocol documentation for the values to be used for different devices.
diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml
index d87dd50f1a4b..d067f2a468ee 100644
--- a/Documentation/devicetree/bindings/riscv/cpus.yaml
+++ b/Documentation/devicetree/bindings/riscv/cpus.yaml
@@ -47,6 +47,7 @@ properties:
- sifive,u74
- sifive,u74-mc
- thead,c906
+ - thead,c908
- thead,c910
- thead,c920
- const: riscv
diff --git a/Documentation/devicetree/bindings/riscv/microchip.yaml b/Documentation/devicetree/bindings/riscv/microchip.yaml
index 4a29c890619a..78ce76ae1b6d 100644
--- a/Documentation/devicetree/bindings/riscv/microchip.yaml
+++ b/Documentation/devicetree/bindings/riscv/microchip.yaml
@@ -29,6 +29,7 @@ properties:
- enum:
- aldec,tysom-m-mpfs250t-rev2
- aries,m100pfsevp
+ - beagle,beaglev-fire
- microchip,mpfs-sev-kit
- sundance,polarberry
- const: microchip,mpfs
diff --git a/Documentation/devicetree/bindings/riscv/starfive.yaml b/Documentation/devicetree/bindings/riscv/starfive.yaml
index b672f8521949..4d5c857b3cac 100644
--- a/Documentation/devicetree/bindings/riscv/starfive.yaml
+++ b/Documentation/devicetree/bindings/riscv/starfive.yaml
@@ -27,6 +27,7 @@ properties:
- items:
- enum:
- milkv,mars
+ - pine64,star64
- starfive,visionfive-2-v1.2a
- starfive,visionfive-2-v1.3b
- const: starfive,jh7110
diff --git a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
deleted file mode 100644
index d10cc06c0c37..000000000000
--- a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-Device tree bindings for Marvell PXA SSP ports
-
-Required properties:
-
- - compatible: Must be one of
- mrvl,pxa25x-ssp
- mvrl,pxa25x-nssp
- mrvl,pxa27x-ssp
- mrvl,pxa3xx-ssp
- mvrl,pxa168-ssp
- mrvl,pxa910-ssp
- mrvl,ce4100-ssp
-
- - reg: The memory base
- - dmas: Two dma phandles, one for rx, one for tx
- - dma-names: Must be "rx", "tx"
-
-
-Example for PXA3xx:
-
- ssp0: ssp@41000000 {
- compatible = "mrvl,pxa3xx-ssp";
- reg = <0x41000000 0x40>;
- ssp-id = <1>;
- interrupts = <24>;
- clock-names = "pxa27x-ssp.0";
- dmas = <&dma 13
- &dma 14>;
- dma-names = "rx", "tx";
- };
-
- ssp1: ssp@41700000 {
- compatible = "mrvl,pxa3xx-ssp";
- reg = <0x41700000 0x40>;
- ssp-id = <2>;
- interrupts = <16>;
- clock-names = "pxa27x-ssp.1";
- dmas = <&dma 15
- &dma 16>;
- dma-names = "rx", "tx";
- };
-
- ssp2: ssp@41900000 {
- compatibl3 = "mrvl,pxa3xx-ssp";
- reg = <0x41900000 0x40>;
- ssp-id = <3>;
- interrupts = <0>;
- clock-names = "pxa27x-ssp.2";
- dmas = <&dma 66
- &dma 67>;
- dma-names = "rx", "tx";
- };
-
- ssp3: ssp@41a00000 {
- compatible = "mrvl,pxa3xx-ssp";
- reg = <0x41a00000 0x40>;
- ssp-id = <4>;
- interrupts = <13>;
- clock-names = "pxa27x-ssp.3";
- dmas = <&dma 2
- &dma 3>;
- dma-names = "rx", "tx";
- };
-
diff --git a/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-dcfg.yaml b/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-dcfg.yaml
index ce1a6505eb51..3fb0534ea597 100644
--- a/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-dcfg.yaml
+++ b/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-dcfg.yaml
@@ -8,7 +8,6 @@ title: Freescale Layerscape Device Configuration Unit
maintainers:
- Shawn Guo <[email protected]>
- - Li Yang <[email protected]>
description: |
DCFG is the device configuration unit, that provides general purpose
diff --git a/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-scfg.yaml b/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-scfg.yaml
index a6a511b00a12..2a456c8af992 100644
--- a/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-scfg.yaml
+++ b/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-scfg.yaml
@@ -8,7 +8,6 @@ title: Freescale Layerscape Supplemental Configuration Unit
maintainers:
- Shawn Guo <[email protected]>
- - Li Yang <[email protected]>
description: |
SCFG is the supplemental configuration unit, that provides SoC specific
diff --git a/Documentation/devicetree/bindings/soc/hisilicon/hisilicon,hi3660-usb3-otg-bc.yaml b/Documentation/devicetree/bindings/soc/hisilicon/hisilicon,hi3660-usb3-otg-bc.yaml
new file mode 100644
index 000000000000..5c77c4925d19
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/hisilicon/hisilicon,hi3660-usb3-otg-bc.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/hisilicon/hisilicon,hi3660-usb3-otg-bc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Hisilicon Kirin 960 USB OTG Battery Charging Syscon
+
+maintainers:
+ - Mauro Carvalho Chehab <[email protected]>
+
+properties:
+ compatible:
+ items:
+ - const: hisilicon,hi3660-usb3-otg-bc
+ - const: syscon
+ - const: simple-mfd
+
+ reg:
+ maxItems: 1
+
+ usb-phy:
+ $ref: /schemas/phy/hisilicon,hi3660-usb3.yaml
+ description: USB Phy node
+
+required:
+ - compatible
+ - reg
+ - usb-phy
+
+additionalProperties: false
+
+examples:
+ - |
+ syscon@ff200000 {
+ compatible = "hisilicon,hi3660-usb3-otg-bc", "syscon", "simple-mfd";
+ reg = <0xff200000 0x1000>;
+
+ usb-phy {
+ compatible = "hisilicon,hi3660-usb-phy";
+ #phy-cells = <0>;
+ hisilicon,pericrg-syscon = <&crg_ctrl>;
+ hisilicon,pctrl-syscon = <&pctrl>;
+ hisilicon,eye-diagram-param = <0x22466e4>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
index ba2014a8725c..a10326a9683d 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
@@ -33,6 +33,7 @@ properties:
- mediatek,mt8186-disp-mutex
- mediatek,mt8186-mdp3-mutex
- mediatek,mt8188-disp-mutex
+ - mediatek,mt8188-vpp-mutex
- mediatek,mt8192-disp-mutex
- mediatek,mt8195-disp-mutex
- mediatek,mt8195-vpp-mutex
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
index b4478f417edc..7afdb60edb22 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
@@ -31,6 +31,7 @@ properties:
- qcom,sc7280-aoss-qmp
- qcom,sc8180x-aoss-qmp
- qcom,sc8280xp-aoss-qmp
+ - qcom,sdx75-aoss-qmp
- qcom,sdm845-aoss-qmp
- qcom,sm6350-aoss-qmp
- qcom,sm8150-aoss-qmp
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml
index 58500529b90f..141d666dc3f7 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml
@@ -41,6 +41,7 @@ properties:
description:
Three entries specifying the outgoing ipc bit used for signaling the
remote end of the smp2p edge.
+ deprecated: true
qcom,local-pid:
$ref: /schemas/types.yaml#/definitions/uint32
@@ -128,7 +129,7 @@ examples:
compatible = "qcom,smp2p";
qcom,smem = <431>, <451>;
interrupts = <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 18>;
+ mboxes = <&apcs 18>;
qcom,local-pid = <0>;
qcom,remote-pid = <4>;
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smsm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smsm.yaml
index db67cf043256..4900215f26af 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smsm.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smsm.yaml
@@ -33,6 +33,14 @@ properties:
specifier of the column in the subscription matrix representing the local
processor.
+ mboxes:
+ minItems: 1
+ maxItems: 5
+ description:
+ Reference to the mailbox representing the outgoing doorbell in APCS for
+ this client. Each entry represents the N:th remote processor by index
+ (0-indexed).
+
'#size-cells':
const: 0
@@ -47,6 +55,7 @@ patternProperties:
description:
Three entries specifying the outgoing ipc bit used for signaling the N:th
remote processor.
+ deprecated: true
"@[0-9a-f]$":
type: object
@@ -98,15 +107,18 @@ required:
- '#address-cells'
- '#size-cells'
-anyOf:
- - required:
- - qcom,ipc-1
- - required:
- - qcom,ipc-2
- - required:
- - qcom,ipc-3
+oneOf:
- required:
- - qcom,ipc-4
+ - mboxes
+ - anyOf:
+ - required:
+ - qcom,ipc-1
+ - required:
+ - qcom,ipc-2
+ - required:
+ - qcom,ipc-3
+ - required:
+ - qcom,ipc-4
additionalProperties: false
@@ -122,7 +134,7 @@ examples:
compatible = "qcom,smsm";
#address-cells = <1>;
#size-cells = <0>;
- qcom,ipc-3 = <&apcs 8 19>;
+ mboxes = <0>, <0>, <0>, <&apcs 19>;
apps_smsm: apps@0 {
reg = <0>;
diff --git a/Documentation/devicetree/bindings/soc/sti/st,sti-syscon.yaml b/Documentation/devicetree/bindings/soc/sti/st,sti-syscon.yaml
index 5f97d9ff17fb..fc933d70d138 100644
--- a/Documentation/devicetree/bindings/soc/sti/st,sti-syscon.yaml
+++ b/Documentation/devicetree/bindings/soc/sti/st,sti-syscon.yaml
@@ -30,6 +30,15 @@ properties:
reg:
maxItems: 1
+ sti-sasg-codec:
+ description: STi internal audio codec
+ type: object
+ additionalProperties: true
+
+ properties:
+ compatible:
+ const: st,stih407-sas-codec
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.yaml b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.yaml
index a750035d6234..b6da72032151 100644
--- a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.yaml
+++ b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.yaml
@@ -40,7 +40,7 @@ properties:
TI_SCI_PD_SHARED - Allows the device to be shared by multiple hosts.
Please refer to dt-bindings/soc/ti,sci_pm_domain.h for the definitions.
- Please see http://processors.wiki.ti.com/index.php/TISCI for
+ Please see https://software-dl.ti.com/tisci/esd/latest/index.html for
protocol documentation for the values to be used for different devices.
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml b/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
index e6289fbe6907..378e9cc5fac2 100644
--- a/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml
+++ b/Documentation/devicetree/bindings/soc/ti/ti,j721e-system-controller.yaml
@@ -2,7 +2,7 @@
# Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
%YAML 1.2
---
-$id: http://devicetree.org/schemas/mfd/ti,j721e-system-controller.yaml#
+$id: http://devicetree.org/schemas/soc/ti/ti,j721e-system-controller.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI J721e System Controller Registers R/W
@@ -19,7 +19,7 @@ description: |
and access the registers directly.
maintainers:
- - Kishon Vijay Abraham I <[email protected]>
+ - Kishon Vijay Abraham I <[email protected]>
- Roger Quadros <[email protected]>
properties:
diff --git a/Documentation/devicetree/bindings/spi/amlogic,a1-spifc.yaml b/Documentation/devicetree/bindings/spi/amlogic,a1-spifc.yaml
index ea47d30eef43..043879b434ac 100644
--- a/Documentation/devicetree/bindings/spi/amlogic,a1-spifc.yaml
+++ b/Documentation/devicetree/bindings/spi/amlogic,a1-spifc.yaml
@@ -23,6 +23,9 @@ properties:
clocks:
maxItems: 1
+ power-domains:
+ maxItems: 1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml b/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml
index 32e7c14033c2..d29772994cf5 100644
--- a/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml
@@ -18,10 +18,10 @@ properties:
oneOf:
- const: atmel,at91rm9200-spi
- items:
- - const: microchip,sam9x60-spi
- - const: atmel,at91rm9200-spi
- - items:
- - const: microchip,sam9x7-spi
+ - enum:
+ - microchip,sam9x60-spi
+ - microchip,sam9x7-spi
+ - microchip,sama7d65-spi
- const: atmel,at91rm9200-spi
reg:
diff --git a/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt
deleted file mode 100644
index 3d55dd64b1be..000000000000
--- a/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-Broadcom BCM2835 SPI0 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 SPI0 controller.
-
-Required properties:
-- compatible: Should be one of "brcm,bcm2835-spi" for BCM2835/2836/2837 or
- "brcm,bcm2711-spi" for BCM2711 or "brcm,bcm7211-spi" for BCM7211.
-- reg: Should contain register location and length.
-- interrupts: Should contain interrupt.
-- clocks: The clock feeding the SPI controller.
-
-Example:
-
-spi@20204000 {
- compatible = "brcm,bcm2835-spi";
- reg = <0x7e204000 0x1000>;
- interrupts = <2 22>;
- clocks = <&clk_spi>;
- #address-cells = <1>;
- #size-cells = <0>;
-};
diff --git a/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml
new file mode 100644
index 000000000000..94da68792194
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/brcm,bcm2835-spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM2835 SPI0 controller
+
+maintainers:
+ - Florian Fainelli <[email protected]>
+ - Kanak Shilledar <[email protected]>
+ - Stefan Wahren <[email protected]>
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+properties:
+ compatible:
+ enum:
+ - brcm,bcm2835-spi
+ - brcm,bcm2711-spi
+ - brcm,bcm7211-spi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi@20204000 {
+ compatible = "brcm,bcm2835-spi";
+ reg = <0x7e204000 0x1000>;
+ interrupts = <2 22>;
+ clocks = <&clk_spi>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/spi/fsl,dspi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/fsl,dspi-peripheral-props.yaml
new file mode 100644
index 000000000000..9b62b75e17a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/fsl,dspi-peripheral-props.yaml
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/fsl,dspi-peripheral-props.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Peripheral-specific properties for Freescale DSPI controller
+
+maintainers:
+ - Vladimir Oltean <[email protected]>
+
+description:
+ See spi-peripheral-props.yaml for more info.
+
+properties:
+ fsl,spi-cs-sck-delay:
+ deprecated: true
+ description:
+ Delay in nanoseconds between activating chip select and the start of
+ clock signal, at the start of a transfer.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ fsl,spi-sck-cs-delay:
+ deprecated: true
+ description:
+ Delay in nanoseconds between stopping the clock signal and
+ deactivating chip select, at the end of a transfer.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/spi/fsl,dspi.yaml b/Documentation/devicetree/bindings/spi/fsl,dspi.yaml
new file mode 100644
index 000000000000..7ca8fceda717
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/fsl,dspi.yaml
@@ -0,0 +1,116 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/fsl,dspi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ARM Freescale DSPI controller
+
+maintainers:
+ - Frank Li <[email protected]>
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - fsl,vf610-dspi
+ - fsl,ls1021a-v1.0-dspi
+ - fsl,ls1012a-dspi
+ - fsl,ls1028a-dspi
+ - fsl,ls1043a-dspi
+ - fsl,ls1046a-dspi
+ - fsl,ls1088a-dspi
+ - fsl,ls2080a-dspi
+ - fsl,ls2085a-dspi
+ - fsl,lx2160a-dspi
+ - items:
+ - enum:
+ - fsl,ls1012a-dspi
+ - fsl,ls1028a-dspi
+ - fsl,ls1043a-dspi
+ - fsl,ls1046a-dspi
+ - fsl,ls1088a-dspi
+ - const: fsl,ls1021a-v1.0-dspi
+ - items:
+ - const: fsl,ls2080a-dspi
+ - const: fsl,ls2085a-dspi
+ - items:
+ - const: fsl,lx2160a-dspi
+ - const: fsl,ls2085a-dspi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: dspi
+
+ dmas:
+ items:
+ - description: DMA controller phandle and request line for TX
+ - description: DMA controller phandle and request line for RX
+
+ dma-names:
+ items:
+ - const: tx
+ - const: rx
+
+ spi-num-chipselects:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ The number of the chip native chipselect signals.
+ cs-gpios don't count against this number.
+
+ big-endian: true
+
+ bus-num:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: SoC-specific identifier for the SPI controller.
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - spi-num-chipselects
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/vf610-clock.h>
+
+ spi@4002c000 {
+ compatible = "fsl,vf610-dspi";
+ reg = <0x4002c000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks VF610_CLK_DSPI0>;
+ clock-names = "dspi";
+ spi-num-chipselects = <5>;
+ bus-num = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dspi0_1>;
+ big-endian;
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <16000000>;
+ spi-cpol;
+ spi-cpha;
+ spi-cs-setup-delay-ns = <100>;
+ spi-cs-hold-delay-ns = <50>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml b/Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml
new file mode 100644
index 000000000000..d7fec4c3a801
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/ibm,spi-fsi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IBM FSI-attached SPI Controller
+
+maintainers:
+ - Eddie James <[email protected]>
+
+description:
+ A SPI controller found on IBM Power processors, accessed over FSI from a
+ service processor. This node will always be a child node of an ibm,fsi2spi
+ node.
+
+properties:
+ compatible:
+ enum:
+ - ibm,spi-fsi
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ fsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ spi@0 {
+ compatible = "ibm,spi-fsi";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ compatible = "atmel,at25";
+ reg = <0>;
+ size = <0x80000>;
+ address-width = <24>;
+ pagesize = <256>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml b/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml
index 5f4f6b5615d0..0a1bada8f800 100644
--- a/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml
+++ b/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml
@@ -10,12 +10,17 @@ title: PXA2xx SSP SPI Controller
maintainers:
- Lubomir Rintel <[email protected]>
-allOf:
- - $ref: spi-controller.yaml#
-
properties:
compatible:
- const: marvell,mmp2-ssp
+ enum:
+ - marvell,mmp2-ssp
+ - mrvl,ce4100-ssp
+ - mvrl,pxa168-ssp
+ - mrvl,pxa25x-ssp
+ - mvrl,pxa25x-nssp
+ - mrvl,pxa27x-ssp
+ - mrvl,pxa3xx-ssp
+ - mrvl,pxa910-ssp
interrupts:
maxItems: 1
@@ -26,6 +31,16 @@ properties:
clocks:
maxItems: 1
+ dmas:
+ items:
+ - description: Receive DMA
+ - description: Transmit DMA
+
+ dma-names:
+ items:
+ - const: rx
+ - const: tx
+
ready-gpios:
description: |
GPIO used to signal a SPI master that the FIFO is filled and we're
@@ -41,6 +56,18 @@ required:
dependencies:
ready-gpios: [ spi-slave ]
+allOf:
+ - $ref: spi-controller.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: marvell,mmp2-ssp
+ then:
+ properties:
+ dmas: false
+ dma-names: false
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml
index 74a817cc7d94..ffa8d1b48f8b 100644
--- a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml
@@ -13,9 +13,6 @@ description:
maintainers:
- Conor Dooley <[email protected]>
-allOf:
- - $ref: spi-controller.yaml#
-
properties:
compatible:
oneOf:
@@ -43,6 +40,32 @@ required:
- interrupts
- clocks
+allOf:
+ - $ref: spi-controller.yaml#
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: microchip,mpfs-spi
+ then:
+ properties:
+ num-cs:
+ default: 1
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: microchip,mpfs-spi
+ not:
+ required:
+ - cs-gpios
+ then:
+ properties:
+ num-cs:
+ maximum: 1
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
index fde3776a558b..bccd00a1ddd0 100644
--- a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
+++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
@@ -88,6 +88,10 @@ properties:
- renesas,r9a06g032-spi # RZ/N1D
- renesas,r9a06g033-spi # RZ/N1S
- const: renesas,rzn1-spi # RZ/N1
+ - description: T-HEAD TH1520 SoC SPI Controller
+ items:
+ - const: thead,th1520-spi
+ - const: snps,dw-apb-ssi
reg:
minItems: 1
diff --git a/Documentation/devicetree/bindings/spi/spi-cadence.yaml b/Documentation/devicetree/bindings/spi/spi-cadence.yaml
index d4b61b0e8301..8de96abe9da1 100644
--- a/Documentation/devicetree/bindings/spi/spi-cadence.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-cadence.yaml
@@ -55,6 +55,13 @@ properties:
label:
description: Descriptive name of the SPI controller.
+ resets:
+ maxItems: 1
+
+ reset-names:
+ items:
+ - const: spi
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
deleted file mode 100644
index 30a79da9c039..000000000000
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ /dev/null
@@ -1,65 +0,0 @@
-ARM Freescale DSPI controller
-
-Required properties:
-- compatible : must be one of:
- "fsl,vf610-dspi",
- "fsl,ls1021a-v1.0-dspi",
- "fsl,ls1012a-dspi" (optionally followed by "fsl,ls1021a-v1.0-dspi"),
- "fsl,ls1028a-dspi",
- "fsl,ls1043a-dspi" (optionally followed by "fsl,ls1021a-v1.0-dspi"),
- "fsl,ls1046a-dspi" (optionally followed by "fsl,ls1021a-v1.0-dspi"),
- "fsl,ls1088a-dspi" (optionally followed by "fsl,ls1021a-v1.0-dspi"),
- "fsl,ls2080a-dspi" (optionally followed by "fsl,ls2085a-dspi"),
- "fsl,ls2085a-dspi",
- "fsl,lx2160a-dspi",
-- reg : Offset and length of the register set for the device
-- interrupts : Should contain SPI controller interrupt
-- clocks: from common clock binding: handle to dspi clock.
-- clock-names: from common clock binding: Shall be "dspi".
-- pinctrl-0: pin control group to be used for this controller.
-- pinctrl-names: must contain a "default" entry.
-- spi-num-chipselects : the number of the chipselect signals.
-
-Optional property:
-- big-endian: If present the dspi device's registers are implemented
- in big endian mode.
-- bus-num : the slave chip chipselect signal number.
-
-Optional SPI slave node properties:
-- fsl,spi-cs-sck-delay: a delay in nanoseconds between activating chip
- select and the start of clock signal, at the start of a transfer.
-- fsl,spi-sck-cs-delay: a delay in nanoseconds between stopping the clock
- signal and deactivating chip select, at the end of a transfer.
-
-Example:
-
-dspi0@4002c000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,vf610-dspi";
- reg = <0x4002c000 0x1000>;
- interrupts = <0 67 0x04>;
- clocks = <&clks VF610_CLK_DSPI0>;
- clock-names = "dspi";
- spi-num-chipselects = <5>;
- bus-num = <0>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_dspi0_1>;
- big-endian;
-
- sflash: at26df081a@0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "atmel,at26df081a";
- spi-max-frequency = <16000000>;
- spi-cpol;
- spi-cpha;
- reg = <0>;
- linux,modalias = "m25p80";
- modal = "at26df081a";
- fsl,spi-cs-sck-delay = <100>;
- fsl,spi-sck-cs-delay = <50>;
- };
-};
-
-
diff --git a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
index 15938f81fdce..0bb443b8decd 100644
--- a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
@@ -122,6 +122,7 @@ properties:
allOf:
- $ref: arm,pl022-peripheral-props.yaml#
- $ref: cdns,qspi-nor-peripheral-props.yaml#
+ - $ref: fsl,dspi-peripheral-props.yaml#
- $ref: samsung,spi-peripheral-props.yaml#
- $ref: nvidia,tegra210-quad-peripheral-props.yaml#
diff --git a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
index cf07b8f787a6..d9322704f358 100644
--- a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
+++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
@@ -56,6 +56,9 @@ properties:
ranges: true
patternProperties:
+ "^regulators@[0-9a-f]+$":
+ $ref: /schemas/regulator/allwinner,sun20i-d1-system-ldos.yaml#
+
"^sram@[a-f0-9]+":
$ref: /schemas/sram/sram.yaml#
unevaluatedProperties: false
@@ -130,3 +133,28 @@ examples:
};
};
};
+
+ - |
+ syscon@3000000 {
+ compatible = "allwinner,sun20i-d1-system-control";
+ reg = <0x3000000 0x1000>;
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ regulators@3000150 {
+ compatible = "allwinner,sun20i-d1-system-ldos";
+ reg = <0x3000150 0x4>;
+
+ reg_ldoa: ldoa {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_ldob: ldob {
+ regulator-name = "vcc-dram";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sram/qcom,imem.yaml b/Documentation/devicetree/bindings/sram/qcom,imem.yaml
index 8025a852bc9c..faef3d6e0a94 100644
--- a/Documentation/devicetree/bindings/sram/qcom,imem.yaml
+++ b/Documentation/devicetree/bindings/sram/qcom,imem.yaml
@@ -22,6 +22,7 @@ properties:
- qcom,msm8974-imem
- qcom,qcs404-imem
- qcom,qdu1000-imem
+ - qcom,sa8775p-imem
- qcom,sc7180-imem
- qcom,sc7280-imem
- qcom,sdm630-imem
diff --git a/Documentation/devicetree/bindings/timer/realtek,otto-timer.yaml b/Documentation/devicetree/bindings/timer/realtek,otto-timer.yaml
new file mode 100644
index 000000000000..7b6ec2c69484
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/realtek,otto-timer.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/timer/realtek,otto-timer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek Otto SoCs Timer/Counter
+
+description:
+ Realtek SoCs support a number of timers/counters. These are used
+ as a per CPU clock event generator and an overall CPU clocksource.
+
+maintainers:
+ - Chris Packham <[email protected]>
+
+properties:
+ $nodename:
+ pattern: "^timer@[0-9a-f]+$"
+
+ compatible:
+ items:
+ - enum:
+ - realtek,rtl9302-timer
+ - const: realtek,otto-timer
+
+ reg:
+ items:
+ - description: timer0 registers
+ - description: timer1 registers
+ - description: timer2 registers
+ - description: timer3 registers
+ - description: timer4 registers
+
+ clocks:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: timer0 interrupt
+ - description: timer1 interrupt
+ - description: timer2 interrupt
+ - description: timer3 interrupt
+ - description: timer4 interrupt
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ timer@3200 {
+ compatible = "realtek,rtl9302-timer", "realtek,otto-timer";
+ reg = <0x3200 0x10>, <0x3210 0x10>, <0x3220 0x10>,
+ <0x3230 0x10>, <0x3240 0x10>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <7>, <8>, <9>, <10>, <11>;
+ clocks = <&lx_clk>;
+ };
diff --git a/Documentation/devicetree/bindings/timer/renesas,tmu.yaml b/Documentation/devicetree/bindings/timer/renesas,tmu.yaml
index 360a5cf1ae9c..b6dd98d956f3 100644
--- a/Documentation/devicetree/bindings/timer/renesas,tmu.yaml
+++ b/Documentation/devicetree/bindings/timer/renesas,tmu.yaml
@@ -21,13 +21,24 @@ properties:
compatible:
items:
- enum:
+ - renesas,tmu-r8a73a4 # R-Mobile APE6
- renesas,tmu-r8a7740 # R-Mobile A1
+ - renesas,tmu-r8a7742 # RZ/G1H
+ - renesas,tmu-r8a7743 # RZ/G1M
+ - renesas,tmu-r8a7744 # RZ/G1N
+ - renesas,tmu-r8a7745 # RZ/G1E
+ - renesas,tmu-r8a77470 # RZ/G1C
- renesas,tmu-r8a774a1 # RZ/G2M
- renesas,tmu-r8a774b1 # RZ/G2N
- renesas,tmu-r8a774c0 # RZ/G2E
- renesas,tmu-r8a774e1 # RZ/G2H
- renesas,tmu-r8a7778 # R-Car M1A
- renesas,tmu-r8a7779 # R-Car H1
+ - renesas,tmu-r8a7790 # R-Car H2
+ - renesas,tmu-r8a7791 # R-Car M2-W
+ - renesas,tmu-r8a7792 # R-Car V2H
+ - renesas,tmu-r8a7793 # R-Car M2-N
+ - renesas,tmu-r8a7794 # R-Car E2
- renesas,tmu-r8a7795 # R-Car H3
- renesas,tmu-r8a7796 # R-Car M3-W
- renesas,tmu-r8a77961 # R-Car M3-W+
@@ -94,6 +105,7 @@ if:
compatible:
contains:
enum:
+ - renesas,tmu-r8a73a4
- renesas,tmu-r8a7740
- renesas,tmu-r8a7778
- renesas,tmu-r8a7779
diff --git a/Documentation/devicetree/bindings/timer/sifive,clint.yaml b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
index fced6f2d8ecb..b42d43d2de48 100644
--- a/Documentation/devicetree/bindings/timer/sifive,clint.yaml
+++ b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
@@ -40,6 +40,7 @@ properties:
- allwinner,sun20i-d1-clint
- sophgo,cv1800b-clint
- sophgo,cv1812h-clint
+ - sophgo,sg2002-clint
- thead,th1520-clint
- const: thead,c900-clint
- items:
diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml
index 0a419453d183..03e290cb65c3 100644
--- a/Documentation/devicetree/bindings/trivial-devices.yaml
+++ b/Documentation/devicetree/bindings/trivial-devices.yaml
@@ -168,6 +168,8 @@ properties:
- isil,isl69269
# Intersil ISL76682 Ambient Light Sensor
- isil,isl76682
+ # JEDEC JESD300 (SPD5118) Hub and Serial Presence Detect
+ - jedec,spd5118
# Linear Technology LTC2488
- lineartechnology,ltc2488
# 5 Bit Programmable, Pulse-Width Modulator
@@ -286,14 +288,22 @@ properties:
- mps,mp2857
# Monolithic Power Systems Inc. multi-phase controller mp2888
- 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
+ - mps,mp5920
# Monolithic Power Systems Inc. multi-phase hot-swap controller mp5990
- mps,mp5990
+ # Monolithic Power Systems Inc. digital step-down converter mp9941
+ - mps,mp9941
# Monolithic Power Systems Inc. synchronous step-down converter mpq8785
- mps,mpq8785
# Temperature sensor with integrated fan control
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index fbf47f0bacf1..87ec6772b2d4 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -338,6 +338,8 @@ patternProperties:
description: Czech Technical University in Prague
"^cubietech,.*":
description: Cubietech, Ltd.
+ "^cudy,.*":
+ description: Shenzhen Cudy Technology Co., Ltd.
"^cui,.*":
description: CUI Devices
"^cypress,.*":
@@ -394,6 +396,8 @@ patternProperties:
description: DPTechnics
"^dragino,.*":
description: Dragino Technology Co., Limited
+ "^dream,.*":
+ description: Dream Property GmbH
"^ds,.*":
description: DaSheng, Inc.
"^dserve,.*":
@@ -995,6 +999,8 @@ patternProperties:
description: MYIR Tech Limited
"^national,.*":
description: National Semiconductor
+ "^neardi,.*":
+ description: Shanghai Neardi Technology Co., Ltd.
"^nec,.*":
description: NEC LCD Technologies, Ltd.
"^neonode,.*":
@@ -1082,6 +1088,8 @@ patternProperties:
description: OpenPandora GmbH
"^openrisc,.*":
description: OpenRISC.io
+ "^openwrt,.*":
+ description: OpenWrt
"^option,.*":
description: Option NV
"^oranth,.*":
@@ -1254,6 +1262,8 @@ patternProperties:
description: Smart Battery System
"^schindler,.*":
description: Schindler
+ "^schneider,.*":
+ description: Schneider Electric
"^seagate,.*":
description: Seagate Technology PLC
"^seeed,.*":
diff --git a/Documentation/driver-api/cxl/memory-devices.rst b/Documentation/driver-api/cxl/memory-devices.rst
index 5149ecdc53c7..d732c42526df 100644
--- a/Documentation/driver-api/cxl/memory-devices.rst
+++ b/Documentation/driver-api/cxl/memory-devices.rst
@@ -328,6 +328,12 @@ CXL Memory Device
.. kernel-doc:: drivers/cxl/mem.c
:doc: cxl mem
+.. kernel-doc:: drivers/cxl/cxlmem.h
+ :internal:
+
+.. kernel-doc:: drivers/cxl/core/memdev.c
+ :identifiers:
+
CXL Port
--------
.. kernel-doc:: drivers/cxl/port.c
@@ -341,6 +347,15 @@ CXL Core
.. kernel-doc:: drivers/cxl/cxl.h
:internal:
+.. kernel-doc:: drivers/cxl/core/hdm.c
+ :doc: cxl core hdm
+
+.. kernel-doc:: drivers/cxl/core/hdm.c
+ :identifiers:
+
+.. kernel-doc:: drivers/cxl/core/cdat.c
+ :identifiers:
+
.. kernel-doc:: drivers/cxl/core/port.c
:doc: cxl core
diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst
index 18caebad7376..ac9ee7441887 100644
--- a/Documentation/driver-api/driver-model/devres.rst
+++ b/Documentation/driver-api/driver-model/devres.rst
@@ -464,7 +464,10 @@ SLAVE DMA ENGINE
SPI
devm_spi_alloc_master()
devm_spi_alloc_slave()
+ devm_spi_optimize_message()
devm_spi_register_controller()
+ devm_spi_register_host()
+ devm_spi_register_target()
WATCHDOG
devm_watchdog_register_device()
diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst
index b33aa04f213f..4fd1cbd8296e 100644
--- a/Documentation/driver-api/gpio/board.rst
+++ b/Documentation/driver-api/gpio/board.rst
@@ -4,12 +4,6 @@ GPIO Mappings
This document explains how GPIOs can be assigned to given devices and functions.
-Note that it only applies to the new descriptor-based interface. For a
-description of the deprecated integer-based GPIO interface please refer to
-legacy.rst (actually, there is no real mapping possible with the old
-interface; you just fetch an integer from somewhere and request the
-corresponding GPIO).
-
All platforms can enable the GPIO library, but if the platform strictly
requires GPIO functionality to be present, it needs to select GPIOLIB from its
Kconfig. Then, how GPIOs are mapped depends on what the platform uses to
diff --git a/Documentation/driver-api/gpio/consumer.rst b/Documentation/driver-api/gpio/consumer.rst
index ab56ab0dd7a6..bb3366047fad 100644
--- a/Documentation/driver-api/gpio/consumer.rst
+++ b/Documentation/driver-api/gpio/consumer.rst
@@ -2,9 +2,7 @@
GPIO Descriptor Consumer Interface
==================================
-This document describes the consumer interface of the GPIO framework. Note that
-it describes the new descriptor-based interface. For a description of the
-deprecated integer-based GPIO interface please refer to legacy.rst.
+This document describes the consumer interface of the GPIO framework.
Guidelines for GPIOs consumers
diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst
index e541bd2e898b..ae433261e11a 100644
--- a/Documentation/driver-api/gpio/driver.rst
+++ b/Documentation/driver-api/gpio/driver.rst
@@ -69,9 +69,8 @@ driver code:
The code implementing a gpio_chip should support multiple instances of the
controller, preferably using the driver model. That code will configure each
-gpio_chip and issue gpiochip_add(), gpiochip_add_data(), or
-devm_gpiochip_add_data(). Removing a GPIO controller should be rare; use
-gpiochip_remove() when it is unavoidable.
+gpio_chip and issue gpiochip_add_data() or devm_gpiochip_add_data(). Removing
+a GPIO controller should be rare; use gpiochip_remove() when it is unavoidable.
Often a gpio_chip is part of an instance-specific structure with states not
exposed by the GPIO interfaces, such as addressing, power management, and more.
diff --git a/Documentation/driver-api/gpio/drivers-on-gpio.rst b/Documentation/driver-api/gpio/drivers-on-gpio.rst
index af632d764ac6..95572d2a94ce 100644
--- a/Documentation/driver-api/gpio/drivers-on-gpio.rst
+++ b/Documentation/driver-api/gpio/drivers-on-gpio.rst
@@ -27,7 +27,12 @@ hardware descriptions such as device tree or ACPI:
to the lines for a more permanent solution of this type.
- gpio-beeper: drivers/input/misc/gpio-beeper.c is used to provide a beep from
- an external speaker connected to a GPIO line.
+ an external speaker connected to a GPIO line. (If the beep is controlled by
+ off/on, for an actual PWM waveform, see pwm-gpio below.)
+
+- pwm-gpio: drivers/pwm/pwm-gpio.c is used to toggle a GPIO with a high
+ resolution timer producing a PWM waveform on the GPIO line, as well as
+ Linux high resolution timers can do.
- extcon-gpio: drivers/extcon/extcon-gpio.c is used when you need to read an
external connector status, such as a headset line for an audio driver or an
diff --git a/Documentation/driver-api/gpio/index.rst b/Documentation/driver-api/gpio/index.rst
index 1d48fe248f05..34b57cee3391 100644
--- a/Documentation/driver-api/gpio/index.rst
+++ b/Documentation/driver-api/gpio/index.rst
@@ -13,7 +13,6 @@ Contents:
consumer
board
drivers-on-gpio
- legacy
bt8xxgpio
Core
diff --git a/Documentation/driver-api/gpio/intro.rst b/Documentation/driver-api/gpio/intro.rst
index c9c19243b97f..5936a9c57df3 100644
--- a/Documentation/driver-api/gpio/intro.rst
+++ b/Documentation/driver-api/gpio/intro.rst
@@ -10,18 +10,6 @@ The documents in this directory give detailed instructions on how to access
GPIOs in drivers, and how to write a driver for a device that provides GPIOs
itself.
-Due to the history of GPIO interfaces in the kernel, there are two different
-ways to obtain and use GPIOs:
-
- - The descriptor-based interface is the preferred way to manipulate GPIOs,
- and is described by all the files in this directory excepted legacy.rst.
- - The legacy integer-based interface which is considered deprecated (but still
- usable for compatibility reasons) is documented in legacy.rst.
-
-The remainder of this document applies to the new descriptor-based interface.
-legacy.rst contains the same information applied to the legacy
-integer-based interface.
-
What is a GPIO?
===============
diff --git a/Documentation/driver-api/gpio/legacy.rst b/Documentation/driver-api/gpio/legacy.rst
deleted file mode 100644
index 534dfe95d128..000000000000
--- a/Documentation/driver-api/gpio/legacy.rst
+++ /dev/null
@@ -1,679 +0,0 @@
-======================
-Legacy GPIO Interfaces
-======================
-
-This provides an overview of GPIO access conventions on Linux.
-
-These calls use the gpio_* naming prefix. No other calls should use that
-prefix, or the related __gpio_* prefix.
-
-
-What is a GPIO?
-===============
-A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
-digital signal. They are provided from many kinds of chip, and are familiar
-to Linux developers working with embedded and custom hardware. Each GPIO
-represents a bit connected to a particular pin, or "ball" on Ball Grid Array
-(BGA) packages. Board schematics show which external hardware connects to
-which GPIOs. Drivers can be written generically, so that board setup code
-passes such pin configuration data to drivers.
-
-System-on-Chip (SOC) processors heavily rely on GPIOs. In some cases, every
-non-dedicated pin can be configured as a GPIO; and most chips have at least
-several dozen of them. Programmable logic devices (like FPGAs) can easily
-provide GPIOs; multifunction chips like power managers, and audio codecs
-often have a few such pins to help with pin scarcity on SOCs; and there are
-also "GPIO Expander" chips that connect using the I2C or SPI serial busses.
-Most PC southbridges have a few dozen GPIO-capable pins (with only the BIOS
-firmware knowing how they're used).
-
-The exact capabilities of GPIOs vary between systems. Common options:
-
- - Output values are writable (high=1, low=0). Some chips also have
- options about how that value is driven, so that for example only one
- value might be driven ... supporting "wire-OR" and similar schemes
- for the other value (notably, "open drain" signaling).
-
- - Input values are likewise readable (1, 0). Some chips support readback
- of pins configured as "output", which is very useful in such "wire-OR"
- cases (to support bidirectional signaling). GPIO controllers may have
- input de-glitch/debounce logic, sometimes with software controls.
-
- - Inputs can often be used as IRQ signals, often edge triggered but
- sometimes level triggered. Such IRQs may be configurable as system
- wakeup events, to wake the system from a low power state.
-
- - Usually a GPIO will be configurable as either input or output, as needed
- by different product boards; single direction ones exist too.
-
- - Most GPIOs can be accessed while holding spinlocks, but those accessed
- through a serial bus normally can't. Some systems support both types.
-
-On a given board each GPIO is used for one specific purpose like monitoring
-MMC/SD card insertion/removal, detecting card writeprotect status, driving
-a LED, configuring a transceiver, bitbanging a serial bus, poking a hardware
-watchdog, sensing a switch, and so on.
-
-
-GPIO conventions
-================
-Note that this is called a "convention" because you don't need to do it this
-way, and it's no crime if you don't. There **are** cases where portability
-is not the main issue; GPIOs are often used for the kind of board-specific
-glue logic that may even change between board revisions, and can't ever be
-used on a board that's wired differently. Only least-common-denominator
-functionality can be very portable. Other features are platform-specific,
-and that can be critical for glue logic.
-
-Plus, this doesn't require any implementation framework, just an interface.
-One platform might implement it as simple inline functions accessing chip
-registers; another might implement it by delegating through abstractions
-used for several very different kinds of GPIO controller. (There is some
-optional code supporting such an implementation strategy, described later
-in this document, but drivers acting as clients to the GPIO interface must
-not care how it's implemented.)
-
-That said, if the convention is supported on their platform, drivers should
-use it when possible. Platforms must select GPIOLIB if GPIO functionality
-is strictly required. Drivers that can't work without
-standard GPIO calls should have Kconfig entries which depend on GPIOLIB. The
-GPIO calls are available, either as "real code" or as optimized-away stubs,
-when drivers use the include file:
-
- #include <linux/gpio.h>
-
-If you stick to this convention then it'll be easier for other developers to
-see what your code is doing, and help maintain it.
-
-Note that these operations include I/O barriers on platforms which need to
-use them; drivers don't need to add them explicitly.
-
-
-Identifying GPIOs
------------------
-GPIOs are identified by unsigned integers in the range 0..MAX_INT. That
-reserves "negative" numbers for other purposes like marking signals as
-"not available on this board", or indicating faults. Code that doesn't
-touch the underlying hardware treats these integers as opaque cookies.
-
-Platforms define how they use those integers, and usually #define symbols
-for the GPIO lines so that board-specific setup code directly corresponds
-to the relevant schematics. In contrast, drivers should only use GPIO
-numbers passed to them from that setup code, using platform_data to hold
-board-specific pin configuration data (along with other board specific
-data they need). That avoids portability problems.
-
-So for example one platform uses numbers 32-159 for GPIOs; while another
-uses numbers 0..63 with one set of GPIO controllers, 64-79 with another
-type of GPIO controller, and on one particular board 80-95 with an FPGA.
-The numbers need not be contiguous; either of those platforms could also
-use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders.
-
-If you want to initialize a structure with an invalid GPIO number, use
-some negative number (perhaps "-EINVAL"); that will never be valid. To
-test if such number from such a structure could reference a GPIO, you
-may use this predicate:
-
- int gpio_is_valid(int number);
-
-A number that's not valid will be rejected by calls which may request
-or free GPIOs (see below). Other numbers may also be rejected; for
-example, a number might be valid but temporarily unused on a given board.
-
-Whether a platform supports multiple GPIO controllers is a platform-specific
-implementation issue, as are whether that support can leave "holes" in the space
-of GPIO numbers, and whether new controllers can be added at runtime. Such issues
-can affect things including whether adjacent GPIO numbers are both valid.
-
-Using GPIOs
------------
-The first thing a system should do with a GPIO is allocate it, using
-the gpio_request() call; see later.
-
-One of the next things to do with a GPIO, often in board setup code when
-setting up a platform_device using the GPIO, is mark its direction::
-
- /* set as input or output, returning 0 or negative errno */
- int gpio_direction_input(unsigned gpio);
- int gpio_direction_output(unsigned gpio, int value);
-
-The return value is zero for success, else a negative errno. It should
-be checked, since the get/set calls don't have error returns and since
-misconfiguration is possible. You should normally issue these calls from
-a task context. However, for spinlock-safe GPIOs it's OK to use them
-before tasking is enabled, as part of early board setup.
-
-For output GPIOs, the value provided becomes the initial output value.
-This helps avoid signal glitching during system startup.
-
-For compatibility with legacy interfaces to GPIOs, setting the direction
-of a GPIO implicitly requests that GPIO (see below) if it has not been
-requested already. That compatibility is being removed from the optional
-gpiolib framework.
-
-Setting the direction can fail if the GPIO number is invalid, or when
-that particular GPIO can't be used in that mode. It's generally a bad
-idea to rely on boot firmware to have set the direction correctly, since
-it probably wasn't validated to do more than boot Linux. (Similarly,
-that board setup code probably needs to multiplex that pin as a GPIO,
-and configure pullups/pulldowns appropriately.)
-
-
-Spinlock-Safe GPIO access
--------------------------
-Most GPIO controllers can be accessed with memory read/write instructions.
-Those don't need to sleep, and can safely be done from inside hard
-(nonthreaded) IRQ handlers and similar contexts.
-
-Use the following calls to access such GPIOs::
-
- /* GPIO INPUT: return zero or nonzero */
- int gpio_get_value(unsigned gpio);
-
- /* GPIO OUTPUT */
- void gpio_set_value(unsigned gpio, int value);
-
-The values are boolean, zero for low, nonzero for high. When reading the
-value of an output pin, the value returned should be what's seen on the
-pin ... that won't always match the specified output value, because of
-issues including open-drain signaling and output latencies.
-
-The get/set calls have no error returns because "invalid GPIO" should have
-been reported earlier from gpio_direction_*(). However, note that not all
-platforms can read the value of output pins; those that can't should always
-return zero. Also, using these calls for GPIOs that can't safely be accessed
-without sleeping (see below) is an error.
-
-Platform-specific implementations are encouraged to optimize the two
-calls to access the GPIO value in cases where the GPIO number (and for
-output, value) are constant. It's normal for them to need only a couple
-of instructions in such cases (reading or writing a hardware register),
-and not to need spinlocks. Such optimized calls can make bitbanging
-applications a lot more efficient (in both space and time) than spending
-dozens of instructions on subroutine calls.
-
-
-GPIO access that may sleep
---------------------------
-Some GPIO controllers must be accessed using message based busses like I2C
-or SPI. Commands to read or write those GPIO values require waiting to
-get to the head of a queue to transmit a command and get its response.
-This requires sleeping, which can't be done from inside IRQ handlers.
-To access such GPIOs, a different set of accessors is defined::
-
- /* GPIO INPUT: return zero or nonzero, might sleep */
- int gpio_get_value_cansleep(unsigned gpio);
-
- /* GPIO OUTPUT, might sleep */
- void gpio_set_value_cansleep(unsigned gpio, int value);
-
-Accessing such GPIOs requires a context which may sleep, for example
-a threaded IRQ handler, and those accessors must be used instead of
-spinlock-safe accessors without the cansleep() name suffix.
-
-Other than the fact that these accessors might sleep, and will work
-on GPIOs that can't be accessed from hardIRQ handlers, these calls act
-the same as the spinlock-safe calls.
-
-**IN ADDITION** calls to setup and configure such GPIOs must be made
-from contexts which may sleep, since they may need to access the GPIO
-controller chip too (These setup calls are usually made from board
-setup or driver probe/teardown code, so this is an easy constraint.)::
-
- gpio_direction_input()
- gpio_direction_output()
- gpio_request()
-
- ## gpio_request_one()
-
- gpio_free()
-
-
-Claiming and Releasing GPIOs
-----------------------------
-To help catch system configuration errors, two calls are defined::
-
- /* request GPIO, returning 0 or negative errno.
- * non-null labels may be useful for diagnostics.
- */
- int gpio_request(unsigned gpio, const char *label);
-
- /* release previously-claimed GPIO */
- void gpio_free(unsigned gpio);
-
-Passing invalid GPIO numbers to gpio_request() will fail, as will requesting
-GPIOs that have already been claimed with that call. The return value of
-gpio_request() must be checked. You should normally issue these calls from
-a task context. However, for spinlock-safe GPIOs it's OK to request GPIOs
-before tasking is enabled, as part of early board setup.
-
-These calls serve two basic purposes. One is marking the signals which
-are actually in use as GPIOs, for better diagnostics; systems may have
-several hundred potential GPIOs, but often only a dozen are used on any
-given board. Another is to catch conflicts, identifying errors when
-(a) two or more drivers wrongly think they have exclusive use of that
-signal, or (b) something wrongly believes it's safe to remove drivers
-needed to manage a signal that's in active use. That is, requesting a
-GPIO can serve as a kind of lock.
-
-Some platforms may also use knowledge about what GPIOs are active for
-power management, such as by powering down unused chip sectors and, more
-easily, gating off unused clocks.
-
-For GPIOs that use pins known to the pinctrl subsystem, that subsystem should
-be informed of their use; a gpiolib driver's .request() operation may call
-pinctrl_gpio_request(), and a gpiolib driver's .free() operation may call
-pinctrl_gpio_free(). The pinctrl subsystem allows a pinctrl_gpio_request()
-to succeed concurrently with a pin or pingroup being "owned" by a device for
-pin multiplexing.
-
-Any programming of pin multiplexing hardware that is needed to route the
-GPIO signal to the appropriate pin should occur within a GPIO driver's
-.direction_input() or .direction_output() operations, and occur after any
-setup of an output GPIO's value. This allows a glitch-free migration from a
-pin's special function to GPIO. This is sometimes required when using a GPIO
-to implement a workaround on signals typically driven by a non-GPIO HW block.
-
-Some platforms allow some or all GPIO signals to be routed to different pins.
-Similarly, other aspects of the GPIO or pin may need to be configured, such as
-pullup/pulldown. Platform software should arrange that any such details are
-configured prior to gpio_request() being called for those GPIOs, e.g. using
-the pinctrl subsystem's mapping table, so that GPIO users need not be aware
-of these details.
-
-Also note that it's your responsibility to have stopped using a GPIO
-before you free it.
-
-Considering in most cases GPIOs are actually configured right after they
-are claimed, three additional calls are defined::
-
- /* request a single GPIO, with initial configuration specified by
- * 'flags', identical to gpio_request() wrt other arguments and
- * return value
- */
- int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
-
-where 'flags' is currently defined to specify the following properties:
-
- * GPIOF_DIR_IN - to configure direction as input
- * GPIOF_DIR_OUT - to configure direction as output
-
- * GPIOF_INIT_LOW - as output, set initial level to LOW
- * GPIOF_INIT_HIGH - as output, set initial level to HIGH
-
-since GPIOF_INIT_* are only valid when configured as output, so group valid
-combinations as:
-
- * GPIOF_IN - configure as input
- * GPIOF_OUT_INIT_LOW - configured as output, initial level LOW
- * GPIOF_OUT_INIT_HIGH - configured as output, initial level HIGH
-
-Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is
-introduced to encapsulate all three fields as::
-
- struct gpio {
- unsigned gpio;
- unsigned long flags;
- const char *label;
- };
-
-A typical example of usage::
-
- static struct gpio leds_gpios[] = {
- { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */
- { 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* default to OFF */
- { 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* default to OFF */
- { 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* default to OFF */
- { ... },
- };
-
- err = gpio_request_one(31, GPIOF_IN, "Reset Button");
- if (err)
- ...
-
-
-GPIOs mapped to IRQs
---------------------
-GPIO numbers are unsigned integers; so are IRQ numbers. These make up
-two logically distinct namespaces (GPIO 0 need not use IRQ 0). You can
-map between them using calls like::
-
- /* map GPIO numbers to IRQ numbers */
- int gpio_to_irq(unsigned gpio);
-
-Those return either the corresponding number in the other namespace, or
-else a negative errno code if the mapping can't be done. (For example,
-some GPIOs can't be used as IRQs.) It is an unchecked error to use a GPIO
-number that wasn't set up as an input using gpio_direction_input(), or
-to use an IRQ number that didn't originally come from gpio_to_irq().
-
-These two mapping calls are expected to cost on the order of a single
-addition or subtraction. They're not allowed to sleep.
-
-Non-error values returned from gpio_to_irq() can be passed to request_irq()
-or free_irq(). They will often be stored into IRQ resources for platform
-devices, by the board-specific initialization code. Note that IRQ trigger
-options are part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are
-system wakeup capabilities.
-
-
-Emulating Open Drain Signals
-----------------------------
-Sometimes shared signals need to use "open drain" signaling, where only the
-low signal level is actually driven. (That term applies to CMOS transistors;
-"open collector" is used for TTL.) A pullup resistor causes the high signal
-level. This is sometimes called a "wire-AND"; or more practically, from the
-negative logic (low=true) perspective this is a "wire-OR".
-
-One common example of an open drain signal is a shared active-low IRQ line.
-Also, bidirectional data bus signals sometimes use open drain signals.
-
-Some GPIO controllers directly support open drain outputs; many don't. When
-you need open drain signaling but your hardware doesn't directly support it,
-there's a common idiom you can use to emulate it with any GPIO pin that can
-be used as either an input or an output:
-
- LOW: gpio_direction_output(gpio, 0) ... this drives the signal
- and overrides the pullup.
-
- HIGH: gpio_direction_input(gpio) ... this turns off the output,
- so the pullup (or some other device) controls the signal.
-
-If you are "driving" the signal high but gpio_get_value(gpio) reports a low
-value (after the appropriate rise time passes), you know some other component
-is driving the shared signal low. That's not necessarily an error. As one
-common example, that's how I2C clocks are stretched: a slave that needs a
-slower clock delays the rising edge of SCK, and the I2C master adjusts its
-signaling rate accordingly.
-
-
-GPIO controllers and the pinctrl subsystem
-------------------------------------------
-
-A GPIO controller on a SOC might be tightly coupled with the pinctrl
-subsystem, in the sense that the pins can be used by other functions
-together with an optional gpio feature. We have already covered the
-case where e.g. a GPIO controller need to reserve a pin or set the
-direction of a pin by calling any of::
-
- pinctrl_gpio_request()
- pinctrl_gpio_free()
- pinctrl_gpio_direction_input()
- pinctrl_gpio_direction_output()
-
-But how does the pin control subsystem cross-correlate the GPIO
-numbers (which are a global business) to a certain pin on a certain
-pin controller?
-
-This is done by registering "ranges" of pins, which are essentially
-cross-reference tables. These are described in
-Documentation/driver-api/pin-control.rst
-
-While the pin allocation is totally managed by the pinctrl subsystem,
-gpio (under gpiolib) is still maintained by gpio drivers. It may happen
-that different pin ranges in a SoC is managed by different gpio drivers.
-
-This makes it logical to let gpio drivers announce their pin ranges to
-the pin ctrl subsystem before it will call 'pinctrl_gpio_request' in order
-to request the corresponding pin to be prepared by the pinctrl subsystem
-before any gpio usage.
-
-For this, the gpio controller can register its pin range with pinctrl
-subsystem. There are two ways of doing it currently: with or without DT.
-
-For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt.
-
-For non-DT support, user can call gpiochip_add_pin_range() with appropriate
-parameters to register a range of gpio pins with a pinctrl driver. For this
-exact name string of pinctrl device has to be passed as one of the
-argument to this routine.
-
-
-What do these conventions omit?
-===============================
-One of the biggest things these conventions omit is pin multiplexing, since
-this is highly chip-specific and nonportable. One platform might not need
-explicit multiplexing; another might have just two options for use of any
-given pin; another might have eight options per pin; another might be able
-to route a given GPIO to any one of several pins. (Yes, those examples all
-come from systems that run Linux today.)
-
-Related to multiplexing is configuration and enabling of the pullups or
-pulldowns integrated on some platforms. Not all platforms support them,
-or support them in the same way; and any given board might use external
-pullups (or pulldowns) so that the on-chip ones should not be used.
-(When a circuit needs 5 kOhm, on-chip 100 kOhm resistors won't do.)
-Likewise drive strength (2 mA vs 20 mA) and voltage (1.8V vs 3.3V) is a
-platform-specific issue, as are models like (not) having a one-to-one
-correspondence between configurable pins and GPIOs.
-
-There are other system-specific mechanisms that are not specified here,
-like the aforementioned options for input de-glitching and wire-OR output.
-Hardware may support reading or writing GPIOs in gangs, but that's usually
-configuration dependent: for GPIOs sharing the same bank. (GPIOs are
-commonly grouped in banks of 16 or 32, with a given SOC having several such
-banks.) Some systems can trigger IRQs from output GPIOs, or read values
-from pins not managed as GPIOs. Code relying on such mechanisms will
-necessarily be nonportable.
-
-Dynamic definition of GPIOs is not currently standard; for example, as
-a side effect of configuring an add-on board with some GPIO expanders.
-
-
-GPIO implementor's framework (OPTIONAL)
-=======================================
-As noted earlier, there is an optional implementation framework making it
-easier for platforms to support different kinds of GPIO controller using
-the same programming interface. This framework is called "gpiolib".
-
-As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
-will be found there. That will list all the controllers registered through
-this framework, and the state of the GPIOs currently in use.
-
-
-Controller Drivers: gpio_chip
------------------------------
-In this framework each GPIO controller is packaged as a "struct gpio_chip"
-with information common to each controller of that type:
-
- - methods to establish GPIO direction
- - methods used to access GPIO values
- - flag saying whether calls to its methods may sleep
- - optional debugfs dump method (showing extra state like pullup config)
- - label for diagnostics
-
-There is also per-instance data, which may come from device.platform_data:
-the number of its first GPIO, and how many GPIOs it exposes.
-
-The code implementing a gpio_chip should support multiple instances of the
-controller, possibly using the driver model. That code will configure each
-gpio_chip and issue gpiochip_add(). Removing a GPIO controller should be
-rare; use gpiochip_remove() when it is unavoidable.
-
-Most often a gpio_chip is part of an instance-specific structure with state
-not exposed by the GPIO interfaces, such as addressing, power management,
-and more. Chips such as codecs will have complex non-GPIO state.
-
-Any debugfs dump method should normally ignore signals which haven't been
-requested as GPIOs. They can use gpiochip_is_requested(), which returns
-either NULL or the label associated with that GPIO when it was requested.
-
-
-Platform Support
-----------------
-To force-enable this framework, a platform's Kconfig will "select" GPIOLIB,
-else it is up to the user to configure support for GPIO.
-
-If neither of these options are selected, the platform does not support
-GPIOs through GPIO-lib and the code cannot be enabled by the user.
-
-Trivial implementations of those functions can directly use framework
-code, which always dispatches through the gpio_chip::
-
- #define gpio_get_value __gpio_get_value
- #define gpio_set_value __gpio_set_value
-
-Fancier implementations could instead define those as inline functions with
-logic optimizing access to specific SOC-based GPIOs. For example, if the
-referenced GPIO is the constant "12", getting or setting its value could
-cost as little as two or three instructions, never sleeping. When such an
-optimization is not possible those calls must delegate to the framework
-code, costing at least a few dozen instructions. For bitbanged I/O, such
-instruction savings can be significant.
-
-For SOCs, platform-specific code defines and registers gpio_chip instances
-for each bank of on-chip GPIOs. Those GPIOs should be numbered/labeled to
-match chip vendor documentation, and directly match board schematics. They
-may well start at zero and go up to a platform-specific limit. Such GPIOs
-are normally integrated into platform initialization to make them always be
-available, from arch_initcall() or earlier; they can often serve as IRQs.
-
-
-Board Support
--------------
-For external GPIO controllers -- such as I2C or SPI expanders, ASICs, multi
-function devices, FPGAs or CPLDs -- most often board-specific code handles
-registering controller devices and ensures that their drivers know what GPIO
-numbers to use with gpiochip_add(). Their numbers often start right after
-platform-specific GPIOs.
-
-For example, board setup code could create structures identifying the range
-of GPIOs that chip will expose, and passes them to each GPIO expander chip
-using platform_data. Then the chip driver's probe() routine could pass that
-data to gpiochip_add().
-
-Initialization order can be important. For example, when a device relies on
-an I2C-based GPIO, its probe() routine should only be called after that GPIO
-becomes available. That may mean the device should not be registered until
-calls for that GPIO can work. One way to address such dependencies is for
-such gpio_chip controllers to provide setup() and teardown() callbacks to
-board specific code; those board specific callbacks would register devices
-once all the necessary resources are available, and remove them later when
-the GPIO controller device becomes unavailable.
-
-
-Sysfs Interface for Userspace (OPTIONAL)
-========================================
-Platforms which use the "gpiolib" implementors framework may choose to
-configure a sysfs user interface to GPIOs. This is different from the
-debugfs interface, since it provides control over GPIO direction and
-value instead of just showing a gpio state summary. Plus, it could be
-present on production systems without debugging support.
-
-Given appropriate hardware documentation for the system, userspace could
-know for example that GPIO #23 controls the write protect line used to
-protect boot loader segments in flash memory. System upgrade procedures
-may need to temporarily remove that protection, first importing a GPIO,
-then changing its output state, then updating the code before re-enabling
-the write protection. In normal use, GPIO #23 would never be touched,
-and the kernel would have no need to know about it.
-
-Again depending on appropriate hardware documentation, on some systems
-userspace GPIO can be used to determine system configuration data that
-standard kernels won't know about. And for some tasks, simple userspace
-GPIO drivers could be all that the system really needs.
-
-Note that standard kernel drivers exist for common "LEDs and Buttons"
-GPIO tasks: "leds-gpio" and "gpio_keys", respectively. Use those
-instead of talking directly to the GPIOs; they integrate with kernel
-frameworks better than your userspace code could.
-
-
-Paths in Sysfs
---------------
-There are three kinds of entry in /sys/class/gpio:
-
- - Control interfaces used to get userspace control over GPIOs;
-
- - GPIOs themselves; and
-
- - GPIO controllers ("gpio_chip" instances).
-
-That's in addition to standard files including the "device" symlink.
-
-The control interfaces are write-only:
-
- /sys/class/gpio/
-
- "export" ... Userspace may ask the kernel to export control of
- a GPIO to userspace by writing its number to this file.
-
- Example: "echo 19 > export" will create a "gpio19" node
- for GPIO #19, if that's not requested by kernel code.
-
- "unexport" ... Reverses the effect of exporting to userspace.
-
- Example: "echo 19 > unexport" will remove a "gpio19"
- node exported using the "export" file.
-
-GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
-and have the following read/write attributes:
-
- /sys/class/gpio/gpioN/
-
- "direction" ... reads as either "in" or "out". This value may
- normally be written. Writing as "out" defaults to
- initializing the value as low. To ensure glitch free
- operation, values "low" and "high" may be written to
- configure the GPIO as an output with that initial value.
-
- Note that this attribute *will not exist* if the kernel
- doesn't support changing the direction of a GPIO, or
- it was exported by kernel code that didn't explicitly
- allow userspace to reconfigure this GPIO's direction.
-
- "value" ... reads as either 0 (low) or 1 (high). If the GPIO
- is configured as an output, this value may be written;
- any nonzero value is treated as high.
-
- If the pin can be configured as interrupt-generating interrupt
- and if it has been configured to generate interrupts (see the
- description of "edge"), you can poll(2) on that file and
- poll(2) will return whenever the interrupt was triggered. If
- you use poll(2), set the events POLLPRI. If you use select(2),
- set the file descriptor in exceptfds. After poll(2) returns,
- either lseek(2) to the beginning of the sysfs file and read the
- new value or close the file and re-open it to read the value.
-
- "edge" ... reads as either "none", "rising", "falling", or
- "both". Write these strings to select the signal edge(s)
- that will make poll(2) on the "value" file return.
-
- This file exists only if the pin can be configured as an
- interrupt generating input pin.
-
- "active_low" ... reads as either 0 (false) or 1 (true). Write
- any nonzero value to invert the value attribute both
- for reading and writing. Existing and subsequent
- poll(2) support configuration via the edge attribute
- for "rising" and "falling" edges will follow this
- setting.
-
-GPIO controllers have paths like /sys/class/gpio/gpiochip42/ (for the
-controller implementing GPIOs starting at #42) and have the following
-read-only attributes:
-
- /sys/class/gpio/gpiochipN/
-
- "base" ... same as N, the first GPIO managed by this chip
-
- "label" ... provided for diagnostics (not always unique)
-
- "ngpio" ... how many GPIOs this manges (N to N + ngpio - 1)
-
-Board documentation should in most cases cover what GPIOs are used for
-what purposes. However, those numbers are not always stable; GPIOs on
-a daughtercard might be different depending on the base board being used,
-or other cards in the stack. In such cases, you may need to use the
-gpiochip nodes (possibly in conjunction with schematics) to determine
-the correct GPIO number to use for a given signal.
-
-
-API Reference
-=============
-
-The functions listed in this section are deprecated. The GPIO descriptor based
-API should be used in new code.
-
-.. kernel-doc:: drivers/gpio/gpiolib-legacy.c
- :export:
diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst
index 8f5c1ee02e2f..e8e496d23e1d 100644
--- a/Documentation/filesystems/index.rst
+++ b/Documentation/filesystems/index.rst
@@ -34,6 +34,7 @@ algorithms work.
seq_file
sharedsubtree
idmappings
+ iomap/index
automount-support
diff --git a/Documentation/filesystems/iomap/design.rst b/Documentation/filesystems/iomap/design.rst
new file mode 100644
index 000000000000..f8ee3427bc1a
--- /dev/null
+++ b/Documentation/filesystems/iomap/design.rst
@@ -0,0 +1,441 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. _iomap_design:
+
+..
+ Dumb style notes to maintain the author's sanity:
+ Please try to start sentences on separate lines so that
+ sentence changes don't bleed colors in diff.
+ Heading decorations are documented in sphinx.rst.
+
+==============
+Library Design
+==============
+
+.. contents:: Table of Contents
+ :local:
+
+Introduction
+============
+
+iomap is a filesystem library for handling common file operations.
+The library has two layers:
+
+ 1. A lower layer that provides an iterator over ranges of file offsets.
+ This layer tries to obtain mappings of each file ranges to storage
+ from the filesystem, but the storage information is not necessarily
+ required.
+
+ 2. An upper layer that acts upon the space mappings provided by the
+ lower layer iterator.
+
+The iteration can involve mappings of file's logical offset ranges to
+physical extents, but the storage layer information is not necessarily
+required, e.g. for walking cached file information.
+The library exports various APIs for implementing file operations such
+as:
+
+ * Pagecache reads and writes
+ * Folio write faults to the pagecache
+ * Writeback of dirty folios
+ * Direct I/O reads and writes
+ * fsdax I/O reads, writes, loads, and stores
+ * FIEMAP
+ * lseek ``SEEK_DATA`` and ``SEEK_HOLE``
+ * swapfile activation
+
+This origins of this library is the file I/O path that XFS once used; it
+has now been extended to cover several other operations.
+
+Who Should Read This?
+=====================
+
+The target audience for this document are filesystem, storage, and
+pagecache programmers and code reviewers.
+
+If you are working on PCI, machine architectures, or device drivers, you
+are most likely in the wrong place.
+
+How Is This Better?
+===================
+
+Unlike the classic Linux I/O model which breaks file I/O into small
+units (generally memory pages or blocks) and looks up space mappings on
+the basis of that unit, the iomap model asks the filesystem for the
+largest space mappings that it can create for a given file operation and
+initiates operations on that basis.
+This strategy improves the filesystem's visibility into the size of the
+operation being performed, which enables it to combat fragmentation with
+larger space allocations when possible.
+Larger space mappings improve runtime performance by amortizing the cost
+of mapping function calls into the filesystem across a larger amount of
+data.
+
+At a high level, an iomap operation `looks like this
+<https://lore.kernel.org/all/[email protected]/>`_:
+
+1. For each byte in the operation range...
+
+ 1. Obtain a space mapping via ``->iomap_begin``
+
+ 2. For each sub-unit of work...
+
+ 1. Revalidate the mapping and go back to (1) above, if necessary.
+ So far only the pagecache operations need to do this.
+
+ 2. Do the work
+
+ 3. Increment operation cursor
+
+ 4. Release the mapping via ``->iomap_end``, if necessary
+
+Each iomap operation will be covered in more detail below.
+This library was covered previously by an `LWN article
+<https://lwn.net/Articles/935934/>`_ and a `KernelNewbies page
+<https://kernelnewbies.org/KernelProjects/iomap>`_.
+
+The goal of this document is to provide a brief discussion of the
+design and capabilities of iomap, followed by a more detailed catalog
+of the interfaces presented by iomap.
+If you change iomap, please update this design document.
+
+File Range Iterator
+===================
+
+Definitions
+-----------
+
+ * **buffer head**: Shattered remnants of the old buffer cache.
+
+ * ``fsblock``: The block size of a file, also known as ``i_blocksize``.
+
+ * ``i_rwsem``: The VFS ``struct inode`` rwsemaphore.
+ Processes hold this in shared mode to read file state and contents.
+ Some filesystems may allow shared mode for writes.
+ Processes often hold this in exclusive mode to change file state and
+ contents.
+
+ * ``invalidate_lock``: The pagecache ``struct address_space``
+ rwsemaphore that protects against folio insertion and removal for
+ filesystems that support punching out folios below EOF.
+ Processes wishing to insert folios must hold this lock in shared
+ mode to prevent removal, though concurrent insertion is allowed.
+ Processes wishing to remove folios must hold this lock in exclusive
+ mode to prevent insertions.
+ Concurrent removals are not allowed.
+
+ * ``dax_read_lock``: The RCU read lock that dax takes to prevent a
+ device pre-shutdown hook from returning before other threads have
+ released resources.
+
+ * **filesystem mapping lock**: This synchronization primitive is
+ internal to the filesystem and must protect the file mapping data
+ from updates while a mapping is being sampled.
+ The filesystem author must determine how this coordination should
+ happen; it does not need to be an actual lock.
+
+ * **iomap internal operation lock**: This is a general term for
+ synchronization primitives that iomap functions take while holding a
+ mapping.
+ A specific example would be taking the folio lock while reading or
+ writing the pagecache.
+
+ * **pure overwrite**: A write operation that does not require any
+ metadata or zeroing operations to perform during either submission
+ or completion.
+ This implies that the fileystem must have already allocated space
+ on disk as ``IOMAP_MAPPED`` and the filesystem must not place any
+ constaints on IO alignment or size.
+ The only constraints on I/O alignment are device level (minimum I/O
+ size and alignment, typically sector size).
+
+``struct iomap``
+----------------
+
+The filesystem communicates to the iomap iterator the mapping of
+byte ranges of a file to byte ranges of a storage device with the
+structure below:
+
+.. code-block:: c
+
+ struct iomap {
+ u64 addr;
+ loff_t offset;
+ u64 length;
+ u16 type;
+ u16 flags;
+ struct block_device *bdev;
+ struct dax_device *dax_dev;
+ voidw *inline_data;
+ void *private;
+ const struct iomap_folio_ops *folio_ops;
+ u64 validity_cookie;
+ };
+
+The fields are as follows:
+
+ * ``offset`` and ``length`` describe the range of file offsets, in
+ bytes, covered by this mapping.
+ These fields must always be set by the filesystem.
+
+ * ``type`` describes the type of the space mapping:
+
+ * **IOMAP_HOLE**: No storage has been allocated.
+ This type must never be returned in response to an ``IOMAP_WRITE``
+ operation because writes must allocate and map space, and return
+ the mapping.
+ The ``addr`` field must be set to ``IOMAP_NULL_ADDR``.
+ iomap does not support writing (whether via pagecache or direct
+ I/O) to a hole.
+
+ * **IOMAP_DELALLOC**: A promise to allocate space at a later time
+ ("delayed allocation").
+ If the filesystem returns IOMAP_F_NEW here and the write fails, the
+ ``->iomap_end`` function must delete the reservation.
+ The ``addr`` field must be set to ``IOMAP_NULL_ADDR``.
+
+ * **IOMAP_MAPPED**: The file range maps to specific space on the
+ storage device.
+ The device is returned in ``bdev`` or ``dax_dev``.
+ The device address, in bytes, is returned via ``addr``.
+
+ * **IOMAP_UNWRITTEN**: The file range maps to specific space on the
+ storage device, but the space has not yet been initialized.
+ The device is returned in ``bdev`` or ``dax_dev``.
+ The device address, in bytes, is returned via ``addr``.
+ Reads from this type of mapping will return zeroes to the caller.
+ For a write or writeback operation, the ioend should update the
+ mapping to MAPPED.
+ Refer to the sections about ioends for more details.
+
+ * **IOMAP_INLINE**: The file range maps to the memory buffer
+ specified by ``inline_data``.
+ For write operation, the ``->iomap_end`` function presumably
+ handles persisting the data.
+ The ``addr`` field must be set to ``IOMAP_NULL_ADDR``.
+
+ * ``flags`` describe the status of the space mapping.
+ These flags should be set by the filesystem in ``->iomap_begin``:
+
+ * **IOMAP_F_NEW**: The space under the mapping is newly allocated.
+ Areas that will not be written to must be zeroed.
+ If a write fails and the mapping is a space reservation, the
+ reservation must be deleted.
+
+ * **IOMAP_F_DIRTY**: The inode will have uncommitted metadata needed
+ to access any data written.
+ fdatasync is required to commit these changes to persistent
+ storage.
+ This needs to take into account metadata changes that *may* be made
+ at I/O completion, such as file size updates from direct I/O.
+
+ * **IOMAP_F_SHARED**: The space under the mapping is shared.
+ Copy on write is necessary to avoid corrupting other file data.
+
+ * **IOMAP_F_BUFFER_HEAD**: This mapping requires the use of buffer
+ heads for pagecache operations.
+ Do not add more uses of this.
+
+ * **IOMAP_F_MERGED**: Multiple contiguous block mappings were
+ coalesced into this single mapping.
+ This is only useful for FIEMAP.
+
+ * **IOMAP_F_XATTR**: The mapping is for extended attribute data, not
+ regular file data.
+ This is only useful for FIEMAP.
+
+ * **IOMAP_F_PRIVATE**: Starting with this value, the upper bits can
+ be set by the filesystem for its own purposes.
+
+ These flags can be set by iomap itself during file operations.
+ The filesystem should supply an ``->iomap_end`` function if it needs
+ to observe these flags:
+
+ * **IOMAP_F_SIZE_CHANGED**: The file size has changed as a result of
+ using this mapping.
+
+ * **IOMAP_F_STALE**: The mapping was found to be stale.
+ iomap will call ``->iomap_end`` on this mapping and then
+ ``->iomap_begin`` to obtain a new mapping.
+
+ Currently, these flags are only set by pagecache operations.
+
+ * ``addr`` describes the device address, in bytes.
+
+ * ``bdev`` describes the block device for this mapping.
+ This only needs to be set for mapped or unwritten operations.
+
+ * ``dax_dev`` describes the DAX device for this mapping.
+ This only needs to be set for mapped or unwritten operations, and
+ only for a fsdax operation.
+
+ * ``inline_data`` points to a memory buffer for I/O involving
+ ``IOMAP_INLINE`` mappings.
+ This value is ignored for all other mapping types.
+
+ * ``private`` is a pointer to `filesystem-private information
+ <https://lore.kernel.org/all/[email protected]/>`_.
+ This value will be passed unchanged to ``->iomap_end``.
+
+ * ``folio_ops`` will be covered in the section on pagecache operations.
+
+ * ``validity_cookie`` is a magic freshness value set by the filesystem
+ that should be used to detect stale mappings.
+ For pagecache operations this is critical for correct operation
+ because page faults can occur, which implies that filesystem locks
+ should not be held between ``->iomap_begin`` and ``->iomap_end``.
+ Filesystems with completely static mappings need not set this value.
+ Only pagecache operations revalidate mappings; see the section about
+ ``iomap_valid`` for details.
+
+``struct iomap_ops``
+--------------------
+
+Every iomap function requires the filesystem to pass an operations
+structure to obtain a mapping and (optionally) to release the mapping:
+
+.. code-block:: c
+
+ struct iomap_ops {
+ int (*iomap_begin)(struct inode *inode, loff_t pos, loff_t length,
+ unsigned flags, struct iomap *iomap,
+ struct iomap *srcmap);
+
+ int (*iomap_end)(struct inode *inode, loff_t pos, loff_t length,
+ ssize_t written, unsigned flags,
+ struct iomap *iomap);
+ };
+
+``->iomap_begin``
+~~~~~~~~~~~~~~~~~
+
+iomap operations call ``->iomap_begin`` to obtain one file mapping for
+the range of bytes specified by ``pos`` and ``length`` for the file
+``inode``.
+This mapping should be returned through the ``iomap`` pointer.
+The mapping must cover at least the first byte of the supplied file
+range, but it does not need to cover the entire requested range.
+
+Each iomap operation describes the requested operation through the
+``flags`` argument.
+The exact value of ``flags`` will be documented in the
+operation-specific sections below.
+These flags can, at least in principle, apply generally to iomap
+operations:
+
+ * ``IOMAP_DIRECT`` is set when the caller wishes to issue file I/O to
+ block storage.
+
+ * ``IOMAP_DAX`` is set when the caller wishes to issue file I/O to
+ memory-like storage.
+
+ * ``IOMAP_NOWAIT`` is set when the caller wishes to perform a best
+ effort attempt to avoid any operation that would result in blocking
+ the submitting task.
+ This is similar in intent to ``O_NONBLOCK`` for network APIs - it is
+ intended for asynchronous applications to keep doing other work
+ instead of waiting for the specific unavailable filesystem resource
+ to become available.
+ Filesystems implementing ``IOMAP_NOWAIT`` semantics need to use
+ trylock algorithms.
+ They need to be able to satisfy the entire I/O request range with a
+ single iomap mapping.
+ They need to avoid reading or writing metadata synchronously.
+ They need to avoid blocking memory allocations.
+ They need to avoid waiting on transaction reservations to allow
+ modifications to take place.
+ They probably should not be allocating new space.
+ And so on.
+ If there is any doubt in the filesystem developer's mind as to
+ whether any specific ``IOMAP_NOWAIT`` operation may end up blocking,
+ then they should return ``-EAGAIN`` as early as possible rather than
+ start the operation and force the submitting task to block.
+ ``IOMAP_NOWAIT`` is often set on behalf of ``IOCB_NOWAIT`` or
+ ``RWF_NOWAIT``.
+
+If it is necessary to read existing file contents from a `different
+<https://lore.kernel.org/all/[email protected]/>`_
+device or address range on a device, the filesystem should return that
+information via ``srcmap``.
+Only pagecache and fsdax operations support reading from one mapping and
+writing to another.
+
+``->iomap_end``
+~~~~~~~~~~~~~~~
+
+After the operation completes, the ``->iomap_end`` function, if present,
+is called to signal that iomap is finished with a mapping.
+Typically, implementations will use this function to tear down any
+context that were set up in ``->iomap_begin``.
+For example, a write might wish to commit the reservations for the bytes
+that were operated upon and unreserve any space that was not operated
+upon.
+``written`` might be zero if no bytes were touched.
+``flags`` will contain the same value passed to ``->iomap_begin``.
+iomap ops for reads are not likely to need to supply this function.
+
+Both functions should return a negative errno code on error, or zero on
+success.
+
+Preparing for File Operations
+=============================
+
+iomap only handles mapping and I/O.
+Filesystems must still call out to the VFS to check input parameters
+and file state before initiating an I/O operation.
+It does not handle obtaining filesystem freeze protection, updating of
+timestamps, stripping privileges, or access control.
+
+Locking Hierarchy
+=================
+
+iomap requires that filesystems supply their own locking model.
+There are three categories of synchronization primitives, as far as
+iomap is concerned:
+
+ * The **upper** level primitive is provided by the filesystem to
+ coordinate access to different iomap operations.
+ The exact primitive is specifc to the filesystem and operation,
+ but is often a VFS inode, pagecache invalidation, or folio lock.
+ For example, a filesystem might take ``i_rwsem`` before calling
+ ``iomap_file_buffered_write`` and ``iomap_file_unshare`` to prevent
+ these two file operations from clobbering each other.
+ Pagecache writeback may lock a folio to prevent other threads from
+ accessing the folio until writeback is underway.
+
+ * The **lower** level primitive is taken by the filesystem in the
+ ``->iomap_begin`` and ``->iomap_end`` functions to coordinate
+ access to the file space mapping information.
+ The fields of the iomap object should be filled out while holding
+ this primitive.
+ The upper level synchronization primitive, if any, remains held
+ while acquiring the lower level synchronization primitive.
+ For example, XFS takes ``ILOCK_EXCL`` and ext4 takes ``i_data_sem``
+ while sampling mappings.
+ Filesystems with immutable mapping information may not require
+ synchronization here.
+
+ * The **operation** primitive is taken by an iomap operation to
+ coordinate access to its own internal data structures.
+ The upper level synchronization primitive, if any, remains held
+ while acquiring this primitive.
+ The lower level primitive is not held while acquiring this
+ primitive.
+ For example, pagecache write operations will obtain a file mapping,
+ then grab and lock a folio to copy new contents.
+ It may also lock an internal folio state object to update metadata.
+
+The exact locking requirements are specific to the filesystem; for
+certain operations, some of these locks can be elided.
+All further mention of locking are *recommendations*, not mandates.
+Each filesystem author must figure out the locking for themself.
+
+Bugs and Limitations
+====================
+
+ * No support for fscrypt.
+ * No support for compression.
+ * No support for fsverity yet.
+ * Strong assumptions that IO should work the way it does on XFS.
+ * Does iomap *actually* work for non-regular file data?
+
+Patches welcome!
diff --git a/Documentation/filesystems/iomap/index.rst b/Documentation/filesystems/iomap/index.rst
new file mode 100644
index 000000000000..3c6a52440250
--- /dev/null
+++ b/Documentation/filesystems/iomap/index.rst
@@ -0,0 +1,13 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======================
+VFS iomap Documentation
+=======================
+
+.. toctree::
+ :maxdepth: 2
+ :numbered:
+
+ design
+ operations
+ porting
diff --git a/Documentation/filesystems/iomap/operations.rst b/Documentation/filesystems/iomap/operations.rst
new file mode 100644
index 000000000000..8e6c721d2330
--- /dev/null
+++ b/Documentation/filesystems/iomap/operations.rst
@@ -0,0 +1,713 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. _iomap_operations:
+
+..
+ Dumb style notes to maintain the author's sanity:
+ Please try to start sentences on separate lines so that
+ sentence changes don't bleed colors in diff.
+ Heading decorations are documented in sphinx.rst.
+
+=========================
+Supported File Operations
+=========================
+
+.. contents:: Table of Contents
+ :local:
+
+Below are a discussion of the high level file operations that iomap
+implements.
+
+Buffered I/O
+============
+
+Buffered I/O is the default file I/O path in Linux.
+File contents are cached in memory ("pagecache") to satisfy reads and
+writes.
+Dirty cache will be written back to disk at some point that can be
+forced via ``fsync`` and variants.
+
+iomap implements nearly all the folio and pagecache management that
+filesystems have to implement themselves under the legacy I/O model.
+This means that the filesystem need not know the details of allocating,
+mapping, managing uptodate and dirty state, or writeback of pagecache
+folios.
+Under the legacy I/O model, this was managed very inefficiently with
+linked lists of buffer heads instead of the per-folio bitmaps that iomap
+uses.
+Unless the filesystem explicitly opts in to buffer heads, they will not
+be used, which makes buffered I/O much more efficient, and the pagecache
+maintainer much happier.
+
+``struct address_space_operations``
+-----------------------------------
+
+The following iomap functions can be referenced directly from the
+address space operations structure:
+
+ * ``iomap_dirty_folio``
+ * ``iomap_release_folio``
+ * ``iomap_invalidate_folio``
+ * ``iomap_is_partially_uptodate``
+
+The following address space operations can be wrapped easily:
+
+ * ``read_folio``
+ * ``readahead``
+ * ``writepages``
+ * ``bmap``
+ * ``swap_activate``
+
+``struct iomap_folio_ops``
+--------------------------
+
+The ``->iomap_begin`` function for pagecache operations may set the
+``struct iomap::folio_ops`` field to an ops structure to override
+default behaviors of iomap:
+
+.. code-block:: c
+
+ struct iomap_folio_ops {
+ struct folio *(*get_folio)(struct iomap_iter *iter, loff_t pos,
+ unsigned len);
+ void (*put_folio)(struct inode *inode, loff_t pos, unsigned copied,
+ struct folio *folio);
+ bool (*iomap_valid)(struct inode *inode, const struct iomap *iomap);
+ };
+
+iomap calls these functions:
+
+ - ``get_folio``: Called to allocate and return an active reference to
+ a locked folio prior to starting a write.
+ If this function is not provided, iomap will call
+ ``iomap_get_folio``.
+ This could be used to `set up per-folio filesystem state
+ <https://lore.kernel.org/all/[email protected]/>`_
+ for a write.
+
+ - ``put_folio``: Called to unlock and put a folio after a pagecache
+ operation completes.
+ If this function is not provided, iomap will ``folio_unlock`` and
+ ``folio_put`` on its own.
+ This could be used to `commit per-folio filesystem state
+ <https://lore.kernel.org/all/[email protected]/>`_
+ that was set up by ``->get_folio``.
+
+ - ``iomap_valid``: The filesystem may not hold locks between
+ ``->iomap_begin`` and ``->iomap_end`` because pagecache operations
+ can take folio locks, fault on userspace pages, initiate writeback
+ for memory reclamation, or engage in other time-consuming actions.
+ If a file's space mapping data are mutable, it is possible that the
+ mapping for a particular pagecache folio can `change in the time it
+ takes
+ <https://lore.kernel.org/all/[email protected]/>`_
+ to allocate, install, and lock that folio.
+
+ For the pagecache, races can happen if writeback doesn't take
+ ``i_rwsem`` or ``invalidate_lock`` and updates mapping information.
+ Races can also happen if the filesytem allows concurrent writes.
+ For such files, the mapping *must* be revalidated after the folio
+ lock has been taken so that iomap can manage the folio correctly.
+
+ fsdax does not need this revalidation because there's no writeback
+ and no support for unwritten extents.
+
+ Filesystems subject to this kind of race must provide a
+ ``->iomap_valid`` function to decide if the mapping is still valid.
+ If the mapping is not valid, the mapping will be sampled again.
+
+ To support making the validity decision, the filesystem's
+ ``->iomap_begin`` function may set ``struct iomap::validity_cookie``
+ at the same time that it populates the other iomap fields.
+ A simple validation cookie implementation is a sequence counter.
+ If the filesystem bumps the sequence counter every time it modifies
+ the inode's extent map, it can be placed in the ``struct
+ iomap::validity_cookie`` during ``->iomap_begin``.
+ If the value in the cookie is found to be different to the value
+ the filesystem holds when the mapping is passed back to
+ ``->iomap_valid``, then the iomap should considered stale and the
+ validation failed.
+
+These ``struct kiocb`` flags are significant for buffered I/O with iomap:
+
+ * ``IOCB_NOWAIT``: Turns on ``IOMAP_NOWAIT``.
+
+Internal per-Folio State
+------------------------
+
+If the fsblock size matches the size of a pagecache folio, it is assumed
+that all disk I/O operations will operate on the entire folio.
+The uptodate (memory contents are at least as new as what's on disk) and
+dirty (memory contents are newer than what's on disk) status of the
+folio are all that's needed for this case.
+
+If the fsblock size is less than the size of a pagecache folio, iomap
+tracks the per-fsblock uptodate and dirty state itself.
+This enables iomap to handle both "bs < ps" `filesystems
+<https://lore.kernel.org/all/[email protected]/>`_
+and large folios in the pagecache.
+
+iomap internally tracks two state bits per fsblock:
+
+ * ``uptodate``: iomap will try to keep folios fully up to date.
+ If there are read(ahead) errors, those fsblocks will not be marked
+ uptodate.
+ The folio itself will be marked uptodate when all fsblocks within the
+ folio are uptodate.
+
+ * ``dirty``: iomap will set the per-block dirty state when programs
+ write to the file.
+ The folio itself will be marked dirty when any fsblock within the
+ folio is dirty.
+
+iomap also tracks the amount of read and write disk IOs that are in
+flight.
+This structure is much lighter weight than ``struct buffer_head``
+because there is only one per folio, and the per-fsblock overhead is two
+bits vs. 104 bytes.
+
+Filesystems wishing to turn on large folios in the pagecache should call
+``mapping_set_large_folios`` when initializing the incore inode.
+
+Buffered Readahead and Reads
+----------------------------
+
+The ``iomap_readahead`` function initiates readahead to the pagecache.
+The ``iomap_read_folio`` function reads one folio's worth of data into
+the pagecache.
+The ``flags`` argument to ``->iomap_begin`` will be set to zero.
+The pagecache takes whatever locks it needs before calling the
+filesystem.
+
+Buffered Writes
+---------------
+
+The ``iomap_file_buffered_write`` function writes an ``iocb`` to the
+pagecache.
+``IOMAP_WRITE`` or ``IOMAP_WRITE`` | ``IOMAP_NOWAIT`` will be passed as
+the ``flags`` argument to ``->iomap_begin``.
+Callers commonly take ``i_rwsem`` in either shared or exclusive mode
+before calling this function.
+
+mmap Write Faults
+~~~~~~~~~~~~~~~~~
+
+The ``iomap_page_mkwrite`` function handles a write fault to a folio in
+the pagecache.
+``IOMAP_WRITE | IOMAP_FAULT`` will be passed as the ``flags`` argument
+to ``->iomap_begin``.
+Callers commonly take the mmap ``invalidate_lock`` in shared or
+exclusive mode before calling this function.
+
+Buffered Write Failures
+~~~~~~~~~~~~~~~~~~~~~~~
+
+After a short write to the pagecache, the areas not written will not
+become marked dirty.
+The filesystem must arrange to `cancel
+<https://lore.kernel.org/all/[email protected]/>`_
+such `reservations
+<https://lore.kernel.org/linux-xfs/[email protected]/>`_
+because writeback will not consume the reservation.
+The ``iomap_file_buffered_write_punch_delalloc`` can be called from a
+``->iomap_end`` function to find all the clean areas of the folios
+caching a fresh (``IOMAP_F_NEW``) delalloc mapping.
+It takes the ``invalidate_lock``.
+
+The filesystem must supply a function ``punch`` to be called for
+each file range in this state.
+This function must *only* remove delayed allocation reservations, in
+case another thread racing with the current thread writes successfully
+to the same region and triggers writeback to flush the dirty data out to
+disk.
+
+Zeroing for File Operations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Filesystems can call ``iomap_zero_range`` to perform zeroing of the
+pagecache for non-truncation file operations that are not aligned to
+the fsblock size.
+``IOMAP_ZERO`` will be passed as the ``flags`` argument to
+``->iomap_begin``.
+Callers typically hold ``i_rwsem`` and ``invalidate_lock`` in exclusive
+mode before calling this function.
+
+Unsharing Reflinked File Data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Filesystems can call ``iomap_file_unshare`` to force a file sharing
+storage with another file to preemptively copy the shared data to newly
+allocate storage.
+``IOMAP_WRITE | IOMAP_UNSHARE`` will be passed as the ``flags`` argument
+to ``->iomap_begin``.
+Callers typically hold ``i_rwsem`` and ``invalidate_lock`` in exclusive
+mode before calling this function.
+
+Truncation
+----------
+
+Filesystems can call ``iomap_truncate_page`` to zero the bytes in the
+pagecache from EOF to the end of the fsblock during a file truncation
+operation.
+``truncate_setsize`` or ``truncate_pagecache`` will take care of
+everything after the EOF block.
+``IOMAP_ZERO`` will be passed as the ``flags`` argument to
+``->iomap_begin``.
+Callers typically hold ``i_rwsem`` and ``invalidate_lock`` in exclusive
+mode before calling this function.
+
+Pagecache Writeback
+-------------------
+
+Filesystems can call ``iomap_writepages`` to respond to a request to
+write dirty pagecache folios to disk.
+The ``mapping`` and ``wbc`` parameters should be passed unchanged.
+The ``wpc`` pointer should be allocated by the filesystem and must
+be initialized to zero.
+
+The pagecache will lock each folio before trying to schedule it for
+writeback.
+It does not lock ``i_rwsem`` or ``invalidate_lock``.
+
+The dirty bit will be cleared for all folios run through the
+``->map_blocks`` machinery described below even if the writeback fails.
+This is to prevent dirty folio clots when storage devices fail; an
+``-EIO`` is recorded for userspace to collect via ``fsync``.
+
+The ``ops`` structure must be specified and is as follows:
+
+``struct iomap_writeback_ops``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+
+ struct iomap_writeback_ops {
+ int (*map_blocks)(struct iomap_writepage_ctx *wpc, struct inode *inode,
+ loff_t offset, unsigned len);
+ int (*prepare_ioend)(struct iomap_ioend *ioend, int status);
+ void (*discard_folio)(struct folio *folio, loff_t pos);
+ };
+
+The fields are as follows:
+
+ - ``map_blocks``: Sets ``wpc->iomap`` to the space mapping of the file
+ range (in bytes) given by ``offset`` and ``len``.
+ iomap calls this function for each dirty fs block in each dirty folio,
+ though it will `reuse mappings
+ <https://lore.kernel.org/all/[email protected]/>`_
+ for runs of contiguous dirty fsblocks within a folio.
+ Do not return ``IOMAP_INLINE`` mappings here; the ``->iomap_end``
+ function must deal with persisting written data.
+ Do not return ``IOMAP_DELALLOC`` mappings here; iomap currently
+ requires mapping to allocated space.
+ Filesystems can skip a potentially expensive mapping lookup if the
+ mappings have not changed.
+ This revalidation must be open-coded by the filesystem; it is
+ unclear if ``iomap::validity_cookie`` can be reused for this
+ purpose.
+ This function must be supplied by the filesystem.
+
+ - ``prepare_ioend``: Enables filesystems to transform the writeback
+ ioend or perform any other preparatory work before the writeback I/O
+ is submitted.
+ This might include pre-write space accounting updates, or installing
+ a custom ``->bi_end_io`` function for internal purposes, such as
+ deferring the ioend completion to a workqueue to run metadata update
+ transactions from process context.
+ This function is optional.
+
+ - ``discard_folio``: iomap calls this function after ``->map_blocks``
+ fails to schedule I/O for any part of a dirty folio.
+ The function should throw away any reservations that may have been
+ made for the write.
+ The folio will be marked clean and an ``-EIO`` recorded in the
+ pagecache.
+ Filesystems can use this callback to `remove
+ <https://lore.kernel.org/all/[email protected]/>`_
+ delalloc reservations to avoid having delalloc reservations for
+ clean pagecache.
+ This function is optional.
+
+Pagecache Writeback Completion
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To handle the bookkeeping that must happen after disk I/O for writeback
+completes, iomap creates chains of ``struct iomap_ioend`` objects that
+wrap the ``bio`` that is used to write pagecache data to disk.
+By default, iomap finishes writeback ioends by clearing the writeback
+bit on the folios attached to the ``ioend``.
+If the write failed, it will also set the error bits on the folios and
+the address space.
+This can happen in interrupt or process context, depending on the
+storage device.
+
+Filesystems that need to update internal bookkeeping (e.g. unwritten
+extent conversions) should provide a ``->prepare_ioend`` function to
+set ``struct iomap_end::bio::bi_end_io`` to its own function.
+This function should call ``iomap_finish_ioends`` after finishing its
+own work (e.g. unwritten extent conversion).
+
+Some filesystems may wish to `amortize the cost of running metadata
+transactions
+<https://lore.kernel.org/all/[email protected]/>`_
+for post-writeback updates by batching them.
+They may also require transactions to run from process context, which
+implies punting batches to a workqueue.
+iomap ioends contain a ``list_head`` to enable batching.
+
+Given a batch of ioends, iomap has a few helpers to assist with
+amortization:
+
+ * ``iomap_sort_ioends``: Sort all the ioends in the list by file
+ offset.
+
+ * ``iomap_ioend_try_merge``: Given an ioend that is not in any list and
+ a separate list of sorted ioends, merge as many of the ioends from
+ the head of the list into the given ioend.
+ ioends can only be merged if the file range and storage addresses are
+ contiguous; the unwritten and shared status are the same; and the
+ write I/O outcome is the same.
+ The merged ioends become their own list.
+
+ * ``iomap_finish_ioends``: Finish an ioend that possibly has other
+ ioends linked to it.
+
+Direct I/O
+==========
+
+In Linux, direct I/O is defined as file I/O that is issued directly to
+storage, bypassing the pagecache.
+The ``iomap_dio_rw`` function implements O_DIRECT (direct I/O) reads and
+writes for files.
+
+.. code-block:: c
+
+ ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
+ const struct iomap_ops *ops,
+ const struct iomap_dio_ops *dops,
+ unsigned int dio_flags, void *private,
+ size_t done_before);
+
+The filesystem can provide the ``dops`` parameter if it needs to perform
+extra work before or after the I/O is issued to storage.
+The ``done_before`` parameter tells the how much of the request has
+already been transferred.
+It is used to continue a request asynchronously when `part of the
+request
+<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c03098d4b9ad76bca2966a8769dcfe59f7f85103>`_
+has already been completed synchronously.
+
+The ``done_before`` parameter should be set if writes for the ``iocb``
+have been initiated prior to the call.
+The direction of the I/O is determined from the ``iocb`` passed in.
+
+The ``dio_flags`` argument can be set to any combination of the
+following values:
+
+ * ``IOMAP_DIO_FORCE_WAIT``: Wait for the I/O to complete even if the
+ kiocb is not synchronous.
+
+ * ``IOMAP_DIO_OVERWRITE_ONLY``: Perform a pure overwrite for this range
+ or fail with ``-EAGAIN``.
+ This can be used by filesystems with complex unaligned I/O
+ write paths to provide an optimised fast path for unaligned writes.
+ If a pure overwrite can be performed, then serialisation against
+ other I/Os to the same filesystem block(s) is unnecessary as there is
+ no risk of stale data exposure or data loss.
+ If a pure overwrite cannot be performed, then the filesystem can
+ perform the serialisation steps needed to provide exclusive access
+ to the unaligned I/O range so that it can perform allocation and
+ sub-block zeroing safely.
+ Filesystems can use this flag to try to reduce locking contention,
+ but a lot of `detailed checking
+ <https://lore.kernel.org/linux-ext4/[email protected]/>`_
+ is required to do it `correctly
+ <https://lore.kernel.org/linux-ext4/[email protected]/>`_.
+
+ * ``IOMAP_DIO_PARTIAL``: If a page fault occurs, return whatever
+ progress has already been made.
+ The caller may deal with the page fault and retry the operation.
+ If the caller decides to retry the operation, it should pass the
+ accumulated return values of all previous calls as the
+ ``done_before`` parameter to the next call.
+
+These ``struct kiocb`` flags are significant for direct I/O with iomap:
+
+ * ``IOCB_NOWAIT``: Turns on ``IOMAP_NOWAIT``.
+
+ * ``IOCB_SYNC``: Ensure that the device has persisted data to disk
+ before completing the call.
+ In the case of pure overwrites, the I/O may be issued with FUA
+ enabled.
+
+ * ``IOCB_HIPRI``: Poll for I/O completion instead of waiting for an
+ interrupt.
+ Only meaningful for asynchronous I/O, and only if the entire I/O can
+ be issued as a single ``struct bio``.
+
+ * ``IOCB_DIO_CALLER_COMP``: Try to run I/O completion from the caller's
+ process context.
+ See ``linux/fs.h`` for more details.
+
+Filesystems should call ``iomap_dio_rw`` from ``->read_iter`` and
+``->write_iter``, and set ``FMODE_CAN_ODIRECT`` in the ``->open``
+function for the file.
+They should not set ``->direct_IO``, which is deprecated.
+
+If a filesystem wishes to perform its own work before direct I/O
+completion, it should call ``__iomap_dio_rw``.
+If its return value is not an error pointer or a NULL pointer, the
+filesystem should pass the return value to ``iomap_dio_complete`` after
+finishing its internal work.
+
+Return Values
+-------------
+
+``iomap_dio_rw`` can return one of the following:
+
+ * A non-negative number of bytes transferred.
+
+ * ``-ENOTBLK``: Fall back to buffered I/O.
+ iomap itself will return this value if it cannot invalidate the page
+ cache before issuing the I/O to storage.
+ The ``->iomap_begin`` or ``->iomap_end`` functions may also return
+ this value.
+
+ * ``-EIOCBQUEUED``: The asynchronous direct I/O request has been
+ queued and will be completed separately.
+
+ * Any of the other negative error codes.
+
+Direct Reads
+------------
+
+A direct I/O read initiates a read I/O from the storage device to the
+caller's buffer.
+Dirty parts of the pagecache are flushed to storage before initiating
+the read io.
+The ``flags`` value for ``->iomap_begin`` will be ``IOMAP_DIRECT`` with
+any combination of the following enhancements:
+
+ * ``IOMAP_NOWAIT``, as defined previously.
+
+Callers commonly hold ``i_rwsem`` in shared mode before calling this
+function.
+
+Direct Writes
+-------------
+
+A direct I/O write initiates a write I/O to the storage device from the
+caller's buffer.
+Dirty parts of the pagecache are flushed to storage before initiating
+the write io.
+The pagecache is invalidated both before and after the write io.
+The ``flags`` value for ``->iomap_begin`` will be ``IOMAP_DIRECT |
+IOMAP_WRITE`` with any combination of the following enhancements:
+
+ * ``IOMAP_NOWAIT``, as defined previously.
+
+ * ``IOMAP_OVERWRITE_ONLY``: Allocating blocks and zeroing partial
+ blocks is not allowed.
+ The entire file range must map to a single written or unwritten
+ extent.
+ The file I/O range must be aligned to the filesystem block size
+ if the mapping is unwritten and the filesystem cannot handle zeroing
+ the unaligned regions without exposing stale contents.
+
+Callers commonly hold ``i_rwsem`` in shared or exclusive mode before
+calling this function.
+
+``struct iomap_dio_ops:``
+-------------------------
+.. code-block:: c
+
+ struct iomap_dio_ops {
+ void (*submit_io)(const struct iomap_iter *iter, struct bio *bio,
+ loff_t file_offset);
+ int (*end_io)(struct kiocb *iocb, ssize_t size, int error,
+ unsigned flags);
+ struct bio_set *bio_set;
+ };
+
+The fields of this structure are as follows:
+
+ - ``submit_io``: iomap calls this function when it has constructed a
+ ``struct bio`` object for the I/O requested, and wishes to submit it
+ to the block device.
+ If no function is provided, ``submit_bio`` will be called directly.
+ Filesystems that would like to perform additional work before (e.g.
+ data replication for btrfs) should implement this function.
+
+ - ``end_io``: This is called after the ``struct bio`` completes.
+ This function should perform post-write conversions of unwritten
+ extent mappings, handle write failures, etc.
+ The ``flags`` argument may be set to a combination of the following:
+
+ * ``IOMAP_DIO_UNWRITTEN``: The mapping was unwritten, so the ioend
+ should mark the extent as written.
+
+ * ``IOMAP_DIO_COW``: Writing to the space in the mapping required a
+ copy on write operation, so the ioend should switch mappings.
+
+ - ``bio_set``: This allows the filesystem to provide a custom bio_set
+ for allocating direct I/O bios.
+ This enables filesystems to `stash additional per-bio information
+ <https://lore.kernel.org/all/[email protected]/>`_
+ for private use.
+ If this field is NULL, generic ``struct bio`` objects will be used.
+
+Filesystems that want to perform extra work after an I/O completion
+should set a custom ``->bi_end_io`` function via ``->submit_io``.
+Afterwards, the custom endio function must call
+``iomap_dio_bio_end_io`` to finish the direct I/O.
+
+DAX I/O
+=======
+
+Some storage devices can be directly mapped as memory.
+These devices support a new access mode known as "fsdax" that allows
+loads and stores through the CPU and memory controller.
+
+fsdax Reads
+-----------
+
+A fsdax read performs a memcpy from storage device to the caller's
+buffer.
+The ``flags`` value for ``->iomap_begin`` will be ``IOMAP_DAX`` with any
+combination of the following enhancements:
+
+ * ``IOMAP_NOWAIT``, as defined previously.
+
+Callers commonly hold ``i_rwsem`` in shared mode before calling this
+function.
+
+fsdax Writes
+------------
+
+A fsdax write initiates a memcpy to the storage device from the caller's
+buffer.
+The ``flags`` value for ``->iomap_begin`` will be ``IOMAP_DAX |
+IOMAP_WRITE`` with any combination of the following enhancements:
+
+ * ``IOMAP_NOWAIT``, as defined previously.
+
+ * ``IOMAP_OVERWRITE_ONLY``: The caller requires a pure overwrite to be
+ performed from this mapping.
+ This requires the filesystem extent mapping to already exist as an
+ ``IOMAP_MAPPED`` type and span the entire range of the write I/O
+ request.
+ If the filesystem cannot map this request in a way that allows the
+ iomap infrastructure to perform a pure overwrite, it must fail the
+ mapping operation with ``-EAGAIN``.
+
+Callers commonly hold ``i_rwsem`` in exclusive mode before calling this
+function.
+
+fsdax mmap Faults
+~~~~~~~~~~~~~~~~~
+
+The ``dax_iomap_fault`` function handles read and write faults to fsdax
+storage.
+For a read fault, ``IOMAP_DAX | IOMAP_FAULT`` will be passed as the
+``flags`` argument to ``->iomap_begin``.
+For a write fault, ``IOMAP_DAX | IOMAP_FAULT | IOMAP_WRITE`` will be
+passed as the ``flags`` argument to ``->iomap_begin``.
+
+Callers commonly hold the same locks as they do to call their iomap
+pagecache counterparts.
+
+fsdax Truncation, fallocate, and Unsharing
+------------------------------------------
+
+For fsdax files, the following functions are provided to replace their
+iomap pagecache I/O counterparts.
+The ``flags`` argument to ``->iomap_begin`` are the same as the
+pagecache counterparts, with ``IOMAP_DAX`` added.
+
+ * ``dax_file_unshare``
+ * ``dax_zero_range``
+ * ``dax_truncate_page``
+
+Callers commonly hold the same locks as they do to call their iomap
+pagecache counterparts.
+
+fsdax Deduplication
+-------------------
+
+Filesystems implementing the ``FIDEDUPERANGE`` ioctl must call the
+``dax_remap_file_range_prep`` function with their own iomap read ops.
+
+Seeking Files
+=============
+
+iomap implements the two iterating whence modes of the ``llseek`` system
+call.
+
+SEEK_DATA
+---------
+
+The ``iomap_seek_data`` function implements the SEEK_DATA "whence" value
+for llseek.
+``IOMAP_REPORT`` will be passed as the ``flags`` argument to
+``->iomap_begin``.
+
+For unwritten mappings, the pagecache will be searched.
+Regions of the pagecache with a folio mapped and uptodate fsblocks
+within those folios will be reported as data areas.
+
+Callers commonly hold ``i_rwsem`` in shared mode before calling this
+function.
+
+SEEK_HOLE
+---------
+
+The ``iomap_seek_hole`` function implements the SEEK_HOLE "whence" value
+for llseek.
+``IOMAP_REPORT`` will be passed as the ``flags`` argument to
+``->iomap_begin``.
+
+For unwritten mappings, the pagecache will be searched.
+Regions of the pagecache with no folio mapped, or a !uptodate fsblock
+within a folio will be reported as sparse hole areas.
+
+Callers commonly hold ``i_rwsem`` in shared mode before calling this
+function.
+
+Swap File Activation
+====================
+
+The ``iomap_swapfile_activate`` function finds all the base-page aligned
+regions in a file and sets them up as swap space.
+The file will be ``fsync()``'d before activation.
+``IOMAP_REPORT`` will be passed as the ``flags`` argument to
+``->iomap_begin``.
+All mappings must be mapped or unwritten; cannot be dirty or shared, and
+cannot span multiple block devices.
+Callers must hold ``i_rwsem`` in exclusive mode; this is already
+provided by ``swapon``.
+
+File Space Mapping Reporting
+============================
+
+iomap implements two of the file space mapping system calls.
+
+FS_IOC_FIEMAP
+-------------
+
+The ``iomap_fiemap`` function exports file extent mappings to userspace
+in the format specified by the ``FS_IOC_FIEMAP`` ioctl.
+``IOMAP_REPORT`` will be passed as the ``flags`` argument to
+``->iomap_begin``.
+Callers commonly hold ``i_rwsem`` in shared mode before calling this
+function.
+
+FIBMAP (deprecated)
+-------------------
+
+``iomap_bmap`` implements FIBMAP.
+The calling conventions are the same as for FIEMAP.
+This function is only provided to maintain compatibility for filesystems
+that implemented FIBMAP prior to conversion.
+This ioctl is deprecated; do **not** add a FIBMAP implementation to
+filesystems that do not have it.
+Callers should probably hold ``i_rwsem`` in shared mode before calling
+this function, but this is unclear.
diff --git a/Documentation/filesystems/iomap/porting.rst b/Documentation/filesystems/iomap/porting.rst
new file mode 100644
index 000000000000..3d49a32c0fff
--- /dev/null
+++ b/Documentation/filesystems/iomap/porting.rst
@@ -0,0 +1,120 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. _iomap_porting:
+
+..
+ Dumb style notes to maintain the author's sanity:
+ Please try to start sentences on separate lines so that
+ sentence changes don't bleed colors in diff.
+ Heading decorations are documented in sphinx.rst.
+
+=======================
+Porting Your Filesystem
+=======================
+
+.. contents:: Table of Contents
+ :local:
+
+Why Convert?
+============
+
+There are several reasons to convert a filesystem to iomap:
+
+ 1. The classic Linux I/O path is not terribly efficient.
+ Pagecache operations lock a single base page at a time and then call
+ into the filesystem to return a mapping for only that page.
+ Direct I/O operations build I/O requests a single file block at a
+ time.
+ This worked well enough for direct/indirect-mapped filesystems such
+ as ext2, but is very inefficient for extent-based filesystems such
+ as XFS.
+
+ 2. Large folios are only supported via iomap; there are no plans to
+ convert the old buffer_head path to use them.
+
+ 3. Direct access to storage on memory-like devices (fsdax) is only
+ supported via iomap.
+
+ 4. Lower maintenance overhead for individual filesystem maintainers.
+ iomap handles common pagecache related operations itself, such as
+ allocating, instantiating, locking, and unlocking of folios.
+ No ->write_begin(), ->write_end() or direct_IO
+ address_space_operations are required to be implemented by
+ filesystem using iomap.
+
+How Do I Convert a Filesystem?
+==============================
+
+First, add ``#include <linux/iomap.h>`` from your source code and add
+``select FS_IOMAP`` to your filesystem's Kconfig option.
+Build the kernel, run fstests with the ``-g all`` option across a wide
+variety of your filesystem's supported configurations to build a
+baseline of which tests pass and which ones fail.
+
+The recommended approach is first to implement ``->iomap_begin`` (and
+``->iomap_end`` if necessary) to allow iomap to obtain a read-only
+mapping of a file range.
+In most cases, this is a relatively trivial conversion of the existing
+``get_block()`` function for read-only mappings.
+``FS_IOC_FIEMAP`` is a good first target because it is trivial to
+implement support for it and then to determine that the extent map
+iteration is correct from userspace.
+If FIEMAP is returning the correct information, it's a good sign that
+other read-only mapping operations will do the right thing.
+
+Next, modify the filesystem's ``get_block(create = false)``
+implementation to use the new ``->iomap_begin`` implementation to map
+file space for selected read operations.
+Hide behind a debugging knob the ability to switch on the iomap mapping
+functions for selected call paths.
+It is necessary to write some code to fill out the bufferhead-based
+mapping information from the ``iomap`` structure, but the new functions
+can be tested without needing to implement any iomap APIs.
+
+Once the read-only functions are working like this, convert each high
+level file operation one by one to use iomap native APIs instead of
+going through ``get_block()``.
+Done one at a time, regressions should be self evident.
+You *do* have a regression test baseline for fstests, right?
+It is suggested to convert swap file activation, ``SEEK_DATA``, and
+``SEEK_HOLE`` before tackling the I/O paths.
+A likely complexity at this point will be converting the buffered read
+I/O path because of bufferheads.
+The buffered read I/O paths doesn't need to be converted yet, though the
+direct I/O read path should be converted in this phase.
+
+At this point, you should look over your ``->iomap_begin`` function.
+If it switches between large blocks of code based on dispatching of the
+``flags`` argument, you should consider breaking it up into
+per-operation iomap ops with smaller, more cohesive functions.
+XFS is a good example of this.
+
+The next thing to do is implement ``get_blocks(create == true)``
+functionality in the ``->iomap_begin``/``->iomap_end`` methods.
+It is strongly recommended to create separate mapping functions and
+iomap ops for write operations.
+Then convert the direct I/O write path to iomap, and start running fsx
+w/ DIO enabled in earnest on filesystem.
+This will flush out lots of data integrity corner case bugs that the new
+write mapping implementation introduces.
+
+Now, convert any remaining file operations to call the iomap functions.
+This will get the entire filesystem using the new mapping functions, and
+they should largely be debugged and working correctly after this step.
+
+Most likely at this point, the buffered read and write paths will still
+need to be converted.
+The mapping functions should all work correctly, so all that needs to be
+done is rewriting all the code that interfaces with bufferheads to
+interface with iomap and folios.
+It is much easier first to get regular file I/O (without any fancy
+features like fscrypt, fsverity, compression, or data=journaling)
+converted to use iomap.
+Some of those fancy features (fscrypt and compression) aren't
+implemented yet in iomap.
+For unjournalled filesystems that use the pagecache for symbolic links
+and directories, you might also try converting their handling to iomap.
+
+The rest is left as an exercise for the reader, as it will be different
+for every filesystem.
+If you encounter problems, email the people and lists in
+``get_maintainers.pl`` for help.
diff --git a/Documentation/filesystems/mount_api.rst b/Documentation/filesystems/mount_api.rst
index 9aaf6ef75eb5..317934c9e8fc 100644
--- a/Documentation/filesystems/mount_api.rst
+++ b/Documentation/filesystems/mount_api.rst
@@ -645,6 +645,8 @@ The members are as follows:
fs_param_is_blockdev Blockdev path * Needs lookup
fs_param_is_path Path * Needs lookup
fs_param_is_fd File descriptor result->int_32
+ fs_param_is_uid User ID (u32) result->uid
+ fs_param_is_gid Group ID (u32) result->gid
======================= ======================= =====================
Note that if the value is of fs_param_is_bool type, fs_parse() will try
@@ -678,6 +680,8 @@ The members are as follows:
fsparam_bdev() fs_param_is_blockdev
fsparam_path() fs_param_is_path
fsparam_fd() fs_param_is_fd
+ fsparam_uid() fs_param_is_uid
+ fsparam_gid() fs_param_is_gid
======================= ===============================================
all of which take two arguments, name string and option number - for
@@ -784,8 +788,9 @@ process the parameters it is given.
option number (which it returns).
If successful, and if the parameter type indicates the result is a
- boolean, integer or enum type, the value is converted by this function and
- the result stored in result->{boolean,int_32,uint_32,uint_64}.
+ boolean, integer, enum, uid, or gid type, the value is converted by this
+ function and the result stored in
+ result->{boolean,int_32,uint_32,uint_64,uid,gid}.
If a match isn't initially made, the key is prefixed with "no" and no
value is present then an attempt will be made to look up the key with the
diff --git a/Documentation/hwmon/adm1021.rst b/Documentation/hwmon/adm1021.rst
deleted file mode 100644
index 116fb2019956..000000000000
--- a/Documentation/hwmon/adm1021.rst
+++ /dev/null
@@ -1,153 +0,0 @@
-Kernel driver adm1021
-=====================
-
-Supported chips:
-
- * Analog Devices ADM1021
-
- Prefix: 'adm1021'
-
- Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
-
- Datasheet: Publicly available at the Analog Devices website
-
- * Analog Devices ADM1021A/ADM1023
-
- Prefix: 'adm1023'
-
- Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
-
- Datasheet: Publicly available at the Analog Devices website
-
- * Genesys Logic GL523SM
-
- Prefix: 'gl523sm'
-
- Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
-
- Datasheet:
-
- * Maxim MAX1617
-
- Prefix: 'max1617'
-
- Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
-
- Datasheet: Publicly available at the Maxim website
-
- * Maxim MAX1617A
-
- Prefix: 'max1617a'
-
- Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
-
- Datasheet: Publicly available at the Maxim website
-
- * National Semiconductor LM84
-
- Prefix: 'lm84'
-
- Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
-
- Datasheet: Publicly available at the National Semiconductor website
-
- * Philips NE1617
-
- Prefix: 'max1617' (probably detected as a max1617)
-
- Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
-
- Datasheet: Publicly available at the Philips website
-
- * Philips NE1617A
-
- Prefix: 'max1617' (probably detected as a max1617)
-
- Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
-
- Datasheet: Publicly available at the Philips website
-
- * TI THMC10
-
- Prefix: 'thmc10'
-
- Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
-
- Datasheet: Publicly available at the TI website
-
- * Onsemi MC1066
-
- Prefix: 'mc1066'
-
- Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
-
- Datasheet: Publicly available at the Onsemi website
-
-
-Authors:
- - Frodo Looijaard <[email protected]>,
- - Philip Edelbrock <[email protected]>
-
-Module Parameters
------------------
-
-* read_only: int
- Don't set any values, read only mode
-
-
-Description
------------
-
-The chips supported by this driver are very similar. The Maxim MAX1617 is
-the oldest; it has the problem that it is not very well detectable. The
-MAX1617A solves that. The ADM1021 is a straight clone of the MAX1617A.
-Ditto for the THMC10. From here on, we will refer to all these chips as
-ADM1021-clones.
-
-The ADM1021 and MAX1617A reports a die code, which is a sort of revision
-code. This can help us pinpoint problems; it is not very useful
-otherwise.
-
-ADM1021-clones implement two temperature sensors. One of them is internal,
-and measures the temperature of the chip itself; the other is external and
-is realised in the form of a transistor-like device. A special alarm
-indicates whether the remote sensor is connected.
-
-Each sensor has its own low and high limits. When they are crossed, the
-corresponding alarm is set and remains on as long as the temperature stays
-out of range. Temperatures are measured in degrees Celsius. Measurements
-are possible between -65 and +127 degrees, with a resolution of one degree.
-
-If an alarm triggers, it will remain triggered until the hardware register
-is read at least once. This means that the cause for the alarm may already
-have disappeared!
-
-This driver only updates its values each 1.5 seconds; reading it more often
-will do no harm, but will return 'old' values. It is possible to make
-ADM1021-clones do faster measurements, but there is really no good reason
-for that.
-
-
-Netburst-based Xeon support
----------------------------
-
-Some Xeon processors based on the Netburst (early Pentium 4, from 2001 to
-2003) microarchitecture had real MAX1617, ADM1021, or compatible chips
-within them, with two temperature sensors. Other Xeon processors of this
-era (with 400 MHz FSB) had chips with only one temperature sensor.
-
-If you have such an old Xeon, and you get two valid temperatures when
-loading the adm1021 module, then things are good.
-
-If nothing happens when loading the adm1021 module, and you are certain
-that your specific Xeon processor model includes compatible sensors, you
-will have to explicitly instantiate the sensor chips from user-space. See
-method 4 in Documentation/i2c/instantiating-devices.rst. Possible slave
-addresses are 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e. It is likely that
-only temp2 will be correct and temp1 will have to be ignored.
-
-Previous generations of the Xeon processor (based on Pentium II/III)
-didn't have these sensors. Next generations of Xeon processors (533 MHz
-FSB and faster) lost them, until the Core-based generation which
-introduced integrated digital thermal sensors. These are supported by
-the coretemp driver.
diff --git a/Documentation/hwmon/amc6821.rst b/Documentation/hwmon/amc6821.rst
index 5ddb2849da90..dbd544cd1160 100644
--- a/Documentation/hwmon/amc6821.rst
+++ b/Documentation/hwmon/amc6821.rst
@@ -47,13 +47,18 @@ fan1_input ro tachometer speed
fan1_min rw "
fan1_max rw "
fan1_fault ro "
-fan1_div rw Fan divisor can be either 2 or 4.
+fan1_pulses rw Pulses per revolution can be either 2 or 4.
+fan1_target rw Target fan speed, to be used with pwm1_enable
+ mode 4.
pwm1 rw pwm1
pwm1_enable rw regulator mode, 1=open loop, 2=fan controlled
by remote temperature, 3=fan controlled by
combination of the on-chip temperature and
remote-sensor temperature,
+ 4=fan controlled by target rpm set with
+ fan1_target attribute.
+pwm1_mode rw Fan duty control mode (0=DC, 1=PWM)
pwm1_auto_channels_temp ro 1 if pwm_enable==2, 3 if pwm_enable==3
pwm1_auto_point1_pwm ro Hardwired to 0, shared for both
temperature channels.
diff --git a/Documentation/hwmon/asus_ec_sensors.rst b/Documentation/hwmon/asus_ec_sensors.rst
index 0bf99ba406dd..ca38922f4ec5 100644
--- a/Documentation/hwmon/asus_ec_sensors.rst
+++ b/Documentation/hwmon/asus_ec_sensors.rst
@@ -8,6 +8,7 @@ Supported boards:
* PRIME X570-PRO
* Pro WS X570-ACE
* ProArt X570-CREATOR WIFI
+ * ProArt X670E-CREATOR WIFI
* ProArt B550-CREATOR
* ROG CROSSHAIR VIII DARK HERO
* ROG CROSSHAIR VIII HERO (WI-FI)
diff --git a/Documentation/hwmon/corsair-cpro.rst b/Documentation/hwmon/corsair-cpro.rst
index 751f95476b57..15077203a2f8 100644
--- a/Documentation/hwmon/corsair-cpro.rst
+++ b/Documentation/hwmon/corsair-cpro.rst
@@ -39,3 +39,11 @@ fan[1-6]_target Sets fan speed target rpm.
pwm[1-6] Sets the fan speed. Values from 0-255. Can only be read if pwm
was set directly.
======================= =====================================================================
+
+Debugfs entries
+---------------
+
+======================= ===================
+firmware_version Firmware version
+bootloader_version Bootloader version
+======================= ===================
diff --git a/Documentation/hwmon/corsair-psu.rst b/Documentation/hwmon/corsair-psu.rst
index 16db34d464dd..7ed794087f84 100644
--- a/Documentation/hwmon/corsair-psu.rst
+++ b/Documentation/hwmon/corsair-psu.rst
@@ -15,11 +15,11 @@ Supported devices:
Corsair HX850i
- Corsair HX1000i (Series 2022 and 2023)
+ Corsair HX1000i (Legacy and Series 2023)
- Corsair HX1200i
+ Corsair HX1200i (Legacy and Series 2023)
- Corsair HX1500i (Series 2022 and 2023)
+ Corsair HX1500i (Legacy and Series 2023)
Corsair RM550i
diff --git a/Documentation/hwmon/cros_ec_hwmon.rst b/Documentation/hwmon/cros_ec_hwmon.rst
new file mode 100644
index 000000000000..47ecae983bdb
--- /dev/null
+++ b/Documentation/hwmon/cros_ec_hwmon.rst
@@ -0,0 +1,26 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Kernel driver cros_ec_hwmon
+===========================
+
+Supported chips:
+
+ * ChromeOS embedded controllers.
+
+ Prefix: 'cros_ec'
+
+ Addresses scanned: -
+
+Author:
+
+ - Thomas Weißschuh <[email protected]>
+
+Description
+-----------
+
+This driver implements support for hardware monitoring commands exposed by the
+ChromeOS embedded controller used in Chromebooks and other devices.
+
+The channel labels exposed via hwmon are retrieved from the EC itself.
+
+Fan and temperature readings are supported.
diff --git a/Documentation/hwmon/dell-smm-hwmon.rst b/Documentation/hwmon/dell-smm-hwmon.rst
index 977263cb57a8..74905675d71f 100644
--- a/Documentation/hwmon/dell-smm-hwmon.rst
+++ b/Documentation/hwmon/dell-smm-hwmon.rst
@@ -360,6 +360,8 @@ Firmware Bug Affected Machines
======================================================= =================
Reading of fan states return spurious errors. Precision 490
+ OptiPlex 7060
+
Reading of fan types causes erratic fan behaviour. Studio XPS 8000
Studio XPS 8100
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 03d313af469a..913c11390a45 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -25,7 +25,6 @@ Hardware Monitoring Kernel Drivers
acpi_power_meter
ad7314
adc128d818
- adm1021
adm1025
adm1026
adm1031
@@ -58,6 +57,7 @@ Hardware Monitoring Kernel Drivers
coretemp
corsair-cpro
corsair-psu
+ cros_ec_hwmon
da9052
da9055
dell-smm-hwmon
@@ -154,7 +154,6 @@ Hardware Monitoring Kernel Drivers
max34440
max6620
max6639
- max6642
max6650
max6697
max8688
@@ -165,9 +164,13 @@ Hardware Monitoring Kernel Drivers
mlxreg-fan
mp2856
mp2888
+ mp2891
mp2975
+ mp2993
mp5023
+ mp5920
mp5990
+ mp9941
mpq8785
nct6683
nct6775
@@ -215,6 +218,7 @@ Hardware Monitoring Kernel Drivers
smsc47m192
smsc47m1
sparx5-temp
+ spd5118
stpddc60
surface_fan
sy7636a-hwmon
diff --git a/Documentation/hwmon/max31827.rst b/Documentation/hwmon/max31827.rst
index 44ab9dc064cb..9c11a9518c67 100644
--- a/Documentation/hwmon/max31827.rst
+++ b/Documentation/hwmon/max31827.rst
@@ -131,7 +131,14 @@ The Fault Queue bits select how many consecutive temperature faults must occur
before overtemperature or undertemperature faults are indicated in the
corresponding status bits.
-Notes
------
+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
+usage (+33% for both write and reads) in normal conditions.
-PEC is not implemented.
+Since this operation implies there will be an extra delay to each
+transaction, PEC can be disabled or enabled through sysfs.
+Just write 1 to the "pec" file for enabling PEC and 0 for disabling it.
diff --git a/Documentation/hwmon/max6642.rst b/Documentation/hwmon/max6642.rst
deleted file mode 100644
index 7e5b7d4f9492..000000000000
--- a/Documentation/hwmon/max6642.rst
+++ /dev/null
@@ -1,27 +0,0 @@
-Kernel driver max6642
-=====================
-
-Supported chips:
-
- * Maxim MAX6642
-
- Prefix: 'max6642'
-
- Addresses scanned: I2C 0x48-0x4f
-
- Datasheet: Publicly available at the Maxim website
-
- http://datasheets.maxim-ic.com/en/ds/MAX6642.pdf
-
-Authors:
-
- Per Dalen <[email protected]>
-
-Description
------------
-
-The MAX6642 is a digital temperature sensor. It senses its own temperature as
-well as the temperature on one external diode.
-
-All temperature values are given in degrees Celsius. Resolution
-is 0.25 degree for the local temperature and for the remote temperature.
diff --git a/Documentation/hwmon/mp2891.rst b/Documentation/hwmon/mp2891.rst
new file mode 100644
index 000000000000..55944d1b5457
--- /dev/null
+++ b/Documentation/hwmon/mp2891.rst
@@ -0,0 +1,179 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver mp2891
+====================
+
+Supported chips:
+
+ * MPS mp2891
+
+ Prefix: 'mp2891'
+
+ * Datasheet
+
+ Publicly available at the MPS website : https://www.monolithicpower.com/en/mp2891.html
+
+Author:
+
+ Noah Wang <[email protected]>
+
+Description
+-----------
+
+This driver implements support for Monolithic Power Systems, Inc. (MPS)
+MP2891 Multi-phase Digital VR Controller.
+
+Device compliant with:
+
+- PMBus rev 1.3 interface.
+
+Device supports direct and linear format for reading input voltage,
+output voltage, input current, output current, input power, output
+power, and temperature.
+
+The driver exports the following attributes via the 'sysfs' files
+for input voltage:
+
+**in1_input**
+
+**in1_label**
+
+**in1_crit**
+
+**in1_crit_alarm**
+
+**in1_lcrit**
+
+**in1_lcrit_alarm**
+
+**in1_min**
+
+**in1_min_alarm**
+
+The driver provides the following attributes for output voltage:
+
+**in2_input**
+
+**in2_label**
+
+**in2_crit**
+
+**in2_crit_alarm**
+
+**in2_lcrit**
+
+**in2_lcrit_alarm**
+
+**in2_min**
+
+**in2_min_alarm**
+
+**in3_input**
+
+**in3_label**
+
+**in3_crit**
+
+**in3_crit_alarm**
+
+**in3_lcrit**
+
+**in3_lcrit_alarm**
+
+**in3_min**
+
+**in3_min_alarm**
+
+The driver provides the following attributes for input current:
+
+**curr1_input**
+
+**curr1_label**
+
+**curr1_max**
+
+**curr1_max_alarm**
+
+**curr2_input**
+
+**curr2_label**
+
+**curr2_max**
+
+**curr2_max_alarm**
+
+The driver provides the following attributes for output current:
+
+**curr3_input**
+
+**curr3_label**
+
+**curr3_crit**
+
+**curr3_crit_alarm**
+
+**curr3_max**
+
+**curr3_max_alarm**
+
+**curr4_input**
+
+**curr4_label**
+
+**curr4_crit**
+
+**curr4_crit_alarm**
+
+**curr4_max**
+
+**curr4_max_alarm**
+
+The driver provides the following attributes for input power:
+
+**power1_input**
+
+**power1_label**
+
+**power1_max**
+
+**power1_alarm**
+
+**power2_input**
+
+**power2_label**
+
+**power2_max**
+
+**power2_alarm**
+
+The driver provides the following attributes for output power:
+
+**power3_input**
+
+**power3_label**
+
+**power4_input**
+
+**power4_label**
+
+The driver provides the following attributes for temperature:
+
+**temp1_input**
+
+**temp1_crit**
+
+**temp1_crit_alarm**
+
+**temp1_max**
+
+**temp1_max_alarm**
+
+**temp2_input**
+
+**temp2_crit**
+
+**temp2_crit_alarm**
+
+**temp2_max**
+
+**temp2_max_alarm**
diff --git a/Documentation/hwmon/mp2993.rst b/Documentation/hwmon/mp2993.rst
new file mode 100644
index 000000000000..7a4fe0d946e0
--- /dev/null
+++ b/Documentation/hwmon/mp2993.rst
@@ -0,0 +1,150 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver mp2993
+====================
+
+Supported chips:
+
+ * MPS mp2993
+
+ Prefix: 'mp2993'
+
+ * Datasheet
+ https://scnbwymvp-my.sharepoint.com/:f:/g/personal/admin_scnbwy_com/Eth4kX1_J1hMsaASHiOYL4QBHU5a75r-tRfLKbHnJFdKLQ?e=vxj3DF
+
+Author:
+
+ Noah Wang <[email protected]>
+
+Description
+-----------
+
+This driver implements support for Monolithic Power Systems, Inc. (MPS)
+MP2993 Dual Loop Digital Multi-phase Controller.
+
+Device compliant with:
+
+- PMBus rev 1.3 interface.
+
+The driver exports the following attributes via the 'sysfs' files
+for input voltage:
+
+**in1_input**
+
+**in1_label**
+
+**in1_crit**
+
+**in1_crit_alarm**
+
+**in1_lcrit**
+
+**in1_lcrit_alarm**
+
+**in1_max**
+
+**in1_max_alarm**
+
+**in1_min**
+
+**in1_min_alarm**
+
+The driver provides the following attributes for output voltage:
+
+**in2_input**
+
+**in2_label**
+
+**in2_crit**
+
+**in2_crit_alarm**
+
+**in2_lcrit**
+
+**in2_lcrit_alarm**
+
+**in3_input**
+
+**in3_label**
+
+**in3_crit**
+
+**in3_crit_alarm**
+
+**in3_lcrit**
+
+**in3_lcrit_alarm**
+
+The driver provides the following attributes for input current:
+
+**curr1_input**
+
+**curr1_label**
+
+**curr1_max**
+
+**curr1_max_alarm**
+
+The driver provides the following attributes for output current:
+
+**curr2_input**
+
+**curr2_label**
+
+**curr2_crit**
+
+**curr2_crit_alarm**
+
+**curr2_max**
+
+**curr2_max_alarm**
+
+**curr3_input**
+
+**curr3_label**
+
+**curr3_crit**
+
+**curr3_crit_alarm**
+
+**curr3_max**
+
+**curr3_max_alarm**
+
+The driver provides the following attributes for input power:
+
+**power1_input**
+
+**power1_label**
+
+The driver provides the following attributes for output power:
+
+**power2_input**
+
+**power2_label**
+
+**power3_input**
+
+**power3_label**
+
+The driver provides the following attributes for temperature:
+
+**temp1_input**
+
+**temp1_crit**
+
+**temp1_crit_alarm**
+
+**temp1_max**
+
+**temp1_max_alarm**
+
+**temp2_input**
+
+**temp2_crit**
+
+**temp2_crit_alarm**
+
+**temp2_max**
+
+**temp2_max_alarm**
diff --git a/Documentation/hwmon/mp5920.rst b/Documentation/hwmon/mp5920.rst
new file mode 100644
index 000000000000..98946e7cf54e
--- /dev/null
+++ b/Documentation/hwmon/mp5920.rst
@@ -0,0 +1,91 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver mp5920
+====================
+
+Supported chips:
+
+ * MPS MP5920
+
+ Prefix: 'mp5920'
+
+ * Datasheet
+
+ Publicly available at the MPS website : https://www.monolithicpower.com/en/mp5920.html
+
+Authors:
+
+ Tony Ao <[email protected]>
+ Alex Vdovydchenko <[email protected]>
+
+Description
+-----------
+
+This driver implements support for Monolithic Power Systems, Inc. (MPS)
+MP5920 Hot-Swap Controller.
+
+Device compliant with:
+
+- PMBus rev 1.3 interface.
+
+Device supports direct and linear format for reading input voltage,
+output voltage, output current, input power and temperature.
+
+The driver exports the following attributes via the 'sysfs' files
+for input voltage:
+
+**in1_input**
+
+**in1_label**
+
+**in1_rated_max**
+
+**in1_rated_min**
+
+**in1_crit**
+
+**in1_alarm**
+
+The driver provides the following attributes for output voltage:
+
+**in2_input**
+
+**in2_label**
+
+**in2_rated_max**
+
+**in2_rated_min**
+
+**in2_alarm**
+
+The driver provides the following attributes for output current:
+
+**curr1_input**
+
+**curr1_label**
+
+**curr1_crit**
+
+**curr1_alarm**
+
+**curr1_rated_max**
+
+The driver provides the following attributes for input power:
+
+**power1_input**
+
+**power1_label**
+
+**power1_max**
+
+**power1_rated_max**
+
+The driver provides the following attributes for temperature:
+
+**temp1_input**
+
+**temp1_max**
+
+**temp1_crit**
+
+**temp1_alarm**
diff --git a/Documentation/hwmon/mp9941.rst b/Documentation/hwmon/mp9941.rst
new file mode 100644
index 000000000000..1274fa20e256
--- /dev/null
+++ b/Documentation/hwmon/mp9941.rst
@@ -0,0 +1,92 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver mp9941
+====================
+
+Supported chips:
+
+ * MPS mp9941
+
+ Prefix: 'mp9941'
+
+ * Datasheet
+ https://scnbwymvp-my.sharepoint.com/:f:/g/personal/admin_scnbwy_com/Eth4kX1_J1hMsaASHiOYL4QBHU5a75r-tRfLKbHnJFdKLQ?e=vxj3DF
+
+Author:
+
+ Noah Wang <[email protected]>
+
+Description
+-----------
+
+This driver implements support for Monolithic Power Systems, Inc. (MPS)
+MP9941 digital step-down converter.
+
+Device compliant with:
+
+- PMBus rev 1.3 interface.
+
+The driver exports the following attributes via the 'sysfs' files
+for input voltage:
+
+**in1_input**
+
+**in1_label**
+
+**in1_crit**
+
+**in1_crit_alarm**
+
+The driver provides the following attributes for output voltage:
+
+**in2_input**
+
+**in2_label**
+
+**in2_lcrit**
+
+**in2_lcrit_alarm**
+
+**in2_rated_max**
+
+**in2_rated_min**
+
+The driver provides the following attributes for input current:
+
+**curr1_input**
+
+**curr1_label**
+
+**curr1_max**
+
+**curr1_max_alarm**
+
+The driver provides the following attributes for output current:
+
+**curr2_input**
+
+**curr2_label**
+
+The driver provides the following attributes for input power:
+
+**power1_input**
+
+**power1_label**
+
+The driver provides the following attributes for output power:
+
+**power2_input**
+
+**power2_label**
+
+The driver provides the following attributes for temperature:
+
+**temp1_input**
+
+**temp1_crit**
+
+**temp1_crit_alarm**
+
+**temp1_max**
+
+**temp1_max_alarm**
diff --git a/Documentation/hwmon/spd5118.rst b/Documentation/hwmon/spd5118.rst
new file mode 100644
index 000000000000..ef7338f46575
--- /dev/null
+++ b/Documentation/hwmon/spd5118.rst
@@ -0,0 +1,63 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Kernel driver spd5118
+=====================
+
+Supported chips:
+
+ * SPD5118 (JEDEC JESD300) compliant temperature sensor chips
+
+ JEDEC standard download:
+ https://www.jedec.org/standards-documents/docs/jesd300-5b01
+ (account required)
+
+
+ Prefix: 'spd5118'
+
+ Addresses scanned: I2C 0x50 - 0x57
+
+Author:
+ Guenter Roeck <[email protected]>
+
+
+Description
+-----------
+
+This driver implements support for SPD5118 (JEDEC JESD300) compliant temperature
+sensors, which are used on many DDR5 memory modules. Some systems use the sensor
+to prevent memory overheating by automatically throttling the memory controller.
+
+The driver auto-detects SPD5118 compliant chips, but can also be instantiated
+using devicetree/firmware nodes.
+
+A SPD5118 compliant chip supports a single temperature sensor. Critical minimum,
+minimum, maximum, and critical temperature can be configured. There are alarms
+for low critical, low, high, and critical thresholds.
+
+
+Hardware monitoring sysfs entries
+---------------------------------
+
+======================= ==================================
+temp1_input Temperature (RO)
+temp1_lcrit Low critical high temperature (RW)
+temp1_min Minimum temperature (RW)
+temp1_max Maximum temperature (RW)
+temp1_crit Critical high temperature (RW)
+
+temp1_lcrit_alarm Temperature low critical alarm
+temp1_min_alarm Temperature low alarm
+temp1_max_alarm Temperature high alarm
+temp1_crit_alarm Temperature critical alarm
+======================= ==================================
+
+Alarm attributes are sticky until read and will be cleared afterwards
+unless the alarm condition still applies.
+
+
+SPD (Serial Presence Detect) support
+------------------------------------
+
+The driver also supports reading the SPD NVRAM on SPD5118 compatible chips.
+SPD data is available from the 'eeprom' binary attribute file attached to the
+chip's I2C device.
diff --git a/Documentation/networking/devlink/devlink-region.rst b/Documentation/networking/devlink/devlink-region.rst
index 9232cd7da301..5d0b68f752c0 100644
--- a/Documentation/networking/devlink/devlink-region.rst
+++ b/Documentation/networking/devlink/devlink-region.rst
@@ -49,7 +49,7 @@ example usage
$ devlink region show [ DEV/REGION ]
$ devlink region del DEV/REGION snapshot SNAPSHOT_ID
$ devlink region dump DEV/REGION [ snapshot SNAPSHOT_ID ]
- $ devlink region read DEV/REGION [ snapshot SNAPSHOT_ID ] address ADDRESS length length
+ $ devlink region read DEV/REGION [ snapshot SNAPSHOT_ID ] address ADDRESS length LENGTH
# Show all of the exposed regions with region sizes:
$ devlink region show
diff --git a/Documentation/power/regulator/consumer.rst b/Documentation/power/regulator/consumer.rst
index 85c2bf5ac07e..9d2416f63f6e 100644
--- a/Documentation/power/regulator/consumer.rst
+++ b/Documentation/power/regulator/consumer.rst
@@ -227,3 +227,9 @@ directly written to the voltage selector register, use::
int regulator_list_hardware_vsel(struct regulator *regulator,
unsigned selector);
+
+To access the hardware for enabling/disabling the regulator, consumers must
+use regulator_get_exclusive(), as it can't work if there's more than one
+consumer. To enable/disable regulator use::
+
+ int regulator_hardware_enable(struct regulator *regulator, bool enable);
diff --git a/Documentation/translations/zh_CN/driver-api/gpio/index.rst b/Documentation/translations/zh_CN/driver-api/gpio/index.rst
index 9a6a14162a6c..e4d54724a1b5 100644
--- a/Documentation/translations/zh_CN/driver-api/gpio/index.rst
+++ b/Documentation/translations/zh_CN/driver-api/gpio/index.rst
@@ -18,8 +18,6 @@
:caption: 目录
:maxdepth: 2
- legacy
-
Todolist:
* intro
diff --git a/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst b/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst
deleted file mode 100644
index 0faf042001d2..000000000000
--- a/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst
+++ /dev/null
@@ -1,618 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. include:: ../../disclaimer-zh_CN.rst
-
-:Original: Documentation/driver-api/gpio/legacy.rst
-
-:翻译:
-
- 傅炜 Fu Wei <[email protected]>
- 司延腾 Yanteng Si <[email protected]>
-
-:校译:
-
-
-传统GPIO接口
-============
-
-本文档概述了Linux下的GPIO访问公约。
-
-这些函数以 gpio_* 作为前缀。其他的函数不允许使用这样的前缀或相关的
-__gpio_* 前缀。
-
-
-什么是GPIO?
-============
-"通用输入/输出口"(GPIO)是一个灵活的由软件控制的数字信号。他们可
-由多种芯片提供,且对于从事嵌入式和定制硬件的 Linux 开发者来说是
-比较熟悉。每个GPIO 都代表一个连接到特定引脚或球栅阵列(BGA)封装中
-“球珠”的一个位。电路板原理图显示了 GPIO 与外部硬件的连接关系。
-驱动可以编写成通用代码,以使板级启动代码可传递引脚配置数据给驱动。
-
-片上系统 (SOC) 处理器对 GPIO 有很大的依赖。在某些情况下,每个
-非专用引脚都可配置为 GPIO,且大多数芯片都最少有一些 GPIO。
-可编程逻辑器件(类似 FPGA) 可以方便地提供 GPIO。像电源管理和
-音频编解码器这样的多功能芯片经常留有一些这样的引脚来帮助那些引脚
-匮乏的 SOC。同时还有通过 I2C 或 SPI 串行总线连接的“GPIO扩展器”
-芯片。大多数 PC 的南桥有一些拥有 GPIO 能力的引脚 (只有BIOS
-固件才知道如何使用他们)。
-
-GPIO 的实际功能因系统而异。通常用法有:
-
- - 输出值可写 (高电平=1,低电平=0)。一些芯片也有如何驱动这些值的选项,
- 例如只允许输出一个值、支持“线与”及其他取值类似的模式(值得注意的是
- “开漏”信号)
-
- - 输入值可读(1、0)。一些芯片支持引脚在配置为“输出”时回读,这对于类似
- “线与”的情况(以支持双向信号)是非常有用的。GPIO 控制器可能有输入
- 去毛刺/消抖逻辑,这有时需要软件控制。
-
- - 输入通常可作为 IRQ 信号,一般是沿触发,但有时是电平触发。这样的 IRQ
- 可能配置为系统唤醒事件,以将系统从低功耗状态下唤醒。
-
- - 通常一个 GPIO 根据不同产品电路板的需求,可以配置为输入或输出,也有仅
- 支持单向的。
-
- - 大部分 GPIO 可以在持有自旋锁时访问,但是通常由串行总线扩展的 GPIO
- 不允许持有自旋锁。但某些系统也支持这种类型。
-
-对于给定的电路板,每个 GPIO 都用于某个特定的目的,如监控 MMC/SD 卡的
-插入/移除、检测卡的写保护状态、驱动 LED、配置收发器、模拟串行总线、
-复位硬件看门狗、感知开关状态等等。
-
-
-GPIO 公约
-=========
-注意,这个叫做“公约”,因为这不是强制性的,不遵循这个公约是无伤大雅的,
-因为此时可移植性并不重要。GPIO 常用于板级特定的电路逻辑,甚至可能
-随着电路板的版本而改变,且不可能在不同走线的电路板上使用。仅有在少数
-功能上才具有可移植性,其他功能是平台特定。这也是由于“胶合”的逻辑造成的。
-
-此外,这不需要任何的执行框架,只是一个接口。某个平台可能通过一个简单地
-访问芯片寄存器的内联函数来实现它,其他平台可能通过委托一系列不同的GPIO
-控制器的抽象函数来实现它。(有一些可选的代码能支持这种策略的实现,本文档
-后面会介绍,但作为 GPIO 接口的客户端驱动程序必须与它的实现无关。)
-
-也就是说,如果在他们的平台上支持这个公约,驱动应尽可能的使用它。同时,平台
-必须在 Kconfig 中选择 ARCH_REQUIRE_GPIOLIB 或者 ARCH_WANT_OPTIONAL_GPIOLIB
-选项。那些调用标准 GPIO 函数的驱动应该在 Kconfig 入口中声明依赖GENERIC_GPIO。
-当驱动包含文件:
-
- #include <linux/gpio.h>
-
-则 GPIO 函数是可用,无论是“真实代码”还是经优化过的语句。如果你遵守
-这个公约,当你的代码完成后,对其他的开发者来说会更容易看懂和维护。
-
-注意,这些操作包含所用平台的 I/O 屏障代码,驱动无须显式地调用他们。
-
-
-标识 GPIO
----------
-
-GPIO 是通过无符号整型来标识的,范围是 0 到 MAX_INT。保留“负”数
-用于其他目的,例如标识信号“在这个板子上不可用”或指示错误。未接触底层
-硬件的代码会忽略这些整数。
-
-平台会定义这些整数的用法,且通常使用 #define 来定义 GPIO,这样
-板级特定的启动代码可以直接关联相应的原理图。相对来说,驱动应该仅使用
-启动代码传递过来的 GPIO 编号,使用 platform_data 保存板级特定
-引脚配置数据 (同时还有其他须要的板级特定数据),避免可能出现的问题。
-
-例如一个平台使用编号 32-159 来标识 GPIO,而在另一个平台使用编号0-63
-标识一组 GPIO 控制器,64-79标识另一类 GPIO 控制器,且在一个含有
-FPGA 的特定板子上使用 80-95。编号不一定要连续,那些平台中,也可以
-使用编号2000-2063来标识一个 I2C 接口的 GPIO 扩展器中的 GPIO。
-
-如果你要初始化一个带有无效 GPIO 编号的结构体,可以使用一些负编码
-(如"-EINVAL"),那将使其永远不会是有效。来测试这样一个结构体中的编号
-是否关联一个 GPIO,你可使用以下断言::
-
- int gpio_is_valid(int number);
-
-如果编号不存在,则请求和释放 GPIO 的函数将拒绝执行相关操作(见下文)。
-其他编号也可能被拒绝,比如一个编号可能存在,但暂时在给定的电路上不可用。
-
-一个平台是否支持多个 GPIO 控制器为平台特定的实现问题,就像是否可以
-在 GPIO 编号空间中有“空洞”和是否可以在运行时添加新的控制器一样。
-这些问题会影响其他事情,包括相邻的 GPIO 编号是否存在等。
-
-使用 GPIO
----------
-
-对于一个 GPIO,系统应该做的第一件事情就是通过 gpio_request()
-函数分配它,见下文。
-
-接下来是设置I/O方向,这通常是在板级启动代码中为所使用的 GPIO 设置
-platform_device 时完成::
-
- /* 设置为输入或输出, 返回 0 或负的错误代码 */
- int gpio_direction_input(unsigned gpio);
- int gpio_direction_output(unsigned gpio, int value);
-
-返回值为零代表成功,否则返回一个负的错误代码。这个返回值需要检查,因为
-get/set(获取/设置)函数调用没法返回错误,且有可能是配置错误。通常,
-你应该在进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO,在板子
-启动的早期、进程启动前使用他们也是可以的。
-
-对于作为输出的 GPIO,为其提供初始输出值,对于避免在系统启动期间出现
-信号毛刺是很有帮助的。
-
-为了与传统的 GPIO 接口兼容, 在设置一个 GPIO 方向时,如果它还未被申请,
-则隐含了申请那个 GPIO 的操作(见下文)。这种兼容性正在从可选的 gpiolib
-框架中移除。
-
-如果这个 GPIO 编码不存在,或者特定的 GPIO 不能用于那种模式,则方向
-设置可能失败。依赖启动固件来正确地设置方向通常是一个坏主意,因为它可能
-除了启动Linux,并没有做更多的验证工作。(同理, 板子的启动代码可能需要
-将这个复用的引脚设置为 GPIO,并正确地配置上拉/下拉电阻。)
-
-
-访问自旋锁安全的 GPIO
----------------------
-
-大多数 GPIO 控制器可以通过内存读/写指令来访问。这些指令不会休眠,可以
-安全地在硬(非线程)中断例程和类似的上下文中完成。
-
-对于那些 GPIO,使用以下的函数访问::
-
- /* GPIO 输入:返回零或非零 */
- int gpio_get_value(unsigned gpio);
-
- /* GPIO 输出 */
- void gpio_set_value(unsigned gpio, int value);
-
-GPIO值是布尔值,零表示低电平,非零表示高电平。当读取一个输出引脚的值时,
-返回值应该是引脚上的值。这个值不总是和输出值相符,因为存在开漏输出信号和
-输出延迟问题。
-
-以上的 get/set 函数无错误返回值,因为之前 gpio_direction_*()应已检查过
-其是否为“无效GPIO”。此外,还需要注意的是并不是所有平台都可以从输出引脚
-中读取数据,对于不能读取的引脚应总返回零。另外,对那些在原子上下文中无法
-安全访问的 GPIO (译者注:因为访问可能导致休眠)使用这些函数是不合适的
-(见下文)。
-
-在 GPIO 编号(还有输出、值)为常数的情况下,鼓励通过平台特定的实现来优化
-这两个函数来访问 GPIO 值。这种情况(读写一个硬件寄存器)下只需要几条指令
-是很正常的,且无须自旋锁。这种优化函数比起那些在子程序上花费许多指令的
-函数可以使得模拟接口(译者注:例如 GPIO 模拟 I2C、1-wire 或 SPI)的
-应用(在空间和时间上都)更具效率。
-
-
-访问可能休眠的 GPIO
--------------------
-
-某些 GPIO 控制器必须通过基于总线(如 I2C 或 SPI)的消息访问。读或写这些
-GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其反馈。期间需要
-休眠,这不能在 IRQ 例程(中断上下文)中执行。
-
-为了访问这种 GPIO,内核定义了一套不同的函数::
-
- /* GPIO 输入:返回零或非零 ,可能会休眠 */
- int gpio_get_value_cansleep(unsigned gpio);
-
- /* GPIO 输出,可能会休眠 */
- void gpio_set_value_cansleep(unsigned gpio, int value);
-
-访问这样的 GPIO 需要一个允许休眠的上下文,例如线程 IRQ 处理例程,并用以上的
-访问函数替换那些没有 cansleep()后缀的自旋锁安全访问函数。
-
-除了这些访问函数可能休眠,且它们操作的 GPIO 不能在硬件 IRQ 处理例程中访问的
-事实,这些处理例程实际上和自旋锁安全的函数是一样的。
-
-** 除此之外 ** 调用设置和配置此类 GPIO 的函数也必须在允许休眠的上下文中,
-因为它们可能也需要访问 GPIO 控制器芯片 (这些设置函数通常在板级启动代码或者
-驱动探测/断开代码中,所以这是一个容易满足的约束条件。) ::
-
- gpio_direction_input()
- gpio_direction_output()
- gpio_request()
-
- ## gpio_request_one()
-
- gpio_free()
-
-
-
-声明和释放 GPIO
-----------------
-
-为了有助于捕获系统配置错误,定义了两个函数::
-
- /* 申请 GPIO, 返回 0 或负的错误代码.
- * 非空标签可能有助于诊断.
- */
- int gpio_request(unsigned gpio, const char *label);
-
- /* 释放之前声明的 GPIO */
- void gpio_free(unsigned gpio);
-
-将无效的 GPIO 编码传递给 gpio_request()会导致失败,申请一个已使用这个
-函数声明过的 GPIO 也会失败。gpio_request()的返回值必须检查。你应该在
-进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO,在板子启动的早期、
-进入进程之前是可以申请的。
-
-这个函数完成两个基本的目标。一是标识那些实际上已作为 GPIO 使用的信号线,
-这样便于更好地诊断;系统可能需要服务几百个可用的 GPIO,但是对于任何一个
-给定的电路板通常只有一些被使用。另一个目的是捕获冲突,查明错误:如两个或
-更多驱动错误地认为他们已经独占了某个信号线,或是错误地认为移除一个管理着
-某个已激活信号的驱动是安全的。也就是说,申请 GPIO 的作用类似一种锁机制。
-
-某些平台可能也使用 GPIO 作为电源管理激活信号(例如通过关闭未使用芯片区和
-简单地关闭未使用时钟)。
-
-对于 GPIO 使用引脚控制子系统已知的引脚,子系统应该被告知其使用情况;
-一个 gpiolib 驱动的 .request()操作应调用 pinctrl_gpio_request(),
-而 gpiolib 驱动的 .free()操作应调用 pinctrl_gpio_free()。引脚控制
-子系统允许 pinctrl_gpio_request()在某个引脚或引脚组以复用形式“属于”
-一个设备时都成功返回。
-
-任何须将 GPIO 信号导向适当引脚的引脚复用硬件的编程应该发生在 GPIO
-驱动的 .direction_input()或 .direction_output()函数中,以及
-任何输出 GPIO 值的设置之后。这样可使从引脚特殊功能到 GPIO 的转换
-不会在引脚产生毛刺波形。有时当用一个 GPIO 实现其信号驱动一个非 GPIO
-硬件模块的解决方案时,就需要这种机制。
-
-某些平台允许部分或所有 GPIO 信号使用不同的引脚。类似的,GPIO 或引脚的
-其他方面也需要配置,如上拉/下拉。平台软件应该在对这些 GPIO 调用
-gpio_request()前将这类细节配置好,例如使用引脚控制子系统的映射表,
-使得 GPIO 的用户无须关注这些细节。
-
-还有一个值得注意的是在释放 GPIO 前,你必须停止使用它。
-
-
-注意:申请一个 GPIO 并没有以任何方式配置它,只不过标识那个 GPIO 处于使用
-状态。必须有另外的代码来处理引脚配置(如控制 GPIO 使用的引脚、上拉/下拉)。
-考虑到大多数情况下声明 GPIO 之后就会立即配置它们,所以定义了以下三个辅助函数::
-
- /* 申请一个 GPIO 信号, 同时通过特定的'flags'初始化配置,
- * 其他和 gpio_request()的参数和返回值相同
- *
- */
- int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
-
-这里 'flags' 当前定义可指定以下属性:
-
- * GPIOF_DIR_IN - 配置方向为输入
- * GPIOF_DIR_OUT - 配置方向为输出
-
- * GPIOF_INIT_LOW - 在作为输出时,初始值为低电平
- * GPIOF_INIT_HIGH - 在作为输出时,初始值为高电平
-
-因为 GPIOF_INIT_* 仅有在配置为输出的时候才存在,所以有效的组合为:
-
- * GPIOF_IN - 配置为输入
- * GPIOF_OUT_INIT_LOW - 配置为输出,并初始化为低电平
- * GPIOF_OUT_INIT_HIGH - 配置为输出,并初始化为高电平
-
-更进一步,为了更简单地声明/释放多个 GPIO,'struct gpio'被引进来封装所有
-这三个领域::
-
- struct gpio {
- unsigned gpio;
- unsigned long flags;
- const char *label;
- };
-
-一个典型的用例::
-
- static struct gpio leds_gpios[] = {
- { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* 默认开启 */
- { 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* 默认关闭 */
- { 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* 默认关闭 */
- { 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* 默认关闭 */
- { ... },
- };
-
- err = gpio_request_one(31, GPIOF_IN, "Reset Button");
- if (err)
- ...
-
-
-GPIO 映射到 IRQ
-----------------
-
-GPIO 编号是无符号整数;IRQ 编号也是。这些构成了两个逻辑上不同的命名空间
-(GPIO 0 不一定使用 IRQ 0)。你可以通过以下函数在它们之间实现映射::
-
- /* 映射 GPIO 编号到 IRQ 编号 */
- int gpio_to_irq(unsigned gpio);
-
-它们的返回值为对应命名空间的相关编号,或是负的错误代码(如果无法映射)。
-(例如,某些 GPIO 无法做为 IRQ 使用。)以下的编号错误是未经检测的:使用一个
-未通过 gpio_direction_input()配置为输入的 GPIO 编号,或者使用一个
-并非来源于gpio_to_irq()的 IRQ 编号。
-
-这两个映射函数可能会在信号编号的加减计算过程上花些时间。它们不可休眠。
-
-gpio_to_irq()返回的非错误值可以传递给 request_irq()或者 free_irq()。
-它们通常通过板级特定的初始化代码存放到平台设备的 IRQ 资源中。注意:IRQ
-触发选项是 IRQ 接口的一部分,如 IRQF_TRIGGER_FALLING,系统唤醒能力
-也是如此。
-
-
-模拟开漏信号
-------------
-
-有时在只有低电平信号作为实际驱动结果(译者注:多个输出连接于一点,逻辑电平
-结果为所有输出的逻辑与)的时候,共享的信号线需要使用“开漏”信号。(该术语
-适用于 CMOS 管;而 TTL 用“集电极开路”。)一个上拉电阻使信号为高电平。这
-有时被称为“线与”。实际上,从负逻辑(低电平为真)的角度来看,这是一个“线或”。
-
-一个开漏信号的常见例子是共享的低电平使能 IRQ 信号线。此外,有时双向数据总线
-信号也使用漏极开路信号。
-
-某些 GPIO 控制器直接支持开漏输出,还有许多不支持。当你需要开漏信号,但
-硬件又不直接支持的时候,一个常用的方法是用任何即可作输入也可作输出的 GPIO
-引脚来模拟:
-
- LOW: gpio_direction_output(gpio, 0) ... 这代码驱动信号并覆盖
- 上拉配置。
-
- HIGH: gpio_direction_input(gpio) ... 这代码关闭输出,所以上拉电阻
- (或其他的一些器件)控制了信号。
-
-如果你将信号线“驱动”为高电平,但是 gpio_get_value(gpio)报告了一个
-低电平(在适当的上升时间后),你就可以知道是其他的一些组件将共享信号线拉低了。
-这不一定是错误的。一个常见的例子就是 I2C 时钟的延长:一个需要较慢时钟的
-从设备延迟 SCK 的上升沿,而 I2C 主设备相应地调整其信号传输速率。
-
-GPIO控制器和引脚控制子系统
---------------------------
-
-SOC上的GPIO控制器可能与引脚控制子系统紧密结合,即引脚可以与可选的gpio功
-能一起被其他功能使用。我们已经涵盖了这样的情况,例如一个GPIO控制器需要保
-留一个引脚或通过调用以下任何一个引脚来设置其方向::
-
- pinctrl_gpio_request()
- pinctrl_gpio_free()
- pinctrl_gpio_direction_input()
- pinctrl_gpio_direction_output()
-
-但是,引脚控制子系统是如何将GPIO号码(这是一个全局事项)与某个引脚控制器
-上的某个引脚交叉关联的?
-
-这是通过注册引脚的“范围”来实现的,这基本上是交叉参考表。这些描述是在
-Documentation/driver-api/pin-control.rst
-
-虽然引脚分配完全由引脚控制子系统管理,但gpio(在gpiolib下)仍由gpio驱动
-维护。可能发生的情况是,SoC中的不同引脚范围由不同的gpio驱动器管理。
-
-这使得在调用 "pinctrl_gpio_request" 之前,让gpio驱动向pin ctrl子系
-统宣布它们的引脚范围是合理的,以便在使用任何gpio之前要求引脚控制子系统准
-备相应的引脚。
-
-为此,gpio控制器可以用引脚控制子系统注册其引脚范围。目前有两种方法:有或
-无DT。
-
-关于对DT的支持,请参考 Documentation/devicetree/bindings/gpio/gpio.txt.
-
-对于非DT支持,用户可以用适当的参数调用gpiochip_add_pin_range(),将一
-系列的gpio引脚注册到引脚控制驱动上。为此,必须将引脚控制设备的名称字符串
-作为参数之一传给这个程序。
-
-
-这些公约忽略了什么?
-====================
-
-这些公约忽略的最大一件事就是引脚复用,因为这属于高度芯片特定的属性且
-没有可移植性。某个平台可能不需要明确的复用信息;有的对于任意给定的引脚
-可能只有两个功能选项;有的可能每个引脚有八个功能选项;有的可能可以将
-几个引脚中的任何一个作为给定的 GPIO。(是的,这些例子都来自于当前运行
-Linux 的系统。)
-
-在某些系统中,与引脚复用相关的是配置和使能集成的上、下拉模式。并不是所有
-平台都支持这种模式,或者不会以相同的方式来支持这种模式;且任何给定的电路板
-可能使用外置的上拉(或下拉)电阻,这时芯片上的就不应该使用。(当一个电路需要
-5kOhm 的拉动电阻,芯片上的 100 kOhm 电阻就不能做到。)同样的,驱动能力
-(2 mA vs 20 mA)和电压(1.8V vs 3.3V)是平台特定问题,就像模型一样在
-可配置引脚和 GPIO 之间(没)有一一对应的关系。
-
-还有其他一些系统特定的机制没有在这里指出,例如上述的输入去毛刺和线与输出
-选项。硬件可能支持批量读或写 GPIO,但是那一般是配置相关的:对于处于同一
-块区(bank)的GPIO。(GPIO 通常以 16 或 32 个组成一个区块,一个给定的
-片上系统一般有几个这样的区块。)某些系统可以通过输出 GPIO 触发 IRQ,
-或者从并非以 GPIO 管理的引脚取值。这些机制的相关代码没有必要具有可移植性。
-
-当前,动态定义 GPIO 并不是标准的,例如作为配置一个带有某些 GPIO 扩展器的
-附加电路板的副作用。
-
-GPIO 实现者的框架(可选)
-=========================
-
-前面提到了,有一个可选的实现框架,让平台使用相同的编程接口,更加简单地支持
-不同种类的 GPIO 控制器。这个框架称为"gpiolib"。
-
-作为一个辅助调试功能,如果 debugfs 可用,就会有一个 /sys/kernel/debug/gpio
-文件。通过这个框架,它可以列出所有注册的控制器,以及当前正在使用中的 GPIO
-的状态。
-
-
-控制器驱动: gpio_chip
----------------------
-
-在框架中每个 GPIO 控制器都包装为一个 "struct gpio_chip",他包含了
-该类型的每个控制器的常用信息:
-
- - 设置 GPIO 方向的方法
- - 用于访问 GPIO 值的方法
- - 告知调用其方法是否可能休眠的标志
- - 可选的 debugfs 信息导出方法 (显示类似上拉配置一样的额外状态)
- - 诊断标签
-
-也包含了来自 device.platform_data 的每个实例的数据:它第一个 GPIO 的
-编号和它可用的 GPIO 的数量。
-
-实现 gpio_chip 的代码应支持多控制器实例,这可能使用驱动模型。那些代码要
-配置每个 gpio_chip,并发起gpiochip_add()。卸载一个 GPIO 控制器很少见,
-但在必要的时候可以使用 gpiochip_remove()。
-
-大部分 gpio_chip 是一个实例特定结构体的一部分,而并不将 GPIO 接口单独
-暴露出来,比如编址、电源管理等。类似编解码器这样的芯片会有复杂的非 GPIO
-状态。
-
-任何一个 debugfs 信息导出方法通常应该忽略还未申请作为 GPIO 的信号线。
-他们可以使用 gpiochip_is_requested()测试,当这个 GPIO 已经申请过了
-就返回相关的标签,否则返回 NULL。
-
-
-平台支持
---------
-
-为了支持这个框架,一个平台的 Kconfig 文件将会 "select"(选择)
-ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,并让它的
-<asm/gpio.h> 包含 <asm-generic/gpio.h>,同时定义两个方法:
-gpio_get_value()、gpio_set_value()。
-
-它也应提供一个 ARCH_NR_GPIOS 的定义值,这样可以更好地反映该平台 GPIO
-的实际数量,节省静态表的空间。(这个定义值应该包含片上系统内建 GPIO 和
-GPIO 扩展器中的数据。)
-
-ARCH_REQUIRE_GPIOLIB 意味着 gpiolib 核心在这个构架中将总是编译进内核。
-
-ARCH_WANT_OPTIONAL_GPIOLIB 意味着 gpiolib 核心默认关闭,且用户可以
-使能它,并将其编译进内核(可选)。
-
-如果这些选项都没被选择,该平台就不通过 GPIO-lib 支持 GPIO,且代码不可以
-被用户使能。
-
-以下这些方法的实现可以直接使用框架代码,并总是通过 gpio_chip 调度::
-
- #define gpio_get_value __gpio_get_value
- #define gpio_set_value __gpio_set_value
-
-这些定义可以用更理想的实现方法替代,那就是使用经过逻辑优化的内联函数来访问
-基于特定片上系统的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量“12”,
-读取或设置它可能只需少则两或三个指令,且不会休眠。当这样的优化无法实现时,
-那些函数必须使用框架提供的代码,那就至少要几十条指令才可以实现。对于用 GPIO
-模拟的 I/O 接口, 如此精简指令是很有意义的。
-
-对于片上系统,平台特定代码为片上 GPIO 每个区(bank)定义并注册 gpio_chip
-实例。那些 GPIO 应该根据芯片厂商的文档进行编码/标签,并直接和电路板原理图
-对应。他们应该开始于零并终止于平台特定的限制。这些 GPIO(代码)通常从
-arch_initcall()或者更早的地方集成进平台初始化代码,使这些 GPIO 总是可用,
-且他们通常可以作为 IRQ 使用。
-
-板级支持
---------
-
-对于外部 GPIO 控制器(例如 I2C 或 SPI 扩展器、专用芯片、多功能器件、FPGA
-或 CPLD),大多数常用板级特定代码都可以注册控制器设备,并保证他们的驱动知道
-gpiochip_add()所使用的 GPIO 编号。他们的起始编号通常跟在平台特定的 GPIO
-编号之后。
-
-例如板级启动代码应该创建结构体指明芯片公开的 GPIO 范围,并使用 platform_data
-将其传递给每个 GPIO 扩展器芯片。然后芯片驱动中的 probe()例程可以将这个
-数据传递给 gpiochip_add()。
-
-初始化顺序很重要。例如,如果一个设备依赖基于 I2C 的(扩展)GPIO,那么它的
-probe()例程就应该在那个 GPIO 有效以后才可以被调用。这意味着设备应该在
-GPIO 可以工作之后才可被注册。解决这类依赖的的一种方法是让这种 gpio_chip
-控制器向板级特定代码提供 setup()和 teardown()回调函数。一旦所有必须的
-资源可用之后,这些板级特定的回调函数将会注册设备,并可以在这些 GPIO 控制器
-设备变成无效时移除它们。
-
-
-用户空间的 Sysfs 接口(可选)
-=============================
-
-使用“gpiolib”实现框架的平台可以选择配置一个 GPIO 的 sysfs 用户接口。
-这不同于 debugfs 接口,因为它提供的是对 GPIO方向和值的控制,而不只显示
-一个GPIO 的状态摘要。此外,它可以出现在没有调试支持的产品级系统中。
-
-例如,通过适当的系统硬件文档,用户空间可以知道 GIOP #23 控制 Flash
-存储器的写保护(用于保护其中 Bootloader 分区)。产品的系统升级可能需要
-临时解除这个保护:首先导入一个 GPIO,改变其输出状态,然后在重新使能写保护
-前升级代码。通常情况下,GPIO #23 是不会被触及的,并且内核也不需要知道他。
-
-根据适当的硬件文档,某些系统的用户空间 GPIO 可以用于确定系统配置数据,
-这些数据是标准内核不知道的。在某些任务中,简单的用户空间 GPIO 驱动可能是
-系统真正需要的。
-
-注意:标准内核驱动中已经存在通用的“LED 和按键”GPIO 任务,分别是:
-"leds-gpio" 和 "gpio_keys"。请使用这些来替代直接访问 GPIO,因为集成在
-内核框架中的这类驱动比你在用户空间的代码更好。
-
-
-Sysfs 中的路径
---------------
-
-在/sys/class/gpio 中有 3 类入口:
-
- - 用于在用户空间控制 GPIO 的控制接口;
-
- - GPIOs 本身;以及
-
- - GPIO 控制器 ("gpio_chip" 实例)。
-
-除了这些标准的文件,还包含“device”符号链接。
-
-控制接口是只写的:
-
- /sys/class/gpio/
-
- "export" ... 用户空间可以通过写其编号到这个文件,要求内核导出
- 一个 GPIO 的控制到用户空间。
-
- 例如: 如果内核代码没有申请 GPIO #19,"echo 19 > export"
- 将会为 GPIO #19 创建一个 "gpio19" 节点。
-
- "unexport" ... 导出到用户空间的逆操作。
-
- 例如: "echo 19 > unexport" 将会移除使用"export"文件导出的
- "gpio19" 节点。
-
-GPIO 信号的路径类似 /sys/class/gpio/gpio42/ (对于 GPIO #42 来说),
-并有如下的读/写属性:
-
- /sys/class/gpio/gpioN/
-
- "direction" ... 读取得到 "in" 或 "out"。这个值通常运行写入。
- 写入"out" 时,其引脚的默认输出为低电平。为了确保无故障运行,
- "low" 或 "high" 的电平值应该写入 GPIO 的配置,作为初始输出值。
-
- 注意:如果内核不支持改变 GPIO 的方向,或者在导出时内核代码没有
- 明确允许用户空间可以重新配置 GPIO 方向,那么这个属性将不存在。
-
- "value" ... 读取得到 0 (低电平) 或 1 (高电平)。如果 GPIO 配置为
- 输出,这个值允许写操作。任何非零值都以高电平看待。
-
- 如果引脚可以配置为中断信号,且如果已经配置了产生中断的模式
- (见"edge"的描述),你可以对这个文件使用轮询操作(poll(2)),
- 且轮询操作会在任何中断触发时返回。如果你使用轮询操作(poll(2)),
- 请在 events 中设置 POLLPRI 和 POLLERR。如果你使用轮询操作
- (select(2)),请在 exceptfds 设置你期望的文件描述符。在
- 轮询操作(poll(2))返回之后,既可以通过 lseek(2)操作读取
- sysfs 文件的开始部分,也可以关闭这个文件并重新打开它来读取数据。
-
- "edge" ... 读取得到“none”、“rising”、“falling”或者“both”。
- 将这些字符串写入这个文件可以选择沿触发模式,会使得轮询操作
- (select(2))在"value"文件中返回。
-
- 这个文件仅有在这个引脚可以配置为可产生中断输入引脚时,才存在。
-
- "active_low" ... 读取得到 0 (假) 或 1 (真)。写入任何非零值可以
- 翻转这个属性的(读写)值。已存在或之后通过"edge"属性设置了"rising"
- 和 "falling" 沿触发模式的轮询操作(poll(2))将会遵循这个设置。
-
-GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO
-开始实现控制的控制器),并有着以下只读属性:
-
- /sys/class/gpio/gpiochipN/
-
- "base" ... 与以上的 N 相同,代表此芯片管理的第一个 GPIO 的编号
-
- "label" ... 用于诊断 (并不总是只有唯一值)
-
- "ngpio" ... 此控制器所管理的 GPIO 数量(而 GPIO 编号从 N 到
- N + ngpio - 1)
-
-大多数情况下,电路板的文档应当标明每个 GPIO 的使用目的。但是那些编号并不总是
-固定的,例如在扩展卡上的 GPIO会根据所使用的主板或所在堆叠架构中其他的板子而
-有所不同。在这种情况下,你可能需要使用 gpiochip 节点(尽可能地结合电路图)来
-确定给定信号所用的 GPIO 编号。
-
-
-API参考
-=======
-
-本节中列出的函数已被废弃。在新的代码中应该使用基于GPIO描述符的API。
diff --git a/Documentation/translations/zh_TW/gpio.txt b/Documentation/translations/zh_TW/gpio.txt
deleted file mode 100644
index 77d69d381316..000000000000
--- a/Documentation/translations/zh_TW/gpio.txt
+++ /dev/null
@@ -1,574 +0,0 @@
-Chinese translated version of Documentation/admin-guide/gpio
-
-If you have any comment or update to the content, please contact the
-original document maintainer directly. However, if you have a problem
-communicating in English you can also ask the Chinese maintainer for
-help. Contact the Chinese maintainer if this translation is outdated
-or if there is a problem with the translation.
-
-Maintainer: Grant Likely <[email protected]>
- Linus Walleij <[email protected]>
-Traditional Chinese maintainer: Hu Haowen <[email protected]>
----------------------------------------------------------------------
-Documentation/admin-guide/gpio 的繁體中文翻譯
-
-如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
-交流有困難的話,也可以向繁體中文版維護者求助。如果本翻譯更新不及時或
-者翻譯存在問題,請聯繫繁體中文版維護者。
-
-英文版維護者: Grant Likely <[email protected]>
- Linus Walleij <[email protected]>
-繁體中文版維護者: 胡皓文 Hu Haowen <[email protected]>
-繁體中文版翻譯者: 胡皓文 Hu Haowen <[email protected]>
-繁體中文版校譯者: 胡皓文 Hu Haowen <[email protected]>
-
-以下爲正文
----------------------------------------------------------------------
-GPIO 接口
-
-本文檔提供了一個在Linux下訪問GPIO的公約概述。
-
-這些函數以 gpio_* 作爲前綴。其他的函數不允許使用這樣的前綴或相關的
-__gpio_* 前綴。
-
-
-什麼是GPIO?
-==========
-"通用輸入/輸出口"(GPIO)是一個靈活的由軟體控制的數位訊號。他們可
-由多種晶片提供,且對於從事嵌入式和定製硬體的 Linux 開發者來說是
-比較熟悉。每個GPIO 都代表一個連接到特定引腳或球柵陣列(BGA)封裝中
-「球珠」的一個位。電路板原理圖顯示了 GPIO 與外部硬體的連接關係。
-驅動可以編寫成通用代碼,以使板級啓動代碼可傳遞引腳配置數據給驅動。
-
-片上系統 (SOC) 處理器對 GPIO 有很大的依賴。在某些情況下,每個
-非專用引腳都可配置爲 GPIO,且大多數晶片都最少有一些 GPIO。
-可編程邏輯器件(類似 FPGA) 可以方便地提供 GPIO。像電源管理和
-音頻編解碼器這樣的多功能晶片經常留有一些這樣的引腳來幫助那些引腳
-匱乏的 SOC。同時還有通過 I2C 或 SPI 串行總線連接的「GPIO擴展器」
-晶片。大多數 PC 的南橋有一些擁有 GPIO 能力的引腳 (只有BIOS
-固件才知道如何使用他們)。
-
-GPIO 的實際功能因系統而異。通常用法有:
-
- - 輸出值可寫 (高電平=1,低電平=0)。一些晶片也有如何驅動這些值的選項,
- 例如只允許輸出一個值、支持「線與」及其他取值類似的模式(值得注意的是
- 「開漏」信號)
-
- - 輸入值可讀(1、0)。一些晶片支持引腳在配置爲「輸出」時回讀,這對於類似
- 「線與」的情況(以支持雙向信號)是非常有用的。GPIO 控制器可能有輸入
- 去毛刺/消抖邏輯,這有時需要軟體控制。
-
- - 輸入通常可作爲 IRQ 信號,一般是沿觸發,但有時是電平觸發。這樣的 IRQ
- 可能配置爲系統喚醒事件,以將系統從低功耗狀態下喚醒。
-
- - 通常一個 GPIO 根據不同產品電路板的需求,可以配置爲輸入或輸出,也有僅
- 支持單向的。
-
- - 大部分 GPIO 可以在持有自旋鎖時訪問,但是通常由串行總線擴展的 GPIO
- 不允許持有自旋鎖。但某些系統也支持這種類型。
-
-對於給定的電路板,每個 GPIO 都用於某個特定的目的,如監控 MMC/SD 卡的
-插入/移除、檢測卡的防寫狀態、驅動 LED、配置收發器、模擬串行總線、
-復位硬體看門狗、感知開關狀態等等。
-
-
-GPIO 公約
-=========
-注意,這個叫做「公約」,因爲這不是強制性的,不遵循這個公約是無傷大雅的,
-因爲此時可移植性並不重要。GPIO 常用於板級特定的電路邏輯,甚至可能
-隨著電路板的版本而改變,且不可能在不同走線的電路板上使用。僅有在少數
-功能上才具有可移植性,其他功能是平台特定。這也是由於「膠合」的邏輯造成的。
-
-此外,這不需要任何的執行框架,只是一個接口。某個平台可能通過一個簡單地
-訪問晶片寄存器的內聯函數來實現它,其他平台可能通過委託一系列不同的GPIO
-控制器的抽象函數來實現它。(有一些可選的代碼能支持這種策略的實現,本文檔
-後面會介紹,但作爲 GPIO 接口的客戶端驅動程序必須與它的實現無關。)
-
-也就是說,如果在他們的平台上支持這個公約,驅動應儘可能的使用它。同時,平台
-必須在 Kconfig 中選擇 ARCH_REQUIRE_GPIOLIB 或者 ARCH_WANT_OPTIONAL_GPIOLIB
-選項。那些調用標準 GPIO 函數的驅動應該在 Kconfig 入口中聲明依賴GENERIC_GPIO。
-當驅動包含文件:
-
- #include <linux/gpio.h>
-
-則 GPIO 函數是可用,無論是「真實代碼」還是經優化過的語句。如果你遵守
-這個公約,當你的代碼完成後,對其他的開發者來說會更容易看懂和維護。
-
-注意,這些操作包含所用平台的 I/O 屏障代碼,驅動無須顯式地調用他們。
-
-
-標識 GPIO
----------
-GPIO 是通過無符號整型來標識的,範圍是 0 到 MAX_INT。保留「負」數
-用於其他目的,例如標識信號「在這個板子上不可用」或指示錯誤。未接觸底層
-硬體的代碼會忽略這些整數。
-
-平台會定義這些整數的用法,且通常使用 #define 來定義 GPIO,這樣
-板級特定的啓動代碼可以直接關聯相應的原理圖。相對來說,驅動應該僅使用
-啓動代碼傳遞過來的 GPIO 編號,使用 platform_data 保存板級特定
-引腳配置數據 (同時還有其他須要的板級特定數據),避免可能出現的問題。
-
-例如一個平台使用編號 32-159 來標識 GPIO,而在另一個平台使用編號0-63
-標識一組 GPIO 控制器,64-79標識另一類 GPIO 控制器,且在一個含有
-FPGA 的特定板子上使用 80-95。編號不一定要連續,那些平台中,也可以
-使用編號2000-2063來標識一個 I2C 接口的 GPIO 擴展器中的 GPIO。
-
-如果你要初始化一個帶有無效 GPIO 編號的結構體,可以使用一些負編碼
-(如"-EINVAL"),那將使其永遠不會是有效。來測試這樣一個結構體中的編號
-是否關聯一個 GPIO,你可使用以下斷言:
-
- int gpio_is_valid(int number);
-
-如果編號不存在,則請求和釋放 GPIO 的函數將拒絕執行相關操作(見下文)。
-其他編號也可能被拒絕,比如一個編號可能存在,但暫時在給定的電路上不可用。
-
-一個平台是否支持多個 GPIO 控制器爲平台特定的實現問題,就像是否可以
-在 GPIO 編號空間中有「空洞」和是否可以在運行時添加新的控制器一樣。
-這些問題會影響其他事情,包括相鄰的 GPIO 編號是否存在等。
-
-使用 GPIO
----------
-對於一個 GPIO,系統應該做的第一件事情就是通過 gpio_request()
-函數分配它,見下文。
-
-接下來是設置I/O方向,這通常是在板級啓動代碼中爲所使用的 GPIO 設置
-platform_device 時完成。
-
- /* 設置爲輸入或輸出, 返回 0 或負的錯誤代碼 */
- int gpio_direction_input(unsigned gpio);
- int gpio_direction_output(unsigned gpio, int value);
-
-返回值爲零代表成功,否則返回一個負的錯誤代碼。這個返回值需要檢查,因爲
-get/set(獲取/設置)函數調用沒法返回錯誤,且有可能是配置錯誤。通常,
-你應該在進程上下文中調用這些函數。然而,對於自旋鎖安全的 GPIO,在板子
-啓動的早期、進程啓動前使用他們也是可以的。
-
-對於作爲輸出的 GPIO,爲其提供初始輸出值,對於避免在系統啓動期間出現
-信號毛刺是很有幫助的。
-
-爲了與傳統的 GPIO 接口兼容, 在設置一個 GPIO 方向時,如果它還未被申請,
-則隱含了申請那個 GPIO 的操作(見下文)。這種兼容性正在從可選的 gpiolib
-框架中移除。
-
-如果這個 GPIO 編碼不存在,或者特定的 GPIO 不能用於那種模式,則方向
-設置可能失敗。依賴啓動固件來正確地設置方向通常是一個壞主意,因爲它可能
-除了啓動Linux,並沒有做更多的驗證工作。(同理, 板子的啓動代碼可能需要
-將這個復用的引腳設置爲 GPIO,並正確地配置上拉/下拉電阻。)
-
-
-訪問自旋鎖安全的 GPIO
--------------------
-大多數 GPIO 控制器可以通過內存讀/寫指令來訪問。這些指令不會休眠,可以
-安全地在硬(非線程)中斷例程和類似的上下文中完成。
-
-對於那些 GPIO,使用以下的函數訪問:
-
- /* GPIO 輸入:返回零或非零 */
- int gpio_get_value(unsigned gpio);
-
- /* GPIO 輸出 */
- void gpio_set_value(unsigned gpio, int value);
-
-GPIO值是布爾值,零表示低電平,非零表示高電平。當讀取一個輸出引腳的值時,
-返回值應該是引腳上的值。這個值不總是和輸出值相符,因爲存在開漏輸出信號和
-輸出延遲問題。
-
-以上的 get/set 函數無錯誤返回值,因爲之前 gpio_direction_*()應已檢查過
-其是否爲「無效GPIO」。此外,還需要注意的是並不是所有平台都可以從輸出引腳
-中讀取數據,對於不能讀取的引腳應總返回零。另外,對那些在原子上下文中無法
-安全訪問的 GPIO (譯者註:因爲訪問可能導致休眠)使用這些函數是不合適的
-(見下文)。
-
-在 GPIO 編號(還有輸出、值)爲常數的情況下,鼓勵通過平台特定的實現來優化
-這兩個函數來訪問 GPIO 值。這種情況(讀寫一個硬體寄存器)下只需要幾條指令
-是很正常的,且無須自旋鎖。這種優化函數比起那些在子程序上花費許多指令的
-函數可以使得模擬接口(譯者注:例如 GPIO 模擬 I2C、1-wire 或 SPI)的
-應用(在空間和時間上都)更具效率。
-
-
-訪問可能休眠的 GPIO
------------------
-某些 GPIO 控制器必須通過基於總線(如 I2C 或 SPI)的消息訪問。讀或寫這些
-GPIO 值的命令需要等待其信息排到隊首才發送命令,再獲得其反饋。期間需要
-休眠,這不能在 IRQ 例程(中斷上下文)中執行。
-
-爲了訪問這種 GPIO,內核定義了一套不同的函數:
-
- /* GPIO 輸入:返回零或非零 ,可能會休眠 */
- int gpio_get_value_cansleep(unsigned gpio);
-
- /* GPIO 輸出,可能會休眠 */
- void gpio_set_value_cansleep(unsigned gpio, int value);
-
-訪問這樣的 GPIO 需要一個允許休眠的上下文,例如線程 IRQ 處理例程,並用以上的
-訪問函數替換那些沒有 cansleep()後綴的自旋鎖安全訪問函數。
-
-除了這些訪問函數可能休眠,且它們操作的 GPIO 不能在硬體 IRQ 處理例程中訪問的
-事實,這些處理例程實際上和自旋鎖安全的函數是一樣的。
-
-** 除此之外 ** 調用設置和配置此類 GPIO 的函數也必須在允許休眠的上下文中,
-因爲它們可能也需要訪問 GPIO 控制器晶片: (這些設置函數通常在板級啓動代碼或者
-驅動探測/斷開代碼中,所以這是一個容易滿足的約束條件。)
-
- gpio_direction_input()
- gpio_direction_output()
- gpio_request()
-
-## gpio_request_one()
-
- gpio_free()
-
-
-聲明和釋放 GPIO
-----------------------------
-爲了有助於捕獲系統配置錯誤,定義了兩個函數。
-
- /* 申請 GPIO, 返回 0 或負的錯誤代碼.
- * 非空標籤可能有助於診斷.
- */
- int gpio_request(unsigned gpio, const char *label);
-
- /* 釋放之前聲明的 GPIO */
- void gpio_free(unsigned gpio);
-
-將無效的 GPIO 編碼傳遞給 gpio_request()會導致失敗,申請一個已使用這個
-函數聲明過的 GPIO 也會失敗。gpio_request()的返回值必須檢查。你應該在
-進程上下文中調用這些函數。然而,對於自旋鎖安全的 GPIO,在板子啓動的早期、
-進入進程之前是可以申請的。
-
-這個函數完成兩個基本的目標。一是標識那些實際上已作爲 GPIO 使用的信號線,
-這樣便於更好地診斷;系統可能需要服務幾百個可用的 GPIO,但是對於任何一個
-給定的電路板通常只有一些被使用。另一個目的是捕獲衝突,查明錯誤:如兩個或
-更多驅動錯誤地認爲他們已經獨占了某個信號線,或是錯誤地認爲移除一個管理著
-某個已激活信號的驅動是安全的。也就是說,申請 GPIO 的作用類似一種鎖機制。
-
-某些平台可能也使用 GPIO 作爲電源管理激活信號(例如通過關閉未使用晶片區和
-簡單地關閉未使用時鐘)。
-
-對於 GPIO 使用 pinctrl 子系統已知的引腳,子系統應該被告知其使用情況;
-一個 gpiolib 驅動的 .request()操作應調用 pinctrl_gpio_request(),
-而 gpiolib 驅動的 .free()操作應調用 pinctrl_gpio_free()。pinctrl
-子系統允許 pinctrl_gpio_request()在某個引腳或引腳組以復用形式「屬於」
-一個設備時都成功返回。
-
-任何須將 GPIO 信號導向適當引腳的引腳復用硬體的編程應該發生在 GPIO
-驅動的 .direction_input()或 .direction_output()函數中,以及
-任何輸出 GPIO 值的設置之後。這樣可使從引腳特殊功能到 GPIO 的轉換
-不會在引腳產生毛刺波形。有時當用一個 GPIO 實現其信號驅動一個非 GPIO
-硬體模塊的解決方案時,就需要這種機制。
-
-某些平台允許部分或所有 GPIO 信號使用不同的引腳。類似的,GPIO 或引腳的
-其他方面也需要配置,如上拉/下拉。平台軟體應該在對這些 GPIO 調用
-gpio_request()前將這類細節配置好,例如使用 pinctrl 子系統的映射表,
-使得 GPIO 的用戶無須關注這些細節。
-
-還有一個值得注意的是在釋放 GPIO 前,你必須停止使用它。
-
-
-注意:申請一個 GPIO 並沒有以任何方式配置它,只不過標識那個 GPIO 處於使用
-狀態。必須有另外的代碼來處理引腳配置(如控制 GPIO 使用的引腳、上拉/下拉)。
-考慮到大多數情況下聲明 GPIO 之後就會立即配置它們,所以定義了以下三個輔助函數:
-
- /* 申請一個 GPIO 信號, 同時通過特定的'flags'初始化配置,
- * 其他和 gpio_request()的參數和返回值相同
- *
- */
- int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
-
-這裡 'flags' 當前定義可指定以下屬性:
-
- * GPIOF_DIR_IN - 配置方向爲輸入
- * GPIOF_DIR_OUT - 配置方向爲輸出
-
- * GPIOF_INIT_LOW - 在作爲輸出時,初始值爲低電平
- * GPIOF_INIT_HIGH - 在作爲輸出時,初始值爲高電平
-
-因爲 GPIOF_INIT_* 僅有在配置爲輸出的時候才存在,所以有效的組合爲:
-
- * GPIOF_IN - 配置爲輸入
- * GPIOF_OUT_INIT_LOW - 配置爲輸出,並初始化爲低電平
- * GPIOF_OUT_INIT_HIGH - 配置爲輸出,並初始化爲高電平
-
-更進一步,爲了更簡單地聲明/釋放多個 GPIO,'struct gpio'被引進來封裝所有
-這三個領域:
-
- struct gpio {
- unsigned gpio;
- unsigned long flags;
- const char *label;
- };
-
-一個典型的用例:
-
- static struct gpio leds_gpios[] = {
- { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* 默認開啓 */
- { 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* 默認關閉 */
- { 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* 默認關閉 */
- { 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* 默認關閉 */
- { ... },
- };
-
- err = gpio_request_one(31, GPIOF_IN, "Reset Button");
- if (err)
- ...
-
-
-GPIO 映射到 IRQ
---------------------
-GPIO 編號是無符號整數;IRQ 編號也是。這些構成了兩個邏輯上不同的命名空間
-(GPIO 0 不一定使用 IRQ 0)。你可以通過以下函數在它們之間實現映射:
-
- /* 映射 GPIO 編號到 IRQ 編號 */
- int gpio_to_irq(unsigned gpio);
-
-它們的返回值爲對應命名空間的相關編號,或是負的錯誤代碼(如果無法映射)。
-(例如,某些 GPIO 無法做爲 IRQ 使用。)以下的編號錯誤是未經檢測的:使用一個
-未通過 gpio_direction_input()配置爲輸入的 GPIO 編號,或者使用一個
-並非來源於gpio_to_irq()的 IRQ 編號。
-
-這兩個映射函數可能會在信號編號的加減計算過程上花些時間。它們不可休眠。
-
-gpio_to_irq()返回的非錯誤值可以傳遞給 request_irq()或者 free_irq()。
-它們通常通過板級特定的初始化代碼存放到平台設備的 IRQ 資源中。注意:IRQ
-觸發選項是 IRQ 接口的一部分,如 IRQF_TRIGGER_FALLING,系統喚醒能力
-也是如此。
-
-
-模擬開漏信號
-----------------------------
-有時在只有低電平信號作爲實際驅動結果(譯者注:多個輸出連接於一點,邏輯電平
-結果爲所有輸出的邏輯與)的時候,共享的信號線需要使用「開漏」信號。(該術語
-適用於 CMOS 管;而 TTL 用「集電極開路」。)一個上拉電阻使信號爲高電平。這
-有時被稱爲「線與」。實際上,從負邏輯(低電平爲真)的角度來看,這是一個「線或」。
-
-一個開漏信號的常見例子是共享的低電平使能 IRQ 信號線。此外,有時雙向數據總線
-信號也使用漏極開路信號。
-
-某些 GPIO 控制器直接支持開漏輸出,還有許多不支持。當你需要開漏信號,但
-硬體又不直接支持的時候,一個常用的方法是用任何即可作輸入也可作輸出的 GPIO
-引腳來模擬:
-
- LOW: gpio_direction_output(gpio, 0) ... 這代碼驅動信號並覆蓋
- 上拉配置。
-
- HIGH: gpio_direction_input(gpio) ... 這代碼關閉輸出,所以上拉電阻
- (或其他的一些器件)控制了信號。
-
-如果你將信號線「驅動」爲高電平,但是 gpio_get_value(gpio)報告了一個
-低電平(在適當的上升時間後),你就可以知道是其他的一些組件將共享信號線拉低了。
-這不一定是錯誤的。一個常見的例子就是 I2C 時鐘的延長:一個需要較慢時鐘的
-從設備延遲 SCK 的上升沿,而 I2C 主設備相應地調整其信號傳輸速率。
-
-
-這些公約忽略了什麼?
-================
-這些公約忽略的最大一件事就是引腳復用,因爲這屬於高度晶片特定的屬性且
-沒有可移植性。某個平台可能不需要明確的復用信息;有的對於任意給定的引腳
-可能只有兩個功能選項;有的可能每個引腳有八個功能選項;有的可能可以將
-幾個引腳中的任何一個作爲給定的 GPIO。(是的,這些例子都來自於當前運行
-Linux 的系統。)
-
-在某些系統中,與引腳復用相關的是配置和使能集成的上、下拉模式。並不是所有
-平台都支持這種模式,或者不會以相同的方式來支持這種模式;且任何給定的電路板
-可能使用外置的上拉(或下拉)電阻,這時晶片上的就不應該使用。(當一個電路需要
-5kOhm 的拉動電阻,晶片上的 100 kOhm 電阻就不能做到。)同樣的,驅動能力
-(2 mA vs 20 mA)和電壓(1.8V vs 3.3V)是平台特定問題,就像模型一樣在
-可配置引腳和 GPIO 之間(沒)有一一對應的關係。
-
-還有其他一些系統特定的機制沒有在這裡指出,例如上述的輸入去毛刺和線與輸出
-選項。硬體可能支持批量讀或寫 GPIO,但是那一般是配置相關的:對於處於同一
-塊區(bank)的GPIO。(GPIO 通常以 16 或 32 個組成一個區塊,一個給定的
-片上系統一般有幾個這樣的區塊。)某些系統可以通過輸出 GPIO 觸發 IRQ,
-或者從並非以 GPIO 管理的引腳取值。這些機制的相關代碼沒有必要具有可移植性。
-
-當前,動態定義 GPIO 並不是標準的,例如作爲配置一個帶有某些 GPIO 擴展器的
-附加電路板的副作用。
-
-GPIO 實現者的框架 (可選)
-=====================
-前面提到了,有一個可選的實現框架,讓平台使用相同的編程接口,更加簡單地支持
-不同種類的 GPIO 控制器。這個框架稱爲"gpiolib"。
-
-作爲一個輔助調試功能,如果 debugfs 可用,就會有一個 /sys/kernel/debug/gpio
-文件。通過這個框架,它可以列出所有註冊的控制器,以及當前正在使用中的 GPIO
-的狀態。
-
-
-控制器驅動: gpio_chip
--------------------
-在框架中每個 GPIO 控制器都包裝爲一個 "struct gpio_chip",他包含了
-該類型的每個控制器的常用信息:
-
- - 設置 GPIO 方向的方法
- - 用於訪問 GPIO 值的方法
- - 告知調用其方法是否可能休眠的標誌
- - 可選的 debugfs 信息導出方法 (顯示類似上拉配置一樣的額外狀態)
- - 診斷標籤
-
-也包含了來自 device.platform_data 的每個實例的數據:它第一個 GPIO 的
-編號和它可用的 GPIO 的數量。
-
-實現 gpio_chip 的代碼應支持多控制器實例,這可能使用驅動模型。那些代碼要
-配置每個 gpio_chip,並發起gpiochip_add()。卸載一個 GPIO 控制器很少見,
-但在必要的時候可以使用 gpiochip_remove()。
-
-大部分 gpio_chip 是一個實例特定結構體的一部分,而並不將 GPIO 接口單獨
-暴露出來,比如編址、電源管理等。類似編解碼器這樣的晶片會有複雜的非 GPIO
-狀態。
-
-任何一個 debugfs 信息導出方法通常應該忽略還未申請作爲 GPIO 的信號線。
-他們可以使用 gpiochip_is_requested()測試,當這個 GPIO 已經申請過了
-就返回相關的標籤,否則返回 NULL。
-
-
-平台支持
--------
-爲了支持這個框架,一個平台的 Kconfig 文件將會 "select"(選擇)
-ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,並讓它的
-<asm/gpio.h> 包含 <asm-generic/gpio.h>,同時定義二個方法:
-gpio_get_value()、gpio_set_value()。
-
-它也應提供一個 ARCH_NR_GPIOS 的定義值,這樣可以更好地反映該平台 GPIO
-的實際數量,節省靜態表的空間。(這個定義值應該包含片上系統內建 GPIO 和
-GPIO 擴展器中的數據。)
-
-ARCH_REQUIRE_GPIOLIB 意味著 gpiolib 核心在這個構架中將總是編譯進內核。
-
-ARCH_WANT_OPTIONAL_GPIOLIB 意味著 gpiolib 核心默認關閉,且用戶可以
-使能它,並將其編譯進內核(可選)。
-
-如果這些選項都沒被選擇,該平台就不通過 GPIO-lib 支持 GPIO,且代碼不可以
-被用戶使能。
-
-以下這些方法的實現可以直接使用框架代碼,並總是通過 gpio_chip 調度:
-
- #define gpio_get_value __gpio_get_value
- #define gpio_set_value __gpio_set_value
-
-這些定義可以用更理想的實現方法替代,那就是使用經過邏輯優化的內聯函數來訪問
-基於特定片上系統的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量「12」,
-讀取或設置它可能只需少則兩或三個指令,且不會休眠。當這樣的優化無法實現時,
-那些函數必須使用框架提供的代碼,那就至少要幾十條指令才可以實現。對於用 GPIO
-模擬的 I/O 接口, 如此精簡指令是很有意義的。
-
-對於片上系統,平台特定代碼爲片上 GPIO 每個區(bank)定義並註冊 gpio_chip
-實例。那些 GPIO 應該根據晶片廠商的文檔進行編碼/標籤,並直接和電路板原理圖
-對應。他們應該開始於零並終止於平台特定的限制。這些 GPIO(代碼)通常從
-arch_initcall()或者更早的地方集成進平台初始化代碼,使這些 GPIO 總是可用,
-且他們通常可以作爲 IRQ 使用。
-
-板級支持
--------
-對於外部 GPIO 控制器(例如 I2C 或 SPI 擴展器、專用晶片、多功能器件、FPGA
-或 CPLD),大多數常用板級特定代碼都可以註冊控制器設備,並保證他們的驅動知道
-gpiochip_add()所使用的 GPIO 編號。他們的起始編號通常跟在平台特定的 GPIO
-編號之後。
-
-例如板級啓動代碼應該創建結構體指明晶片公開的 GPIO 範圍,並使用 platform_data
-將其傳遞給每個 GPIO 擴展器晶片。然後晶片驅動中的 probe()例程可以將這個
-數據傳遞給 gpiochip_add()。
-
-初始化順序很重要。例如,如果一個設備依賴基於 I2C 的(擴展)GPIO,那麼它的
-probe()例程就應該在那個 GPIO 有效以後才可以被調用。這意味著設備應該在
-GPIO 可以工作之後才可被註冊。解決這類依賴的的一種方法是讓這種 gpio_chip
-控制器向板級特定代碼提供 setup()和 teardown()回調函數。一旦所有必須的
-資源可用之後,這些板級特定的回調函數將會註冊設備,並可以在這些 GPIO 控制器
-設備變成無效時移除它們。
-
-
-用戶空間的 Sysfs 接口(可選)
-========================
-使用「gpiolib」實現框架的平台可以選擇配置一個 GPIO 的 sysfs 用戶接口。
-這不同於 debugfs 接口,因爲它提供的是對 GPIO方向和值的控制,而不只顯示
-一個GPIO 的狀態摘要。此外,它可以出現在沒有調試支持的產品級系統中。
-
-例如,通過適當的系統硬體文檔,用戶空間可以知道 GIOP #23 控制 Flash
-存儲器的防寫(用於保護其中 Bootloader 分區)。產品的系統升級可能需要
-臨時解除這個保護:首先導入一個 GPIO,改變其輸出狀態,然後在重新使能防寫
-前升級代碼。通常情況下,GPIO #23 是不會被觸及的,並且內核也不需要知道他。
-
-根據適當的硬體文檔,某些系統的用戶空間 GPIO 可以用於確定系統配置數據,
-這些數據是標準內核不知道的。在某些任務中,簡單的用戶空間 GPIO 驅動可能是
-系統真正需要的。
-
-注意:標準內核驅動中已經存在通用的「LED 和按鍵」GPIO 任務,分別是:
-"leds-gpio" 和 "gpio_keys"。請使用這些來替代直接訪問 GPIO,因爲集成在
-內核框架中的這類驅動比你在用戶空間的代碼更好。
-
-
-Sysfs 中的路徑
---------------
-在/sys/class/gpio 中有 3 類入口:
-
- - 用於在用戶空間控制 GPIO 的控制接口;
-
- - GPIOs 本身;以及
-
- - GPIO 控制器 ("gpio_chip" 實例)。
-
-除了這些標準的文件,還包含「device」符號連結。
-
-控制接口是只寫的:
-
- /sys/class/gpio/
-
- "export" ... 用戶空間可以通過寫其編號到這個文件,要求內核導出
- 一個 GPIO 的控制到用戶空間。
-
- 例如: 如果內核代碼沒有申請 GPIO #19,"echo 19 > export"
- 將會爲 GPIO #19 創建一個 "gpio19" 節點。
-
- "unexport" ... 導出到用戶空間的逆操作。
-
- 例如: "echo 19 > unexport" 將會移除使用"export"文件導出的
- "gpio19" 節點。
-
-GPIO 信號的路徑類似 /sys/class/gpio/gpio42/ (對於 GPIO #42 來說),
-並有如下的讀/寫屬性:
-
- /sys/class/gpio/gpioN/
-
- "direction" ... 讀取得到 "in" 或 "out"。這個值通常運行寫入。
- 寫入"out" 時,其引腳的默認輸出爲低電平。爲了確保無故障運行,
- "low" 或 "high" 的電平值應該寫入 GPIO 的配置,作爲初始輸出值。
-
- 注意:如果內核不支持改變 GPIO 的方向,或者在導出時內核代碼沒有
- 明確允許用戶空間可以重新配置 GPIO 方向,那麼這個屬性將不存在。
-
- "value" ... 讀取得到 0 (低電平) 或 1 (高電平)。如果 GPIO 配置爲
- 輸出,這個值允許寫操作。任何非零值都以高電平看待。
-
- 如果引腳可以配置爲中斷信號,且如果已經配置了產生中斷的模式
- (見"edge"的描述),你可以對這個文件使用輪詢操作(poll(2)),
- 且輪詢操作會在任何中斷觸發時返回。如果你使用輪詢操作(poll(2)),
- 請在 events 中設置 POLLPRI 和 POLLERR。如果你使用輪詢操作
- (select(2)),請在 exceptfds 設置你期望的文件描述符。在
- 輪詢操作(poll(2))返回之後,既可以通過 lseek(2)操作讀取
- sysfs 文件的開始部分,也可以關閉這個文件並重新打開它來讀取數據。
-
- "edge" ... 讀取得到「none」、「rising」、「falling」或者「both」。
- 將這些字符串寫入這個文件可以選擇沿觸發模式,會使得輪詢操作
- (select(2))在"value"文件中返回。
-
- 這個文件僅有在這個引腳可以配置爲可產生中斷輸入引腳時,才存在。
-
- "active_low" ... 讀取得到 0 (假) 或 1 (真)。寫入任何非零值可以
- 翻轉這個屬性的(讀寫)值。已存在或之後通過"edge"屬性設置了"rising"
- 和 "falling" 沿觸發模式的輪詢操作(poll(2))將會遵循這個設置。
-
-GPIO 控制器的路徑類似 /sys/class/gpio/gpiochip42/ (對於從#42 GPIO
-開始實現控制的控制器),並有著以下只讀屬性:
-
- /sys/class/gpio/gpiochipN/
-
- "base" ... 與以上的 N 相同,代表此晶片管理的第一個 GPIO 的編號
-
- "label" ... 用於診斷 (並不總是只有唯一值)
-
- "ngpio" ... 此控制器所管理的 GPIO 數量(而 GPIO 編號從 N 到
- N + ngpio - 1)
-
-大多數情況下,電路板的文檔應當標明每個 GPIO 的使用目的。但是那些編號並不總是
-固定的,例如在擴展卡上的 GPIO會根據所使用的主板或所在堆疊架構中其他的板子而
-有所不同。在這種情況下,你可能需要使用 gpiochip 節點(儘可能地結合電路圖)來
-確定給定信號所用的 GPIO 編號。
diff --git a/Documentation/userspace-api/gpio/gpio-handle-get-line-values-ioctl.rst b/Documentation/userspace-api/gpio/gpio-handle-get-line-values-ioctl.rst
index 25263b8f0588..2e3a52c113d5 100644
--- a/Documentation/userspace-api/gpio/gpio-handle-get-line-values-ioctl.rst
+++ b/Documentation/userspace-api/gpio/gpio-handle-get-line-values-ioctl.rst
@@ -36,6 +36,13 @@ Description
Get the values of all requested lines.
+The values returned are logical, indicating if the line is active or inactive.
+The ``GPIOHANDLE_REQUEST_ACTIVE_LOW`` flag controls the mapping between physical
+values (high/low) and logical values (active/inactive).
+If ``GPIOHANDLE_REQUEST_ACTIVE_LOW`` is not set then high is active and
+low is inactive. If ``GPIOHANDLE_REQUEST_ACTIVE_LOW`` is set then low is active
+and high is inactive.
+
The values of both input and output lines may be read.
For output lines, the value returned is driver and configuration dependent and
diff --git a/Documentation/userspace-api/gpio/gpio-handle-set-config-ioctl.rst b/Documentation/userspace-api/gpio/gpio-handle-set-config-ioctl.rst
index d002a84681ac..a03f30db63ab 100644
--- a/Documentation/userspace-api/gpio/gpio-handle-set-config-ioctl.rst
+++ b/Documentation/userspace-api/gpio/gpio-handle-set-config-ioctl.rst
@@ -43,7 +43,10 @@ The configuration applies to all requested lines.
The same :ref:`gpio-get-linehandle-config-rules` and
:ref:`gpio-get-linehandle-config-support` that apply when requesting the
-lines also apply when updating the line configuration.
+lines also apply when updating the line configuration, with the additional
+restriction that a direction flag must be set. Requesting an invalid
+configuration, including without a direction flag set, is an error
+(**EINVAL**).
The motivating use case for this command is changing direction of
bi-directional lines between input and output, but it may be used more
diff --git a/Documentation/userspace-api/gpio/gpio-handle-set-line-values-ioctl.rst b/Documentation/userspace-api/gpio/gpio-handle-set-line-values-ioctl.rst
index 0aa05e623a6c..12862132b420 100644
--- a/Documentation/userspace-api/gpio/gpio-handle-set-line-values-ioctl.rst
+++ b/Documentation/userspace-api/gpio/gpio-handle-set-line-values-ioctl.rst
@@ -36,6 +36,13 @@ Description
Set the values of all requested output lines.
+The values set are logical, indicating if the line is to be active or inactive.
+The ``GPIOHANDLE_REQUEST_ACTIVE_LOW`` flag controls the mapping between logical
+values (active/inactive) and physical values (high/low).
+If ``GPIOHANDLE_REQUEST_ACTIVE_LOW`` is not set then active is high and
+inactive is low. If ``GPIOHANDLE_REQUEST_ACTIVE_LOW`` is set then active is low
+and inactive is high.
+
Only the values of output lines may be set.
Attempting to set the value of input lines is an error (**EPERM**).
diff --git a/Documentation/userspace-api/gpio/gpio-lineevent-data-read.rst b/Documentation/userspace-api/gpio/gpio-lineevent-data-read.rst
index 68b8d4f9f604..d1e7e2383b0d 100644
--- a/Documentation/userspace-api/gpio/gpio-lineevent-data-read.rst
+++ b/Documentation/userspace-api/gpio/gpio-lineevent-data-read.rst
@@ -44,6 +44,11 @@ Edge detection must be enabled for the input line using either
both. Edge events are then generated whenever edge interrupts are detected on
the input line.
+Edges are defined in terms of changes to the logical line value, so an inactive
+to active transition is a rising edge. If ``GPIOHANDLE_REQUEST_ACTIVE_LOW`` is
+set then logical polarity is the opposite of physical polarity, and
+``GPIOEVENT_REQUEST_RISING_EDGE`` then corresponds to a falling physical edge.
+
The kernel captures and timestamps edge events as close as possible to their
occurrence and stores them in a buffer from where they can be read by
userspace at its convenience using `read()`.
diff --git a/Documentation/userspace-api/gpio/gpio-v2-line-event-read.rst b/Documentation/userspace-api/gpio/gpio-v2-line-event-read.rst
index 6513c23fb7ca..1312668e0f6a 100644
--- a/Documentation/userspace-api/gpio/gpio-v2-line-event-read.rst
+++ b/Documentation/userspace-api/gpio/gpio-v2-line-event-read.rst
@@ -40,6 +40,11 @@ Edge detection must be enabled for the input line using either
both. Edge events are then generated whenever edge interrupts are detected on
the input line.
+Edges are defined in terms of changes to the logical line value, so an inactive
+to active transition is a rising edge. If ``GPIO_V2_LINE_FLAG_ACTIVE_LOW`` is
+set then logical polarity is the opposite of physical polarity, and
+``GPIO_V2_LINE_FLAG_EDGE_RISING`` then corresponds to a falling physical edge.
+
The kernel captures and timestamps edge events as close as possible to their
occurrence and stores them in a buffer from where they can be read by
userspace at its convenience using `read()`.
diff --git a/Documentation/userspace-api/gpio/gpio-v2-line-get-values-ioctl.rst b/Documentation/userspace-api/gpio/gpio-v2-line-get-values-ioctl.rst
index e4e74a1926d8..d7defd4ca397 100644
--- a/Documentation/userspace-api/gpio/gpio-v2-line-get-values-ioctl.rst
+++ b/Documentation/userspace-api/gpio/gpio-v2-line-get-values-ioctl.rst
@@ -34,6 +34,13 @@ Description
Get the values of requested lines.
+The values returned are logical, indicating if the line is active or inactive.
+The ``GPIO_V2_LINE_FLAG_ACTIVE_LOW`` flag controls the mapping between physical
+values (high/low) and logical values (active/inactive).
+If ``GPIO_V2_LINE_FLAG_ACTIVE_LOW`` is not set then high is active and low is
+inactive. If ``GPIO_V2_LINE_FLAG_ACTIVE_LOW`` is set then low is active and
+high is inactive.
+
The values of both input and output lines may be read.
For output lines, the value returned is driver and configuration dependent and
diff --git a/Documentation/userspace-api/gpio/gpio-v2-line-set-config-ioctl.rst b/Documentation/userspace-api/gpio/gpio-v2-line-set-config-ioctl.rst
index 9b942a8a53ca..cfaab801556c 100644
--- a/Documentation/userspace-api/gpio/gpio-v2-line-set-config-ioctl.rst
+++ b/Documentation/userspace-api/gpio/gpio-v2-line-set-config-ioctl.rst
@@ -35,11 +35,14 @@ Description
Update the configuration of previously requested lines, without releasing the
line or introducing potential glitches.
-The new configuration must specify the configuration of all requested lines.
+The new configuration must specify a configuration for all requested lines.
The same :ref:`gpio-v2-get-line-config-rules` and
:ref:`gpio-v2-get-line-config-support` that apply when requesting the lines
-also apply when updating the line configuration.
+also apply when updating the line configuration, with the additional
+restriction that a direction flag must be set to enable reconfiguration.
+If no direction flag is set in the configuration for a given line then the
+configuration for that line is left unchanged.
The motivating use case for this command is changing direction of
bi-directional lines between input and output, but it may also be used to
diff --git a/Documentation/userspace-api/gpio/gpio-v2-line-set-values-ioctl.rst b/Documentation/userspace-api/gpio/gpio-v2-line-set-values-ioctl.rst
index 6d2d1886950b..16dd50fc60ca 100644
--- a/Documentation/userspace-api/gpio/gpio-v2-line-set-values-ioctl.rst
+++ b/Documentation/userspace-api/gpio/gpio-v2-line-set-values-ioctl.rst
@@ -35,6 +35,13 @@ Description
Set the values of requested output lines.
+The values set are logical, indicating if the line is to be active or inactive.
+The ``GPIO_V2_LINE_FLAG_ACTIVE_LOW`` flag controls the mapping between logical
+values (active/inactive) and physical values (high/low).
+If ``GPIO_V2_LINE_FLAG_ACTIVE_LOW`` is not set then active is high and inactive
+is low. If ``GPIO_V2_LINE_FLAG_ACTIVE_LOW`` is set then active is low and
+inactive is high.
+
Only the values of output lines may be set.
Attempting to set the value of an input line is an error (**EPERM**).
diff --git a/Documentation/userspace-api/gpio/sysfs.rst b/Documentation/userspace-api/gpio/sysfs.rst
index 116921048b18..bd64896de91a 100644
--- a/Documentation/userspace-api/gpio/sysfs.rst
+++ b/Documentation/userspace-api/gpio/sysfs.rst
@@ -97,9 +97,10 @@ and have the following read/write attributes:
poll(2) will return whenever the interrupt was triggered. If
you use poll(2), set the events POLLPRI and POLLERR. If you
use select(2), set the file descriptor in exceptfds. After
- poll(2) returns, either lseek(2) to the beginning of the sysfs
- file and read the new value or close the file and re-open it
- to read the value.
+ poll(2) returns, use pread(2) to read the value at offset
+ zero. Alternatively, either lseek(2) to the beginning of the
+ sysfs file and read the new value or close the file and
+ re-open it to read the value.
"edge" ...
reads as either "none", "rising", "falling", or
diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
index a141e8e65c5d..9a97030c6c8d 100644
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -186,6 +186,7 @@ Code Seq# Include File Comments
'Q' all linux/soundcard.h
'R' 00-1F linux/random.h conflict!
'R' 01 linux/rfkill.h conflict!
+'R' 20-2F linux/trace_mmap.h
'R' C0-DF net/bluetooth/rfcomm.h
'R' E0 uapi/linux/fsl_mc.h
'S' all linux/cdrom.h conflict!
diff --git a/Documentation/virt/coco/sev-guest.rst b/Documentation/virt/coco/sev-guest.rst
index e1eaf6a830ce..9d00967a5b2b 100644
--- a/Documentation/virt/coco/sev-guest.rst
+++ b/Documentation/virt/coco/sev-guest.rst
@@ -204,6 +204,17 @@ has taken care to make use of the SEV-SNP CPUID throughout all stages of boot.
Otherwise, guest owner attestation provides no assurance that the kernel wasn't
fed incorrect values at some point during boot.
+4. SEV Guest Driver Communication Key
+=====================================
+
+Communication between an SEV guest and the SEV firmware in the AMD Secure
+Processor (ASP, aka PSP) is protected by a VM Platform Communication Key
+(VMPCK). By default, the sev-guest driver uses the VMPCK associated with the
+VM Privilege Level (VMPL) at which the guest is running. Should this key be
+wiped by the sev-guest driver (see the driver for reasons why a VMPCK can be
+wiped), a different key can be used by reloading the sev-guest driver and
+specifying the desired key using the vmpck_id module parameter.
+
Reference
---------
diff --git a/MAINTAINERS b/MAINTAINERS
index 3c4fdf74a3f9..104ccfea9e57 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -846,12 +846,6 @@ ALPS PS/2 TOUCHPAD DRIVER
R: Pali Rohár <[email protected]>
F: drivers/input/mouse/alps.*
-ALTERA I2C CONTROLLER DRIVER
-M: Thor Thayer <[email protected]>
-S: Maintained
-F: Documentation/devicetree/bindings/i2c/i2c-altera.txt
-F: drivers/i2c/busses/i2c-altera.c
-
ALTERA MAILBOX DRIVER
M: Mun Yew Tham <[email protected]>
S: Maintained
@@ -871,21 +865,6 @@ L: [email protected]
S: Maintained
F: drivers/gpio/gpio-altera.c
-ALTERA SYSTEM MANAGER DRIVER
-M: Thor Thayer <[email protected]>
-S: Maintained
-F: drivers/mfd/altera-sysmgr.c
-F: include/linux/mfd/altera-sysmgr.h
-
-ALTERA SYSTEM RESOURCE DRIVER FOR ARRIA10 DEVKIT
-M: Thor Thayer <[email protected]>
-S: Maintained
-F: drivers/gpio/gpio-altera-a10sr.c
-F: drivers/mfd/altera-a10sr.c
-F: drivers/reset/reset-a10sr.c
-F: include/dt-bindings/reset/altr,rst-mgr-a10sr.h
-F: include/linux/mfd/altera-a10sr.h
-
ALTERA TRIPLE SPEED ETHERNET DRIVER
M: Joyce Ooi <[email protected]>
@@ -1908,6 +1887,15 @@ F: include/dt-bindings/reset/actions,*
F: include/linux/soc/actions/
N: owl
+ARM/AIROHA SOC SUPPORT
+M: Matthias Brugger <[email protected]>
+M: AngeloGioacchino Del Regno <[email protected]>
+L: [email protected] (moderated for non-subscribers)
+L: [email protected] (moderated for non-subscribers)
+S: Odd Fixes
+F: arch/arm/boot/dts/airoha/
+F: arch/arm64/boot/dts/airoha/
+
ARM/Allwinner SoC Clock Support
M: Emilio López <[email protected]>
S: Maintained
@@ -1930,6 +1918,16 @@ N: allwinner
N: sun[x456789]i
N: sun[25]0i
+ARM/ALPHASCALE ARCHITECTURE
+M: Krzysztof Kozlowski <[email protected]>
+L: [email protected] (moderated for non-subscribers)
+S: Odd Fixes
+F: arch/arm/boot/dts/alphascale/
+F: drivers/clk/clk-asm9260.c
+F: drivers/clocksource/asm9260_timer.c
+F: drivers/rtc/rtc-asm9260.c
+F: drivers/watchdog/asm9260_wdt.c
+
ARM/AMD PENSANDO ARM64 ARCHITECTURE
M: Brad Larson <[email protected]>
L: [email protected] (moderated for non-subscribers)
@@ -1985,10 +1983,9 @@ F: drivers/soc/amlogic/
N: meson
ARM/Annapurna Labs ALPINE ARCHITECTURE
-M: Tsahee Zidenberg <[email protected]>
M: Antoine Tenart <[email protected]>
L: [email protected] (moderated for non-subscribers)
-S: Maintained
+S: Odd Fixes
F: arch/arm/boot/dts/amazon/
F: arch/arm/mach-alpine/
F: arch/arm64/boot/dts/amazon/
@@ -2093,6 +2090,14 @@ F: arch/arm/boot/dts/aspeed/
F: arch/arm/mach-aspeed/
N: aspeed
+ARM/AXM LSI SOC
+M: Krzysztof Kozlowski <[email protected]>
+L: [email protected] (moderated for non-subscribers)
+S: Odd Fixes
+F: Documentation/devicetree/bindings/arm/axxia.yaml
+F: arch/arm/boot/dts/intel/axm/
+F: arch/arm/mach-axxia/
+
ARM/BITMAIN ARCHITECTURE
M: Manivannan Sadhasivam <[email protected]>
L: [email protected] (moderated for non-subscribers)
@@ -2206,11 +2211,14 @@ M: Marek Behún <[email protected]>
S: Maintained
W: https://www.turris.cz/
F: Documentation/ABI/testing/debugfs-moxtet
+F: Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu
F: Documentation/ABI/testing/sysfs-bus-moxtet-devices
F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
F: Documentation/devicetree/bindings/bus/moxtet.txt
F: Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt
+F: Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml
F: Documentation/devicetree/bindings/gpio/gpio-moxtet.txt
+F: Documentation/devicetree/bindings/interrupt-controller/marvell,mpic.yaml
F: Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml
F: Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt
F: drivers/bus/moxtet.c
@@ -2218,10 +2226,12 @@ F: drivers/firmware/turris-mox-rwtm.c
F: drivers/gpio/gpio-moxtet.c
F: drivers/leds/leds-turris-omnia.c
F: drivers/mailbox/armada-37xx-rwtm-mailbox.c
+F: drivers/platform/cznic/
F: drivers/watchdog/armada_37xx_wdt.c
F: include/dt-bindings/bus/moxtet.h
F: include/linux/armada-37xx-rwtm-mailbox.h
F: include/linux/moxtet.h
+F: include/linux/turris-omnia-mcu-interface.h
ARM/FARADAY FA526 PORT
M: Hans Ulli Kroll <[email protected]>
@@ -2523,6 +2533,15 @@ F: arch/arm/boot/dts/socionext/milbeaut*
F: arch/arm/mach-milbeaut/
N: milbeaut
+ARM/MOXA ART SOC
+M: Krzysztof Kozlowski <[email protected]>
+L: [email protected] (moderated for non-subscribers)
+S: Odd Fixes
+F: Documentation/devicetree/bindings/arm/moxart.yaml
+F: Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt
+F: arch/arm/boot/dts/moxa/
+F: drivers/clk/clk-moxart.c
+
ARM/MStar/Sigmastar Armv7 SoC support
M: Daniel Palmer <[email protected]>
M: Romain Perier <[email protected]>
@@ -2892,7 +2911,7 @@ F: drivers/edac/altera_edac.[ch]
ARM/SPREADTRUM SoC SUPPORT
M: Orson Zhai <[email protected]>
M: Baolin Wang <[email protected]>
-M: Chunyan Zhang <[email protected]>
+R: Chunyan Zhang <[email protected]>
S: Maintained
F: arch/arm64/boot/dts/sprd
N: sprd
@@ -3033,6 +3052,15 @@ F: Documentation/devicetree/bindings/hwinfo/ti,k3-socinfo.yaml
F: arch/arm64/boot/dts/ti/Makefile
F: arch/arm64/boot/dts/ti/k3-*
+ARM/TEXAS INSTRUMENTS NSPIRE ARCHITECTURE
+M: Krzysztof Kozlowski <[email protected]>
+L: [email protected] (moderated for non-subscribers)
+S: Odd Fixes
+F: Documentation/devicetree/bindings/*/*/ti,nspire*
+F: Documentation/devicetree/bindings/*/ti,nspire*
+F: Documentation/devicetree/bindings/arm/ti/nspire.yaml
+F: arch/arm/boot/dts/nspire/
+
ARM/TOSHIBA VISCONTI ARCHITECTURE
M: Nobuhiro Iwamatsu <[email protected]>
L: [email protected] (moderated for non-subscribers)
@@ -3102,9 +3130,12 @@ W: http://www.armlinux.org.uk/
F: arch/arm/vfp/
ARM/VT8500 ARM ARCHITECTURE
+M: Alexey Charkov <[email protected]>
+M: Krzysztof Kozlowski <[email protected]>
L: [email protected] (moderated for non-subscribers)
-S: Orphan
+S: Odd Fixes
F: Documentation/devicetree/bindings/i2c/i2c-wmt.txt
+F: arch/arm/boot/dts/vt8500/
F: arch/arm/mach-vt8500/
F: drivers/clocksource/timer-vt8500.c
F: drivers/i2c/busses/i2c-viai2c-wmt.c
@@ -3570,6 +3601,15 @@ W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/spi/adi,axi-spi-engine.yaml
F: drivers/spi/spi-axi-spi-engine.c
+AXI PWM GENERATOR
+M: Michael Hennerich <[email protected]>
+M: Nuno Sá <[email protected]>
+S: Supported
+W: https://ez.analog.com/linux-software-drivers
+F: Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml
+F: drivers/pwm/pwm-axi-pwmgen.c
+
AXXIA I2C CONTROLLER
M: Krzysztof Adamski <[email protected]>
@@ -3601,10 +3641,9 @@ W: https://wireless.wiki.kernel.org/en/users/Drivers/b43
F: drivers/net/wireless/broadcom/b43/
B43LEGACY WIRELESS DRIVER
-M: Larry Finger <[email protected]>
-S: Maintained
+S: Orphan
W: https://wireless.wiki.kernel.org/en/users/Drivers/b43
F: drivers/net/wireless/broadcom/b43legacy/
@@ -3781,6 +3820,20 @@ F: include/linux/blk*
F: kernel/trace/blktrace.c
F: lib/sbitmap.c
+BLOCK LAYER DEVICE DRIVER API [RUST]
+M: Andreas Hindborg <[email protected]>
+R: Boqun Feng <[email protected]>
+S: Supported
+W: https://rust-for-linux.com
+B: https://github.com/Rust-for-Linux/linux/issues
+C: https://rust-for-linux.zulipchat.com/#narrow/stream/Block
+T: git https://github.com/Rust-for-Linux/linux.git rust-block-next
+F: drivers/block/rnull.rs
+F: rust/kernel/block.rs
+F: rust/kernel/block/
+
BLOCK2MTD DRIVER
M: Joern Engel <[email protected]>
@@ -5136,11 +5189,25 @@ S: Maintained
F: Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
F: sound/soc/codecs/cros_ec_codec.*
+CHROMEOS EC CHARGE CONTROL
+M: Thomas Weißschuh <[email protected]>
+S: Maintained
+F: drivers/power/supply/cros_charge-control.c
+
+CHROMEOS EC HARDWARE MONITORING
+M: Thomas Weißschuh <[email protected]>
+S: Maintained
+F: Documentation/hwmon/cros_ec_hwmon.rst
+F: drivers/hwmon/cros_ec_hwmon.c
+
CHROMEOS EC SUBDRIVERS
M: Benson Leung <[email protected]>
R: Guenter Roeck <[email protected]>
S: Maintained
+F: drivers/power/supply/cros_charge-control.c
F: drivers/power/supply/cros_usbpd-charger.c
N: cros_ec
N: cros-ec
@@ -5536,6 +5603,7 @@ CONTROL GROUP (CGROUP)
M: Tejun Heo <[email protected]>
M: Zefan Li <[email protected]>
M: Johannes Weiner <[email protected]>
+M: Michal Koutný <[email protected]>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
@@ -6239,9 +6307,8 @@ S: Maintained
F: drivers/usb/dwc3/
DESIGNWARE XDATA IP DRIVER
-M: Gustavo Pimentel <[email protected]>
-S: Maintained
+S: Orphan
F: Documentation/misc-devices/dw-xdata-pcie.rst
F: drivers/misc/dw-xdata-pcie.c
@@ -8483,6 +8550,7 @@ R: Darrick J. Wong <[email protected]>
S: Supported
+F: Documentation/filesystems/iomap/*
F: fs/iomap/
F: include/linux/iomap.h
@@ -8709,7 +8777,7 @@ FREESCALE DSPI DRIVER
M: Vladimir Oltean <[email protected]>
S: Maintained
-F: Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+F: Documentation/devicetree/bindings/spi/fsl,dspi*.yaml
F: drivers/spi/spi-fsl-dspi.c
F: include/linux/spi/spi-fsl-dspi.h
@@ -8834,6 +8902,7 @@ F: drivers/spi/spi-fsl-qspi.c
FREESCALE QUICC ENGINE LIBRARY
M: Qiang Zhao <[email protected]>
+M: Christophe Leroy <[email protected]>
S: Maintained
F: drivers/soc/fsl/qe/
@@ -8883,9 +8952,10 @@ S: Maintained
F: drivers/tty/serial/ucc_uart.c
FREESCALE SOC DRIVERS
+M: Christophe Leroy <[email protected]>
L: [email protected] (moderated for non-subscribers)
-S: Orphan
+S: Maintained
F: Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
F: Documentation/devicetree/bindings/soc/fsl/
F: drivers/soc/fsl/
@@ -11571,7 +11641,7 @@ F: include/linux/iosys-map.h
IO_URING
M: Jens Axboe <[email protected]>
-R: Pavel Begunkov <[email protected]>
+M: Pavel Begunkov <[email protected]>
S: Maintained
T: git git://git.kernel.dk/linux-block
@@ -14474,7 +14544,7 @@ MEMORY MAPPING
M: Andrew Morton <[email protected]>
R: Liam R. Howlett <[email protected]>
R: Vlastimil Babka <[email protected]>
-R: Lorenzo Stoakes <[email protected]>
+R: Lorenzo Stoakes <[email protected]>
S: Maintained
W: http://www.linux-mm.org
@@ -14849,6 +14919,7 @@ MICROCHIP SOC DRIVERS
M: Conor Dooley <[email protected]>
S: Supported
T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
+F: Documentation/devicetree/bindings/soc/microchip/
F: drivers/soc/microchip/
MICROCHIP SPI DRIVER
@@ -15256,6 +15327,27 @@ S: Maintained
F: Documentation/devicetree/bindings/leds/backlight/mps,mp3309c.yaml
F: drivers/video/backlight/mp3309c.c
+MPS MP2891 DRIVER
+M: Noah Wang <[email protected]>
+S: Maintained
+F: Documentation/hwmon/mp2891.rst
+F: drivers/hwmon/pmbus/mp2891.c
+
+MPS MP2993 DRIVER
+M: Noah Wang <[email protected]>
+S: Maintained
+F: Documentation/hwmon/mp2993.rst
+F: drivers/hwmon/pmbus/mp2993.c
+
+MPS MP9941 DRIVER
+M: Noah Wang <[email protected]>
+S: Maintained
+F: Documentation/hwmon/mp9941.rst
+F: drivers/hwmon/pmbus/mp9941.c
+
MR800 AVERMEDIA USB FM RADIO DRIVER
M: Alexey Klimov <[email protected]>
@@ -16330,7 +16422,6 @@ S: Maintained
F: arch/arm/*omap*/*clock*
OMAP DEVICE TREE SUPPORT
-M: Benoît Cousson <[email protected]>
M: Tony Lindgren <[email protected]>
@@ -16385,7 +16476,6 @@ S: Maintained
F: arch/arm/mach-omap2/omap_hwmod*data*
OMAP HWMOD SUPPORT
-M: Benoît Cousson <[email protected]>
M: Paul Walmsley <[email protected]>
S: Maintained
@@ -16447,7 +16537,7 @@ F: arch/arm/boot/dts/ti/omap/am335x-nano.dts
OMAP1 SUPPORT
M: Aaro Koskinen <[email protected]>
M: Janusz Krzysztofik <[email protected]>
-M: Tony Lindgren <[email protected]>
+R: Tony Lindgren <[email protected]>
S: Maintained
Q: http://patchwork.kernel.org/project/linux-omap/list/
@@ -16459,10 +16549,13 @@ F: include/linux/platform_data/ams-delta-fiq.h
F: include/linux/platform_data/i2c-omap.h
OMAP2+ SUPPORT
+M: Aaro Koskinen <[email protected]>
+M: Andreas Kemnade <[email protected]>
+M: Kevin Hilman <[email protected]>
+M: Roger Quadros <[email protected]>
M: Tony Lindgren <[email protected]>
S: Maintained
-W: http://www.muru.com/linux/omap/
W: http://linux.omap.com/
Q: http://patchwork.kernel.org/project/linux-omap/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
@@ -17349,6 +17442,14 @@ F: Documentation/driver-api/pci/p2pdma.rst
F: drivers/pci/p2pdma.c
F: include/linux/pci-p2pdma.h
+PCI POWER CONTROL
+M: Bartosz Golaszewski <[email protected]>
+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
+
PCI SUBSYSTEM
M: Bjorn Helgaas <[email protected]>
@@ -17889,6 +17990,14 @@ F: include/linux/pm_*
F: include/linux/powercap.h
F: kernel/configs/nopm.config
+POWER SEQUENCING
+M: Bartosz Golaszewski <[email protected]>
+S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git
+F: drivers/power/sequencing/
+F: include/linux/pwrseq/
+
POWER STATE COORDINATION INTERFACE (PSCI)
M: Mark Rutland <[email protected]>
M: Lorenzo Pieralisi <[email protected]>
@@ -18374,7 +18483,7 @@ M: Jeff Johnson <[email protected]>
S: Supported
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath12k
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git
F: drivers/net/wireless/ath/ath12k/
N: ath12k
@@ -18384,7 +18493,7 @@ M: Jeff Johnson <[email protected]>
S: Supported
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git
F: drivers/net/wireless/ath/ath10k/
N: ath10k
@@ -18395,7 +18504,7 @@ L: [email protected]
S: Supported
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath11k
B: https://wireless.wiki.kernel.org/en/users/Drivers/ath11k/bugreport
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git
F: drivers/net/wireless/ath/ath11k/
N: ath11k
@@ -18404,7 +18513,7 @@ M: Toke Høiland-Jørgensen <[email protected]>
S: Maintained
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath9k
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git
F: Documentation/devicetree/bindings/net/wireless/qca,ath9k.yaml
F: drivers/net/wireless/ath/ath9k/
@@ -18603,6 +18712,14 @@ F: Documentation/networking/device_drivers/cellular/qualcomm/rmnet.rst
F: drivers/net/ethernet/qualcomm/rmnet/
F: include/linux/if_rmnet.h
+QUALCOMM TRUST ZONE MEMORY ALLOCATOR
+M: Bartosz Golaszewski <[email protected]>
+S: Maintained
+F: drivers/firmware/qcom/qcom_tzmem.c
+F: drivers/firmware/qcom/qcom_tzmem.h
+F: include/linux/firmware/qcom/qcom_tzmem.h
+
QUALCOMM TSENS THERMAL DRIVER
M: Amit Kucheria <[email protected]>
M: Thara Gopinath <[email protected]>
@@ -18866,6 +18983,7 @@ M: Neeraj Upadhyay <[email protected]> (kernel/rcu/tasks.h)
M: Joel Fernandes <[email protected]>
M: Josh Triplett <[email protected]>
M: Boqun Feng <[email protected]>
+M: Uladzislau Rezki <[email protected]>
R: Steven Rostedt <[email protected]>
R: Mathieu Desnoyers <[email protected]>
R: Lai Jiangshan <[email protected]>
@@ -19304,6 +19422,7 @@ 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/
RISC-V PMU DRIVERS
M: Atish Patra <[email protected]>
@@ -19315,11 +19434,12 @@ F: drivers/perf/riscv_pmu_legacy.c
F: drivers/perf/riscv_pmu_sbi.c
RISC-V THEAD SoC SUPPORT
-M: Jisheng Zhang <[email protected]>
+M: Drew Fustini <[email protected]>
M: Guo Ren <[email protected]>
M: Fu Wei <[email protected]>
S: Maintained
+T: git https://github.com/pdp7/linux.git
F: arch/riscv/boot/dts/thead/
RNBD BLOCK DRIVERS
@@ -19509,7 +19629,6 @@ F: drivers/net/wireless/realtek/rtl818x/rtl8180/
RTL8187 WIRELESS DRIVER
M: Hin-Tak Leung <[email protected]>
-M: Larry Finger <[email protected]>
S: Maintained
T: git https://github.com/pkshih/rtw.git
@@ -20098,6 +20217,7 @@ SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) NXP i.MX DRIVER
M: Haibo Chen <[email protected]>
S: Maintained
F: drivers/mmc/host/sdhci-esdhc-imx.c
@@ -21247,7 +21367,6 @@ W: http://wiki.laptop.org/go/DCON
F: drivers/staging/olpc_dcon/
STAGING - REALTEK RTL8712U DRIVERS
-M: Larry Finger <[email protected]>
M: Florian Schilhabel <[email protected]>.
S: Odd Fixes
F: drivers/staging/rtl8712/
@@ -21281,9 +21400,9 @@ F: drivers/staging/
STANDALONE CACHE CONTROLLER DRIVERS
M: Conor Dooley <[email protected]>
S: Maintained
T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
+F: Documentation/devicetree/bindings/cache/
F: drivers/cache
STARFIRE/DURALAN NETWORK DRIVER
@@ -21796,6 +21915,7 @@ F: drivers/mfd/syscon.c
SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message Protocol drivers
M: Sudeep Holla <[email protected]>
R: Cristian Marussi <[email protected]>
L: [email protected] (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/firmware/arm,sc[mp]i.yaml
@@ -22525,6 +22645,7 @@ L: [email protected]
L: [email protected] (moderated for non-subscribers)
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
+F: Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml
F: drivers/pmdomain/ti/omap_prm.c
F: drivers/soc/ti/*
@@ -23645,12 +23766,6 @@ M: Kevin Brace <[email protected]>
S: Maintained
F: drivers/net/ethernet/via/via-rhine.c
-VIA SD/MMC CARD CONTROLLER DRIVER
-M: Bruce Chang <[email protected]>
-M: Harald Welte <[email protected]>
-S: Maintained
-F: drivers/mmc/host/via-sdmmc.c
-
VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER
M: Florian Tobias Schandinat <[email protected]>
@@ -23863,8 +23978,8 @@ S: Maintained
F: drivers/vhost/scsi.c
VIRTIO I2C DRIVER
-M: Conghui Chen <[email protected]>
M: Viresh Kumar <[email protected]>
+R: "Chen, Jian Jun" <[email protected]>
S: Maintained
diff --git a/Makefile b/Makefile
index 06aa6402b385..67ce3b7d558e 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
VERSION = 6
PATCHLEVEL = 10
SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION =
NAME = Baby Opossum Posse
# *DOCUMENTATION*
@@ -1219,7 +1219,7 @@ remove-stale-files:
$(Q)$(srctree)/scripts/remove-stale-files
# Support for using generic headers in asm-generic
-asm-generic := -f $(srctree)/scripts/Makefile.asm-generic obj
+asm-generic := -f $(srctree)/scripts/Makefile.asm-headers obj
PHONY += asm-generic uapi-asm-generic
asm-generic: uapi-asm-generic
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 3c1afa524b9c..49285a3ce239 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += syscall_table_32.h
+
generic-y += extable.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
diff --git a/arch/arc/include/asm/unistd.h b/arch/arc/include/asm/unistd.h
new file mode 100644
index 000000000000..211c230d88d6
--- /dev/null
+++ b/arch/arc/include/asm/unistd.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _ASM_ARC_UNISTD_H
+#define _ASM_ARC_UNISTD_H
+
+#include <uapi/asm/unistd.h>
+
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_FORK
+
+#define NR_syscalls __NR_syscalls
+
+#endif
diff --git a/arch/arc/include/uapi/asm/Kbuild b/arch/arc/include/uapi/asm/Kbuild
index e78470141932..2501e82a1a0a 100644
--- a/arch/arc/include/uapi/asm/Kbuild
+++ b/arch/arc/include/uapi/asm/Kbuild
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += unistd_32.h
+
generic-y += ucontext.h
diff --git a/arch/arc/include/uapi/asm/unistd.h b/arch/arc/include/uapi/asm/unistd.h
index fa2713ae6bea..cb2905c7c5da 100644
--- a/arch/arc/include/uapi/asm/unistd.h
+++ b/arch/arc/include/uapi/asm/unistd.h
@@ -7,46 +7,4 @@
* published by the Free Software Foundation.
*/
-/******** no-legacy-syscalls-ABI *******/
-
-/*
- * Non-typical guard macro to enable inclusion twice in ARCH sys.c
- * That is how the Generic syscall wrapper generator works
- */
-#if !defined(_UAPI_ASM_ARC_UNISTD_H) || defined(__SYSCALL)
-#define _UAPI_ASM_ARC_UNISTD_H
-
-#define __ARCH_WANT_RENAMEAT
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SET_GET_RLIMIT
-#define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
-#define __ARCH_WANT_SYS_VFORK
-#define __ARCH_WANT_SYS_FORK
-#define __ARCH_WANT_TIME32_SYSCALLS
-
-#define sys_mmap2 sys_mmap_pgoff
-
-#include <asm-generic/unistd.h>
-
-#define NR_syscalls __NR_syscalls
-
-/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
-#define __NR_sysfs (__NR_arch_specific_syscall + 3)
-
-/* ARC specific syscall */
-#define __NR_cacheflush (__NR_arch_specific_syscall + 0)
-#define __NR_arc_settls (__NR_arch_specific_syscall + 1)
-#define __NR_arc_gettls (__NR_arch_specific_syscall + 2)
-#define __NR_arc_usr_cmpxchg (__NR_arch_specific_syscall + 4)
-
-__SYSCALL(__NR_cacheflush, sys_cacheflush)
-__SYSCALL(__NR_arc_settls, sys_arc_settls)
-__SYSCALL(__NR_arc_gettls, sys_arc_gettls)
-__SYSCALL(__NR_arc_usr_cmpxchg, sys_arc_usr_cmpxchg)
-__SYSCALL(__NR_sysfs, sys_sysfs)
-
-#undef __SYSCALL
-
-#endif
+#include <asm/unistd_32.h>
diff --git a/arch/arc/kernel/Makefile.syscalls b/arch/arc/kernel/Makefile.syscalls
new file mode 100644
index 000000000000..391d30ab7a83
--- /dev/null
+++ b/arch/arc/kernel/Makefile.syscalls
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+syscall_abis_32 += arc time32 renameat stat64 rlimit
diff --git a/arch/arc/kernel/sys.c b/arch/arc/kernel/sys.c
index 1069446bdc58..36a2a95c083b 100644
--- a/arch/arc/kernel/sys.c
+++ b/arch/arc/kernel/sys.c
@@ -8,11 +8,12 @@
#define sys_clone sys_clone_wrapper
#define sys_clone3 sys_clone3_wrapper
+#define sys_mmap2 sys_mmap_pgoff
-#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = (call),
+#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
void *sys_call_table[NR_syscalls] = {
[0 ... NR_syscalls-1] = sys_ni_syscall,
-#include <asm/unistd.h>
+#include <asm/syscall_table_32.h>
};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ee5115252aac..a867a7d967aa 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -34,6 +34,7 @@ config ARM
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7
+ select ARCH_NEED_CMPXCHG_1_EMU if CPU_V6
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_CFI_CLANG
select ARCH_SUPPORTS_HUGETLBFS if ARM_LPAE
diff --git a/arch/arm/boot/dts/allwinner/Makefile b/arch/arm/boot/dts/allwinner/Makefile
index 4247f19b1adc..cd0d044882cf 100644
--- a/arch/arm/boot/dts/allwinner/Makefile
+++ b/arch/arm/boot/dts/allwinner/Makefile
@@ -261,68 +261,6 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-v3s-licheepi-zero.dtb \
sun8i-v3s-licheepi-zero-dock.dtb \
sun8i-v40-bananapi-m2-berry.dtb
-dtb-$(CONFIG_MACH_SUN8I) += \
- sun8i-a23-evb.dtb \
- sun8i-a23-gt90h-v4.dtb \
- sun8i-a23-inet86dz.dtb \
- sun8i-a23-ippo-q8h-v5.dtb \
- sun8i-a23-ippo-q8h-v1.2.dtb \
- sun8i-a23-polaroid-mid2407pxe03.dtb \
- sun8i-a23-polaroid-mid2809pxe04.dtb \
- sun8i-a23-q8-tablet.dtb \
- sun8i-a33-et-q8-v1.6.dtb \
- sun8i-a33-ga10h-v1.1.dtb \
- sun8i-a33-inet-d978-rev2.dtb \
- sun8i-a33-ippo-q8h-v1.2.dtb \
- sun8i-a33-olinuxino.dtb \
- sun8i-a33-q8-tablet.dtb \
- sun8i-a33-sinlinx-sina33.dtb \
- sun8i-a83t-allwinner-h8homlet-v2.dtb \
- sun8i-a83t-bananapi-m3.dtb \
- sun8i-a83t-cubietruck-plus.dtb \
- sun8i-a83t-tbs-a711.dtb \
- sun8i-h2-plus-bananapi-m2-zero.dtb \
- sun8i-h2-plus-libretech-all-h3-cc.dtb \
- sun8i-h2-plus-orangepi-r1.dtb \
- sun8i-h2-plus-orangepi-zero.dtb \
- sun8i-h3-bananapi-m2-plus.dtb \
- sun8i-h3-bananapi-m2-plus-v1.2.dtb \
- sun8i-h3-beelink-x2.dtb \
- sun8i-h3-libretech-all-h3-cc.dtb \
- sun8i-h3-mapleboard-mp130.dtb \
- sun8i-h3-nanopi-duo2.dtb \
- sun8i-h3-nanopi-m1.dtb\
- \
- sun8i-h3-nanopi-m1-plus.dtb \
- sun8i-h3-nanopi-neo.dtb \
- sun8i-h3-nanopi-neo-air.dtb \
- sun8i-h3-nanopi-r1.dtb \
- sun8i-h3-orangepi-2.dtb \
- sun8i-h3-orangepi-lite.dtb \
- sun8i-h3-orangepi-one.dtb \
- sun8i-h3-orangepi-pc.dtb \
- sun8i-h3-orangepi-pc-plus.dtb \
- sun8i-h3-orangepi-plus.dtb \
- sun8i-h3-orangepi-plus2e.dtb \
- sun8i-h3-orangepi-zero-plus2.dtb \
- sun8i-h3-rervision-dvk.dtb \
- sun8i-h3-zeropi.dtb \
- sun8i-h3-emlid-neutis-n5h3-devboard.dtb \
- sun8i-r16-bananapi-m2m.dtb \
- sun8i-r16-nintendo-nes-classic.dtb \
- sun8i-r16-nintendo-super-nes-classic.dtb \
- sun8i-r16-parrot.dtb \
- sun8i-r40-bananapi-m2-ultra.dtb \
- sun8i-r40-oka40i-c.dtb \
- sun8i-s3-elimo-initium.dtb \
- sun8i-s3-lichee-zero-plus.dtb \
- sun8i-s3-pinecube.dtb \
- sun8i-t113s-mangopi-mq-r-t113.dtb \
- sun8i-t3-cqa3t-bv3.dtb \
- sun8i-v3-sl631-imx179.dtb \
- sun8i-v3s-licheepi-zero.dtb \
- sun8i-v3s-licheepi-zero-dock.dtb \
- sun8i-v40-bananapi-m2-berry.dtb
dtb-$(CONFIG_MACH_SUN9I) += \
sun9i-a80-optimus.dtb \
sun9i-a80-cubieboard4.dtb
diff --git a/arch/arm/boot/dts/arm/arm-realview-eb-bbrevd.dtsi b/arch/arm/boot/dts/arm/arm-realview-eb-bbrevd.dtsi
index a79e1d1d30a7..7f62aef9ca8a 100644
--- a/arch/arm/boot/dts/arm/arm-realview-eb-bbrevd.dtsi
+++ b/arch/arm/boot/dts/arm/arm-realview-eb-bbrevd.dtsi
@@ -22,7 +22,7 @@
/ {
/* Introduce a fixed regulator for the new ethernet controller */
- veth: fixedregulator@0 {
+ veth: regulator-veth {
compatible = "regulator-fixed";
regulator-name = "veth";
regulator-min-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/arm/arm-realview-eb.dtsi b/arch/arm/boot/dts/arm/arm-realview-eb.dtsi
index fbb2258b451f..16f784da5a55 100644
--- a/arch/arm/boot/dts/arm/arm-realview-eb.dtsi
+++ b/arch/arm/boot/dts/arm/arm-realview-eb.dtsi
@@ -45,7 +45,7 @@
};
/* The voltage to the MMC card is hardwired at 3.3V */
- vmmc: fixedregulator@0 {
+ vmmc: regulator-vmmc {
compatible = "regulator-fixed";
regulator-name = "vmmc";
regulator-min-microvolt = <3300000>;
@@ -53,13 +53,13 @@
regulator-boot-on;
};
- xtal24mhz: xtal24mhz@24M {
+ xtal24mhz: mclk: kmiclk: sspclk: uartclk: wdogclk: clock-24000000 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
- timclk: timclk@1M {
+ timclk: clock-1000000 {
#clock-cells = <0>;
compatible = "fixed-factor-clock";
clock-div = <24>;
@@ -67,48 +67,8 @@
clocks = <&xtal24mhz>;
};
- mclk: mclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- kmiclk: kmiclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- sspclk: sspclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- uartclk: uartclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- wdogclk: wdogclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
/* FIXME: this actually hangs off the PLL clocks */
- pclk: pclk@0 {
+ pclk: clock-pclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <0>;
diff --git a/arch/arm/boot/dts/arm/arm-realview-pb1176.dts b/arch/arm/boot/dts/arm/arm-realview-pb1176.dts
index d99bac02232b..b9b10cbd65aa 100644
--- a/arch/arm/boot/dts/arm/arm-realview-pb1176.dts
+++ b/arch/arm/boot/dts/arm/arm-realview-pb1176.dts
@@ -63,13 +63,13 @@
regulator-boot-on;
};
- xtal24mhz: xtal24mhz@24M {
+ xtal24mhz: mclk: kmiclk: sspclk: uartclk: clock-24000000 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
- timclk: timclk@1M {
+ timclk: clock-1000000 {
#clock-cells = <0>;
compatible = "fixed-factor-clock";
clock-div = <24>;
@@ -77,40 +77,8 @@
clocks = <&xtal24mhz>;
};
- mclk: mclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- kmiclk: kmiclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- sspclk: sspclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- uartclk: uartclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
/* FIXME: this actually hangs off the PLL clocks */
- pclk: pclk@0 {
+ pclk: clock-pclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <0>;
diff --git a/arch/arm/boot/dts/arm/arm-realview-pb11mp.dts b/arch/arm/boot/dts/arm/arm-realview-pb11mp.dts
index 89103d54ecc1..ce35748f3d25 100644
--- a/arch/arm/boot/dts/arm/arm-realview-pb11mp.dts
+++ b/arch/arm/boot/dts/arm/arm-realview-pb11mp.dts
@@ -163,19 +163,19 @@
regulator-boot-on;
};
- xtal24mhz: xtal24mhz@24M {
+ xtal24mhz: mclk: kmiclk: sspclk: uartclk: wdogclk: clock-24000000 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
- refclk32khz: refclk32khz {
+ refclk32khz: clock-32768 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
};
- timclk: timclk@1M {
+ timclk: clock-1000000 {
#clock-cells = <0>;
compatible = "fixed-factor-clock";
clock-div = <24>;
@@ -183,48 +183,8 @@
clocks = <&xtal24mhz>;
};
- mclk: mclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- kmiclk: kmiclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- sspclk: sspclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- uartclk: uartclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- wdogclk: wdogclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
/* FIXME: this actually hangs off the PLL clocks */
- pclk: pclk@0 {
+ pclk: clock-pclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <0>;
diff --git a/arch/arm/boot/dts/arm/arm-realview-pbx.dtsi b/arch/arm/boot/dts/arm/arm-realview-pbx.dtsi
index ec1507c5147c..e625403a9456 100644
--- a/arch/arm/boot/dts/arm/arm-realview-pbx.dtsi
+++ b/arch/arm/boot/dts/arm/arm-realview-pbx.dtsi
@@ -62,19 +62,19 @@
regulator-boot-on;
};
- xtal24mhz: xtal24mhz@24M {
+ xtal24mhz: mclk: kmiclk: sspclk: uartclk: wdogclk: clock-24000000 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
- refclk32khz: refclk32khz {
+ refclk32khz: clock-32768 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
};
- timclk: timclk@1M {
+ timclk: clock-1000000 {
#clock-cells = <0>;
compatible = "fixed-factor-clock";
clock-div = <24>;
@@ -82,48 +82,8 @@
clocks = <&xtal24mhz>;
};
- mclk: mclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- kmiclk: kmiclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- sspclk: sspclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- uartclk: uartclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
- wdogclk: wdogclk@24M {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
/* FIXME: this actually hangs off the PLL clocks */
- pclk: pclk@0 {
+ pclk: clock-pclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <0>;
diff --git a/arch/arm/boot/dts/arm/integratorap-im-pd1.dts b/arch/arm/boot/dts/arm/integratorap-im-pd1.dts
index 367850ea0912..db13e09f2fab 100644
--- a/arch/arm/boot/dts/arm/integratorap-im-pd1.dts
+++ b/arch/arm/boot/dts/arm/integratorap-im-pd1.dts
@@ -54,7 +54,7 @@
};
/* Also used for the Smart Card Interface SCI */
- impd1_uartclk: clock@1_4 {
+ impd1_uartclk: clock-uart {
compatible = "fixed-factor-clock";
#clock-cells = <0>;
clock-div = <4>;
@@ -64,7 +64,7 @@
};
/* For the SSP the clock is divided by 64 */
- impd1_sspclk: clock@1_64 {
+ impd1_sspclk: clock-ssp {
compatible = "fixed-factor-clock";
#clock-cells = <0>;
clock-div = <64>;
diff --git a/arch/arm/boot/dts/arm/integratorap.dts b/arch/arm/boot/dts/arm/integratorap.dts
index d9927d3181dc..9b6a1dbaf265 100644
--- a/arch/arm/boot/dts/arm/integratorap.dts
+++ b/arch/arm/boot/dts/arm/integratorap.dts
@@ -57,22 +57,14 @@
};
/* 24 MHz chrystal on the Integrator/AP development board */
- xtal24mhz: xtal24mhz@24M {
+ xtal24mhz: pclk: clock-24000000 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
- pclk: pclk@0 {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clock-div = <1>;
- clock-mult = <1>;
- clocks = <&xtal24mhz>;
- };
-
/* The UART clock is 14.74 MHz divided by an ICS525 */
- uartclk: [email protected] {
+ uartclk: clock-14745600 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <14745600>;
@@ -81,7 +73,7 @@
core-module@10000000 {
/* 24 MHz chrystal on the core module */
- cm24mhz: cm24mhz@24M {
+ cm24mhz: clock-24000000 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
diff --git a/arch/arm/boot/dts/arm/integratorcp.dts b/arch/arm/boot/dts/arm/integratorcp.dts
index c011333eb165..8ad1a8957ace 100644
--- a/arch/arm/boot/dts/arm/integratorcp.dts
+++ b/arch/arm/boot/dts/arm/integratorcp.dts
@@ -47,14 +47,14 @@
*/
/* The codec chrystal operates at 24.576 MHz */
- xtal_codec: [email protected] {
+ xtal_codec: clock-24576000 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24576000>;
};
/* The chrystal is divided by 2 by the codec for the AACI bit clock */
- aaci_bitclk: [email protected] {
+ aaci_bitclk: clock-12288000 {
#clock-cells = <0>;
compatible = "fixed-factor-clock";
clock-div = <2>;
@@ -63,21 +63,21 @@
};
/* This is a 25MHz chrystal on the base board */
- xtal25mhz: xtal25mhz@25M {
+ xtal25mhz: clock-25000000 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <25000000>;
};
/* The UART clock is 14.74 MHz divided from 25MHz by an ICS525 */
- uartclk: [email protected] {
+ uartclk: clock-14745600 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <14745600>;
};
/* Actually sysclk I think */
- pclk: pclk@0 {
+ pclk: clock-pclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <0>;
@@ -85,7 +85,7 @@
core-module@10000000 {
/* 24 MHz chrystal on the core module */
- cm24mhz: cm24mhz@24M {
+ cm24mhz: clock-24000000 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
@@ -131,7 +131,7 @@
};
/* The timer clock is the 24 MHz oscillator divided to 1MHz */
- timclk: timclk@1M {
+ timclk: clock-1000000 {
#clock-cells = <0>;
compatible = "fixed-factor-clock";
clock-div = <24>;
diff --git a/arch/arm/boot/dts/arm/mps2.dtsi b/arch/arm/boot/dts/arm/mps2.dtsi
index ce308820765b..e240bc8aa605 100644
--- a/arch/arm/boot/dts/arm/mps2.dtsi
+++ b/arch/arm/boot/dts/arm/mps2.dtsi
@@ -48,37 +48,37 @@
#address-cells = <1>;
#size-cells = <1>;
- oscclk0: clk-osc0 {
+ oscclk0: clock-50000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <50000000>;
};
- oscclk1: clk-osc1 {
+ oscclk1: clock-24576000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24576000>;
};
- oscclk2: clk-osc2 {
+ oscclk2: clock-25000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <25000000>;
};
- cfgclk: clk-cfg {
+ cfgclk: clock-5000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <5000000>;
};
- spicfgclk: clk-spicfg {
+ spicfgclk: clock-75000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <75000000>;
};
- sysclk: clk-sys {
+ sysclk: spiclcd: spicon: i2cclcd: i2caud: clock-sys {
compatible = "fixed-factor-clock";
clocks = <&oscclk0>;
#clock-cells = <0>;
@@ -86,7 +86,7 @@
clock-mult = <1>;
};
- audmclk: clk-audm {
+ audmclk: clk-12388000 {
compatible = "fixed-factor-clock";
clocks = <&oscclk1>;
#clock-cells = <0>;
@@ -94,7 +94,7 @@
clock-mult = <1>;
};
- audsclk: clk-auds {
+ audsclk: clk-3072000 {
compatible = "fixed-factor-clock";
clocks = <&oscclk1>;
#clock-cells = <0>;
@@ -102,38 +102,6 @@
clock-mult = <1>;
};
- spiclcd: clk-cpiclcd {
- compatible = "fixed-factor-clock";
- clocks = <&oscclk0>;
- #clock-cells = <0>;
- clock-div = <2>;
- clock-mult = <1>;
- };
-
- spicon: clk-spicon {
- compatible = "fixed-factor-clock";
- clocks = <&oscclk0>;
- #clock-cells = <0>;
- clock-div = <2>;
- clock-mult = <1>;
- };
-
- i2cclcd: clk-i2cclcd {
- compatible = "fixed-factor-clock";
- clocks = <&oscclk0>;
- #clock-cells = <0>;
- clock-div = <2>;
- clock-mult = <1>;
- };
-
- i2caud: clk-i2caud {
- compatible = "fixed-factor-clock";
- clocks = <&oscclk0>;
- #clock-cells = <0>;
- clock-div = <2>;
- clock-mult = <1>;
- };
-
soc {
compatible = "simple-bus";
ranges;
diff --git a/arch/arm/boot/dts/arm/versatile-ab.dts b/arch/arm/boot/dts/arm/versatile-ab.dts
index de45aa99e260..6fe6b49f5d8e 100644
--- a/arch/arm/boot/dts/arm/versatile-ab.dts
+++ b/arch/arm/boot/dts/arm/versatile-ab.dts
@@ -24,7 +24,7 @@
reg = <0x0 0x08000000>;
};
- xtal24mhz: xtal24mhz@24M {
+ xtal24mhz: clock-24000000 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
@@ -142,14 +142,14 @@
};
/* OSC1 on AB, OSC4 on PB */
- osc1: cm_aux_osc@24M {
+ osc1: clock-osc {
#clock-cells = <0>;
compatible = "arm,versatile-cm-auxosc";
clocks = <&xtal24mhz>;
};
/* The timer clock is the 24 MHz oscillator divided to 1MHz */
- timclk: timclk@1M {
+ timclk: clock-1000000 {
#clock-cells = <0>;
compatible = "fixed-factor-clock";
clock-div = <24>;
@@ -157,7 +157,7 @@
clocks = <&xtal24mhz>;
};
- pclk: pclk@24M {
+ pclk: clock-24000000 {
#clock-cells = <0>;
compatible = "fixed-factor-clock";
clock-div = <1>;
diff --git a/arch/arm/boot/dts/arm/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/arm/vexpress-v2m-rs1.dtsi
index 8af4b77fe655..158b3923eae3 100644
--- a/arch/arm/boot/dts/arm/vexpress-v2m-rs1.dtsi
+++ b/arch/arm/boot/dts/arm/vexpress-v2m-rs1.dtsi
@@ -20,7 +20,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
/ {
- v2m_fixed_3v3: fixed-regulator-0 {
+ v2m_fixed_3v3: regulator-3v3 {
compatible = "regulator-fixed";
regulator-name = "3V3";
regulator-min-microvolt = <3300000>;
@@ -28,21 +28,21 @@
regulator-always-on;
};
- v2m_clk24mhz: clk24mhz {
+ v2m_clk24mhz: clock-24000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>;
clock-output-names = "v2m:clk24mhz";
};
- v2m_refclk1mhz: refclk1mhz {
+ v2m_refclk1mhz: clock-1000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1000000>;
clock-output-names = "v2m:refclk1mhz";
};
- v2m_refclk32khz: refclk32khz {
+ v2m_refclk32khz: clock-32768 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
diff --git a/arch/arm/boot/dts/arm/vexpress-v2m.dtsi b/arch/arm/boot/dts/arm/vexpress-v2m.dtsi
index c5e92f6d2fcd..be03f2a8a57a 100644
--- a/arch/arm/boot/dts/arm/vexpress-v2m.dtsi
+++ b/arch/arm/boot/dts/arm/vexpress-v2m.dtsi
@@ -351,7 +351,7 @@
};
};
- v2m_fixed_3v3: fixed-regulator-0 {
+ v2m_fixed_3v3: regulator-3v3 {
compatible = "regulator-fixed";
regulator-name = "3V3";
regulator-min-microvolt = <3300000>;
@@ -359,21 +359,21 @@
regulator-always-on;
};
- v2m_clk24mhz: clk24mhz {
+ v2m_clk24mhz: clock-24000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>;
clock-output-names = "v2m:clk24mhz";
};
- v2m_refclk1mhz: refclk1mhz {
+ v2m_refclk1mhz: clock-1000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1000000>;
clock-output-names = "v2m:refclk1mhz";
};
- v2m_refclk32khz: refclk32khz {
+ v2m_refclk32khz: clock-32768 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
@@ -436,7 +436,7 @@
compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
- oscclk0 {
+ clock-controller-0 {
/* MCC static memory clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 0>;
@@ -445,7 +445,7 @@
clock-output-names = "v2m:oscclk0";
};
- v2m_oscclk1: oscclk1 {
+ v2m_oscclk1: clock-controller-1 {
/* CLCD clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 1>;
@@ -454,7 +454,7 @@
clock-output-names = "v2m:oscclk1";
};
- v2m_oscclk2: oscclk2 {
+ v2m_oscclk2: clock-controller-2 {
/* IO FPGA peripheral clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 2>;
@@ -463,7 +463,7 @@
clock-output-names = "v2m:oscclk2";
};
- volt-vio {
+ regulator-vio {
/* Logic level voltage */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 0>;
diff --git a/arch/arm/boot/dts/arm/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/arm/vexpress-v2p-ca15-tc1.dts
index 679537e17ff5..5a91e936edef 100644
--- a/arch/arm/boot/dts/arm/vexpress-v2p-ca15-tc1.dts
+++ b/arch/arm/boot/dts/arm/vexpress-v2p-ca15-tc1.dts
@@ -142,7 +142,7 @@
compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
- oscclk0 {
+ clock-controller-0 {
/* CPU PLL reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 0>;
@@ -151,7 +151,7 @@
clock-output-names = "oscclk0";
};
- oscclk4 {
+ clock-controller-4 {
/* Multiplexed AXI master clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 4>;
@@ -160,7 +160,7 @@
clock-output-names = "oscclk4";
};
- hdlcd_clk: oscclk5 {
+ hdlcd_clk: clock-controller-5 {
/* HDLCD PLL reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 5>;
@@ -169,7 +169,7 @@
clock-output-names = "oscclk5";
};
- smbclk: oscclk6 {
+ smbclk: clock-controller-6 {
/* SMB clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 6>;
@@ -178,7 +178,7 @@
clock-output-names = "oscclk6";
};
- sys_pll: oscclk7 {
+ sys_pll: clock-controller-7 {
/* SYS PLL reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 7>;
@@ -187,7 +187,7 @@
clock-output-names = "oscclk7";
};
- oscclk8 {
+ clock-controller-8 {
/* DDR2 PLL reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 8>;
@@ -196,7 +196,7 @@
clock-output-names = "oscclk8";
};
- volt-cores {
+ regulator-cores {
/* CPU core voltage */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 0>;
diff --git a/arch/arm/boot/dts/arm/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/arm/vexpress-v2p-ca15_a7.dts
index 511e87cc2bc5..6ef23c53d2d8 100644
--- a/arch/arm/boot/dts/arm/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/arm/vexpress-v2p-ca15_a7.dts
@@ -253,7 +253,7 @@
compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
- oscclk0 {
+ clock-controller-0 {
/* A15 PLL 0 reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 0>;
@@ -262,7 +262,7 @@
clock-output-names = "oscclk0";
};
- oscclk1 {
+ clock-controller-1 {
/* A15 PLL 1 reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 1>;
@@ -271,7 +271,7 @@
clock-output-names = "oscclk1";
};
- oscclk2 {
+ clock-controller-2 {
/* A7 PLL 0 reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 2>;
@@ -280,7 +280,7 @@
clock-output-names = "oscclk2";
};
- oscclk3 {
+ clock-controller-3 {
/* A7 PLL 1 reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 3>;
@@ -289,7 +289,7 @@
clock-output-names = "oscclk3";
};
- oscclk4 {
+ clock-controller-4 {
/* External AXI master clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 4>;
@@ -298,7 +298,7 @@
clock-output-names = "oscclk4";
};
- hdlcd_clk: oscclk5 {
+ hdlcd_clk: clock-controller-5 {
/* HDLCD PLL reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 5>;
@@ -307,7 +307,7 @@
clock-output-names = "oscclk5";
};
- smbclk: oscclk6 {
+ smbclk: clock-controller-6 {
/* Static memory controller clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 6>;
@@ -316,7 +316,7 @@
clock-output-names = "oscclk6";
};
- oscclk7 {
+ clock-controller-7 {
/* SYS PLL reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 7>;
@@ -325,7 +325,7 @@
clock-output-names = "oscclk7";
};
- oscclk8 {
+ clock-controller-8 {
/* DDR2 PLL reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 8>;
@@ -334,7 +334,7 @@
clock-output-names = "oscclk8";
};
- volt-a15 {
+ regulator-a15 {
/* A15 CPU core voltage */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 0>;
@@ -345,7 +345,7 @@
label = "A15 Vcore";
};
- volt-a7 {
+ regulator-a7 {
/* A7 CPU core voltage */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 1>;
diff --git a/arch/arm/boot/dts/arm/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/arm/vexpress-v2p-ca5s.dts
index ff1f9a1bcfcf..e3896253f33e 100644
--- a/arch/arm/boot/dts/arm/vexpress-v2p-ca5s.dts
+++ b/arch/arm/boot/dts/arm/vexpress-v2p-ca5s.dts
@@ -145,7 +145,7 @@
compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
- cpu_clk: oscclk0 {
+ cpu_clk: clock-controller-0 {
/* CPU and internal AXI reference clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 0>;
@@ -154,7 +154,7 @@
clock-output-names = "oscclk0";
};
- axi_clk: oscclk1 {
+ axi_clk: clock-controller-1 {
/* Multiplexed AXI master clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 1>;
@@ -163,7 +163,7 @@
clock-output-names = "oscclk1";
};
- oscclk2 {
+ clock-controller-2 {
/* DDR2 */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 2>;
@@ -172,7 +172,7 @@
clock-output-names = "oscclk2";
};
- hdlcd_clk: oscclk3 {
+ hdlcd_clk: clock-controller-3 {
/* HDLCD */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 3>;
@@ -181,7 +181,7 @@
clock-output-names = "oscclk3";
};
- oscclk4 {
+ clock-controller-4 {
/* Test chip gate configuration */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 4>;
@@ -190,7 +190,7 @@
clock-output-names = "oscclk4";
};
- smbclk: oscclk5 {
+ smbclk: clock-controller-5 {
/* SMB clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 5>;
diff --git a/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dts
index 8bf35666412b..43a5a4ab6ff0 100644
--- a/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dts
+++ b/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dts
@@ -187,7 +187,7 @@
compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
- oscclk0: extsaxiclk {
+ oscclk0: clock-controller-0 {
/* ACLK clock to the AXI master port on the test chip */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 0>;
@@ -196,7 +196,7 @@
clock-output-names = "extsaxiclk";
};
- oscclk1: clcdclk {
+ oscclk1: clock-controller-1 {
/* Reference clock for the CLCD */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 1>;
@@ -205,7 +205,7 @@
clock-output-names = "clcdclk";
};
- smbclk: oscclk2: tcrefclk {
+ smbclk: oscclk2: clock-controller-2 {
/* Reference clock for the test chip internal PLLs */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 2>;
@@ -214,7 +214,7 @@
clock-output-names = "tcrefclk";
};
- volt-vd10 {
+ regulator-vd10 {
/* Test Chip internal logic voltage */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 0>;
@@ -223,7 +223,7 @@
label = "VD10";
};
- volt-vd10-s2 {
+ regulator-vd10-s2 {
/* PL310, L2 cache, RAM cell supply (not PL310 logic) */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 1>;
@@ -232,7 +232,7 @@
label = "VD10_S2";
};
- volt-vd10-s3 {
+ regulator-vd10-s3 {
/* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 2>;
@@ -241,7 +241,7 @@
label = "VD10_S3";
};
- volt-vcc1v8 {
+ regulator-vcc1v8 {
/* DDR2 SDRAM and Test Chip DDR2 I/O supply */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 3>;
@@ -250,7 +250,7 @@
label = "VCC1V8";
};
- volt-ddr2vtt {
+ regulator-ddr2vtt {
/* DDR2 SDRAM VTT termination voltage */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 4>;
@@ -259,7 +259,7 @@
label = "DDR2VTT";
};
- volt-vcc3v3 {
+ regulator-vcc3v3 {
/* Local board supply for miscellaneous logic external to the Test Chip */
arm,vexpress-sysreg,func = <2 5>;
compatible = "arm,vexpress-volt";
diff --git a/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi
index 857cb26ed6d7..c669ec202085 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi
@@ -463,7 +463,7 @@
interrupt-controller;
};
- i2c0: i2c-bus@40 {
+ i2c0: i2c@40 {
#address-cells = <1>;
#size-cells = <0>;
@@ -478,7 +478,7 @@
/* Does not need pinctrl properties */
};
- i2c1: i2c-bus@80 {
+ i2c1: i2c@80 {
#address-cells = <1>;
#size-cells = <0>;
@@ -493,7 +493,7 @@
/* Does not need pinctrl properties */
};
- i2c2: i2c-bus@c0 {
+ i2c2: i2c@c0 {
#address-cells = <1>;
#size-cells = <0>;
@@ -509,7 +509,7 @@
status = "disabled";
};
- i2c3: i2c-bus@100 {
+ i2c3: i2c@100 {
#address-cells = <1>;
#size-cells = <0>;
@@ -525,7 +525,7 @@
status = "disabled";
};
- i2c4: i2c-bus@140 {
+ i2c4: i2c@140 {
#address-cells = <1>;
#size-cells = <0>;
@@ -541,7 +541,7 @@
status = "disabled";
};
- i2c5: i2c-bus@180 {
+ i2c5: i2c@180 {
#address-cells = <1>;
#size-cells = <0>;
@@ -557,7 +557,7 @@
status = "disabled";
};
- i2c6: i2c-bus@1c0 {
+ i2c6: i2c@1c0 {
#address-cells = <1>;
#size-cells = <0>;
@@ -573,7 +573,7 @@
status = "disabled";
};
- i2c7: i2c-bus@300 {
+ i2c7: i2c@300 {
#address-cells = <1>;
#size-cells = <0>;
@@ -589,7 +589,7 @@
status = "disabled";
};
- i2c8: i2c-bus@340 {
+ i2c8: i2c@340 {
#address-cells = <1>;
#size-cells = <0>;
@@ -605,7 +605,7 @@
status = "disabled";
};
- i2c9: i2c-bus@380 {
+ i2c9: i2c@380 {
#address-cells = <1>;
#size-cells = <0>;
@@ -621,7 +621,7 @@
status = "disabled";
};
- i2c10: i2c-bus@3c0 {
+ i2c10: i2c@3c0 {
#address-cells = <1>;
#size-cells = <0>;
@@ -637,7 +637,7 @@
status = "disabled";
};
- i2c11: i2c-bus@400 {
+ i2c11: i2c@400 {
#address-cells = <1>;
#size-cells = <0>;
@@ -653,7 +653,7 @@
status = "disabled";
};
- i2c12: i2c-bus@440 {
+ i2c12: i2c@440 {
#address-cells = <1>;
#size-cells = <0>;
@@ -669,7 +669,7 @@
status = "disabled";
};
- i2c13: i2c-bus@480 {
+ i2c13: i2c@480 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi
index e6f3cf3c721e..6e05cbcce49c 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi
@@ -592,7 +592,7 @@
interrupt-controller;
};
- i2c0: i2c-bus@40 {
+ i2c0: i2c@40 {
#address-cells = <1>;
#size-cells = <0>;
@@ -607,7 +607,7 @@
/* Does not need pinctrl properties */
};
- i2c1: i2c-bus@80 {
+ i2c1: i2c@80 {
#address-cells = <1>;
#size-cells = <0>;
@@ -622,7 +622,7 @@
/* Does not need pinctrl properties */
};
- i2c2: i2c-bus@c0 {
+ i2c2: i2c@c0 {
#address-cells = <1>;
#size-cells = <0>;
@@ -638,7 +638,7 @@
status = "disabled";
};
- i2c3: i2c-bus@100 {
+ i2c3: i2c@100 {
#address-cells = <1>;
#size-cells = <0>;
@@ -654,7 +654,7 @@
status = "disabled";
};
- i2c4: i2c-bus@140 {
+ i2c4: i2c@140 {
#address-cells = <1>;
#size-cells = <0>;
@@ -670,7 +670,7 @@
status = "disabled";
};
- i2c5: i2c-bus@180 {
+ i2c5: i2c@180 {
#address-cells = <1>;
#size-cells = <0>;
@@ -686,7 +686,7 @@
status = "disabled";
};
- i2c6: i2c-bus@1c0 {
+ i2c6: i2c@1c0 {
#address-cells = <1>;
#size-cells = <0>;
@@ -702,7 +702,7 @@
status = "disabled";
};
- i2c7: i2c-bus@300 {
+ i2c7: i2c@300 {
#address-cells = <1>;
#size-cells = <0>;
@@ -718,7 +718,7 @@
status = "disabled";
};
- i2c8: i2c-bus@340 {
+ i2c8: i2c@340 {
#address-cells = <1>;
#size-cells = <0>;
@@ -734,7 +734,7 @@
status = "disabled";
};
- i2c9: i2c-bus@380 {
+ i2c9: i2c@380 {
#address-cells = <1>;
#size-cells = <0>;
@@ -750,7 +750,7 @@
status = "disabled";
};
- i2c10: i2c-bus@3c0 {
+ i2c10: i2c@3c0 {
#address-cells = <1>;
#size-cells = <0>;
@@ -766,7 +766,7 @@
status = "disabled";
};
- i2c11: i2c-bus@400 {
+ i2c11: i2c@400 {
#address-cells = <1>;
#size-cells = <0>;
@@ -782,7 +782,7 @@
status = "disabled";
};
- i2c12: i2c-bus@440 {
+ i2c12: i2c@440 {
#address-cells = <1>;
#size-cells = <0>;
@@ -798,7 +798,7 @@
status = "disabled";
};
- i2c13: i2c-bus@480 {
+ i2c13: i2c@480 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
index 7fb421153596..0c00882f111a 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
@@ -905,7 +905,7 @@
#include "aspeed-g6-pinctrl.dtsi"
&i2c {
- i2c0: i2c-bus@80 {
+ i2c0: i2c@80 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x80 0x80>;
@@ -919,7 +919,7 @@
status = "disabled";
};
- i2c1: i2c-bus@100 {
+ i2c1: i2c@100 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x100 0x80>;
@@ -933,7 +933,7 @@
status = "disabled";
};
- i2c2: i2c-bus@180 {
+ i2c2: i2c@180 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x180 0x80>;
@@ -947,7 +947,7 @@
status = "disabled";
};
- i2c3: i2c-bus@200 {
+ i2c3: i2c@200 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x200 0x80>;
@@ -961,7 +961,7 @@
status = "disabled";
};
- i2c4: i2c-bus@280 {
+ i2c4: i2c@280 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x280 0x80>;
@@ -975,7 +975,7 @@
status = "disabled";
};
- i2c5: i2c-bus@300 {
+ i2c5: i2c@300 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x300 0x80>;
@@ -989,7 +989,7 @@
status = "disabled";
};
- i2c6: i2c-bus@380 {
+ i2c6: i2c@380 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x380 0x80>;
@@ -1003,7 +1003,7 @@
status = "disabled";
};
- i2c7: i2c-bus@400 {
+ i2c7: i2c@400 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x400 0x80>;
@@ -1017,7 +1017,7 @@
status = "disabled";
};
- i2c8: i2c-bus@480 {
+ i2c8: i2c@480 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x480 0x80>;
@@ -1031,7 +1031,7 @@
status = "disabled";
};
- i2c9: i2c-bus@500 {
+ i2c9: i2c@500 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x500 0x80>;
@@ -1045,7 +1045,7 @@
status = "disabled";
};
- i2c10: i2c-bus@580 {
+ i2c10: i2c@580 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x580 0x80>;
@@ -1059,7 +1059,7 @@
status = "disabled";
};
- i2c11: i2c-bus@600 {
+ i2c11: i2c@600 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x600 0x80>;
@@ -1073,7 +1073,7 @@
status = "disabled";
};
- i2c12: i2c-bus@680 {
+ i2c12: i2c@680 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x680 0x80>;
@@ -1087,7 +1087,7 @@
status = "disabled";
};
- i2c13: i2c-bus@700 {
+ i2c13: i2c@700 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x700 0x80>;
@@ -1101,7 +1101,7 @@
status = "disabled";
};
- i2c14: i2c-bus@780 {
+ i2c14: i2c@780 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x780 0x80>;
@@ -1115,7 +1115,7 @@
status = "disabled";
};
- i2c15: i2c-bus@800 {
+ i2c15: i2c@800 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x800 0x80>;
diff --git a/arch/arm/boot/dts/cirrus/ep7211-edb7211.dts b/arch/arm/boot/dts/cirrus/ep7211-edb7211.dts
index 7fb532f227af..808cd5778e27 100644
--- a/arch/arm/boot/dts/cirrus/ep7211-edb7211.dts
+++ b/arch/arm/boot/dts/cirrus/ep7211-edb7211.dts
@@ -30,7 +30,7 @@
display-timings {
native-mode = <&timing0>;
- timing0: 320x240 {
+ timing0: timing-320x240 {
hactive = <320>;
hback-porch = <0>;
hfront-porch = <0>;
diff --git a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts
index 2eec5f63d399..2f7c34c649ea 100644
--- a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts
+++ b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts
@@ -90,11 +90,18 @@
timeout-ms = <5000>;
};
- gpio-beeper {
- compatible = "gpio-beeper";
+ gpio_pwm: pwm {
+ #pwm-cells = <3>;
+ compatible = "pwm-gpio";
gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
};
+ beeper {
+ compatible = "pwm-beeper";
+ pwms = <&gpio_pwm 0 1 0>;
+ beeper-hz = <1000>;
+ };
+
soc {
bus@c4000000 {
/* The first 16MB region at CS0 on the expansion bus */
diff --git a/arch/arm/boot/dts/marvell/armada-370-xp.dtsi b/arch/arm/boot/dts/marvell/armada-370-xp.dtsi
index 0b8c2a64b36f..954c891e5aee 100644
--- a/arch/arm/boot/dts/marvell/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/marvell/armada-370-xp.dtsi
@@ -168,7 +168,6 @@
mpic: interrupt-controller@20a00 {
compatible = "marvell,mpic";
#interrupt-cells = <1>;
- #size-cells = <1>;
interrupt-controller;
msi-controller;
};
diff --git a/arch/arm/boot/dts/marvell/armada-375.dtsi b/arch/arm/boot/dts/marvell/armada-375.dtsi
index ddc49547d786..99778b4b7e7b 100644
--- a/arch/arm/boot/dts/marvell/armada-375.dtsi
+++ b/arch/arm/boot/dts/marvell/armada-375.dtsi
@@ -376,7 +376,6 @@
compatible = "marvell,mpic";
reg = <0x20a00 0x2d0>, <0x21070 0x58>;
#interrupt-cells = <1>;
- #size-cells = <1>;
interrupt-controller;
msi-controller;
interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/boot/dts/marvell/armada-385-atl-x530.dts b/arch/arm/boot/dts/marvell/armada-385-atl-x530.dts
index 5a9ab8410b7b..2fb7304039be 100644
--- a/arch/arm/boot/dts/marvell/armada-385-atl-x530.dts
+++ b/arch/arm/boot/dts/marvell/armada-385-atl-x530.dts
@@ -43,6 +43,17 @@
};
};
};
+
+ led-7seg {
+ compatible = "gpio-7-segment";
+ segment-gpios = <&led_7seg_gpio 0 GPIO_ACTIVE_LOW>,
+ <&led_7seg_gpio 1 GPIO_ACTIVE_LOW>,
+ <&led_7seg_gpio 2 GPIO_ACTIVE_LOW>,
+ <&led_7seg_gpio 3 GPIO_ACTIVE_LOW>,
+ <&led_7seg_gpio 4 GPIO_ACTIVE_LOW>,
+ <&led_7seg_gpio 5 GPIO_ACTIVE_LOW>,
+ <&led_7seg_gpio 6 GPIO_ACTIVE_LOW>;
+ };
};
&pciec {
@@ -149,7 +160,7 @@
#size-cells = <0>;
reg = <3>;
- gpio@20 {
+ led_7seg_gpio: gpio@20 {
compatible = "nxp,pca9554";
gpio-controller;
#gpio-cells = <2>;
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 7b755bb4e4e7..43202890c959 100644
--- a/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts
+++ b/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts
@@ -112,6 +112,19 @@
status = "disabled";
};
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ front-button {
+ label = "Front Button";
+ linux,code = <KEY_VENDOR>;
+ linux,can-disable;
+ gpios = <&mcu 0 12 GPIO_ACTIVE_HIGH>;
+ /* debouncing is done by the microcontroller */
+ debounce-interval = <0>;
+ };
+ };
+
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "SPDIF";
@@ -218,7 +231,22 @@
#size-cells = <0>;
reg = <0>;
- /* STM32F0 command interface at address 0x2a */
+ mcu: system-controller@2a {
+ compatible = "cznic,turris-omnia-mcu";
+ reg = <0x2a>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_pins>;
+
+ interrupt-parent = <&gpio1>;
+ interrupts = <11 IRQ_TYPE_NONE>;
+
+ gpio-controller;
+ #gpio-cells = <3>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
led-controller@2b {
compatible = "cznic,turris-omnia-leds";
@@ -501,6 +529,11 @@
};
&pinctrl {
+ mcu_pins: mcu-pins {
+ marvell,pins = "mpp43";
+ marvell,function = "gpio";
+ };
+
pcawan_pins: pcawan-pins {
marvell,pins = "mpp46";
marvell,function = "gpio";
diff --git a/arch/arm/boot/dts/marvell/armada-38x.dtsi b/arch/arm/boot/dts/marvell/armada-38x.dtsi
index 446861b6b17b..1181b13deabc 100644
--- a/arch/arm/boot/dts/marvell/armada-38x.dtsi
+++ b/arch/arm/boot/dts/marvell/armada-38x.dtsi
@@ -408,7 +408,6 @@
compatible = "marvell,mpic";
reg = <0x20a00 0x2d0>, <0x21070 0x58>;
#interrupt-cells = <1>;
- #size-cells = <1>;
interrupt-controller;
msi-controller;
interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/boot/dts/marvell/armada-39x.dtsi b/arch/arm/boot/dts/marvell/armada-39x.dtsi
index 9d1cac49c022..6d05835efb42 100644
--- a/arch/arm/boot/dts/marvell/armada-39x.dtsi
+++ b/arch/arm/boot/dts/marvell/armada-39x.dtsi
@@ -268,7 +268,6 @@
compatible = "marvell,mpic";
reg = <0x20a00 0x2d0>, <0x21070 0x58>;
#interrupt-cells = <1>;
- #size-cells = <1>;
interrupt-controller;
msi-controller;
interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-blackarmor-nas220.dts b/arch/arm/boot/dts/marvell/kirkwood-blackarmor-nas220.dts
index 07fbfca444d5..36b90c632fd6 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-blackarmor-nas220.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-blackarmor-nas220.dts
@@ -35,13 +35,13 @@
gpio_keys {
compatible = "gpio-keys";
- reset {
+ button-reset {
label = "Reset";
linux,code = <KEY_POWER>;
gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
};
- button {
+ button-power {
label = "Power";
linux,code = <KEY_SLEEP>;
gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
@@ -51,7 +51,7 @@
gpio-leds {
compatible = "gpio-leds";
- blue-power {
+ led-blue-power {
label = "nas220:blue:power";
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
diff --git a/arch/arm/boot/dts/marvell/kirkwood-c200-v1.dts b/arch/arm/boot/dts/marvell/kirkwood-c200-v1.dts
index f59ff7578dfc..7e3ee64d4bdf 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-c200-v1.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-c200-v1.dts
@@ -29,25 +29,25 @@
pinctrl-0 = <&pmx_buttons>;
pinctrl-names = "default";
- power {
+ button-power {
label = "Power Button";
linux,code = <KEY_POWER>;
gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
};
- reset {
+ button-reset {
label = "Reset Button";
linux,code = <KEY_RESTART>;
gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
};
- usb1 {
+ button-usb1 {
label = "USB1 Button";
linux,code = <BTN_0>;
gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
};
- usb2 {
+ button-usb2 {
label = "USB2 Button";
linux,code = <BTN_1>;
gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-cloudbox.dts b/arch/arm/boot/dts/marvell/kirkwood-cloudbox.dts
index 448b0cd23b5f..151edcd140a0 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-cloudbox.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-cloudbox.dts
@@ -58,10 +58,8 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- power {
+ key-power {
label = "Power push button";
linux,code = <KEY_POWER>;
gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
@@ -71,11 +69,11 @@
gpio-leds {
compatible = "gpio-leds";
- red-fail {
+ led-red-fail {
label = "cloudbox:red:fail";
gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
};
- blue-sata {
+ led-blue-sata {
label = "cloudbox:blue:sata";
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-d2net.dts b/arch/arm/boot/dts/marvell/kirkwood-d2net.dts
index bd3b266dd766..fcce8730d3e3 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-d2net.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-d2net.dts
@@ -37,7 +37,7 @@
gpio-leds {
compatible = "gpio-leds";
- red-fail {
+ led-red-fail {
label = "d2net_v2:red:fail";
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-dir665.dts b/arch/arm/boot/dts/marvell/kirkwood-dir665.dts
index 0c0851cd9bec..2f6793f794cd 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-dir665.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-dir665.dts
@@ -137,38 +137,38 @@
gpio-leds {
compatible = "gpio-leds";
- blue-usb {
+ led-blue-usb {
label = "dir665:blue:usb";
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
};
- blue-internet {
+ led-blue-internet {
/* Can only be turned on if the Internet
* Ethernet port has Link
*/
label = "dir665:blue:internet";
gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
};
- amber-internet {
+ led-amber-internet {
label = "dir665:amber:internet";
gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
};
- blue-wifi5g {
+ led-blue-wifi5g {
label = "dir665:blue:5g";
gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
};
- blue-status {
+ led-blue-status {
label = "dir665:blue:status";
gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
};
- blue-wps {
+ led-blue-wps {
label = "dir665:blue:wps";
gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
};
- amber-status {
+ led-amber-status {
label = "dir665:amber:status";
gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
};
- blue-24g {
+ led-blue-24g {
label = "dir665:blue:24g";
gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
};
@@ -176,15 +176,13 @@
gpio-keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- reset {
+ button-reset {
label = "reset";
linux,code = <KEY_RESTART>;
gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
};
- wps {
+ button-wps {
label = "wps";
linux,code = <KEY_WPS_BUTTON>;
gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-dns320.dts b/arch/arm/boot/dts/marvell/kirkwood-dns320.dts
index d6b0f418fd01..d8279e0c4c4f 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-dns320.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-dns320.dts
@@ -24,24 +24,24 @@
&pmx_led_white_usb>;
pinctrl-names = "default";
- blue-power {
+ led-blue-power {
label = "dns320:blue:power";
gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
- blue-usb {
+ led-blue-usb {
label = "dns320:blue:usb";
gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
};
- orange-l_hdd {
+ led-orange-l_hdd {
label = "dns320:orange:l_hdd";
gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
};
- orange-r_hdd {
+ led-orange-r_hdd {
label = "dns320:orange:r_hdd";
gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
};
- orange-usb {
+ led-orange-usb {
label = "dns320:orange:usb";
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; /* GPIO 35 */
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-dns325.dts b/arch/arm/boot/dts/marvell/kirkwood-dns325.dts
index 94d9c06cbbf5..7f396195e977 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-dns325.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-dns325.dts
@@ -24,24 +24,24 @@
&pmx_led_white_usb>;
pinctrl-names = "default";
- white-power {
+ led-white-power {
label = "dns325:white:power";
gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
- white-usb {
+ led-white-usb {
label = "dns325:white:usb";
gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; /* GPIO 43 */
};
- red-l_hdd {
+ led-red-l_hdd {
label = "dns325:red:l_hdd";
gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
};
- red-r_hdd {
+ led-red-r_hdd {
label = "dns325:red:r_hdd";
gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
};
- red-usb {
+ led-red-usb {
label = "dns325:red:usb";
gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-dnskw.dtsi b/arch/arm/boot/dts/marvell/kirkwood-dnskw.dtsi
index 0738eb679fcd..20bcd031f3f5 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-dnskw.dtsi
+++ b/arch/arm/boot/dts/marvell/kirkwood-dnskw.dtsi
@@ -8,23 +8,21 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_button_power &pmx_button_unmount
&pmx_button_reset>;
pinctrl-names = "default";
- power {
+ button-power {
label = "Power button";
linux,code = <KEY_POWER>;
gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
};
- eject {
+ button-eject {
label = "USB unmount button";
linux,code = <KEY_EJECTCD>;
gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
};
- reset {
+ button-reset {
label = "Reset button";
linux,code = <KEY_RESTART>;
gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-dockstar.dts b/arch/arm/boot/dts/marvell/kirkwood-dockstar.dts
index 264938dfa4d9..090f1e2e5bb6 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-dockstar.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-dockstar.dts
@@ -42,12 +42,12 @@
pinctrl-0 = <&pmx_led_green &pmx_led_orange>;
pinctrl-names = "default";
- health {
+ led-health {
label = "status:green:health";
gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
- fault {
+ led-fault {
label = "status:orange:fault";
gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-dreamplug.dts b/arch/arm/boot/dts/marvell/kirkwood-dreamplug.dts
index 328516351e84..590bee3c561c 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-dreamplug.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-dreamplug.dts
@@ -85,15 +85,15 @@
&pmx_led_wifi_ap >;
pinctrl-names = "default";
- bluetooth {
+ led-bluetooth {
label = "dreamplug:blue:bluetooth";
gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
};
- wifi {
+ led-wifi {
label = "dreamplug:green:wifi";
gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
};
- wifi-ap {
+ led-wifi-ap {
label = "dreamplug:green:wifi_ap";
gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-goflexnet.dts b/arch/arm/boot/dts/marvell/kirkwood-goflexnet.dts
index d4cb3cd3e2a2..d5ac4e3974da 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-goflexnet.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-goflexnet.dts
@@ -85,44 +85,44 @@
>;
pinctrl-names = "default";
- health {
+ led-health {
label = "status:green:health";
gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
- fault {
+ led-fault {
label = "status:orange:fault";
gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
};
- left0 {
+ led-left0 {
label = "status:white:left0";
gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
};
- left1 {
+ led-left1 {
label = "status:white:left1";
gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
};
- left2 {
+ led-left2 {
label = "status:white:left2";
gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
};
- left3 {
+ led-left3 {
label = "status:white:left3";
gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
};
- right0 {
+ led-right0 {
label = "status:white:right0";
gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
};
- right1 {
+ led-right1 {
label = "status:white:right1";
gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
};
- right2 {
+ led-right2 {
label = "status:white:right2";
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
};
- right3 {
+ led-right3 {
label = "status:white:right3";
gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-guruplug-server-plus.dts b/arch/arm/boot/dts/marvell/kirkwood-guruplug-server-plus.dts
index dfb41393941d..d5aa8b505cc0 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-guruplug-server-plus.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-guruplug-server-plus.dts
@@ -59,19 +59,19 @@
&pmx_led_wmode_r &pmx_led_wmode_g >;
pinctrl-names = "default";
- health-r {
+ led-health-r {
label = "guruplug:red:health";
gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
};
- health-g {
+ led-health-g {
label = "guruplug:green:health";
gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
};
- wmode-r {
+ led-wmode-r {
label = "guruplug:red:wmode";
gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
};
- wmode-g {
+ led-wmode-g {
label = "guruplug:green:wmode";
gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-ib62x0.dts b/arch/arm/boot/dts/marvell/kirkwood-ib62x0.dts
index 962a910a6f5c..018c6b8f3e8a 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-ib62x0.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-ib62x0.dts
@@ -58,17 +58,15 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_button_reset &pmx_button_usb_copy>;
pinctrl-names = "default";
- copy {
+ button-copy {
label = "USB Copy";
linux,code = <KEY_COPY>;
gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
};
- reset {
+ button-reset {
label = "Reset";
linux,code = <KEY_RESTART>;
gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
@@ -81,16 +79,16 @@
&pmx_led_usb_transfer>;
pinctrl-names = "default";
- green-os {
+ led-green-os {
label = "ib62x0:green:os";
gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
default-state = "keep";
};
- red-os {
+ led-red-os {
label = "ib62x0:red:os";
gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;
};
- usb-copy {
+ led-usb-copy {
label = "ib62x0:red:usb_copy";
gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-iconnect.dts b/arch/arm/boot/dts/marvell/kirkwood-iconnect.dts
index aed20185fd7a..91b46e77e0b6 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-iconnect.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-iconnect.dts
@@ -89,32 +89,32 @@
gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
default-state = "on";
};
- power-blue {
+ led-power-blue {
label = "power:blue";
gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
default-state = "keep";
};
- power-red {
+ led-power-red {
label = "power:red";
gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
};
- usb1 {
+ led-usb1 {
label = "usb1:blue";
gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
};
- usb2 {
+ led-usb2 {
label = "usb2:blue";
gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
};
- usb3 {
+ led-usb3 {
label = "usb3:blue";
gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
};
- usb4 {
+ led-usb4 {
label = "usb4:blue";
gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
};
- otb {
+ led-otb {
label = "otb:blue";
gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
};
@@ -122,18 +122,16 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = < &pmx_button_reset &pmx_button_otb >;
pinctrl-names = "default";
- otb {
+ button-otb {
label = "OTB Button";
linux,code = <KEY_COPY>;
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
- reset {
+ button-reset {
label = "Reset";
linux,code = <KEY_RESTART>;
gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/marvell/kirkwood-iomega_ix2_200.dts
index 2338f495d517..039362152650 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-iomega_ix2_200.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-iomega_ix2_200.dts
@@ -127,44 +127,42 @@
&pmx_led_rebuild &pmx_led_health >;
pinctrl-names = "default";
- power_led {
+ led-power-led {
label = "status:white:power_led";
gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
default-state = "keep";
};
- rebuild_led {
+ led-rebuild-led {
label = "status:white:rebuild_led";
gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
};
- health_led {
+ led-health-led {
label = "status:red:health_led";
gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
};
- backup_led {
+ led-backup-led {
label = "status:blue:backup_led";
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
};
};
gpio-keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_button_reset &pmx_button_power
&pmx_button_otb>;
pinctrl-names = "default";
- Power {
+ button-power {
label = "Power Button";
linux,code = <KEY_POWER>;
gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
};
- Reset {
+ button-reset {
label = "Reset Button";
linux,code = <KEY_RESTART>;
gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
};
- OTB {
+ button-otb {
label = "OTB Button";
linux,code = <KEY_COPY>;
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-l-50.dts b/arch/arm/boot/dts/marvell/kirkwood-l-50.dts
index c841eb8e7fb1..974bc9de4702 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-l-50.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-l-50.dts
@@ -97,52 +97,52 @@
leds {
compatible = "gpio-leds";
- status_green {
+ led-status-green {
label = "l-50:green:status";
gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
};
- status_red {
+ led-status-red {
label = "l-50:red:status";
gpios = <&gpio3 2 GPIO_ACTIVE_LOW>;
};
- wifi {
+ led-wifi {
label = "l-50:green:wifi";
gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;
linux,default-trigger = "phy0tpt";
};
- internet_green {
+ led-internet-green {
label = "l-50:green:internet";
gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
};
- internet_red {
+ led-internet-red {
label = "l-50:red:internet";
gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
};
- usb1_green {
+ led-usb1-green {
label = "l-50:green:usb1";
gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "usbport";
trigger-sources = <&hub_port3>;
};
- usb1_red {
+ led-usb1-red {
label = "l-50:red:usb1";
gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
};
- usb2_green {
+ led-usb2-green {
label = "l-50:green:usb2";
gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
linux,default-trigger = "usbport";
trigger-sources = <&hub_port1>;
};
- usb2_red {
+ led-usb2-red {
label = "l-50:red:usb2";
gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
};
@@ -193,7 +193,7 @@
keys {
compatible = "gpio-keys";
- factory_defaults {
+ button-factory-defaults {
label = "factory_defaults";
gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-laplug.dts b/arch/arm/boot/dts/marvell/kirkwood-laplug.dts
index 8c2b540eaf4f..90ea6cdee8e0 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-laplug.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-laplug.dts
@@ -51,7 +51,7 @@
gpio_keys {
compatible = "gpio-keys";
- power {
+ button-power {
label = "Power push button";
linux,code = <KEY_POWER>;
gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
@@ -61,11 +61,11 @@
gpio-leds {
compatible = "gpio-leds";
- red-fail {
+ led-red-fail {
label = "laplug_v2:red:power";
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
};
- blue-power {
+ led-blue-power {
label = "laplug_v2:blue:power";
gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
diff --git a/arch/arm/boot/dts/marvell/kirkwood-linkstation.dtsi b/arch/arm/boot/dts/marvell/kirkwood-linkstation.dtsi
index b54c9980f636..8a11d2b9d449 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-linkstation.dtsi
+++ b/arch/arm/boot/dts/marvell/kirkwood-linkstation.dtsi
@@ -88,8 +88,6 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_button_function &pmx_power_switch
&pmx_power_auto_switch>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/marvell/kirkwood-linksys-viper.dts b/arch/arm/boot/dts/marvell/kirkwood-linksys-viper.dts
index 27fd6e2337d5..8a1c38ab6111 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-linksys-viper.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-linksys-viper.dts
@@ -33,18 +33,16 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = < &pmx_btn_wps &pmx_btn_reset >;
pinctrl-names = "default";
- wps {
+ button-wps {
label = "WPS Button";
linux,code = <KEY_WPS_BUTTON>;
gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
};
- reset {
+ button-reset {
label = "Reset Button";
linux,code = <KEY_RESTART>;
gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
@@ -56,12 +54,12 @@
pinctrl-0 = < &pmx_led_white_health &pmx_led_white_pulse >;
pinctrl-names = "default";
- white-health {
+ led-white-health {
label = "viper:white:health";
gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
};
- white-pulse {
+ led-white-pulse {
label = "viper:white:pulse";
gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-lsxl.dtsi b/arch/arm/boot/dts/marvell/kirkwood-lsxl.dtsi
index f80af24b9e90..5e0b139dd4fb 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-lsxl.dtsi
+++ b/arch/arm/boot/dts/marvell/kirkwood-lsxl.dtsi
@@ -107,24 +107,22 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_button_function &pmx_power_switch
&pmx_power_auto_switch>;
pinctrl-names = "default";
- option {
+ button-option {
label = "Function Button";
linux,code = <KEY_OPTION>;
gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
};
- reserved {
+ button-reserved {
label = "Power-on Switch";
linux,code = <KEY_RESERVED>;
linux,input-type = <5>;
gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
};
- power {
+ button-power {
label = "Power-auto Switch";
linux,code = <KEY_ESC>;
linux,input-type = <5>;
@@ -139,28 +137,28 @@
&pmx_led_function_blue>;
pinctrl-names = "default";
- func_blue {
+ led-func-blue {
label = "lsxl:blue:func";
gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
};
- alarm {
+ led-alarm {
label = "lsxl:red:alarm";
gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
};
- info {
+ led-info {
label = "lsxl:amber:info";
gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
};
- power {
+ led-power {
label = "lsxl:blue:power";
gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
- func_red {
+ led-func-red {
label = "lsxl:red:func";
gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-mplcec4.dts b/arch/arm/boot/dts/marvell/kirkwood-mplcec4.dts
index e87ea7146546..6533b49a15b2 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-mplcec4.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-mplcec4.dts
@@ -114,36 +114,36 @@
>;
pinctrl-names = "default";
- health {
+ led-health {
label = "status:green:health";
gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
};
- user1o {
+ led-user1o {
label = "user1:orange";
gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
default-state = "on";
};
- user1g {
+ led-user1g {
label = "user1:green";
gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
default-state = "on";
};
- user0o {
+ led-user0o {
label = "user0:orange";
gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
default-state = "on";
};
- user0g {
+ led-user0g {
label = "user0:green";
gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
default-state = "on";
};
- misc {
+ led-misc {
label = "status:orange:misc";
gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
default-state = "on";
diff --git a/arch/arm/boot/dts/marvell/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/marvell/kirkwood-mv88f6281gtw-ge.dts
index 5a77286136c7..e3b41784c876 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-mv88f6281gtw-ge.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-mv88f6281gtw-ge.dts
@@ -73,17 +73,17 @@
pinctrl-0 = <&pmx_leds &pmx_usb_led>;
pinctrl-names = "default";
- green-status {
+ led-green-status {
label = "gtw:green:Status";
gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
};
- red-status {
+ led-red-status {
label = "gtw:red:Status";
gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
};
- green-usb {
+ led-green-usb {
label = "gtw:green:USB";
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
};
@@ -91,17 +91,15 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_keys>;
pinctrl-names = "default";
- restart {
+ button-restart {
label = "SWR Button";
linux,code = <KEY_RESTART>;
gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
};
- wps {
+ button-wps {
label = "WPS Button";
linux,code = <KEY_WPS_BUTTON>;
gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-netxbig.dtsi b/arch/arm/boot/dts/marvell/kirkwood-netxbig.dtsi
index b5737026e244..d4edf2727388 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-netxbig.dtsi
+++ b/arch/arm/boot/dts/marvell/kirkwood-netxbig.dtsi
@@ -53,26 +53,24 @@
gpio-keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
/*
* esc and power represent a three position rocker
* switch. Thus the conventional KEY_POWER does not fit
*/
- exc {
+ button-exc {
label = "Back power switch (on|auto)";
linux,code = <KEY_ESC>;
linux,input-type = <5>;
gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
};
- power {
+ button-power {
label = "Back power switch (auto|off)";
linux,code = <KEY_1>;
linux,input-type = <5>;
gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
};
- option {
+ button-option {
label = "Function button";
linux,code = <KEY_OPTION>;
gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/marvell/kirkwood-ns2-common.dtsi
index 51530ea86622..d6b615cf6390 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-ns2-common.dtsi
+++ b/arch/arm/boot/dts/marvell/kirkwood-ns2-common.dtsi
@@ -55,10 +55,8 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- power {
+ button-power {
label = "Power push button";
linux,code = <KEY_POWER>;
gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
@@ -68,7 +66,7 @@
gpio-leds {
compatible = "gpio-leds";
- red-fail {
+ led-red-fail {
label = "ns2:red:fail";
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-ns2lite.dts b/arch/arm/boot/dts/marvell/kirkwood-ns2lite.dts
index b0cb5907ed63..686bcd6f0f3c 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-ns2lite.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-ns2lite.dts
@@ -24,7 +24,7 @@
gpio-leds {
compatible = "gpio-leds";
- blue-sata {
+ led-blue-sata {
label = "ns2:blue:sata";
gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
linux,default-trigger = "disk-activity";
diff --git a/arch/arm/boot/dts/marvell/kirkwood-nsa310.dts b/arch/arm/boot/dts/marvell/kirkwood-nsa310.dts
index c1799a07816e..3555ac1c3b15 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-nsa310.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-nsa310.dts
@@ -87,43 +87,43 @@
&pmx_led_hdd_green &pmx_led_hdd_red>;
pinctrl-names = "default";
- green-sys {
+ led-green-sys {
label = "nsa310:green:sys";
gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
};
- red-sys {
+ led-red-sys {
label = "nsa310:red:sys";
gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
};
- green-hdd {
+ led-green-hdd {
label = "nsa310:green:hdd";
gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
};
- red-hdd {
+ led-red-hdd {
label = "nsa310:red:hdd";
gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
};
- green-esata {
+ led-green-esata {
label = "nsa310:green:esata";
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
};
- red-esata {
+ led-red-esata {
label = "nsa310:red:esata";
gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
};
- green-usb {
+ led-green-usb {
label = "nsa310:green:usb";
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
};
- red-usb {
+ led-red-usb {
label = "nsa310:red:usb";
gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
};
- green-copy {
+ led-green-copy {
label = "nsa310:green:copy";
gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
};
- red-copy {
+ led-red-copy {
label = "nsa310:red:copy";
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-nsa310a.dts b/arch/arm/boot/dts/marvell/kirkwood-nsa310a.dts
index b85e314f045a..ddf84092aade 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-nsa310a.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-nsa310a.dts
@@ -75,39 +75,39 @@
gpio-leds {
compatible = "gpio-leds";
- green-sys {
+ led-green-sys {
label = "nsa310:green:sys";
gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
};
- red-sys {
+ led-red-sys {
label = "nsa310:red:sys";
gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
};
- green-hdd {
+ led-green-hdd {
label = "nsa310:green:hdd";
gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
};
- red-hdd {
+ led-red-hdd {
label = "nsa310:red:hdd";
gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
};
- green-esata {
+ led-green-esata {
label = "nsa310:green:esata";
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
};
- red-esata {
+ led-red-esata {
label = "nsa310:red:esata";
gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
};
- green-usb {
+ led-green-usb {
label = "nsa310:green:usb";
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
};
- green-copy {
+ led-green-copy {
label = "nsa310:green:copy";
gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
};
- red-copy {
+ led-red-copy {
label = "nsa310:red:copy";
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-nsa310s.dts b/arch/arm/boot/dts/marvell/kirkwood-nsa310s.dts
index 49da633a1bc0..47deb93c90a5 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-nsa310s.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-nsa310s.dts
@@ -35,24 +35,22 @@
keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_buttons>;
pinctrl-names = "default";
- power {
+ button-power {
label = "Power Button";
linux,code = <KEY_POWER>;
gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
};
- copy {
+ button-copy {
label = "Copy Button";
linux,code = <KEY_COPY>;
gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
};
- reset {
+ button-reset {
label = "Reset Button";
linux,code = <KEY_RESTART>;
gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-nsa320.dts b/arch/arm/boot/dts/marvell/kirkwood-nsa320.dts
index 652405e65006..dd5c8ffc8781 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-nsa320.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-nsa320.dts
@@ -142,39 +142,39 @@
&pmx_led_hdd1_green &pmx_led_hdd1_red>;
pinctrl-names = "default";
- green-sys {
+ led-green-sys {
label = "nsa320:green:sys";
gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
};
- orange-sys {
+ led-orange-sys {
label = "nsa320:orange:sys";
gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
};
- green-hdd1 {
+ led-green-hdd1 {
label = "nsa320:green:hdd1";
gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
};
- red-hdd1 {
+ led-red-hdd1 {
label = "nsa320:red:hdd1";
gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
};
- green-hdd2 {
+ led-green-hdd2 {
label = "nsa320:green:hdd2";
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
};
- red-hdd2 {
+ led-red-hdd2 {
label = "nsa320:red:hdd2";
gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
};
- green-usb {
+ led-green-usb {
label = "nsa320:green:usb";
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
};
- green-copy {
+ led-green-copy {
label = "nsa320:green:copy";
gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
};
- red-copy {
+ led-red-copy {
label = "nsa320:red:copy";
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-nsa325.dts b/arch/arm/boot/dts/marvell/kirkwood-nsa325.dts
index 371456de34b2..f0786a5f2ce6 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-nsa325.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-nsa325.dts
@@ -162,39 +162,39 @@
&pmx_led_hdd1_green &pmx_led_hdd1_red>;
pinctrl-names = "default";
- green-sys {
+ led-green-sys {
label = "nsa325:green:sys";
gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
};
- orange-sys {
+ led-orange-sys {
label = "nsa325:orange:sys";
gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
};
- green-hdd1 {
+ led-green-hdd1 {
label = "nsa325:green:hdd1";
gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
};
- red-hdd1 {
+ led-red-hdd1 {
label = "nsa325:red:hdd1";
gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
};
- green-hdd2 {
+ led-green-hdd2 {
label = "nsa325:green:hdd2";
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
};
- red-hdd2 {
+ led-red-hdd2 {
label = "nsa325:red:hdd2";
gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
};
- green-usb {
+ led-green-usb {
label = "nsa325:green:usb";
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
};
- green-copy {
+ led-green-copy {
label = "nsa325:green:copy";
gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
};
- red-copy {
+ led-red-copy {
label = "nsa325:red:copy";
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-nsa3x0-common.dtsi b/arch/arm/boot/dts/marvell/kirkwood-nsa3x0-common.dtsi
index ea3d36512e9f..e9bd9c551af5 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-nsa3x0-common.dtsi
+++ b/arch/arm/boot/dts/marvell/kirkwood-nsa3x0-common.dtsi
@@ -63,22 +63,20 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_btn_reset &pmx_btn_copy &pmx_btn_power>;
pinctrl-names = "default";
- power {
+ button-power {
label = "Power Button";
linux,code = <KEY_POWER>;
gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
};
- copy {
+ button-copy {
label = "Copy Button";
linux,code = <KEY_COPY>;
gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
};
- reset {
+ button-reset {
label = "Reset Button";
linux,code = <KEY_RESTART>;
gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-openblocks_a6.dts b/arch/arm/boot/dts/marvell/kirkwood-openblocks_a6.dts
index 8ea430168ea5..20c6290d2037 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-openblocks_a6.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-openblocks_a6.dts
@@ -115,10 +115,8 @@
compatible = "gpio-keys";
pinctrl-0 = <&pmx_gpio_init>;
pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- power {
+ button-power {
label = "Init Button";
linux,code = <KEY_POWER>;
gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts b/arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts
index 946f0f453dd1..9c438f10f737 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts
@@ -136,8 +136,6 @@
compatible = "gpio-keys";
pinctrl-0 = <&pmx_gpio_init>;
pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
button {
label = "Init Button";
diff --git a/arch/arm/boot/dts/marvell/kirkwood-pogo_e02.dts b/arch/arm/boot/dts/marvell/kirkwood-pogo_e02.dts
index f9e95e55f36d..39a5345332da 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-pogo_e02.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-pogo_e02.dts
@@ -33,12 +33,12 @@
gpio-leds {
compatible = "gpio-leds";
- health {
+ led-health {
label = "pogo_e02:green:health";
gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
- fault {
+ led-fault {
label = "pogo_e02:orange:fault";
gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-pogoplug-series-4.dts b/arch/arm/boot/dts/marvell/kirkwood-pogoplug-series-4.dts
index 5aa4669ae254..0e9c4cf79822 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-pogoplug-series-4.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-pogoplug-series-4.dts
@@ -29,12 +29,10 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_button_eject>;
pinctrl-names = "default";
- eject {
+ button-eject {
debounce-interval = <50>;
wakeup-source;
linux,code = <KEY_EJECTCD>;
@@ -48,12 +46,12 @@
pinctrl-0 = <&pmx_led_green &pmx_led_red>;
pinctrl-names = "default";
- health {
+ led-health {
label = "pogoplugv4:green:health";
gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
default-state = "on";
};
- fault {
+ led-fault {
label = "pogoplugv4:red:fault";
gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-sheevaplug-esata.dts b/arch/arm/boot/dts/marvell/kirkwood-sheevaplug-esata.dts
index ae8f493c9a0f..eb185273376e 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-sheevaplug-esata.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-sheevaplug-esata.dts
@@ -33,7 +33,7 @@
pinctrl-0 = <&pmx_led_blue>;
pinctrl-names = "default";
- health {
+ led-health {
label = "sheevaplug:blue:health";
gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
default-state = "keep";
diff --git a/arch/arm/boot/dts/marvell/kirkwood-sheevaplug.dts b/arch/arm/boot/dts/marvell/kirkwood-sheevaplug.dts
index c73cc904e5c4..ce73fcf2255f 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-sheevaplug.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-sheevaplug.dts
@@ -28,13 +28,13 @@
pinctrl-0 = <&pmx_led_blue &pmx_led_red>;
pinctrl-names = "default";
- health {
+ led-health {
label = "sheevaplug:blue:health";
gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
- misc {
+ led-misc {
label = "sheevaplug:red:misc";
gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-synology.dtsi b/arch/arm/boot/dts/marvell/kirkwood-synology.dtsi
index 20964eb48fd7..6b7c5218b1fb 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-synology.dtsi
+++ b/arch/arm/boot/dts/marvell/kirkwood-synology.dtsi
@@ -410,7 +410,7 @@
pinctrl-0 = <&pmx_alarmled_12>;
pinctrl-names = "default";
- hdd1-green {
+ led-hdd1-green {
label = "synology:alarm";
gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
};
@@ -424,42 +424,42 @@
&pmx_hddled_26 &pmx_hddled_27>;
pinctrl-names = "default";
- hdd1-green {
+ led-hdd1-green {
label = "synology:green:hdd1";
gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
};
- hdd1-amber {
+ led-hdd1-amber {
label = "synology:amber:hdd1";
gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
};
- hdd2-green {
+ led-hdd2-green {
label = "synology:green:hdd2";
gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
};
- hdd2-amber {
+ led-hdd2-amber {
label = "synology:amber:hdd2";
gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
};
- hdd3-green {
+ led-hdd3-green {
label = "synology:green:hdd3";
gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
};
- hdd3-amber {
+ led-hdd3-amber {
label = "synology:amber:hdd3";
gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
};
- hdd4-green {
+ led-hdd4-green {
label = "synology:green:hdd4";
gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
};
- hdd4-amber {
+ led-hdd4-amber {
label = "synology:amber:hdd4";
gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
};
@@ -471,12 +471,12 @@
pinctrl-0 = <&pmx_hddled_21 &pmx_hddled_23>;
pinctrl-names = "default";
- hdd1-green {
+ led-hdd1-green {
label = "synology:green:hdd1";
gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
};
- hdd1-amber {
+ led-hdd1-amber {
label = "synology:amber:hdd1";
gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
};
@@ -488,22 +488,22 @@
pinctrl-0 = <&pmx_hddled_21 &pmx_hddled_23 &pmx_hddled_20 &pmx_hddled_22>;
pinctrl-names = "default";
- hdd1-green {
+ led-hdd1-green {
label = "synology:green:hdd1";
gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
};
- hdd1-amber {
+ led-hdd1-amber {
label = "synology:amber:hdd1";
gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
};
- hdd2-green {
+ led-hdd2-green {
label = "synology:green:hdd2";
gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
};
- hdd2-amber {
+ led-hdd2-amber {
label = "synology:amber:hdd2";
gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
};
@@ -518,52 +518,52 @@
&pmx_hddled_45>;
pinctrl-names = "default";
- hdd1-green {
+ led-hdd1-green {
label = "synology:green:hdd1";
gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
};
- hdd1-amber {
+ led-hdd1-amber {
label = "synology:amber:hdd1";
gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
};
- hdd2-green {
+ led-hdd2-green {
label = "synology:green:hdd2";
gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
};
- hdd2-amber {
+ led-hdd2-amber {
label = "synology:amber:hdd2";
gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
};
- hdd3-green {
+ led-hdd3-green {
label = "synology:green:hdd3";
gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
};
- hdd3-amber {
+ led-hdd3-amber {
label = "synology:amber:hdd3";
gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
};
- hdd4-green {
+ led-hdd4-green {
label = "synology:green:hdd4";
gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
};
- hdd4-amber {
+ led-hdd4-amber {
label = "synology:amber:hdd4";
gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
};
- hdd5-green {
+ led-hdd5-green {
label = "synology:green:hdd5";
gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
};
- hdd5-amber {
+ led-hdd5-amber {
label = "synology:amber:hdd5";
gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
};
@@ -575,22 +575,22 @@
pinctrl-0 = <&pmx_hddled_38 &pmx_hddled_39 &pmx_hddled_36 &pmx_hddled_37>;
pinctrl-names = "default";
- hdd1-green {
+ led-hdd1-green {
label = "synology:green:hdd1";
gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
};
- hdd1-amber {
+ led-hdd1-amber {
label = "synology:amber:hdd1";
gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
};
- hdd2-green {
+ led-hdd2-green {
label = "synology:green:hdd2";
gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
};
- hdd2-amber {
+ led-hdd2-amber {
label = "synology:amber:hdd2";
gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/kirkwood-t5325.dts b/arch/arm/boot/dts/marvell/kirkwood-t5325.dts
index ad093324e075..a6e77a487d00 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-t5325.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-t5325.dts
@@ -156,12 +156,10 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_button_power>;
pinctrl-names = "default";
- power {
+ button-power {
label = "Power Button";
linux,code = <KEY_POWER>;
gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-ts219-6281.dts b/arch/arm/boot/dts/marvell/kirkwood-ts219-6281.dts
index 30892c19aceb..a2e0ad4b84d8 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-ts219-6281.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-ts219-6281.dts
@@ -35,17 +35,15 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_reset_button &pmx_USB_copy_button>;
pinctrl-names = "default";
- copy {
+ button-copy {
label = "USB Copy";
linux,code = <KEY_COPY>;
gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
};
- reset {
+ button-reset {
label = "Reset";
linux,code = <KEY_RESTART>;
gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-ts219-6282.dts b/arch/arm/boot/dts/marvell/kirkwood-ts219-6282.dts
index aba1205981f1..35be6bce1dba 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-ts219-6282.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-ts219-6282.dts
@@ -35,17 +35,15 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_reset_button &pmx_USB_copy_button>;
pinctrl-names = "default";
- copy {
+ button-copy {
label = "USB Copy";
linux,code = <KEY_COPY>;
gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
};
- reset {
+ button-reset {
label = "Reset";
linux,code = <KEY_RESTART>;
gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/kirkwood-ts419.dtsi b/arch/arm/boot/dts/marvell/kirkwood-ts419.dtsi
index 717236853e45..f136059607b7 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-ts419.dtsi
+++ b/arch/arm/boot/dts/marvell/kirkwood-ts419.dtsi
@@ -36,17 +36,15 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_reset_button &pmx_USB_copy_button>;
pinctrl-names = "default";
- copy {
+ button-copy {
label = "USB Copy";
linux,code = <KEY_COPY>;
gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
};
- reset {
+ button-reset {
label = "Reset";
linux,code = <KEY_RESTART>;
gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/mvebu-linkstation-gpio-simple.dtsi b/arch/arm/boot/dts/marvell/mvebu-linkstation-gpio-simple.dtsi
index c2d87ba6190a..055ac754c5fd 100644
--- a/arch/arm/boot/dts/marvell/mvebu-linkstation-gpio-simple.dtsi
+++ b/arch/arm/boot/dts/marvell/mvebu-linkstation-gpio-simple.dtsi
@@ -48,8 +48,6 @@
/ {
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-0 = <&pmx_power_switch>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/marvell/orion5x-lacie-d2-network.dts b/arch/arm/boot/dts/marvell/orion5x-lacie-d2-network.dts
index 03471d30bfd9..12a4aac2633e 100644
--- a/arch/arm/boot/dts/marvell/orion5x-lacie-d2-network.dts
+++ b/arch/arm/boot/dts/marvell/orion5x-lacie-d2-network.dts
@@ -35,22 +35,21 @@
compatible = "gpio-keys";
pinctrl-0 = <&pmx_buttons>;
pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- front_button {
+
+ button-front {
label = "Front Push Button";
linux,code = <KEY_POWER>;
gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>;
};
- power_rocker_sw_on {
+ switch-power-rocker-sw-on {
label = "Power rocker switch (on|auto)";
linux,input-type = <5>; /* EV_SW */
linux,code = <1>; /* D2NET_SWITCH_POWER_ON */
gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
};
- power_rocker_sw_off {
+ switch-power-rocker-sw-off {
label = "Power rocker switch (auto|off)";
linux,input-type = <5>; /* EV_SW */
linux,code = <2>; /* D2NET_SWITCH_POWER_OFF */
diff --git a/arch/arm/boot/dts/marvell/orion5x-lacie-ethernet-disk-mini-v2.dts b/arch/arm/boot/dts/marvell/orion5x-lacie-ethernet-disk-mini-v2.dts
index f17e25ac98dd..f81acb9b7223 100644
--- a/arch/arm/boot/dts/marvell/orion5x-lacie-ethernet-disk-mini-v2.dts
+++ b/arch/arm/boot/dts/marvell/orion5x-lacie-ethernet-disk-mini-v2.dts
@@ -39,9 +39,8 @@
compatible = "gpio-keys";
pinctrl-0 = <&pmx_power_button>;
pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- button@1 {
+
+ button-1 {
label = "Power-on Switch";
linux,code = <KEY_POWER>;
gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>;
@@ -53,7 +52,7 @@
pinctrl-0 = <&pmx_power_led>;
pinctrl-names = "default";
- led@1 {
+ led-1 {
label = "power:blue";
gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/orion5x-linkstation-lschl.dts b/arch/arm/boot/dts/marvell/orion5x-linkstation-lschl.dts
index ee751995c8d0..79fee048c900 100644
--- a/arch/arm/boot/dts/marvell/orion5x-linkstation-lschl.dts
+++ b/arch/arm/boot/dts/marvell/orion5x-linkstation-lschl.dts
@@ -61,7 +61,7 @@
};
gpio_keys {
- func {
+ func-button {
label = "Function Button";
linux,code = <KEY_OPTION>;
gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
@@ -90,7 +90,7 @@
gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
};
- func {
+ func-led {
label = "lschl:func:blue:top";
gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/marvell/orion5x-lswsgl.dts b/arch/arm/boot/dts/marvell/orion5x-lswsgl.dts
index 2fbc17d6dfa4..e0da406c430f 100644
--- a/arch/arm/boot/dts/marvell/orion5x-lswsgl.dts
+++ b/arch/arm/boot/dts/marvell/orion5x-lswsgl.dts
@@ -74,22 +74,21 @@
compatible = "gpio-keys";
pinctrl-0 = <&pmx_buttons>;
pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- func {
+
+ key-func {
label = "Function Button";
linux,code = <KEY_OPTION>;
gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
};
- power {
+ key-power {
label = "Power-on Switch";
linux,input-type = <5>; /* EV_SW */
linux,code = <KEY_RESERVED>; /* LSMINI_SW_POWER */
gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
};
- autopower {
+ key-autopower {
label = "Power-auto Switch";
linux,input-type = <5>; /* EV_SW */
linux,code = <KEY_ESC>; /* LSMINI_SW_AUTOPOWER */
@@ -103,24 +102,24 @@
&pmx_led_power>;
pinctrl-names = "default";
- alarm {
+ led-alarm {
label = "lswsgl:alarm:red";
- gpio = <&gpio0 2 GPIO_ACTIVE_LOW>;
+ gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
};
- info {
+ led-info {
label = "lswsgl:info:amber";
- gpio = <&gpio0 3 GPIO_ACTIVE_LOW>;
+ gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
};
- func {
+ led-func {
label = "lswsgl:func:blue:top";
- gpio = <&gpio0 9 GPIO_ACTIVE_LOW>;
+ gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
};
- power {
+ led-power {
label = "lswsgl:power:blue:bottom";
- gpio = <&gpio0 14 GPIO_ACTIVE_LOW>;
+ gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
default-state = "on";
};
};
diff --git a/arch/arm/boot/dts/marvell/orion5x-maxtor-shared-storage-2.dts b/arch/arm/boot/dts/marvell/orion5x-maxtor-shared-storage-2.dts
index d57859998350..cb1bd24b7ae3 100644
--- a/arch/arm/boot/dts/marvell/orion5x-maxtor-shared-storage-2.dts
+++ b/arch/arm/boot/dts/marvell/orion5x-maxtor-shared-storage-2.dts
@@ -35,15 +35,14 @@
compatible = "gpio-keys";
pinctrl-0 = <&pmx_buttons>;
pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- power {
+
+ key-power {
label = "Power";
linux,code = <KEY_POWER>;
gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
};
- reset {
+ key-reset {
label = "Reset";
linux,code = <KEY_RESTART>;
gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/orion5x-netgear-wnr854t.dts b/arch/arm/boot/dts/marvell/orion5x-netgear-wnr854t.dts
index fb203e7d37f5..d63ea15539aa 100644
--- a/arch/arm/boot/dts/marvell/orion5x-netgear-wnr854t.dts
+++ b/arch/arm/boot/dts/marvell/orion5x-netgear-wnr854t.dts
@@ -35,7 +35,7 @@
pinctrl-0 = <&pmx_reset_button>;
pinctrl-names = "default";
- reset {
+ key-reset {
label = "Reset Button";
linux,code = <KEY_RESTART>;
gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/marvell/orion5x-rd88f5182-nas.dts b/arch/arm/boot/dts/marvell/orion5x-rd88f5182-nas.dts
index fd78aa02a3c5..75ab913b21e5 100644
--- a/arch/arm/boot/dts/marvell/orion5x-rd88f5182-nas.dts
+++ b/arch/arm/boot/dts/marvell/orion5x-rd88f5182-nas.dts
@@ -32,7 +32,7 @@
pinctrl-0 = <&pmx_debug_led>;
pinctrl-names = "default";
- led@0 {
+ led-0 {
label = "rd88f5182:cpu";
linux,default-trigger = "heartbeat";
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/mediatek/mt2701-evb.dts b/arch/arm/boot/dts/mediatek/mt2701-evb.dts
index 9c7325f18933..4c76366aa938 100644
--- a/arch/arm/boot/dts/mediatek/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mediatek/mt2701-evb.dts
@@ -231,7 +231,7 @@
<MT2701_PIN_238_EXT_SDIO1__FUNC_EXT_SDIO1>,
<MT2701_PIN_237_EXT_SDIO2__FUNC_EXT_SDIO2>,
<MT2701_PIN_236_EXT_SDIO3__FUNC_EXT_SDIO3>;
- drive-strength = <MTK_DRIVE_4mA>;
+ drive-strength = <4>;
bias-pull-up;
};
};
diff --git a/arch/arm/boot/dts/mediatek/mt7623.dtsi b/arch/arm/boot/dts/mediatek/mt7623.dtsi
index f0b4a09004b3..814586abc297 100644
--- a/arch/arm/boot/dts/mediatek/mt7623.dtsi
+++ b/arch/arm/boot/dts/mediatek/mt7623.dtsi
@@ -1143,13 +1143,13 @@
<MT7623_PIN_121_MSDC0_DAT0_FUNC_MSDC0_DAT0>,
<MT7623_PIN_116_MSDC0_CMD_FUNC_MSDC0_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_2mA>;
+ drive-strength = <2>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
pins-clk {
pinmux = <MT7623_PIN_117_MSDC0_CLK_FUNC_MSDC0_CLK>;
- drive-strength = <MTK_DRIVE_2mA>;
+ drive-strength = <2>;
bias-pull-down = <MTK_PUPD_SET_R1R0_01>;
};
@@ -1167,14 +1167,14 @@
<MT7623_PIN_110_MSDC1_DAT3_FUNC_MSDC1_DAT3>,
<MT7623_PIN_105_MSDC1_CMD_FUNC_MSDC1_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_4mA>;
+ drive-strength = <4>;
bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
};
pins-clk {
pinmux = <MT7623_PIN_106_MSDC1_CLK_FUNC_MSDC1_CLK>;
bias-pull-down;
- drive-strength = <MTK_DRIVE_4mA>;
+ drive-strength = <4>;
};
pins-wp {
@@ -1197,13 +1197,13 @@
<MT7623_PIN_110_MSDC1_DAT3_FUNC_MSDC1_DAT3>,
<MT7623_PIN_105_MSDC1_CMD_FUNC_MSDC1_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_4mA>;
+ drive-strength = <4>;
bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
};
pins-clk {
pinmux = <MT7623_PIN_106_MSDC1_CLK_FUNC_MSDC1_CLK>;
- drive-strength = <MTK_DRIVE_4mA>;
+ drive-strength = <4>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
};
@@ -1211,7 +1211,7 @@
nand_pins_default: nanddefault {
pins-ale {
pinmux = <MT7623_PIN_116_MSDC0_CMD_FUNC_NALE>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
@@ -1226,13 +1226,13 @@
<MT7623_PIN_115_MSDC0_RSTB_FUNC_NLD8>,
<MT7623_PIN_119_MSDC0_DAT2_FUNC_NLD2>;
input-enable;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-up;
};
pins-we {
pinmux = <MT7623_PIN_117_MSDC0_CLK_FUNC_NWEB>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
};
};
diff --git a/arch/arm/boot/dts/nspire/nspire-classic.dtsi b/arch/arm/boot/dts/nspire/nspire-classic.dtsi
index a6e9cbf51524..0ee53d3ecd54 100644
--- a/arch/arm/boot/dts/nspire/nspire-classic.dtsi
+++ b/arch/arm/boot/dts/nspire/nspire-classic.dtsi
@@ -55,7 +55,7 @@
};
/ {
- memory {
+ memory@10000000 {
device_type = "memory";
reg = <0x10000000 0x2000000>; /* 32 MB */
};
diff --git a/arch/arm/boot/dts/nspire/nspire-cx.dts b/arch/arm/boot/dts/nspire/nspire-cx.dts
index 29f0181e5b38..debeff0ec010 100644
--- a/arch/arm/boot/dts/nspire/nspire-cx.dts
+++ b/arch/arm/boot/dts/nspire/nspire-cx.dts
@@ -122,7 +122,7 @@
model = "TI-NSPIRE CX";
compatible = "ti,nspire-cx";
- memory {
+ memory@10000000 {
device_type = "memory";
reg = <0x10000000 0x4000000>; /* 64 MB */
};
diff --git a/arch/arm/boot/dts/nspire/nspire.dtsi b/arch/arm/boot/dts/nspire/nspire.dtsi
index d56fef7250db..95588b716c6f 100644
--- a/arch/arm/boot/dts/nspire/nspire.dtsi
+++ b/arch/arm/boot/dts/nspire/nspire.dtsi
@@ -170,9 +170,12 @@
};
watchdog: watchdog@90060000 {
- compatible = "arm,primecell";
+ compatible = "arm,sp805", "arm,primecell";
reg = <0x90060000 0x1000>;
interrupts = <3>;
+ clocks = <&apb_pclk>, <&apb_pclk>;
+ clock-names = "wdog_clk", "apb_pclk";
+ status = "disabled";
};
rtc: rtc@90090000 {
diff --git a/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts
index 5787ae95d3b4..1f07ba382910 100644
--- a/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts
+++ b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts
@@ -525,7 +525,7 @@
};
};
- i2c-bus@4 {
+ i2c@4 {
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
@@ -537,7 +537,7 @@
};
};
- i2c-bus@5 {
+ i2c@5 {
#address-cells = <1>;
#size-cells = <0>;
reg = <5>;
@@ -549,7 +549,7 @@
};
};
- i2c-bus@6 {
+ i2c@6 {
#address-cells = <1>;
#size-cells = <0>;
reg = <6>;
@@ -561,7 +561,7 @@
};
};
- i2c-bus@7 {
+ i2c@7 {
#address-cells = <1>;
#size-cells = <0>;
reg = <7>;
@@ -580,7 +580,7 @@
reg = <0x77>;
i2c-mux-idle-disconnect;
- i2c-bus@2 {
+ i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
@@ -620,7 +620,7 @@
reg = <0x77>;
i2c-mux-idle-disconnect;
- i2c-bus@0 {
+ i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
@@ -632,7 +632,7 @@
};
};
- i2c-bus@1 {
+ i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
@@ -691,7 +691,7 @@
reg = <0x77>;
i2c-mux-idle-disconnect;
- i2c-bus@3 {
+ i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
@@ -703,7 +703,7 @@
};
};
- i2c-bus@4 {
+ i2c@4 {
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
@@ -715,7 +715,7 @@
};
};
- i2c-bus@5 {
+ i2c@5 {
#address-cells = <1>;
#size-cells = <0>;
reg = <5>;
@@ -726,7 +726,7 @@
reg = <0x28>;
};
};
- i2c-bus@6 {
+ i2c@6 {
#address-cells = <1>;
#size-cells = <0>;
reg = <6>;
diff --git a/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts
index baa39d0c1032..087f4ac43187 100644
--- a/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts
+++ b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts
@@ -215,43 +215,43 @@
reg = <0x70>;
i2c-mux-idle-disconnect;
- i2c_slot1a: i2c-bus@0 {
+ i2c_slot1a: i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
};
- i2c_slot1b: i2c-bus@1 {
+ i2c_slot1b: i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
};
- i2c_slot2a: i2c-bus@2 {
+ i2c_slot2a: i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
};
- i2c_slot2b: i2c-bus@3 {
+ i2c_slot2b: i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
};
- i2c_slot3: i2c-bus@4 {
+ i2c_slot3: i2c@4 {
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
};
- i2c_slot4: i2c-bus@5 {
+ i2c_slot4: i2c@5 {
#address-cells = <1>;
#size-cells = <0>;
reg = <5>;
};
- i2c_slot5: i2c-bus@6 {
+ i2c_slot5: i2c@6 {
#address-cells = <1>;
#size-cells = <0>;
reg = <6>;
@@ -265,24 +265,24 @@
#size-cells = <0>;
i2c-mux-idle-disconnect;
- i2c_m2_s1: i2c-bus@0 {
+ i2c_m2_s1: i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
};
- i2c_m2_s2: i2c-bus@1 {
+ i2c_m2_s2: i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
};
- i2c_m2_s3: i2c-bus@2 {
+ i2c_m2_s3: i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
};
- i2c_m2_s4: i2c-bus@3 {
+ i2c_m2_s4: i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile
index 231c0d73a53e..92e291603ea1 100644
--- a/arch/arm/boot/dts/nxp/imx/Makefile
+++ b/arch/arm/boot/dts/nxp/imx/Makefile
@@ -99,6 +99,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6dl-icore.dtb \
imx6dl-icore-mipi.dtb \
imx6dl-icore-rqs.dtb \
+ imx6dl-kontron-samx6i-ads2.dtb \
imx6dl-lanmcu.dtb \
imx6dl-mamoj.dtb \
imx6dl-mba6a.dtb \
@@ -207,6 +208,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-icore-ofcap10.dtb \
imx6q-icore-ofcap12.dtb \
imx6q-icore-rqs.dtb \
+ imx6q-kontron-samx6i-ads2.dtb \
imx6q-kp-tpc.dtb \
imx6q-logicpd.dtb \
imx6q-marsboard.dtb \
diff --git a/arch/arm/boot/dts/nxp/imx/e60k02.dtsi b/arch/arm/boot/dts/nxp/imx/e60k02.dtsi
index 13756d39fb7b..0029c12f16c8 100644
--- a/arch/arm/boot/dts/nxp/imx/e60k02.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/e60k02.dtsi
@@ -14,6 +14,10 @@
#include <dt-bindings/input/input.h>
/ {
+ aliases {
+ mmc0 = &usdhc2;
+ mmc1 = &usdhc3;
+ };
chosen {
stdout-path = &uart1;
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts b/arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts
index b61d55ca1467..de6b7607510a 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts
@@ -25,8 +25,8 @@
pinctrl-0 = <&pinctrl_ipu_disp1>;
display-timings {
- lw700 {
- native-mode;
+ native-mode = <&timing0>;
+ timing0: timing-lw700 {
clock-frequency = <33000033>;
hactive = <800>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-babbage.dts b/arch/arm/boot/dts/nxp/imx/imx51-babbage.dts
index 16ff543f3fbf..f4a47e8348b2 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-babbage.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx51-babbage.dts
@@ -89,7 +89,7 @@
status = "disabled";
display-timings {
native-mode = <&timing1>;
- timing1: claawvga {
+ timing1: timing-claawvga {
clock-frequency = <27000000>;
hactive = <800>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-ts4800.dts b/arch/arm/boot/dts/nxp/imx/imx51-ts4800.dts
index 2bd0761c7e90..079bd3d14999 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-ts4800.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx51-ts4800.dts
@@ -58,8 +58,8 @@
pinctrl-0 = <&pinctrl_lcd>;
display-timings {
- 800x480p60 {
- native-mode;
+ native-mode = <&timing0>;
+ timing0: timing-800x480p60 {
clock-frequency = <30066000>;
hactive = <800>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts b/arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts
index 1353d985969c..ba0c62994f75 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts
@@ -17,8 +17,8 @@
pinctrl-0 = <&pinctrl_ipu_disp1>;
display-timings {
- 800x480p60 {
- native-mode;
+ native-mode = <&timing0>;
+ timing0: timing-800x480p60 {
clock-frequency = <31500000>;
hactive = <800>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts b/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
index 4d77b6077fc1..558751e730f3 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
@@ -64,6 +64,7 @@
reg = <0>;
lvds_decoder_in: endpoint {
+ data-mapping = "jeida-18";
remote-endpoint = <&lvds0_out>;
};
};
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 a7f77527269d..a02d77bb5672 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts
@@ -67,7 +67,7 @@
};
display-timings {
- VGA {
+ timing-vga {
clock-frequency = <25200000>;
hactive = <640>;
vactive = <480>;
@@ -83,7 +83,7 @@
pixelclk-active = <0>;
};
- ETV570 {
+ timing-etc570 {
clock-frequency = <25200000>;
hactive = <640>;
vactive = <480>;
@@ -99,7 +99,7 @@
pixelclk-active = <0>;
};
- ET0350 {
+ timing-et0350 {
clock-frequency = <6413760>;
hactive = <320>;
vactive = <240>;
@@ -115,7 +115,7 @@
pixelclk-active = <0>;
};
- ET0430 {
+ timing-et0430 {
clock-frequency = <9009000>;
hactive = <480>;
vactive = <272>;
@@ -131,7 +131,7 @@
pixelclk-active = <1>;
};
- ET0500 {
+ timing-et0500 {
clock-frequency = <33264000>;
hactive = <800>;
vactive = <480>;
@@ -147,7 +147,7 @@
pixelclk-active = <0>;
};
- ET0700 { /* same as ET0500 */
+ timing-et0700 { /* same as ET0500 */
clock-frequency = <33264000>;
hactive = <800>;
vactive = <480>;
@@ -163,7 +163,7 @@
pixelclk-active = <0>;
};
- ETQ570 {
+ timing-etq570 {
clock-frequency = <6596040>;
hactive = <320>;
vactive = <240>;
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 6cdf2082c742..e10c179dbdb3 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-tx53-x13x.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-tx53-x13x.dts
@@ -191,7 +191,7 @@
display-timings {
native-mode = <&lvds0_timing0>;
- lvds0_timing0: hsd100pxn1 {
+ lvds0_timing0: timing-hsd100pxn1 {
clock-frequency = <65000000>;
hactive = <1024>;
vactive = <768>;
@@ -207,7 +207,7 @@
pixelclk-active = <1>;
};
- lvds0_timing1: nl12880bc20 {
+ lvds0_timing1: timing-nl12880bc20 {
clock-frequency = <71000000>;
hactive = <1280>;
vactive = <800>;
@@ -233,7 +233,7 @@
display-timings {
native-mode = <&lvds1_timing0>;
- lvds1_timing0: hsd100pxn1 {
+ lvds1_timing0: timing-hsd100pxn1 {
clock-frequency = <65000000>;
hactive = <1024>;
vactive = <768>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos2_4.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos2_4.dts
index dfa6f64d43cc..c9b2ea2b24b2 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos2_4.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos2_4.dts
@@ -82,11 +82,10 @@
compatible = "lg,lg4573";
spi-max-frequency = <10000000>;
reg = <0>;
- power-on-delay = <10>;
display-timings {
- 480x800p57 {
- native-mode;
+ native-mode = <&timing0>;
+ timing0: timing-480x800p57 {
clock-frequency = <27000027>;
hactive = <480>;
vactive = <800>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_4.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_4.dts
index a5ac79346854..9ec038f1d0ff 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_4.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_4.dts
@@ -36,8 +36,8 @@
status = "okay";
display-timings {
- 480x800p60 {
- native-mode;
+ native-mode = <&timing0>;
+ timing0: timing-480x800p60 {
clock-frequency = <30000000>;
hactive = <480>;
vactive = <800>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_7.dts
index 5a25bdbbeb68..b3129832f471 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_7.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_7.dts
@@ -25,8 +25,8 @@
status = "okay";
display-timings {
- 800x480p60 {
- native-mode;
+ native-mode = <&timing0>;
+ timing0: timing-800x480p60 {
clock-frequency = <33246000>;
hactive = <800>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i-ads2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i-ads2.dts
new file mode 100644
index 000000000000..6a0c53f23a15
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i-ads2.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-kontron-samx6i.dtsi"
+#include "imx6qdl-kontron-samx6i-ads2.dtsi"
+
+/ {
+ model = "Kontron SMARC-sAMX6i Dual-Lite/Solo on SMARC Eval 2.0 carrier";
+ compatible = "kontron,imx6dl-samx6i-ads2", "kontron,imx6dl-samx6i", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i.dtsi
index a864fdbd5f16..5a9b819d7ee8 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i.dtsi
@@ -7,6 +7,6 @@
#include "imx6qdl-kontron-samx6i.dtsi"
/ {
- model = "Kontron SMARC sAMX6i Dual-Lite/Solo";
+ model = "Kontron SMARC-sAMX6i Dual-Lite/Solo";
compatible = "kontron,imx6dl-samx6i", "fsl,imx6dl";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i-ads2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i-ads2.dts
new file mode 100644
index 000000000000..94c395cc020e
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i-ads2.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-kontron-samx6i.dtsi"
+#include "imx6qdl-kontron-samx6i-ads2.dtsi"
+
+/ {
+ model = "Kontron SMARC-sAMX6i Quad/Dual on SMARC Eval 2.0 carrier";
+ compatible = "kontron,imx6q-samx6i-ads2", "kontron,imx6q-samx6i", "fsl,imx6q";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i.dtsi
index 4d6a0c3e8455..e76963436079 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i.dtsi
@@ -5,31 +5,8 @@
#include "imx6q.dtsi"
#include "imx6qdl-kontron-samx6i.dtsi"
-#include <dt-bindings/gpio/gpio.h>
/ {
- model = "Kontron SMARC sAMX6i Quad/Dual";
+ model = "Kontron SMARC-sAMX6i Quad/Dual";
compatible = "kontron,imx6q-samx6i", "fsl,imx6q";
};
-
-/* Quad/Dual SoMs have 3 chip-select signals */
-&ecspi4 {
- cs-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>,
- <&gpio3 29 GPIO_ACTIVE_LOW>,
- <&gpio3 25 GPIO_ACTIVE_LOW>;
-};
-
-&pinctrl_ecspi4 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__ECSPI4_SCLK 0x100b1
- MX6QDL_PAD_EIM_D28__ECSPI4_MOSI 0x100b1
- MX6QDL_PAD_EIM_D22__ECSPI4_MISO 0x100b1
-
- /* SPI4_IMX_CS2# - connected to internal flash */
- MX6QDL_PAD_EIM_D24__GPIO3_IO24 0x1b0b0
- /* SPI4_IMX_CS0# - connected to SMARC SPI0_CS0# */
- MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b0
- /* SPI4_CS3# - connected to SMARC SPI0_CS1# */
- MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x1b0b0
- >;
-};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi
index 48ffb3ee01bd..082a2e3a391f 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi
@@ -485,7 +485,7 @@
display-timings {
native-mode = <&timing0>;
- timing0: hsd100pxn1 {
+ timing0: timing-hsd100pxn1 {
clock-frequency = <65000000>;
hactive = <1024>;
vactive = <768>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi
index 1eae438fbdae..8ec442038ea0 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi
@@ -482,7 +482,7 @@
display-timings {
native-mode = <&timing0>;
- timing0: hsd100pxn1 {
+ timing0: timing-hsd100pxn1 {
clock-frequency = <65000000>;
hactive = <1024>;
vactive = <768>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi
index c2ec8572c8a5..9df9f79affae 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi
@@ -529,7 +529,7 @@
display-timings {
native-mode = <&timing0>;
- timing0: hsd100pxn1 {
+ timing0: timing-hsd100pxn1 {
clock-frequency = <65000000>;
hactive = <1024>;
vactive = <768>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi
index 7cee983da669..7693f92195d5 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi
@@ -584,7 +584,7 @@
display-timings {
native-mode = <&timing0>;
- timing0: hsd100pxn1 {
+ timing0: timing-hsd100pxn1 {
clock-frequency = <65000000>;
hactive = <1024>;
vactive = <768>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi
index fbc704c064b6..9d0836df0fed 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi
@@ -486,7 +486,7 @@
display-timings {
native-mode = <&timing0>;
- timing0: g101evn010 {
+ timing0: timing-g101evn010 {
clock-frequency = <68930000>;
hactive = <1280>;
vactive = <800>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi
index 070506279186..f4cb9e1d34a9 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi
@@ -551,7 +551,7 @@
display-timings {
native-mode = <&timing0>;
- timing0: hsd100pxn1 {
+ timing0: timing-hsd100pxn1 {
clock-frequency = <65000000>;
hactive = <1024>;
vactive = <768>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i-ads2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i-ads2.dtsi
new file mode 100644
index 000000000000..b4a79245b7b6
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i-ads2.dtsi
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree include for the Kontron SMARC-sAMX6i board on a SMARC Eval
+ * 2.0 carrier (ADS2).
+ *
+ */
+
+/ {
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ sound {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,frame-master = <&dailink_master>;
+ simple-audio-card,widgets =
+ "Headphone", "Headphone Jack",
+ "Line", "Line Out Jack",
+ "Microphone", "Microphone Jack",
+ "Line", "Line In Jack";
+ simple-audio-card,routing =
+ "Line Out Jack", "LINEOUTR",
+ "Line Out Jack", "LINEOUTL",
+ "Headphone Jack", "HPOUTR",
+ "Headphone Jack", "HPOUTL",
+ "IN1L", "Line In Jack",
+ "IN1R", "Line In Jack",
+ "Microphone Jack", "MICBIAS",
+ "IN2L", "Microphone Jack",
+ "IN2R", "Microphone Jack";
+
+ simple-audio-card,cpu {
+ sound-dai = <&ssi1>;
+ };
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&wm8904>;
+ };
+ };
+
+ reg_codec_mic: regulator-codec-mic {
+ compatible = "regulator-fixed";
+ regulator-name = "V_3V3_MIC";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ reg_codec_1p8v: regulator-codec-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "V_1V8_S0_CODEC";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&audmux {
+ status = "okay";
+};
+
+&can1 {
+ status = "okay";
+};
+
+&can2 {
+ status = "okay";
+};
+
+&ecspi4 {
+ flash@1 {
+ compatible = "jedec,spi-nor";
+ reg = <1>;
+ spi-max-frequency = <100000000>;
+ m25p,fast-read;
+ };
+};
+
+&fec {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ wm8904: audio-codec@1a {
+ compatible = "wlf,wm8904";
+ reg = <0x1a>;
+ #sound-dai-cells = <0>;
+ clocks = <&clks IMX6QDL_CLK_CKO2>;
+ clock-names = "mclk";
+ AVDD-supply = <&reg_codec_1p8v>;
+ CPVDD-supply = <&reg_codec_1p8v>;
+ DBVDD-supply = <&reg_codec_1p8v>;
+ DCVDD-supply = <&reg_codec_1p8v>;
+ MICVDD-supply = <&reg_codec_mic>;
+ };
+};
+
+&i2c3 {
+ eeprom@57 {
+ compatible = "atmel,24c64";
+ reg = <0x57>;
+ pagesize = <32>;
+ };
+};
+
+&pcie {
+ status = "okay";
+};
+
+&ssi1 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&usbh1 {
+ status = "okay";
+};
+
+&usbotg {
+ status = "okay";
+};
+
+&usdhc3 {
+ status = "okay";
+};
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 85aeebc9485d..99b5e78458aa 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i.dtsi
@@ -61,6 +61,18 @@
vin-supply = <&reg_smarc_suppy>;
};
+ reg_sdio: regulator-sdio {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_sdio>;
+ regulator-name = "V_3V3_SD";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ off-on-delay-us = <20000>;
+ };
+
reg_smarc_lcdbklt: regulator-smarc-lcdbklt {
compatible = "regulator-fixed";
pinctrl-names = "default";
@@ -137,7 +149,7 @@
status = "disabled";
};
- i2c_intern: i2c-gpio-intern {
+ i2c_intern: i2c-0 {
compatible = "i2c-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c_gpio_intern>;
@@ -148,7 +160,7 @@
#size-cells = <0>;
};
- i2c_lcd: i2c-gpio-lcd {
+ i2c_lcd: i2c-1 {
compatible = "i2c-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c_gpio_lcd>;
@@ -160,7 +172,7 @@
status = "disabled";
};
- i2c_cam: i2c-gpio-cam {
+ i2c_cam: i2c-2 {
compatible = "i2c-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c_gpio_cam>;
@@ -178,7 +190,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audmux>;
- audmux_ssi1 {
+ mux-ssi1 {
fsl,audmux-port = <MX51_AUDMUX_PORT1_SSI0>;
fsl,port-config = <
(IMX_AUDMUX_V2_PTCR_TFSEL(MX51_AUDMUX_PORT3) |
@@ -190,7 +202,7 @@
>;
};
- audmux_adu3 {
+ mux-aud3 {
fsl,audmux-port = <MX51_AUDMUX_PORT3>;
fsl,port-config = <
IMX_AUDMUX_V2_PTCR_SYN
@@ -198,7 +210,7 @@
>;
};
- audmux_ssi2 {
+ mux-ssi2 {
fsl,audmux-port = <MX51_AUDMUX_PORT2_SSI1>;
fsl,port-config = <
(IMX_AUDMUX_V2_PTCR_TFSEL(MX51_AUDMUX_PORT4) |
@@ -210,7 +222,7 @@
>;
};
- audmux_adu4 {
+ mux-aud4 {
fsl,audmux-port = <MX51_AUDMUX_PORT4>;
fsl,port-config = <
IMX_AUDMUX_V2_PTCR_SYN
@@ -244,7 +256,8 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi4>;
cs-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>,
- <&gpio3 29 GPIO_ACTIVE_LOW>;
+ <&gpio3 29 GPIO_ACTIVE_LOW>,
+ <&gpio3 25 GPIO_ACTIVE_LOW>;
status = "okay";
/* default boot source: workaround #1 for errata ERR006282 */
@@ -259,7 +272,7 @@
&fec {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet>;
- phy-mode = "rgmii";
+ phy-connection-type = "rgmii-id";
phy-handle = <&ethphy>;
mdio {
@@ -269,7 +282,7 @@
ethphy: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
- reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
reset-assert-us = <1000>;
};
};
@@ -356,10 +369,6 @@
regulator-always-on;
};
- /*
- * Per schematics, of all VGEN's, only VGEN5 has some
- * usage ... but even that - over DNI resistor
- */
vgen1 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1550000>;
@@ -380,8 +389,7 @@
regulator-max-microvolt = <3300000>;
};
- reg_2p5v_s0: vgen5 {
- regulator-name = "V_2V5_S0";
+ vgen5 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
};
@@ -464,6 +472,8 @@
MX6QDL_PAD_EIM_D24__GPIO3_IO24 0x1b0b0
/* SPI_IMX_CS0# - connected to SMARC SPI0_CS0# */
MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b0
+ /* SPI4_CS3# - connected to SMARC SPI0_CS1# */
+ MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x1b0b0
>;
};
@@ -516,7 +526,7 @@
MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x1b0b0 /* RST_GBE0_PHY# */
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0 /* RST_GBE0_PHY# */
>;
};
@@ -642,6 +652,12 @@
>;
};
+ pinctrl_reg_sdio: reg-sdiogrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x1b0b0 /* SDIO_PWR_EN */
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
@@ -694,7 +710,6 @@
MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x1b0b0 /* CD */
MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x1b0b0 /* WP */
- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x1b0b0 /* PWR_EN */
>;
};
@@ -728,8 +743,7 @@
&pcie {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pcie>;
- wake-up-gpio = <&gpio6 18 GPIO_ACTIVE_HIGH>;
- reset-gpio = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+ reset-gpio = <&gpio3 13 GPIO_ACTIVE_LOW>;
};
/* LCD_BKLT_PWM */
@@ -797,12 +811,12 @@
pinctrl-0 = <&pinctrl_usdhc3>;
cd-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+ vmmc-supply = <&reg_sdio>;
no-1-8-v;
};
/* SDMMC */
&usdhc4 {
- /* Internal eMMC, optional on some boards */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc4>;
bus-width = <8>;
@@ -811,11 +825,13 @@
non-removable;
vmmc-supply = <&reg_3p3v_s0>;
vqmmc-supply = <&reg_1p8v_s0>;
+ status = "okay";
};
&wdog1 {
/* CPLD is feeded by watchdog (hardwired) */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_wdog1>;
+ fsl,ext-reset-output;
status = "okay";
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi
index 238f3af42822..807f3c95e3ce 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi
@@ -22,12 +22,16 @@
compatible = "atmel,24c64";
reg = <0x57>;
pagesize = <32>;
- #address-cells = <1>;
- #size-cells = <1>;
vcc-supply = <&reg_mba6_3p3v>;
- mba_mac_address: mac-address@20 {
- reg = <0x20 0x6>;
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mba_mac_address: mac-address@20 {
+ reg = <0x20 0x6>;
+ };
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi
index a587bc88f76f..789733a45b95 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi
@@ -32,12 +32,16 @@
compatible = "atmel,24c64";
reg = <0x57>;
pagesize = <32>;
- #address-cells = <1>;
- #size-cells = <1>;
vcc-supply = <&reg_mba6_3p3v>;
- mba_mac_address: mac-address@20 {
- reg = <0x20 0x6>;
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mba_mac_address: mac-address@20 {
+ reg = <0x20 0x6>;
+ };
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
index 6656e2e762a1..0a3deaf92eea 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
@@ -786,7 +786,7 @@
display-timings {
native-mode = <&timing0>;
- timing0: hsd100pxn1 {
+ timing0: timing-hsd100pxn1 {
clock-frequency = <65000000>;
hactive = <1024>;
vactive = <768>;
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 79f2354886b7..ded241a39906 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lcd.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lcd.dtsi
@@ -110,7 +110,7 @@
};
display-timings {
- VGA {
+ timing-vga {
clock-frequency = <25200000>;
hactive = <640>;
vactive = <480>;
@@ -126,8 +126,7 @@
pixelclk-active = <0>;
};
- ETV570 {
- u-boot,panel-name = "edt,et057090dhu";
+ timing-etv570 {
clock-frequency = <25200000>;
hactive = <640>;
vactive = <480>;
@@ -143,8 +142,7 @@
pixelclk-active = <0>;
};
- ET0350 {
- u-boot,panel-name = "edt,et0350g0dh6";
+ timing-et0350 {
clock-frequency = <6413760>;
hactive = <320>;
vactive = <240>;
@@ -160,8 +158,7 @@
pixelclk-active = <0>;
};
- ET0430 {
- u-boot,panel-name = "edt,et0430g0dh6";
+ timing-et0430 {
clock-frequency = <9009000>;
hactive = <480>;
vactive = <272>;
@@ -177,7 +174,7 @@
pixelclk-active = <1>;
};
- ET0500 {
+ timing-et0500 {
clock-frequency = <33264000>;
hactive = <800>;
vactive = <480>;
@@ -193,8 +190,7 @@
pixelclk-active = <0>;
};
- ET0700 { /* same as ET0500 */
- u-boot,panel-name = "edt,etm0700g0dh6";
+ timing-et0700 { /* same as ET0500 */
clock-frequency = <33264000>;
hactive = <800>;
vactive = <480>;
@@ -210,7 +206,7 @@
pixelclk-active = <0>;
};
- ETQ570 {
+ timing-etq570 {
clock-frequency = <6596040>;
hactive = <320>;
vactive = <240>;
@@ -226,8 +222,7 @@
pixelclk-active = <0>;
};
- CoMTFT { /* same as ET0700 but with inverted pixel clock */
- u-boot,panel-name = "edt,etm0700g0edh6";
+ timing-comtft { /* same as ET0700 but with inverted pixel clock */
clock-frequency = <33264000>;
hactive = <800>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lvds.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lvds.dtsi
index 2ca2eb37e14f..4eb53d5677a6 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lvds.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lvds.dtsi
@@ -127,8 +127,7 @@
};
display-timings {
- hsd100pxn1 {
- u-boot,panel-name = "hannstar,hsd100pxn1";
+ timing-hsd100pxn1 {
clock-frequency = <65000000>;
hactive = <1024>;
vactive = <768>;
@@ -142,7 +141,7 @@
pixelclk-active = <1>;
};
- VGA {
+ timing-vga {
clock-frequency = <25200000>;
hactive = <640>;
vactive = <480>;
@@ -158,8 +157,7 @@
pixelclk-active = <0>;
};
- nl12880bc20 {
- u-boot,panel-name = "nlt,nl12880bc20-spwg-24";
+ timing-nl12880bc20 {
clock-frequency = <71000000>;
hactive = <1280>;
vactive = <800>;
@@ -175,8 +173,7 @@
pixelclk-active = <1>;
};
- ET0700 {
- u-boot,panel-name = "edt,etm0700g0dh6";
+ timing-et0700 {
clock-frequency = <33264000>;
hactive = <800>;
vactive = <480>;
@@ -192,8 +189,7 @@
pixelclk-active = <0>;
};
- ETV570 {
- u-boot,panel-name = "edt,et057090dhu";
+ timing-etv570 {
clock-frequency = <25200000>;
hactive = <640>;
vactive = <480>;
@@ -224,7 +220,7 @@
};
display-timings {
- hsd100pxn1 {
+ timing-hsd100pxn1 {
clock-frequency = <65000000>;
hactive = <1024>;
vactive = <768>;
@@ -238,7 +234,7 @@
pixelclk-active = <1>;
};
- VGA {
+ timing-vga {
clock-frequency = <25200000>;
hactive = <640>;
vactive = <480>;
@@ -254,7 +250,7 @@
pixelclk-active = <0>;
};
- nl12880bc20 {
+ timing-nl12880bc20 {
clock-frequency = <71000000>;
hactive = <1280>;
vactive = <800>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi
index 1db146ac1c17..864173e30709 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi
@@ -405,7 +405,7 @@
status = "okay";
display-timings {
- VGA {
+ timing-vga {
clock-frequency = <25200000>;
hactive = <640>;
vactive = <480>;
@@ -421,7 +421,7 @@
pixelclk-active = <1>;
};
- ETV570 {
+ timing-etv570 {
clock-frequency = <25200000>;
hactive = <640>;
vactive = <480>;
@@ -437,7 +437,7 @@
pixelclk-active = <1>;
};
- ET0350 {
+ timing-et0350 {
clock-frequency = <6413760>;
hactive = <320>;
vactive = <240>;
@@ -453,7 +453,7 @@
pixelclk-active = <1>;
};
- ET0430 {
+ timing-et0430 {
clock-frequency = <9009000>;
hactive = <480>;
vactive = <272>;
@@ -469,7 +469,7 @@
pixelclk-active = <0>;
};
- ET0500 {
+ timing-et0500 {
clock-frequency = <33264000>;
hactive = <800>;
vactive = <480>;
@@ -485,7 +485,7 @@
pixelclk-active = <1>;
};
- ET0700 { /* same as ET0500 */
+ timing-et0700 { /* same as ET0500 */
clock-frequency = <33264000>;
hactive = <800>;
vactive = <480>;
@@ -501,7 +501,7 @@
pixelclk-active = <1>;
};
- ETQ570 {
+ timing-etq570 {
clock-frequency = <6596040>;
hactive = <320>;
vactive = <240>;
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts b/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts
index 5485fe118dc4..d38183edf0fd 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts
@@ -323,7 +323,6 @@
display-timings {
native-mode = <&timing5>;
timing0: timing0 {
- panel-name = "VGA";
clock-frequency = <25175000>;
hactive = <640>;
vactive = <480>;
@@ -340,7 +339,6 @@
};
timing1: timing1 {
- panel-name = "ETV570";
clock-frequency = <25175000>;
hactive = <640>;
vactive = <480>;
@@ -357,7 +355,6 @@
};
timing2: timing2 {
- panel-name = "ET0350";
clock-frequency = <6500000>;
hactive = <320>;
vactive = <240>;
@@ -374,7 +371,6 @@
};
timing3: timing3 {
- panel-name = "ET0430";
clock-frequency = <9000000>;
hactive = <480>;
vactive = <272>;
@@ -391,7 +387,6 @@
};
timing4: timing4 {
- panel-name = "ET0500", "ET0700";
clock-frequency = <33260000>;
hactive = <800>;
vactive = <480>;
@@ -408,7 +403,6 @@
};
timing5: timing5 {
- panel-name = "ETQ570";
clock-frequency = <6400000>;
hactive = <320>;
vactive = <240>;
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index e2e922bdc9e9..f06c6d425e91 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -6,6 +6,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-apq8026-huawei-sturgeon.dtb \
qcom-apq8026-lg-lenok.dtb \
qcom-apq8026-samsung-matisse-wifi.dtb \
+ qcom-apq8026-samsung-milletwifi.dtb \
qcom-apq8060-dragonboard.dtb \
qcom-apq8064-cm-qs600.dtb \
qcom-apq8064-ifc6410.dtb \
@@ -27,6 +28,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-msm8226-microsoft-dempsey.dtb \
qcom-msm8226-microsoft-makepeace.dtb \
qcom-msm8226-microsoft-moneypenny.dtb \
+ qcom-msm8226-samsung-ms013g.dtb \
qcom-msm8226-samsung-s3ve3g.dtb \
qcom-msm8660-surf.dtb \
qcom-msm8916-samsung-e5.dtb \
@@ -41,12 +43,15 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-msm8960-cdp.dtb \
qcom-msm8960-samsung-expressatt.dtb \
qcom-msm8974-lge-nexus5-hammerhead.dtb \
+ qcom-msm8974-samsung-hlte.dtb \
qcom-msm8974-sony-xperia-rhine-amami.dtb \
qcom-msm8974-sony-xperia-rhine-honami.dtb \
qcom-msm8974pro-fairphone-fp2.dtb \
+ qcom-msm8974pro-htc-m8.dtb \
qcom-msm8974pro-oneplus-bacon.dtb \
qcom-msm8974pro-samsung-klte.dtb \
qcom-msm8974pro-samsung-kltechn.dtb \
+ qcom-msm8974pro-sony-xperia-shinano-aries.dtb \
qcom-msm8974pro-sony-xperia-shinano-castor.dtb \
qcom-msm8974pro-sony-xperia-shinano-leo.dtb \
qcom-mdm9615-wp8548-mangoh-green.dtb \
diff --git a/arch/arm/boot/dts/qcom/msm8226-motorola-falcon.dts b/arch/arm/boot/dts/qcom/msm8226-motorola-falcon.dts
index 029e1b1659c9..5dbca83f2230 100644
--- a/arch/arm/boot/dts/qcom/msm8226-motorola-falcon.dts
+++ b/arch/arm/boot/dts/qcom/msm8226-motorola-falcon.dts
@@ -96,6 +96,35 @@
};
};
+&blsp1_i2c2 {
+ status = "okay";
+
+ magnetometer@c {
+ compatible = "asahi-kasei,ak8963";
+ reg = <0xc>;
+ interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&tlmm 62 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&pm8226_l19>;
+ vid-supply = <&pm8226_lvs1>;
+ pinctrl-0 = <&mag_int_default &mag_reset_default>;
+ pinctrl-names = "default";
+ };
+
+ accelerometer@19 {
+ compatible = "st,lis3dh-accel";
+ reg = <0x19>;
+ interrupts-extended = <&tlmm 63 IRQ_TYPE_EDGE_FALLING>;
+ vdd-supply = <&pm8226_l19>;
+ vddio-supply = <&pm8226_lvs1>;
+ pinctrl-0 = <&accel_int_default>;
+ pinctrl-names = "default";
+ mount-matrix = "0", "1", "0",
+ "1", "0", "0",
+ "0", "0", "-1";
+ st,drdy-int-pin = <1>;
+ };
+};
+
&blsp1_i2c3 {
status = "okay";
@@ -321,6 +350,30 @@
};
&tlmm {
+ accel_int_default: accel-int-default-state {
+ pins = "gpio63";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-disable;
+ };
+
+ mag_int_default: mag-int-default-state {
+ pins = "gpio66";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-disable;
+ };
+
+ mag_reset_default: mag-reset-default-state {
+ pins = "gpio62";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
reg_lcd_default: reg-lcd-default-state {
pins = "gpio31", "gpio33";
function = "gpio";
diff --git a/arch/arm/boot/dts/qcom/qcom-apq8026-samsung-milletwifi.dts b/arch/arm/boot/dts/qcom/qcom-apq8026-samsung-milletwifi.dts
new file mode 100644
index 000000000000..7d519156d91d
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/qcom-apq8026-samsung-milletwifi.dts
@@ -0,0 +1,573 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, Matti Lehtimäki <[email protected]>
+ * Copyright (c) 2023, Bryant Mairs <[email protected]>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/power/summit,smb347-charger.h>
+#include "qcom-msm8226.dtsi"
+#include "pm8226.dtsi"
+
+/delete-node/ &adsp_region;
+/delete-node/ &smem_region;
+
+/ {
+ model = "Samsung Galaxy Tab 4 8.0 Wi-Fi";
+ compatible = "samsung,milletwifi", "qcom,apq8026";
+ chassis-type = "tablet";
+
+ aliases {
+ display0 = &framebuffer0;
+ mmc0 = &sdhc_1; /* SDC1 eMMC slot */
+ mmc1 = &sdhc_2; /* SDC2 SD card slot */
+ };
+
+ chosen {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ stdout-path = "display0";
+
+ framebuffer0: framebuffer@3200000 {
+ compatible = "simple-framebuffer";
+ reg = <0x03200000 0x800000>;
+ width = <800>;
+ height = <1280>;
+ stride = <(800 * 3)>;
+ format = "r8g8b8";
+ };
+ };
+
+ gpio-hall-sensor {
+ compatible = "gpio-keys";
+
+ event-hall-sensor {
+ label = "Cover";
+ gpios = <&tlmm 37 GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ debounce-interval = <15>;
+ linux,can-disable;
+ wakeup-source;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ autorepeat;
+
+ key-home {
+ label = "Home";
+ gpios = <&tlmm 108 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ debounce-interval = <15>;
+ };
+
+ key-volume-down {
+ label = "Volume Down";
+ gpios = <&tlmm 107 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ debounce-interval = <15>;
+ };
+
+ key-volume-up {
+ label = "Volume Up";
+ gpios = <&tlmm 106 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <15>;
+ };
+ };
+
+ i2c-backlight {
+ compatible = "i2c-gpio";
+ sda-gpios = <&tlmm 20 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&tlmm 21 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+
+ pinctrl-0 = <&backlight_i2c_default_state>;
+ pinctrl-names = "default";
+
+ i2c-gpio,delay-us = <4>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ backlight@2c {
+ compatible = "ti,lp8556";
+ reg = <0x2c>;
+ enable-supply = <&reg_backlight_vddio>;
+
+ dev-ctrl = /bits/ 8 <0x80>;
+ init-brt = /bits/ 8 <0x3f>;
+
+ /*
+ * Change transition duration: 200ms, Change
+ * transition strength: heavy, PWM hysteresis:
+ * 1-bit w/ 8-bit resolution
+ */
+ rom-a3h {
+ rom-addr = /bits/ 8 <0xa3>;
+ rom-val = /bits/ 8 <0x5e>;
+ };
+
+ /*
+ * PWM phase configuration: 3-phase/3 drivers
+ * (0, 120deg, 240deg, -, -, -),
+ * PWM frequency: 9616Hz (10-bit)
+ */
+ rom-a5h {
+ rom-addr = /bits/ 8 <0xa5>;
+ rom-val = /bits/ 8 <0x34>;
+ };
+
+ /*
+ * Enable LED drivers 2 & 3, Boot inductor
+ * current limit: 1.5A/2.6A
+ */
+ rom-a7h {
+ rom-addr = /bits/ 8 <0xa7>;
+ rom-val = /bits/ 8 <0xfa>;
+ };
+ };
+ };
+
+ reg_backlight_vddio: regulator-backlight-vddio {
+ compatible = "regulator-fixed";
+ regulator-name = "backlight_vddio";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&backlight_vddio_default_state>;
+ pinctrl-names = "default";
+ };
+
+ reg_tsp_1p8v: regulator-tsp-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "tsp_1p8v";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&tlmm 114 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&tsp_en1_default_state>;
+ pinctrl-names = "default";
+ };
+
+ reg_tsp_3p3v: regulator-tsp-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "tsp_3p3v";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 31 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&tsp_en_default_state>;
+ pinctrl-names = "default";
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ framebuffer@3200000 {
+ reg = <0x03200000 0x800000>;
+ no-map;
+ };
+
+ mpss_region: mpss@8400000 {
+ reg = <0x08400000 0x1f00000>;
+ no-map;
+ };
+
+ mba_region: mba@a300000 {
+ reg = <0x0a300000 0x100000>;
+ no-map;
+ };
+
+ reserved@cb00000 {
+ reg = <0x0cb00000 0x700000>;
+ no-map;
+ };
+
+ wcnss_region: wcnss@d200000 {
+ reg = <0x0d200000 0x700000>;
+ no-map;
+ };
+
+ adsp_region: adsp@d900000 {
+ reg = <0x0d900000 0x1800000>;
+ no-map;
+ };
+
+ venus@f100000 {
+ reg = <0x0f100000 0x500000>;
+ no-map;
+ };
+
+ smem_region: smem@fa00000 {
+ reg = <0x0fa00000 0x100000>;
+ no-map;
+ };
+
+ reserved@fb00000 {
+ reg = <0x0fb00000 0x260000>;
+ no-map;
+ };
+
+ rfsa@fd60000 {
+ reg = <0x0fd60000 0x20000>;
+ no-map;
+ };
+
+ rmtfs@fd80000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0x0fd80000 0x180000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ };
+ };
+};
+
+&blsp1_i2c2 {
+ status = "okay";
+
+ accelerometer@1d {
+ compatible = "st,lis2hh12";
+ reg = <0x1d>;
+
+ interrupts-extended = <&tlmm 54 IRQ_TYPE_LEVEL_HIGH>;
+
+ pinctrl-0 = <&accel_int_default_state>;
+ pinctrl-names = "default";
+
+ vdd-supply = <&pm8226_l19>;
+ vddio-supply = <&pm8226_lvs1>;
+
+ mount-matrix = "0", "1", "0",
+ "-1", "0", "0",
+ "0", "0", "1";
+
+ st,drdy-int-pin = <1>;
+ };
+};
+
+&blsp1_i2c3 {
+ status = "okay";
+
+ charger@6a {
+ compatible = "summit,smb358";
+ reg = <0x6a>;
+
+ interrupts-extended = <&tlmm 115 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&charger_int_default_state>;
+ pinctrl-names = "default";
+
+ summit,enable-usb-charging;
+ summit,enable-charge-control = <SMB3XX_CHG_ENABLE_SW>;
+ summit,fast-voltage-threshold-microvolt = <3000000>;
+ summit,chip-temperature-threshold-celsius = <130>;
+ summit,usb-current-limit-microamp = <1500000>;
+ };
+};
+
+&blsp1_i2c4 {
+ status = "okay";
+
+ muic: usb-switch@25 {
+ compatible = "siliconmitus,sm5502-muic";
+ reg = <0x25>;
+
+ interrupts-extended = <&tlmm 67 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&muic_int_default_state>;
+ pinctrl-names = "default";
+ };
+};
+
+&blsp1_i2c5 {
+ status = "okay";
+
+ touchscreen@48 {
+ compatible = "melfas,mms252", "melfas,mms114";
+ reg = <0x48>;
+ interrupts-extended = <&tlmm 17 IRQ_TYPE_EDGE_FALLING>;
+ touchscreen-size-x = <800>;
+ touchscreen-size-y = <1280>;
+ avdd-supply = <&reg_tsp_3p3v>;
+ vdd-supply = <&reg_tsp_1p8v>;
+ linux,keycodes = <KEY_APPSELECT KEY_BACK>;
+
+ pinctrl-0 = <&tsp_int_rst_default_state>;
+ pinctrl-names = "default";
+ };
+};
+
+&rpm_requests {
+ regulators {
+ compatible = "qcom,rpm-pm8226-regulators";
+
+ pm8226_s3: s3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm8226_s4: s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_s5: s5 {
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ };
+
+ pm8226_l1: l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8226_l2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l3: l3 {
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1337500>;
+ regulator-always-on;
+ };
+
+ pm8226_l4: l4 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l5: l5 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l6: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ pm8226_l7: l7 {
+ regulator-min-microvolt = <1850000>;
+ regulator-max-microvolt = <1850000>;
+ };
+
+ pm8226_l8: l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ pm8226_l9: l9 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8226_l10: l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l12: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l14: l14 {
+ regulator-min-microvolt = <2750000>;
+ regulator-max-microvolt = <2750000>;
+ };
+
+ pm8226_l15: l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8226_l16: l16 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3350000>;
+ };
+
+ pm8226_l17: l17 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+
+ regulator-system-load = <200000>;
+ regulator-allow-set-load;
+ regulator-always-on;
+ };
+
+ pm8226_l18: l18 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l19: l19 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8226_l20: l20 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+
+ pm8226_l21: l21 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l22: l22 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8226_l23: l23 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8226_l24: l24 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ pm8226_l25: l25 {
+ regulator-min-microvolt = <1775000>;
+ regulator-max-microvolt = <2125000>;
+ };
+
+ pm8226_l26: l26 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm8226_l27: l27 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l28: l28 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_lvs1: lvs1 {};
+ };
+};
+
+&sdhc_1 {
+ vmmc-supply = <&pm8226_l17>;
+ vqmmc-supply = <&pm8226_l6>;
+
+ bus-width = <8>;
+ non-removable;
+
+ status = "okay";
+};
+
+&sdhc_2 {
+ vmmc-supply = <&pm8226_l18>;
+ vqmmc-supply = <&pm8226_l21>;
+
+ bus-width = <4>;
+ cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&sdhc2_default_state>, <&sdc2_cd_default_state>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&tlmm {
+ accel_int_default_state: accel-int-default-state {
+ pins = "gpio54";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ backlight_i2c_default_state: backlight-i2c-default-state {
+ pins = "gpio20", "gpio21";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ backlight_vddio_default_state: backlight-vddio-default-state {
+ pins = "gpio74";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ charger_int_default_state: charger-int-default-state {
+ pins = "gpio115";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ muic_int_default_state: muic-int-default-state {
+ pins = "gpio67";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ sdc2_cd_default_state: sdc2-cd-default-state {
+ pins = "gpio38";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tsp_en_default_state: tsp-en-default-state {
+ pins = "gpio31";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tsp_en1_default_state: tsp-en1-default-state {
+ pins = "gpio114";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tsp_int_rst_default_state: tsp-int-rst-default-state {
+ pins = "gpio17";
+ function = "gpio";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+};
+
+&usb {
+ extcon = <&muic>, <&muic>;
+ status = "okay";
+};
+
+&usb_hs_phy {
+ extcon = <&muic>;
+ v1p8-supply = <&pm8226_l10>;
+ v3p3-supply = <&pm8226_l20>;
+};
diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index 11e60b74c3c9..769e151747c3 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -666,12 +666,12 @@
qcom,controller-type = "pmic-arbiter";
};
- qfprom: qfprom@700000 {
+ qfprom: efuse@700000 {
compatible = "qcom,apq8064-qfprom", "qcom,qfprom";
reg = <0x00700000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
- ranges;
+
tsens_calib: calib@404 {
reg = <0x404 0x10>;
};
@@ -684,7 +684,6 @@
compatible = "qcom,gcc-apq8064", "syscon";
reg = <0x00900000 0x4000>;
#clock-cells = <1>;
- #power-domain-cells = <1>;
#reset-cells = <1>;
clocks = <&cxo_board>,
<&pxo_board>,
@@ -993,7 +992,7 @@
reg = <0x1a400000 0x100>;
};
- gpu: adreno-3xx@4300000 {
+ gpu: gpu@4300000 {
compatible = "qcom,adreno-320.2", "qcom,adreno";
reg = <0x04300000 0x20000>;
reg-names = "kgsl_3d0_reg_memory";
diff --git a/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi
index ca53dff820ef..2b52e5d5eb51 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi
@@ -245,7 +245,7 @@
reg = <0xfc190000 0x10000>;
};
- qfprom: qfprom@fc4bc000 {
+ qfprom: efuse@fc4bc000 {
compatible = "qcom,apq8084-qfprom", "qcom,qfprom";
reg = <0xfc4bc000 0x1000>;
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi
index 0fb65f2bbcdf..56415ab34083 100644
--- a/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi
@@ -187,7 +187,6 @@
gcc: clock-controller@1800000 {
compatible = "qcom,gcc-ipq4019";
#clock-cells = <1>;
- #power-domain-cells = <1>;
#reset-cells = <1>;
reg = <0x1800000 0x60000>;
clocks = <&xo>, <&sleep_clk>;
diff --git a/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
index f128510d8445..da0fd75f4711 100644
--- a/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
@@ -372,7 +372,7 @@
qcom,controller-type = "pmic-arbiter";
};
- qfprom: qfprom@700000 {
+ qfprom: efuse@700000 {
compatible = "qcom,ipq8064-qfprom", "qcom,qfprom";
reg = <0x00700000 0x1000>;
#address-cells = <1>;
@@ -519,7 +519,6 @@
reg = <0x00900000 0x4000>;
#clock-cells = <1>;
#reset-cells = <1>;
- #power-domain-cells = <1>;
tsens: thermal-sensor {
compatible = "qcom,ipq8064-tsens";
diff --git a/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi b/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi
index 34c60994d026..573feb3218c3 100644
--- a/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi
@@ -102,7 +102,6 @@
gcc: clock-controller@900000 {
compatible = "qcom,gcc-mdm9615";
#clock-cells = <1>;
- #power-domain-cells = <1>;
#reset-cells = <1>;
reg = <0x900000 0x4000>;
clocks = <&cxo_board>,
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-common.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-common.dtsi
index 525d8c608b06..8839b23fc693 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-common.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-common.dtsi
@@ -287,6 +287,10 @@
status = "okay";
};
+&smbb {
+ status = "okay";
+};
+
&usb {
extcon = <&smbb>;
dr_mode = "peripheral";
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8226-samsung-ms013g.dts b/arch/arm/boot/dts/qcom/qcom-msm8226-samsung-ms013g.dts
new file mode 100644
index 000000000000..2ecc5983d365
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/qcom-msm8226-samsung-ms013g.dts
@@ -0,0 +1,386 @@
+// SPDX-License-Identifier: BSD-3-Clause
+
+/dts-v1/;
+
+#include "qcom-msm8226.dtsi"
+#include "pm8226.dtsi"
+
+/delete-node/ &smem_region;
+
+/ {
+ model = "Samsung Galaxy Grand 2";
+ compatible = "samsung,ms013g", "qcom,msm8226";
+ chassis-type = "handset";
+
+ aliases {
+ mmc0 = &sdhc_1; /* SDC1 eMMC slot */
+ mmc1 = &sdhc_2; /* SDC2 SD card slot */
+ serial0 = &blsp1_uart3;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio-hall-sensor {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&gpio_hall_sensor_default>;
+ pinctrl-names = "default";
+
+ label = "GPIO Hall Effect Sensor";
+
+ event-hall-sensor {
+ label = "Hall Effect Sensor";
+ gpios = <&tlmm 50 GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ linux,can-disable;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&gpio_keys_default>;
+ pinctrl-names = "default";
+
+ label = "GPIO Buttons";
+
+ button-volume-up {
+ label = "Volume Up";
+ gpios = <&tlmm 106 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ button-volume-down {
+ label = "Volume Down";
+ gpios = <&tlmm 107 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-home {
+ label = "Home Key";
+ gpios = <&tlmm 108 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ };
+ };
+
+ reg_motor_vdd: regulator-motor-vdd {
+ compatible = "regulator-fixed";
+ regulator-name = "motor_vdd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 111 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&motor_en_default>;
+ pinctrl-names = "default";
+ };
+
+ reg_vdd_tsp_a: regulator-vdd-tsp-a {
+ compatible = "regulator-fixed";
+ regulator-name = "tsp_3p3v";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 31 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&tsp_en_default>;
+ pinctrl-names = "default";
+ };
+
+ reserved-memory {
+ smem_region: smem@fa00000 {
+ reg = <0x0fa00000 0x100000>;
+ no-map;
+ };
+ };
+
+ vibrator {
+ compatible = "regulator-haptic";
+ haptic-supply = <&reg_motor_vdd>;
+ min-microvolt = <3300000>;
+ max-microvolt = <3300000>;
+ };
+};
+
+&blsp1_i2c2 {
+ status = "okay";
+
+ accelerometer@18 {
+ compatible = "bosch,bma255";
+ reg = <0x18>;
+ interrupts-extended = <&tlmm 64 IRQ_TYPE_EDGE_RISING>;
+
+ vdd-supply = <&pm8226_l19>;
+ vddio-supply = <&pm8226_lvs1>;
+
+ pinctrl-0 = <&accel_int_default>;
+ pinctrl-names = "default";
+
+ mount-matrix = "0", "1", "0",
+ "-1", "0", "0",
+ "0", "0", "-1";
+ };
+};
+
+&blsp1_i2c5 {
+ status = "okay";
+
+ touchscreen@20 {
+ compatible = "zinitix,bt541";
+
+ reg = <0x20>;
+ interrupts-extended = <&tlmm 17 IRQ_TYPE_EDGE_FALLING>;
+
+ touchscreen-size-x = <720>;
+ touchscreen-size-y = <1280>;
+
+ vcca-supply = <&reg_vdd_tsp_a>;
+ vdd-supply = <&pm8226_lvs1>;
+
+ pinctrl-0 = <&tsp_int_default>;
+ pinctrl-names = "default";
+ };
+};
+
+&blsp1_uart3 {
+ status = "okay";
+};
+
+&rpm_requests {
+ regulators {
+ compatible = "qcom,rpm-pm8226-regulators";
+
+ pm8226_s3: s3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm8226_s4: s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2200000>;
+ };
+
+ pm8226_s5: s5 {
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ };
+
+ pm8226_l1: l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8226_l2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l3: l3 {
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1337500>;
+ };
+
+ pm8226_l4: l4 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l5: l5 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l6: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allow-set-load;
+ regulator-always-on;
+ };
+
+ pm8226_l7: l7 {
+ regulator-min-microvolt = <1850000>;
+ regulator-max-microvolt = <1850000>;
+ };
+
+ pm8226_l8: l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l9: l9 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8226_l10: l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l12: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l14: l14 {
+ regulator-min-microvolt = <2750000>;
+ regulator-max-microvolt = <2750000>;
+ };
+
+ pm8226_l15: l15 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ pm8226_l16: l16 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3350000>;
+ };
+
+ pm8226_l17: l17 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+
+ regulator-system-load = <200000>;
+ regulator-allow-set-load;
+ regulator-always-on;
+ };
+
+ pm8226_l18: l18 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l19: l19 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8226_l20: l20 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+
+ pm8226_l21: l21 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-allow-set-load;
+ };
+
+ pm8226_l22: l22 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l23: l23 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8226_l24: l24 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ pm8226_l25: l25 {
+ regulator-min-microvolt = <1775000>;
+ regulator-max-microvolt = <2125000>;
+ };
+
+ pm8226_l26: l26 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm8226_l27: l27 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8226_l28: l28 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_lvs1: lvs1 {};
+ };
+};
+
+&sdhc_1 {
+ vmmc-supply = <&pm8226_l17>;
+ vqmmc-supply = <&pm8226_l6>;
+
+ bus-width = <8>;
+ non-removable;
+
+ status = "okay";
+};
+
+&sdhc_2 {
+ vmmc-supply = <&pm8226_l18>;
+ vqmmc-supply = <&pm8226_l21>;
+
+ bus-width = <4>;
+ cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&sdhc2_default_state &sdhc2_cd_default>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&tlmm {
+ accel_int_default: accel-int-default-state {
+ pins = "gpio64";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ gpio_hall_sensor_default: gpio-hall-sensor-default-state {
+ pins = "gpio50";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ gpio_keys_default: gpio-keys-default-state {
+ pins = "gpio106", "gpio107", "gpio108";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ motor_en_default: motor-en-default-state {
+ pins = "gpio111";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ sdhc2_cd_default: sdhc2-cd-default-state {
+ pins = "gpio38";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tsp_en_default: tsp-en-default-state {
+ pins = "gpio31";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tsp_int_default: tsp-int-default-state {
+ pins = "gpio17";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi
index 270973e85625..b2f92ad6499a 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi
@@ -635,7 +635,7 @@
reg = <0xfc4ab000 0x4>;
};
- qfprom: qfprom@fc4bc000 {
+ qfprom: efuse@fc4bc000 {
compatible = "qcom,msm8226-qfprom", "qcom,qfprom";
reg = <0xfc4bc000 0x1000>;
#address-cells = <1>;
@@ -1046,7 +1046,7 @@
};
};
- gpu: adreno@fdb00000 {
+ gpu: gpu@fdb00000 {
compatible = "qcom,adreno-305.18", "qcom,adreno";
reg = <0xfdb00000 0x10000>;
reg-names = "kgsl_3d0_reg_memory";
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8660.dtsi
index 455ba4bf1bf4..a66c474cd1aa 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8660.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8660.dtsi
@@ -113,7 +113,6 @@
gcc: clock-controller@900000 {
compatible = "qcom,gcc-msm8660";
#clock-cells = <1>;
- #power-domain-cells = <1>;
#reset-cells = <1>;
reg = <0x900000 0x4000>;
clocks = <&pxo_board>, <&cxo_board>;
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8926-motorola-peregrine.dts b/arch/arm/boot/dts/qcom/qcom-msm8926-motorola-peregrine.dts
index 0cbe2d2fbbb1..376a33125941 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8926-motorola-peregrine.dts
+++ b/arch/arm/boot/dts/qcom/qcom-msm8926-motorola-peregrine.dts
@@ -29,6 +29,10 @@
height = <1280>;
stride = <(720 * 3)>;
format = "r8g8b8";
+ vsp-supply = <&reg_lcd_pos>;
+ vsn-supply = <&reg_lcd_neg>;
+ vdd-supply = <&pm8226_l28>;
+ vddio-supply = <&vddio_disp_vreg>;
};
};
@@ -51,6 +55,18 @@
};
};
+ vddio_disp_vreg: regulator-vddio-disp {
+ compatible = "regulator-fixed";
+ regulator-name = "vddio_disp";
+ gpio = <&tlmm 34 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <300>;
+ enable-active-high;
+ regulator-boot-on;
+ vin-supply = <&pm8226_l8>;
+ pinctrl-0 = <&disp_vddio_default>;
+ pinctrl-names = "default";
+ };
+
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
@@ -68,12 +84,67 @@
};
};
+&blsp1_i2c2 {
+ clock-frequency = <100000>;
+ status = "okay";
+
+ magnetometer@c {
+ compatible = "asahi-kasei,ak8963";
+ reg = <0xc>;
+ interrupts-extended = <&tlmm 38 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&tlmm 62 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&pm8226_l19>;
+ pinctrl-0 = <&mag_int_default &mag_reset_default>;
+ pinctrl-names = "default";
+ };
+
+ accelerometer@18 {
+ compatible = "st,lis3dh-accel";
+ reg = <0x18>;
+ interrupts-extended = <&tlmm 1 IRQ_TYPE_EDGE_FALLING>;
+ vdd-supply = <&pm8226_l19>;
+ pinctrl-0 = <&accel_int_default>;
+ pinctrl-names = "default";
+ st,drdy-int-pin = <1>;
+ };
+};
+
&blsp1_i2c3 {
+ clock-frequency = <400000>;
status = "okay";
+ regulator@3e {
+ compatible = "ti,tps65132";
+ reg = <0x3e>;
+ pinctrl-0 = <&reg_lcd_default>;
+ pinctrl-names = "default";
+
+ reg_lcd_pos: outp {
+ regulator-name = "outp";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ regulator-active-discharge = <1>;
+ regulator-boot-on;
+ enable-gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>;
+ };
+
+ reg_lcd_neg: outn {
+ regulator-name = "outn";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ regulator-active-discharge = <1>;
+ regulator-boot-on;
+ enable-gpios = <&tlmm 33 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
sensor@48 {
compatible = "ti,tmp108";
reg = <0x48>;
+ interrupts-extended = <&tlmm 13 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&temp_alert_default>;
+ pinctrl-names = "default";
+ #thermal-sensor-cells = <0>;
};
};
@@ -278,6 +349,56 @@
status = "okay";
};
+&tlmm {
+ accel_int_default: accel-int-default-state {
+ pins = "gpio1";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-disable;
+ };
+
+ disp_vddio_default: disp-vddio-default-state {
+ pins = "gpio34";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ mag_int_default: mag-int-default-state {
+ pins = "gpio38";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-disable;
+ };
+
+ mag_reset_default: mag-reset-default-state {
+ pins = "gpio62";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ reg_lcd_default: reg-lcd-default-state {
+ pins = "gpio31", "gpio33";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ temp_alert_default: temp-alert-default-state {
+ pins = "gpio13";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-disable;
+ };
+};
+
&usb {
extcon = <&smbb>;
dr_mode = "peripheral";
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi
index 922f9e49468a..ebc43c5c6e5f 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi
@@ -47,9 +47,9 @@
};
};
- memory {
+ memory@80000000 {
device_type = "memory";
- reg = <0x0 0x0>;
+ reg = <0x80000000 0>;
};
cpu-pmu {
@@ -129,7 +129,6 @@
gcc: clock-controller@900000 {
compatible = "qcom,gcc-msm8960";
#clock-cells = <1>;
- #power-domain-cells = <1>;
#reset-cells = <1>;
reg = <0x900000 0x4000>;
clocks = <&cxo_board>,
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 4aaae8537a3f..fdb6e22986cf 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
@@ -182,7 +182,7 @@
status = "okay";
clock-frequency = <355000>;
- led-controller@38 {
+ backlight: led-controller@38 {
compatible = "ti,lm3630a";
status = "okay";
reg = <0x38>;
@@ -272,6 +272,8 @@
reg = <0>;
compatible = "lg,acx467akm-7";
+ backlight = <&backlight>;
+
pinctrl-names = "default";
pinctrl-0 = <&panel_pin>;
@@ -328,7 +330,7 @@
power-source = <PM8941_GPIO_S3>;
};
- otg {
+ otg-hog {
gpio-hog;
gpios = <35 GPIO_ACTIVE_HIGH>;
output-high;
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974-samsung-hlte.dts b/arch/arm/boot/dts/qcom/qcom-msm8974-samsung-hlte.dts
new file mode 100644
index 000000000000..903bb4d12513
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/qcom-msm8974-samsung-hlte.dts
@@ -0,0 +1,401 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "qcom-msm8974.dtsi"
+#include "pm8841.dtsi"
+#include "pm8941.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+
+/ {
+ model = "Samsung Galaxy Note 3";
+ compatible = "samsung,hlte", "qcom,msm8974";
+ chassis-type = "handset";
+
+ aliases {
+ mmc0 = &sdhc_1; /* SDC1 eMMC slot */
+ mmc1 = &sdhc_3; /* SDC3 SD card slot */
+ serial0 = &blsp1_uart1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&gpio_keys_pin_a>;
+ pinctrl-names = "default";
+
+ key-home {
+ label = "Home Key";
+ gpios = <&pm8941_gpios 3 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ debounce-interval = <15>;
+ };
+
+ key-volume-down {
+ label = "Volume Down";
+ gpios = <&pm8941_gpios 2 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ debounce-interval = <15>;
+ };
+
+ key-volume-up {
+ label = "Volume Up";
+ gpios = <&pm8941_gpios 5 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <15>;
+ };
+ };
+
+ touch_ldo: regulator-touch {
+ compatible = "regulator-fixed";
+ regulator-name = "touch-ldo";
+
+ gpio = <&pm8941_gpios 9 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-boot-on;
+
+ pinctrl-0 = <&touch_ldo_pin>;
+ pinctrl-names = "default";
+ };
+};
+
+&blsp1_i2c2 {
+ status = "okay";
+
+ touchscreen@20 {
+ compatible = "syna,rmi4-i2c";
+ reg = <0x20>;
+
+ interrupt-parent = <&pm8941_gpios>;
+ interrupts = <30 IRQ_TYPE_EDGE_FALLING>;
+
+ vdd-supply = <&pm8941_l10>;
+ vio-supply = <&touch_ldo>;
+
+ pinctrl-0 = <&touch_pin>;
+ pinctrl-names = "default";
+
+ syna,startup-delay-ms = <100>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rmi4-f01@1 {
+ reg = <0x1>;
+ syna,nosleep-mode = <1>;
+ };
+
+ rmi4-f12@12 {
+ reg = <0x12>;
+ syna,sensor-type = <1>;
+ };
+ };
+};
+
+&blsp2_i2c6 {
+ status = "okay";
+
+ fuelgauge@36 {
+ compatible = "maxim,max17048";
+ reg = <0x36>;
+
+ maxim,double-soc;
+ maxim,rcomp = /bits/ 8 <0x56>;
+
+ interrupt-parent = <&pm8941_gpios>;
+ interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&fuelgauge_pin>;
+ pinctrl-names = "default";
+ };
+};
+
+&blsp1_uart2 {
+ status = "okay";
+};
+
+&pm8941_gpios {
+ gpio_keys_pin_a: gpio-keys-active-state {
+ pins = "gpio2", "gpio3", "gpio5";
+ function = "normal";
+ bias-pull-up;
+ power-source = <PM8941_GPIO_S3>;
+ };
+
+ fuelgauge_pin: fuelgauge-int-state {
+ pins = "gpio26";
+ function = "normal";
+ bias-disable;
+ input-enable;
+ power-source = <PM8941_GPIO_S3>;
+ };
+
+ touch_pin: touchscreen-int-state {
+ pins = "gpio30";
+ function = "normal";
+ bias-disable;
+ input-enable;
+ power-source = <PM8941_GPIO_S3>;
+ };
+
+ touch_ldo_pin: touchscreen-ldo-state {
+ pins = "gpio9";
+ function = "normal";
+ output-high;
+ power-source = <PM8941_GPIO_S3>;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>;
+ };
+};
+
+&remoteproc_adsp {
+ cx-supply = <&pm8841_s2>;
+ status = "okay";
+};
+
+&remoteproc_mss {
+ cx-supply = <&pm8841_s2>;
+ mss-supply = <&pm8841_s3>;
+ mx-supply = <&pm8841_s1>;
+ pll-supply = <&pm8941_l12>;
+ status = "okay";
+};
+
+&rpm_requests {
+ regulators-0 {
+ compatible = "qcom,rpm-pm8841-regulators";
+
+ pm8841_s1: s1 {
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ pm8841_s2: s2 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ pm8841_s3: s3 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ pm8841_s4: s4 {
+ regulator-min-microvolt = <815000>;
+ regulator-max-microvolt = <900000>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,rpm-pm8941-regulators";
+
+ pm8941_s1: s1 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ };
+
+ pm8941_s2: s2 {
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ };
+
+ pm8941_s3: s3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l1: l1 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8941_l2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8941_l3: l3 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8941_l4: l4 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8941_l5: l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l6: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l7: l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l8: l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l9: l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8941_l10: l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l11: l11 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ pm8941_l12: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ pm8941_l13: l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8941_l14: l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l15: l15 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8941_l16: l16 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+
+ pm8941_l17: l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8941_l18: l18 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ pm8941_l19: l19 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <3350000>;
+ };
+
+ pm8941_l20: l20 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-system-load = <200000>;
+ regulator-allow-set-load;
+ };
+
+ pm8941_l21: l21 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-system-load = <200000>;
+ regulator-allow-set-load;
+ };
+
+ pm8941_l22: l22 {
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8941_l23: l23 {
+ regulator-min-microvolt = <2400000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8941_l24: l24 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+ };
+};
+
+&sdhc_1 {
+ vmmc-supply = <&pm8941_l20>;
+ vqmmc-supply = <&pm8941_s3>;
+
+ pinctrl-0 = <&sdhc1_pin_a>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&sdhc_3 {
+ max-frequency = <100000000>;
+
+ vmmc-supply = <&pm8941_l21>;
+ vqmmc-supply = <&pm8941_l21>;
+
+ pinctrl-0 = <&sdhc3_pin_a>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&tlmm {
+ sdhc1_pin_a: sdhc1-pin-active-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ drive-strength = <4>;
+ bias-disable;
+ };
+
+ cmd-data-pins {
+ pins = "sdc1_cmd", "sdc1_data";
+ drive-strength = <4>;
+ bias-pull-up;
+ };
+ };
+
+ sdhc3_pin_a: sdhc3-pin-active-state {
+ pins = "gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40";
+ function = "sdc3";
+ drive-strength = <8>;
+ bias-disable;
+ };
+};
+
+&usb {
+ phys = <&usb_hs1_phy>;
+ phy-select = <&tcsr 0xb000 0>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+
+ status = "okay";
+};
+
+&usb_hs1_phy {
+ v1p8-supply = <&pm8941_l6>;
+ v3p3-supply = <&pm8941_l24>;
+
+ qcom,init-seq = /bits/ 8 <0x1 0x64>;
+
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
index 5651bb31bd54..15568579459a 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
@@ -132,7 +132,7 @@
smd-edge {
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 0>;
+ mboxes = <&apcs 0>;
qcom,smd-edge = <15>;
rpm_requests: rpm-requests {
@@ -219,7 +219,7 @@
interrupt-parent = <&intc>;
interrupts = <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 10>;
+ mboxes = <&apcs 10>;
qcom,local-pid = <0>;
qcom,remote-pid = <2>;
@@ -244,7 +244,7 @@
interrupt-parent = <&intc>;
interrupts = <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 14>;
+ mboxes = <&apcs 14>;
qcom,local-pid = <0>;
qcom,remote-pid = <1>;
@@ -269,7 +269,7 @@
interrupt-parent = <&intc>;
interrupts = <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 18>;
+ mboxes = <&apcs 18>;
qcom,local-pid = <0>;
qcom,remote-pid = <4>;
@@ -294,9 +294,7 @@
#address-cells = <1>;
#size-cells = <0>;
- qcom,ipc-1 = <&apcs 8 13>;
- qcom,ipc-2 = <&apcs 8 9>;
- qcom,ipc-3 = <&apcs 8 19>;
+ mboxes = <0>, <&apcs 13>, <&apcs 9>, <&apcs 19>;
apps_smsm: apps@0 {
reg = <0>;
@@ -343,9 +341,11 @@
<0xf9002000 0x1000>;
};
- apcs: syscon@f9011000 {
- compatible = "syscon";
+ apcs: mailbox@f9011000 {
+ compatible = "qcom,msm8974-apcs-kpss-global",
+ "qcom,msm8994-apcs-kpss-global", "syscon";
reg = <0xf9011000 0x1000>;
+ #mbox-cells = <1>;
};
saw_l2: power-manager@f9012000 {
@@ -757,7 +757,7 @@
smd-edge {
interrupts = <GIC_SPI 142 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 17>;
+ mboxes = <&apcs 17>;
qcom,smd-edge = <6>;
wcnss {
@@ -1233,7 +1233,7 @@
reg = <0xfc4ab000 0x4>;
};
- qfprom: qfprom@fc4bc000 {
+ qfprom: efuse@fc4bc000 {
compatible = "qcom,msm8974-qfprom", "qcom,qfprom";
reg = <0xfc4bc000 0x2100>;
#address-cells = <1>;
@@ -1576,7 +1576,7 @@
smd-edge {
interrupts = <GIC_SPI 25 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 12>;
+ mboxes = <&apcs 12>;
qcom,smd-edge = <0>;
label = "modem";
@@ -2129,7 +2129,7 @@
};
};
- gpu: adreno@fdb00000 {
+ gpu: gpu@fdb00000 {
compatible = "qcom,adreno-330.1", "qcom,adreno";
reg = <0xfdb00000 0x10000>;
reg-names = "kgsl_3d0_reg_memory";
@@ -2213,7 +2213,7 @@
smd-edge {
interrupts = <GIC_SPI 156 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 8>;
+ mboxes = <&apcs 8>;
qcom,smd-edge = <1>;
label = "lpass";
};
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974pro-htc-m8.dts b/arch/arm/boot/dts/qcom/qcom-msm8974pro-htc-m8.dts
new file mode 100644
index 000000000000..b896cc1ad6f7
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/qcom-msm8974pro-htc-m8.dts
@@ -0,0 +1,353 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include "qcom-msm8974pro.dtsi"
+#include "pm8841.dtsi"
+#include "pm8941.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "HTC One (M8)";
+ compatible = "htc,m8", "qcom,msm8974pro", "qcom,msm8974";
+ chassis-type = "handset";
+
+ aliases {
+ mmc0 = &sdhc_1;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&gpio_keys_default>;
+ pinctrl-names = "default";
+
+ key-volume-down {
+ label = "volume_down";
+ gpios = <&tlmm 27 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ debounce-interval = <20>;
+ wakeup-source;
+ };
+
+ key-volume-up {
+ label = "volume_up";
+ gpios = <&tlmm 28 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <20>;
+ wakeup-source;
+ };
+ };
+
+ vreg_boost: vreg-boost {
+ compatible = "regulator-fixed";
+
+ regulator-name = "vreg-boost";
+ regulator-min-microvolt = <3150000>;
+ regulator-max-microvolt = <3150000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+
+ gpio = <&pm8941_gpios 21 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&boost_bypass_n_pin>;
+ pinctrl-names = "default";
+ };
+
+ vreg_vph_pwr: vreg-vph-pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "vph-pwr";
+
+ regulator-min-microvolt = <3600000>;
+ regulator-max-microvolt = <3600000>;
+
+ regulator-always-on;
+ };
+};
+
+&pm8941_vib {
+ status = "okay";
+};
+
+&pronto {
+ vddmx-supply = <&pm8841_s1>;
+ vddcx-supply = <&pm8841_s2>;
+ vddpx-supply = <&pm8941_s3>;
+
+ pinctrl-0 = <&wcnss_pin_a>;
+ pinctrl-names = "default";
+
+ status = "okay";
+
+ iris {
+ vddxo-supply = <&pm8941_l6>;
+ vddrfa-supply = <&pm8941_l11>;
+ vddpa-supply = <&pm8941_l19>;
+ vdddig-supply = <&pm8941_s3>;
+ };
+
+ smd-edge {
+ qcom,remote-pid = <4>;
+ label = "pronto";
+
+ wcnss {
+ status = "okay";
+ };
+ };
+};
+
+&rpm_requests {
+ regulators-0 {
+ compatible = "qcom,rpm-pm8841-regulators";
+
+ pm8841_s1: s1 {
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ pm8841_s2: s2 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ pm8841_s3: s3 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ pm8841_s4: s4 {
+ regulator-min-microvolt = <815000>;
+ regulator-max-microvolt = <900000>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,rpm-pm8941-regulators";
+
+ vdd_l1_l3-supply = <&pm8941_s1>;
+ vdd_l2_lvs1_2_3-supply = <&pm8941_s3>;
+ vdd_l4_l11-supply = <&pm8941_s1>;
+ vdd_l5_l7-supply = <&pm8941_s2>;
+ vdd_l6_l12_l14_l15-supply = <&pm8941_s2>;
+ vdd_l8_l16_l18_l19-supply = <&vreg_vph_pwr>;
+ vdd_l9_l10_l17_l22-supply = <&vreg_boost>;
+ vdd_l13_l20_l23_l24-supply = <&vreg_boost>;
+ vdd_l21-supply = <&vreg_boost>;
+
+ pm8941_s1: s1 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ pm8941_s2: s2 {
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ regulator-boot-on;
+ };
+
+ pm8941_s3: s3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ pm8941_l1: l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ pm8941_l2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8941_l3: l3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8941_l4: l4 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8941_l5: l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l6: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ pm8941_l7: l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ pm8941_l8: l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l9: l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8941_l10: l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8941_l11: l11 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ pm8941_l12: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ pm8941_l13: l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-boot-on;
+ };
+
+ pm8941_l14: l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l15: l15 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8941_l16: l16 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+
+ pm8941_l17: l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ pm8941_l18: l18 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ pm8941_l19: l19 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <3350000>;
+ };
+
+ pm8941_l20: l20 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-system-load = <200000>;
+ regulator-allow-set-load;
+ regulator-boot-on;
+ };
+
+ pm8941_l21: l21 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-boot-on;
+ };
+
+ pm8941_l22: l22 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8941_l23: l23 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8941_l24: l24 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ regulator-boot-on;
+ };
+ };
+};
+
+&sdhc_1 {
+ vmmc-supply = <&pm8941_l20>;
+ vqmmc-supply = <&pm8941_s3>;
+
+ pinctrl-0 = <&sdc1_on>;
+ pinctrl-1 = <&sdc1_off>;
+ pinctrl-names = "default", "sleep";
+
+ status = "okay";
+};
+
+&smbb {
+ status = "okay";
+};
+
+&tlmm {
+ gpio_keys_default: gpio-keys-default-state {
+ pins = "gpio27", "gpio28";
+ function = "gpio";
+ bias-pull-up;
+ };
+
+ sdc1_on: sdc1-on-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ drive-strength = <10>;
+ bias-disable;
+ };
+
+ cmd-data-pins {
+ pins = "sdc1_cmd", "sdc1_data";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+ };
+
+ wcnss_pin_a: wcnss-pin-active-state {
+ pins = "gpio36", "gpio37", "gpio38", "gpio39", "gpio40";
+ function = "wlan";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+};
+
+&usb {
+ phys = <&usb_hs1_phy>;
+ phy-select = <&tcsr 0xb000 0>;
+ extcon = <&smbb>, <&usb_id>;
+ vbus-supply = <&chg_otg>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+
+ status = "okay";
+};
+
+&usb_hs1_phy {
+ v1p8-supply = <&pm8941_l6>;
+ v3p3-supply = <&pm8941_l24>;
+ extcon = <&smbb>;
+ qcom,init-seq = /bits/ 8 <0x1 0x63>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-aries.dts b/arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-aries.dts
new file mode 100644
index 000000000000..2621c5928b6a
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-aries.dts
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "qcom-msm8974pro-sony-xperia-shinano-common.dtsi"
+
+/ {
+ model = "Sony Xperia Z3 Compact";
+ compatible = "sony,xperia-aries", "qcom,msm8974pro", "qcom,msm8974";
+ chassis-type = "handset";
+
+ gpio-keys {
+ key-camera-snapshot {
+ label = "camera_snapshot";
+ gpios = <&pm8941_gpios 3 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_CAMERA>;
+ debounce-interval = <15>;
+ };
+
+ key-camera-focus {
+ label = "camera_focus";
+ gpios = <&pm8941_gpios 4 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_CAMERA_FOCUS>;
+ debounce-interval = <15>;
+ };
+ };
+};
+
+&gpio_keys_pin_a {
+ pins = "gpio2", "gpio3", "gpio4", "gpio5";
+};
+
+&smbb {
+ usb-charge-current-limit = <1500000>;
+ qcom,fast-charge-safe-current = <2100000>;
+ qcom,fast-charge-current-limit = <1800000>;
+ qcom,fast-charge-safe-voltage = <4400000>;
+ qcom,fast-charge-high-threshold-voltage = <4350000>;
+ qcom,auto-recharge-threshold-voltage = <4280000>;
+ qcom,minimum-input-voltage = <4200000>;
+
+ status = "okay";
+};
+
+&synaptics_touchscreen {
+ vio-supply = <&pm8941_s3>;
+};
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-common.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-common.dtsi
index e129bb1bd6ec..6af7c71c7158 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-common.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-common.dtsi
@@ -380,6 +380,8 @@
pm8941_l21: l21 {
regulator-min-microvolt = <2950000>;
regulator-max-microvolt = <2950000>;
+ regulator-system-load = <500000>;
+ regulator-allow-set-load;
regulator-boot-on;
};
diff --git a/arch/arm/boot/dts/renesas/r8a73a4.dtsi b/arch/arm/boot/dts/renesas/r8a73a4.dtsi
index 9a2ae282a46b..85261684b5d5 100644
--- a/arch/arm/boot/dts/renesas/r8a73a4.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a73a4.dtsi
@@ -58,6 +58,7 @@
<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)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
tmu0: timer@e61e0000 {
diff --git a/arch/arm/boot/dts/renesas/r8a7742.dtsi b/arch/arm/boot/dts/renesas/r8a7742.dtsi
index d55c344c1cd2..3a5d6b434d09 100644
--- a/arch/arm/boot/dts/renesas/r8a7742.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7742.dtsi
@@ -1938,6 +1938,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clock - can be overridden by the board */
diff --git a/arch/arm/boot/dts/renesas/r8a7743.dtsi b/arch/arm/boot/dts/renesas/r8a7743.dtsi
index d917c0a971f5..8833898d5557 100644
--- a/arch/arm/boot/dts/renesas/r8a7743.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7743.dtsi
@@ -1846,6 +1846,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clock - can be overridden by the board */
diff --git a/arch/arm/boot/dts/renesas/r8a7744.dtsi b/arch/arm/boot/dts/renesas/r8a7744.dtsi
index 754859c38a93..c66c1102fb72 100644
--- a/arch/arm/boot/dts/renesas/r8a7744.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7744.dtsi
@@ -1832,6 +1832,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clock - can be overridden by the board */
diff --git a/arch/arm/boot/dts/renesas/r8a7745.dtsi b/arch/arm/boot/dts/renesas/r8a7745.dtsi
index 168298300490..6ddde364782b 100644
--- a/arch/arm/boot/dts/renesas/r8a7745.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7745.dtsi
@@ -1636,6 +1636,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clock - can be overridden by the board */
diff --git a/arch/arm/boot/dts/renesas/r8a77470.dtsi b/arch/arm/boot/dts/renesas/r8a77470.dtsi
index 2375438d83c9..a8a12275c98a 100644
--- a/arch/arm/boot/dts/renesas/r8a77470.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a77470.dtsi
@@ -1061,6 +1061,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clock - can be overridden by the board */
diff --git a/arch/arm/boot/dts/renesas/r8a7790.dtsi b/arch/arm/boot/dts/renesas/r8a7790.dtsi
index 583b74a9f071..20e4d4c6e748 100644
--- a/arch/arm/boot/dts/renesas/r8a7790.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7790.dtsi
@@ -2012,6 +2012,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clock - can be overridden by the board */
diff --git a/arch/arm/boot/dts/renesas/r8a7791.dtsi b/arch/arm/boot/dts/renesas/r8a7791.dtsi
index de08ceb62230..f9c9e1d8f669 100644
--- a/arch/arm/boot/dts/renesas/r8a7791.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7791.dtsi
@@ -1938,6 +1938,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clock - can be overridden by the board */
diff --git a/arch/arm/boot/dts/renesas/r8a7792.dtsi b/arch/arm/boot/dts/renesas/r8a7792.dtsi
index 7defeb8e4cd1..dd3bc32668b7 100644
--- a/arch/arm/boot/dts/renesas/r8a7792.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7792.dtsi
@@ -990,5 +990,6 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
};
diff --git a/arch/arm/boot/dts/renesas/r8a7793.dtsi b/arch/arm/boot/dts/renesas/r8a7793.dtsi
index d32a9d5d3faa..24e66ddf37e0 100644
--- a/arch/arm/boot/dts/renesas/r8a7793.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7793.dtsi
@@ -1517,6 +1517,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clock - can be overridden by the board */
diff --git a/arch/arm/boot/dts/renesas/r8a7794.dtsi b/arch/arm/boot/dts/renesas/r8a7794.dtsi
index f37f094cecc8..8e6386a79aea 100644
--- a/arch/arm/boot/dts/renesas/r8a7794.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7794.dtsi
@@ -1484,6 +1484,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clock - can be overridden by the board */
diff --git a/arch/arm/boot/dts/renesas/r9a06g032.dtsi b/arch/arm/boot/dts/renesas/r9a06g032.dtsi
index 45f60eeeaaa1..7548291c8d7e 100644
--- a/arch/arm/boot/dts/renesas/r9a06g032.dtsi
+++ b/arch/arm/boot/dts/renesas/r9a06g032.dtsi
@@ -316,6 +316,24 @@
data-width = <8>;
};
+ gmac1: ethernet@44000000 {
+ compatible = "renesas,r9a06g032-gmac", "renesas,rzn1-gmac", "snps,dwmac";
+ reg = <0x44000000 0x2000>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
+ clocks = <&sysctrl R9A06G032_HCLK_GMAC0>;
+ clock-names = "stmmaceth";
+ power-domains = <&sysctrl>;
+ snps,multicast-filter-bins = <256>;
+ snps,perfect-filter-entries = <128>;
+ tx-fifo-depth = <2048>;
+ rx-fifo-depth = <4096>;
+ pcs-handle = <&mii_conv1>;
+ status = "disabled";
+ };
+
gmac2: ethernet@44002000 {
compatible = "renesas,r9a06g032-gmac", "renesas,rzn1-gmac", "snps,dwmac";
reg = <0x44002000 0x2000>;
@@ -466,6 +484,7 @@
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
usbphy: usb-phy {
diff --git a/arch/arm/boot/dts/rockchip/rk3036.dtsi b/arch/arm/boot/dts/rockchip/rk3036.dtsi
index 04af224005f8..96279d1e02fe 100644
--- a/arch/arm/boot/dts/rockchip/rk3036.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3036.dtsi
@@ -402,6 +402,7 @@
rockchip,grf = <&grf>;
pinctrl-names = "default";
pinctrl-0 = <&hdmi_ctl>;
+ #sound-dai-cells = <0>;
status = "disabled";
ports {
diff --git a/arch/arm/boot/dts/rockchip/rk3066a-mk808.dts b/arch/arm/boot/dts/rockchip/rk3066a-mk808.dts
index 06790f05b395..4de9a45c4883 100644
--- a/arch/arm/boot/dts/rockchip/rk3066a-mk808.dts
+++ b/arch/arm/boot/dts/rockchip/rk3066a-mk808.dts
@@ -143,6 +143,14 @@
};
};
+&hdmi_sound {
+ status = "okay";
+};
+
+&i2s0 {
+ status = "okay";
+};
+
&mmc0 {
bus-width = <4>;
cap-mmc-highspeed;
diff --git a/arch/arm/boot/dts/rockchip/rk3066a.dtsi b/arch/arm/boot/dts/rockchip/rk3066a.dtsi
index 30139f21de64..5e0750547ab5 100644
--- a/arch/arm/boot/dts/rockchip/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3066a.dtsi
@@ -53,6 +53,22 @@
ports = <&vop0_out>, <&vop1_out>;
};
+ hdmi_sound: hdmi-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "HDMI";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,mclk-fs = <256>;
+ status = "disabled";
+
+ simple-audio-card,codec {
+ sound-dai = <&hdmi>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s0>;
+ };
+ };
+
sram: sram@10080000 {
compatible = "mmio-sram";
reg = <0x10080000 0x10000>;
@@ -128,6 +144,7 @@
pinctrl-0 = <&hdmii2c_xfer>, <&hdmi_hpd>;
power-domains = <&power RK3066_PD_VIO>;
rockchip,grf = <&grf>;
+ #sound-dai-cells = <0>;
status = "disabled";
ports {
diff --git a/arch/arm/boot/dts/rockchip/rk3128.dtsi b/arch/arm/boot/dts/rockchip/rk3128.dtsi
index fb98873fd94e..23e633387c24 100644
--- a/arch/arm/boot/dts/rockchip/rk3128.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3128.dtsi
@@ -216,6 +216,8 @@
<&cru ACLK_LCDC0>,
<&cru HCLK_LCDC0>,
<&cru PCLK_MIPI>,
+ <&cru PCLK_MIPIPHY>,
+ <&cru SCLK_MIPI_24M>,
<&cru ACLK_RGA>,
<&cru HCLK_RGA>,
<&cru ACLK_VIO0>,
@@ -275,6 +277,43 @@
reg = <0>;
remote-endpoint = <&hdmi_in_vop>;
};
+
+ vop_out_dsi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dsi_in_vop>;
+ };
+ };
+ };
+
+ dsi: dsi@10110000 {
+ compatible = "rockchip,rk3128-mipi-dsi", "snps,dw-mipi-dsi";
+ reg = <0x10110000 0x4000>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_MIPI>;
+ clock-names = "pclk";
+ phys = <&dphy>;
+ phy-names = "dphy";
+ power-domains = <&power RK3128_PD_VIO>;
+ resets = <&cru SRST_VIO_MIPI_DSI>;
+ reset-names = "apb";
+ rockchip,grf = <&grf>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dsi_in: port@0 {
+ reg = <0>;
+
+ dsi_in_vop: endpoint {
+ remote-endpoint = <&vop_out_dsi>;
+ };
+ };
+
+ dsi_out: port@1 {
+ reg = <1>;
+ };
};
};
@@ -360,6 +399,41 @@
status = "disabled";
};
+ i2s_8ch: i2s@10200000 {
+ compatible = "rockchip,rk3128-i2s", "rockchip,rk3066-i2s";
+ reg = <0x10200000 0x1000>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru SCLK_I2S0>, <&cru HCLK_I2S_8CH>;
+ clock-names = "i2s_clk", "i2s_hclk";
+ dmas = <&pdma 14>, <&pdma 15>;
+ dma-names = "tx", "rx";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ spdif: spdif@10204000 {
+ compatible = "rockchip,rk3128-spdif", "rockchip,rk3066-spdif";
+ reg = <0x10204000 0x1000>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru SCLK_SPDIF>, <&cru HCLK_SPDIF>;
+ clock-names = "mclk", "hclk";
+ dmas = <&pdma 13>;
+ dma-names = "tx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spdif_tx>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ sfc: spi@1020c000 {
+ compatible = "rockchip,sfc";
+ reg = <0x1020c000 0x8000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru SCLK_SFC>, <&cru 479>;
+ clock-names = "clk_sfc", "hclk_sfc";
+ status = "disabled";
+ };
+
sdmmc: mmc@10214000 {
compatible = "rockchip,rk3128-dw-mshc", "rockchip,rk3288-dw-mshc";
reg = <0x10214000 0x4000>;
@@ -408,6 +482,21 @@
status = "disabled";
};
+ i2s_2ch: i2s@10220000 {
+ compatible = "rockchip,rk3128-i2s", "rockchip,rk3066-i2s";
+ reg = <0x10220000 0x1000>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru SCLK_I2S1>, <&cru HCLK_I2S_2CH>;
+ clock-names = "i2s_clk", "i2s_hclk";
+ dmas = <&pdma 0>, <&pdma 1>;
+ dma-names = "tx", "rx";
+ rockchip,playback-channels = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s_bus>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
nfc: nand-controller@10500000 {
compatible = "rockchip,rk3128-nfc", "rockchip,rk2928-nfc";
reg = <0x10500000 0x4000>;
@@ -477,6 +566,7 @@
pinctrl-names = "default";
pinctrl-0 = <&hdmii2c_xfer &hdmi_hpd &hdmi_cec>;
power-domains = <&power RK3128_PD_VIO>;
+ #sound-dai-cells = <0>;
status = "disabled";
ports {
@@ -496,6 +586,18 @@
};
};
+ dphy: phy@20038000 {
+ compatible = "rockchip,rk3128-dsi-dphy";
+ reg = <0x20038000 0x4000>;
+ clocks = <&cru SCLK_MIPI_24M>, <&cru PCLK_MIPIPHY>;
+ clock-names = "ref", "pclk";
+ #phy-cells = <0>;
+ power-domains = <&power RK3128_PD_VIO>;
+ resets = <&cru SRST_MIPIPHY_P>;
+ reset-names = "apb";
+ status = "disabled";
+ };
+
timer0: timer@20044000 {
compatible = "rockchip,rk3128-timer", "rockchip,rk3288-timer";
reg = <0x20044000 0x20>;
@@ -1104,6 +1206,32 @@
};
};
+ sfc {
+ sfc_bus2: sfc-bus2 {
+ rockchip,pins = <1 RK_PD0 3 &pcfg_pull_default>,
+ <1 RK_PD1 3 &pcfg_pull_default>;
+ };
+
+ sfc_bus4: sfc-bus4 {
+ rockchip,pins = <1 RK_PD0 3 &pcfg_pull_default>,
+ <1 RK_PD1 3 &pcfg_pull_default>,
+ <1 RK_PD2 3 &pcfg_pull_default>,
+ <1 RK_PD3 3 &pcfg_pull_default>;
+ };
+
+ sfc_clk: sfc-clk {
+ rockchip,pins = <2 RK_PA4 3 &pcfg_pull_none>;
+ };
+
+ sfc_cs0: sfc-cs0 {
+ rockchip,pins = <2 RK_PA2 2 &pcfg_pull_default>;
+ };
+
+ sfc_cs1: sfc-cs1 {
+ rockchip,pins = <2 RK_PA3 2 &pcfg_pull_default>;
+ };
+ };
+
spdif {
spdif_tx: spdif-tx {
rockchip,pins = <3 RK_PD3 1 &pcfg_pull_none>;
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 0c2396b8f8db..7707d1b01440 100644
--- a/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts
+++ b/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts
@@ -69,8 +69,7 @@
&mdio {
phy: ethernet-phy@0 {
- compatible = "ethernet-phy-id001c.c916",
- "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-id001c.c916";
reg = <0x0>;
pinctrl-names = "default";
pinctrl-0 = <&eth_phy_rst>;
diff --git a/arch/arm/boot/dts/st/Makefile b/arch/arm/boot/dts/st/Makefile
index 9fedd6776208..015903d09323 100644
--- a/arch/arm/boot/dts/st/Makefile
+++ b/arch/arm/boot/dts/st/Makefile
@@ -29,6 +29,7 @@ dtb-$(CONFIG_ARCH_STM32) += \
stm32h743i-eval.dtb \
stm32h743i-disco.dtb \
stm32h750i-art-pi.dtb \
+ stm32mp135f-dhcor-dhsbc.dtb \
stm32mp135f-dk.dtb \
stm32mp151a-prtt1a.dtb \
stm32mp151a-prtt1c.dtb \
diff --git a/arch/arm/boot/dts/st/stih407-family.dtsi b/arch/arm/boot/dts/st/stih407-family.dtsi
index 29302e74aa1d..35a55aef7f4b 100644
--- a/arch/arm/boot/dts/st/stih407-family.dtsi
+++ b/arch/arm/boot/dts/st/stih407-family.dtsi
@@ -33,7 +33,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
@@ -52,8 +52,9 @@
clock-latency = <100000>;
cpu0-supply = <&pwm_regulator>;
st,syscfg = <&syscfg_core 0x8e0>;
+ #cooling-cells = <2>;
};
- cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <1>;
@@ -66,6 +67,7 @@
1200000 0
800000 0
500000 0>;
+ #cooling-cells = <2>;
};
};
diff --git a/arch/arm/boot/dts/st/stih410.dtsi b/arch/arm/boot/dts/st/stih410.dtsi
index 29e95e9d3229..a69231854f78 100644
--- a/arch/arm/boot/dts/st/stih410.dtsi
+++ b/arch/arm/boot/dts/st/stih410.dtsi
@@ -270,6 +270,7 @@
clock-names = "thermal";
clocks = <&clk_sysin>;
interrupts = <GIC_SPI 205 IRQ_TYPE_EDGE_RISING>;
+ #thermal-sensor-cells = <0>;
};
cec@94a087c {
diff --git a/arch/arm/boot/dts/st/stih418.dtsi b/arch/arm/boot/dts/st/stih418.dtsi
index b35b9b7a7ccc..8fb8b3af5e49 100644
--- a/arch/arm/boot/dts/st/stih418.dtsi
+++ b/arch/arm/boot/dts/st/stih418.dtsi
@@ -6,23 +6,26 @@
#include "stih418-clock.dtsi"
#include "stih407-family.dtsi"
#include "stih410-pinctrl.dtsi"
+#include <dt-bindings/thermal/thermal.h>
/ {
cpus {
#address-cells = <1>;
#size-cells = <0>;
- cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <2>;
/* u-boot puts hpen in SBC dmem at 0xa4 offset */
cpu-release-addr = <0x94100A4>;
+ #cooling-cells = <2>;
};
- cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <3>;
/* u-boot puts hpen in SBC dmem at 0xa4 offset */
cpu-release-addr = <0x94100A4>;
+ #cooling-cells = <2>;
};
};
@@ -44,6 +47,38 @@
reset-names = "global", "port";
};
+ thermal-zones {
+ cpu_thermal: cpu-thermal {
+ polling-delay-passive = <250>; /* 250ms */
+ polling-delay = <1000>; /* 1000ms */
+
+ thermal-sensors = <&thermal>;
+
+ trips {
+ cpu_crit: cpu-crit {
+ temperature = <95000>; /* 95C */
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ cpu_alert: cpu-alert {
+ temperature = <85000>; /* 85C */
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ };
+
+ cooling-maps {
+ map {
+ 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>;
+ };
+ };
+ };
+ };
+
soc {
rng11: rng@8a8a000 {
status = "disabled";
@@ -107,12 +142,13 @@
assigned-clock-rates = <200000000>;
};
- thermal@91a0000 {
+ thermal: thermal@91a0000 {
compatible = "st,stih407-thermal";
reg = <0x91a0000 0x28>;
clock-names = "thermal";
clocks = <&clk_sysin>;
interrupts = <GIC_SPI 205 IRQ_TYPE_EDGE_RISING>;
+ #thermal-sensor-cells = <0>;
};
};
};
diff --git a/arch/arm/boot/dts/st/stm32f429.dtsi b/arch/arm/boot/dts/st/stm32f429.dtsi
index 8efcda9ef8ae..ad91b74ddd0d 100644
--- a/arch/arm/boot/dts/st/stm32f429.dtsi
+++ b/arch/arm/boot/dts/st/stm32f429.dtsi
@@ -579,6 +579,7 @@
syscfg: syscon@40013800 {
compatible = "st,stm32-syscfg", "syscon";
reg = <0x40013800 0x400>;
+ clocks = <&rcc 0 STM32F4_APB2_CLOCK(SYSCFG)>;
};
exti: interrupt-controller@40013c00 {
diff --git a/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi
index 32c5d8a1e06a..c9f588a65094 100644
--- a/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi
@@ -6,6 +6,14 @@
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
&pinctrl {
+ /omit-if-no-ref/
+ adc1_pins_a: adc1-pins-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 3, ANALOG)>; /* ADC1 in12 */
+ };
+ };
+
+ /omit-if-no-ref/
adc1_usb_cc_pins_a: adc1-usb-cc-pins-0 {
pins {
pinmux = <STM32_PINMUX('F', 12, ANALOG)>, /* ADC1 in6 */
@@ -13,6 +21,241 @@
};
};
+ /omit-if-no-ref/
+ adc1_usb_cc_pins_b: adc1-usb-cc-pins-1 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 5, ANALOG)>, /* ADC1_INP2 */
+ <STM32_PINMUX('F', 13, ANALOG)>; /* ADC1_INP11 */
+ };
+ };
+
+ /omit-if-no-ref/
+ dcmipp_pins_a: dcmi-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('H', 8, AF13)>,/* DCMI_HSYNC */
+ <STM32_PINMUX('G', 9, AF13)>,/* DCMI_VSYNC */
+ <STM32_PINMUX('B', 7, AF14)>,/* DCMI_PIXCLK */
+ <STM32_PINMUX('A', 9, AF13)>,/* DCMI_D0 */
+ <STM32_PINMUX('D', 0, AF13)>,/* DCMI_D1 */
+ <STM32_PINMUX('G', 10, AF13)>,/* DCMI_D2 */
+ <STM32_PINMUX('E', 4, AF13)>,/* DCMI_D3 */
+ <STM32_PINMUX('D', 11, AF14)>,/* DCMI_D4 */
+ <STM32_PINMUX('D', 3, AF13)>,/* DCMI_D5 */
+ <STM32_PINMUX('B', 8, AF13)>,/* DCMI_D6 */
+ <STM32_PINMUX('E', 14, AF13)>;/* DCMI_D7 */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ dcmipp_sleep_pins_a: dcmi-sleep-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('H', 8, ANALOG)>,/* DCMI_HSYNC */
+ <STM32_PINMUX('G', 9, ANALOG)>,/* DCMI_VSYNC */
+ <STM32_PINMUX('B', 7, ANALOG)>,/* DCMI_PIXCLK */
+ <STM32_PINMUX('A', 9, ANALOG)>,/* DCMI_D0 */
+ <STM32_PINMUX('D', 0, ANALOG)>,/* DCMI_D1 */
+ <STM32_PINMUX('G', 10, ANALOG)>,/* DCMI_D2 */
+ <STM32_PINMUX('E', 4, ANALOG)>,/* DCMI_D3 */
+ <STM32_PINMUX('D', 11, ANALOG)>,/* DCMI_D4 */
+ <STM32_PINMUX('D', 3, ANALOG)>,/* DCMI_D5 */
+ <STM32_PINMUX('B', 8, ANALOG)>,/* DCMI_D6 */
+ <STM32_PINMUX('E', 14, ANALOG)>;/* DCMI_D7 */
+ };
+ };
+
+ /omit-if-no-ref/
+ eth1_rgmii_pins_a: eth1-rgmii-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */
+ <STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */
+ <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
+ <STM32_PINMUX('E', 5, AF10)>, /* ETH_RGMII_TXD3 */
+ <STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */
+ <STM32_PINMUX('C', 1, AF11)>, /* ETH_RGMII_GTX_CLK */
+ <STM32_PINMUX('A', 2, AF11)>, /* ETH_MDIO */
+ <STM32_PINMUX('G', 2, AF11)>; /* ETH_MDC */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <2>;
+ };
+
+ pins2 {
+ pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
+ <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
+ <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
+ <STM32_PINMUX('B', 1, AF11)>, /* ETH_RGMII_RXD3 */
+ <STM32_PINMUX('A', 7, AF11)>, /* ETH_RGMII_RX_CTL */
+ <STM32_PINMUX('D', 7, AF10)>; /* ETH_RGMII_RX_CLK */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ eth1_rgmii_sleep_pins_a: eth1-rgmii-sleep-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */
+ <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */
+ <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */
+ <STM32_PINMUX('E', 5, ANALOG)>, /* ETH_RGMII_TXD3 */
+ <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */
+ <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_RGMII_GTX_CLK */
+ <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */
+ <STM32_PINMUX('G', 2, ANALOG)>, /* ETH_MDC */
+ <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */
+ <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */
+ <STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD1 */
+ <STM32_PINMUX('B', 1, ANALOG)>, /* ETH_RGMII_RXD1 */
+ <STM32_PINMUX('A', 7, ANALOG)>, /* ETH_RGMII_RX_CTL */
+ <STM32_PINMUX('D', 7, ANALOG)>; /* ETH_RGMII_RX_CLK */
+ };
+ };
+
+ /omit-if-no-ref/
+ eth1_rmii_pins_a: eth1-rmii-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('G', 13, AF11)>, /* ETH_RMII_TXD0 */
+ <STM32_PINMUX('G', 14, AF11)>, /* ETH_RMII_TXD1 */
+ <STM32_PINMUX('B', 11, AF11)>, /* ETH_RMII_TX_EN */
+ <STM32_PINMUX('A', 1, AF11)>, /* ETH_RMII_REF_CLK */
+ <STM32_PINMUX('A', 2, AF11)>, /* ETH_MDIO */
+ <STM32_PINMUX('G', 2, AF11)>; /* ETH_MDC */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+
+ pins2 {
+ pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RMII_RXD0 */
+ <STM32_PINMUX('C', 5, AF11)>, /* ETH_RMII_RXD1 */
+ <STM32_PINMUX('C', 1, AF10)>; /* ETH_RMII_CRS_DV */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ eth1_rmii_sleep_pins_a: eth1-rmii-sleep-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RMII_TXD0 */
+ <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RMII_TXD1 */
+ <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RMII_TX_EN */
+ <STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RMII_REF_CLK */
+ <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */
+ <STM32_PINMUX('G', 2, ANALOG)>, /* ETH_MDC */
+ <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RMII_RXD0 */
+ <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RMII_RXD1 */
+ <STM32_PINMUX('C', 1, ANALOG)>; /* ETH_RMII_CRS_DV */
+ };
+ };
+
+ /omit-if-no-ref/
+ eth2_rgmii_pins_a: eth2-rgmii-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 7, AF11)>, /* ETH_RGMII_TXD0 */
+ <STM32_PINMUX('G', 11, AF10)>, /* ETH_RGMII_TXD1 */
+ <STM32_PINMUX('G', 1, AF10)>, /* ETH_RGMII_TXD2 */
+ <STM32_PINMUX('E', 6, AF11)>, /* ETH_RGMII_TXD3 */
+ <STM32_PINMUX('F', 6, AF11)>, /* ETH_RGMII_TX_CTL */
+ <STM32_PINMUX('G', 3, AF10)>, /* ETH_RGMII_GTX_CLK */
+ <STM32_PINMUX('B', 6, AF11)>, /* ETH_MDIO */
+ <STM32_PINMUX('G', 5, AF10)>; /* ETH_MDC */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <2>;
+ };
+
+ pins2 {
+ pinmux = <STM32_PINMUX('F', 4, AF11)>, /* ETH_RGMII_RXD0 */
+ <STM32_PINMUX('E', 2, AF10)>, /* ETH_RGMII_RXD1 */
+ <STM32_PINMUX('H', 6, AF12)>, /* ETH_RGMII_RXD2 */
+ <STM32_PINMUX('A', 8, AF11)>, /* ETH_RGMII_RXD3 */
+ <STM32_PINMUX('A', 12, AF11)>, /* ETH_RGMII_RX_CTL */
+ <STM32_PINMUX('H', 11, AF11)>; /* ETH_RGMII_RX_CLK */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ eth2_rgmii_sleep_pins_a: eth2-rgmii-sleep-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 7, ANALOG)>, /* ETH_RGMII_TXD0 */
+ <STM32_PINMUX('G', 11, ANALOG)>, /* ETH_RGMII_TXD1 */
+ <STM32_PINMUX('G', 1, ANALOG)>, /* ETH_RGMII_TXD2 */
+ <STM32_PINMUX('E', 6, ANALOG)>, /* ETH_RGMII_TXD3 */
+ <STM32_PINMUX('F', 6, ANALOG)>, /* ETH_RGMII_TX_CTL */
+ <STM32_PINMUX('G', 3, ANALOG)>, /* ETH_RGMII_GTX_CLK */
+ <STM32_PINMUX('B', 6, ANALOG)>, /* ETH_MDIO */
+ <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_MDC */
+ <STM32_PINMUX('F', 4, ANALOG)>, /* ETH_RGMII_RXD0 */
+ <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_RXD1 */
+ <STM32_PINMUX('H', 6, ANALOG)>, /* ETH_RGMII_RXD2 */
+ <STM32_PINMUX('A', 8, ANALOG)>, /* ETH_RGMII_RXD3 */
+ <STM32_PINMUX('A', 12, ANALOG)>, /* ETH_RGMII_RX_CTL */
+ <STM32_PINMUX('H', 11, ANALOG)>; /* ETH_RGMII_RX_CLK */
+ };
+ };
+
+ /omit-if-no-ref/
+ eth2_rmii_pins_a: eth2-rmii-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 7, AF11)>, /* ETH_RMII_TXD0 */
+ <STM32_PINMUX('G', 11, AF10)>, /* ETH_RMII_TXD1 */
+ <STM32_PINMUX('G', 8, AF13)>, /* ETH_RMII_ETHCK */
+ <STM32_PINMUX('F', 6, AF11)>, /* ETH_RMII_TX_EN */
+ <STM32_PINMUX('B', 2, AF11)>, /* ETH_MDIO */
+ <STM32_PINMUX('G', 5, AF10)>; /* ETH_MDC */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+
+ pins2 {
+ pinmux = <STM32_PINMUX('F', 4, AF11)>, /* ETH_RMII_RXD0 */
+ <STM32_PINMUX('E', 2, AF10)>, /* ETH_RMII_RXD1 */
+ <STM32_PINMUX('A', 12, AF11)>; /* ETH_RMII_CRS_DV */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ eth2_rmii_sleep_pins_a: eth2-rmii-sleep-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 7, ANALOG)>, /* ETH_RMII_TXD0 */
+ <STM32_PINMUX('G', 11, ANALOG)>, /* ETH_RMII_TXD1 */
+ <STM32_PINMUX('G', 8, ANALOG)>, /* ETH_RMII_ETHCK */
+ <STM32_PINMUX('F', 6, ANALOG)>, /* ETH_RMII_TX_EN */
+ <STM32_PINMUX('B', 2, ANALOG)>, /* ETH_MDIO */
+ <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_MDC */
+ <STM32_PINMUX('F', 4, ANALOG)>, /* ETH_RMII_RXD0 */
+ <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RMII_RXD1 */
+ <STM32_PINMUX('A', 12, ANALOG)>; /* ETH_RMII_CRS_DV */
+ };
+ };
+
+ /omit-if-no-ref/
+ goodix_pins_a: goodix-0 {
+ /*
+ * touchscreen reset needs to be configured
+ * via the pinctrl not the driver (a pull-down resistor
+ * has been soldered onto the reset line which forces
+ * the touchscreen to reset state).
+ */
+ pins1 {
+ pinmux = <STM32_PINMUX('H', 2, GPIO)>;
+ output-high;
+ bias-pull-up;
+ };
+ /*
+ * Interrupt line must have a pull-down resistor
+ * in order to freeze the i2c address at 0x5D
+ */
+ pins2 {
+ pinmux = <STM32_PINMUX('F', 5, GPIO)>;
+ bias-pull-down;
+ };
+ };
+
+ /omit-if-no-ref/
i2c1_pins_a: i2c1-0 {
pins {
pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
@@ -23,6 +266,7 @@
};
};
+ /omit-if-no-ref/
i2c1_sleep_pins_a: i2c1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('D', 12, ANALOG)>, /* I2C1_SCL */
@@ -30,6 +274,7 @@
};
};
+ /omit-if-no-ref/
i2c5_pins_a: i2c5-0 {
pins {
pinmux = <STM32_PINMUX('D', 1, AF4)>, /* I2C5_SCL */
@@ -40,6 +285,7 @@
};
};
+ /omit-if-no-ref/
i2c5_sleep_pins_a: i2c5-sleep-0 {
pins {
pinmux = <STM32_PINMUX('D', 1, ANALOG)>, /* I2C5_SCL */
@@ -47,6 +293,26 @@
};
};
+ /omit-if-no-ref/
+ i2c5_pins_b: i2c5-1 {
+ pins {
+ pinmux = <STM32_PINMUX('D', 1, AF4)>, /* I2C5_SCL */
+ <STM32_PINMUX('E', 13, AF4)>; /* I2C5_SDA */
+ bias-disable;
+ drive-open-drain;
+ slew-rate = <0>;
+ };
+ };
+
+ /omit-if-no-ref/
+ i2c5_sleep_pins_b: i2c5-sleep-1 {
+ pins {
+ pinmux = <STM32_PINMUX('D', 1, ANALOG)>, /* I2C5_SCL */
+ <STM32_PINMUX('E', 13, ANALOG)>; /* I2C5_SDA */
+ };
+ };
+
+ /omit-if-no-ref/
ltdc_pins_a: ltdc-0 {
pins {
pinmux = <STM32_PINMUX('D', 9, AF13)>, /* LCD_CLK */
@@ -77,6 +343,7 @@
};
};
+ /omit-if-no-ref/
ltdc_sleep_pins_a: ltdc-sleep-0 {
pins {
pinmux = <STM32_PINMUX('D', 9, ANALOG)>, /* LCD_CLK */
@@ -104,6 +371,51 @@
};
};
+ /omit-if-no-ref/
+ m_can1_pins_a: m-can1-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('G', 10, AF9)>; /* CAN1_TX */
+ slew-rate = <1>;
+ drive-push-pull;
+ bias-disable;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('D', 0, AF9)>; /* CAN1_RX */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ m_can1_sleep_pins_a: m_can1-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('G', 10, ANALOG)>, /* CAN1_TX */
+ <STM32_PINMUX('D', 0, ANALOG)>; /* CAN1_RX */
+ };
+ };
+
+ /omit-if-no-ref/
+ m_can2_pins_a: m-can2-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('G', 0, AF9)>; /* CAN2_TX */
+ slew-rate = <1>;
+ drive-push-pull;
+ bias-disable;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 0, AF9)>; /* CAN2_RX */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ m_can2_sleep_pins_a: m_can2-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('G', 0, ANALOG)>, /* CAN2_TX */
+ <STM32_PINMUX('E', 0, ANALOG)>; /* CAN2_RX */
+ };
+ };
+
+ /omit-if-no-ref/
mcp23017_pins_a: mcp23017-0 {
pins {
pinmux = <STM32_PINMUX('G', 12, GPIO)>;
@@ -111,6 +423,7 @@
};
};
+ /omit-if-no-ref/
pwm3_pins_a: pwm3-0 {
pins {
pinmux = <STM32_PINMUX('B', 1, AF2)>; /* TIM3_CH4 */
@@ -120,12 +433,14 @@
};
};
+ /omit-if-no-ref/
pwm3_sleep_pins_a: pwm3-sleep-0 {
pins {
pinmux = <STM32_PINMUX('B', 1, ANALOG)>; /* TIM3_CH4 */
};
};
+ /omit-if-no-ref/
pwm4_pins_a: pwm4-0 {
pins {
pinmux = <STM32_PINMUX('D', 13, AF2)>; /* TIM4_CH2 */
@@ -135,12 +450,31 @@
};
};
+ /omit-if-no-ref/
pwm4_sleep_pins_a: pwm4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('D', 13, ANALOG)>; /* TIM4_CH2 */
};
};
+ /omit-if-no-ref/
+ pwm5_pins_a: pwm5-0 {
+ pins {
+ pinmux = <STM32_PINMUX('H', 12, AF2)>; /* TIM5_CH3 */
+ bias-pull-down;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ };
+
+ /omit-if-no-ref/
+ pwm5_sleep_pins_a: pwm5-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('H', 12, ANALOG)>; /* TIM5_CH3 */
+ };
+ };
+
+ /omit-if-no-ref/
pwm8_pins_a: pwm8-0 {
pins {
pinmux = <STM32_PINMUX('E', 5, AF3)>; /* TIM8_CH3 */
@@ -150,12 +484,31 @@
};
};
+ /omit-if-no-ref/
pwm8_sleep_pins_a: pwm8-sleep-0 {
pins {
pinmux = <STM32_PINMUX('E', 5, ANALOG)>; /* TIM8_CH3 */
};
};
+ /omit-if-no-ref/
+ pwm13_pins_a: pwm13-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 6, AF9)>; /* TIM13_CH1 */
+ bias-pull-down;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ };
+
+ /omit-if-no-ref/
+ pwm13_sleep_pins_a: pwm13-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 6, ANALOG)>; /* TIM13_CH1 */
+ };
+ };
+
+ /omit-if-no-ref/
pwm14_pins_a: pwm14-0 {
pins {
pinmux = <STM32_PINMUX('F', 9, AF9)>; /* TIM14_CH1 */
@@ -165,12 +518,107 @@
};
};
+ /omit-if-no-ref/
pwm14_sleep_pins_a: pwm14-sleep-0 {
pins {
pinmux = <STM32_PINMUX('F', 9, ANALOG)>; /* TIM14_CH1 */
};
};
+ /omit-if-no-ref/
+ qspi_clk_pins_a: qspi-clk-0 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 10, AF9)>; /* QSPI_CLK */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <3>;
+ };
+ };
+
+ /omit-if-no-ref/
+ qspi_clk_sleep_pins_a: qspi-clk-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 10, ANALOG)>; /* QSPI_CLK */
+ };
+ };
+
+ /omit-if-no-ref/
+ qspi_bk1_pins_a: qspi-bk1-0 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */
+ <STM32_PINMUX('F', 9, AF10)>, /* QSPI_BK1_IO1 */
+ <STM32_PINMUX('D', 11, AF9)>, /* QSPI_BK1_IO2 */
+ <STM32_PINMUX('H', 7, AF13)>; /* QSPI_BK1_IO3 */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+ };
+
+ /omit-if-no-ref/
+ qspi_bk1_sleep_pins_a: qspi-bk1-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 8, ANALOG)>, /* QSPI_BK1_IO0 */
+ <STM32_PINMUX('F', 9, ANALOG)>, /* QSPI_BK1_IO1 */
+ <STM32_PINMUX('D', 11, ANALOG)>, /* QSPI_BK1_IO2 */
+ <STM32_PINMUX('H', 7, ANALOG)>; /* QSPI_BK1_IO3 */
+ };
+ };
+
+ /omit-if-no-ref/
+ qspi_cs1_pins_a: qspi-cs1-0 {
+ pins {
+ pinmux = <STM32_PINMUX('B', 2, AF9)>; /* QSPI_BK1_NCS */
+ bias-pull-up;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+ };
+
+ /omit-if-no-ref/
+ qspi_cs1_sleep_pins_a: qspi-cs1-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('B', 2, ANALOG)>; /* QSPI_BK1_NCS */
+ };
+ };
+
+ /omit-if-no-ref/
+ sai1a_pins_a: sai1a-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 4, AF12)>, /* SAI1_SCK_A */
+ <STM32_PINMUX('D', 6, AF6)>, /* SAI1_SD_A */
+ <STM32_PINMUX('E', 11, AF6)>; /* SAI1_FS_A */
+ slew-rate = <0>;
+ drive-push-pull;
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ sai1a_sleep_pins_a: sai1a-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 4, ANALOG)>, /* SAI1_SCK_A */
+ <STM32_PINMUX('D', 6, ANALOG)>, /* SAI1_SD_A */
+ <STM32_PINMUX('E', 11, ANALOG)>; /* SAI1_FS_A */
+ };
+ };
+
+ /omit-if-no-ref/
+ sai1b_pins_a: sai1b-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 0, AF6)>; /* SAI1_SD_B */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ sai1b_sleep_pins_a: sai1b-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 0, ANALOG)>; /* SAI1_SD_B */
+ };
+ };
+
+ /omit-if-no-ref/
sdmmc1_b4_pins_a: sdmmc1-b4-0 {
pins {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
@@ -184,6 +632,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
pins1 {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
@@ -202,6 +651,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */
@@ -213,6 +663,7 @@
};
};
+ /omit-if-no-ref/
sdmmc1_clk_pins_a: sdmmc1-clk-0 {
pins {
pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
@@ -222,6 +673,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_b4_pins_a: sdmmc2-b4-0 {
pins {
pinmux = <STM32_PINMUX('B', 14, AF10)>, /* SDMMC2_D0 */
@@ -235,6 +687,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_b4_od_pins_a: sdmmc2-b4-od-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF10)>, /* SDMMC2_D0 */
@@ -253,6 +706,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_b4_sleep_pins_a: sdmmc2-b4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */
@@ -264,6 +718,7 @@
};
};
+ /omit-if-no-ref/
sdmmc2_clk_pins_a: sdmmc2-clk-0 {
pins {
pinmux = <STM32_PINMUX('E', 3, AF10)>; /* SDMMC2_CK */
@@ -273,6 +728,80 @@
};
};
+ /omit-if-no-ref/
+ sdmmc2_d47_pins_a: sdmmc2-d47-0 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 0, AF10)>, /* SDMMC2_D4 */
+ <STM32_PINMUX('B', 9, AF10)>, /* SDMMC2_D5 */
+ <STM32_PINMUX('C', 6, AF10)>, /* SDMMC2_D6 */
+ <STM32_PINMUX('C', 7, AF10)>; /* SDMMC2_D7 */
+ slew-rate = <1>;
+ drive-push-pull;
+ bias-pull-up;
+ };
+ };
+
+ /omit-if-no-ref/
+ sdmmc2_d47_sleep_pins_a: sdmmc2-d47-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 0, ANALOG)>, /* SDMMC2_D4 */
+ <STM32_PINMUX('B', 9, ANALOG)>, /* SDMMC2_D5 */
+ <STM32_PINMUX('C', 6, ANALOG)>, /* SDMMC2_D6 */
+ <STM32_PINMUX('C', 7, ANALOG)>; /* SDMMC2_D7 */
+ };
+ };
+
+ /omit-if-no-ref/
+ spi2_pins_a: spi2-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('B', 10, AF6)>, /* SPI2_SCK */
+ <STM32_PINMUX('H', 10, AF6)>; /* SPI2_MOSI */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+
+ pins2 {
+ pinmux = <STM32_PINMUX('B', 5, AF5)>; /* SPI2_MISO */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ spi2_sleep_pins_a: spi2-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* SPI2_SCK */
+ <STM32_PINMUX('B', 5, ANALOG)>, /* SPI2_MISO */
+ <STM32_PINMUX('H', 10, ANALOG)>; /* SPI2_MOSI */
+ };
+ };
+
+ /omit-if-no-ref/
+ spi3_pins_a: spi3-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('H', 13, AF6)>, /* SPI3_SCK */
+ <STM32_PINMUX('F', 1, AF5)>; /* SPI3_MOSI */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+
+ pins2 {
+ pinmux = <STM32_PINMUX('D', 4, AF5)>; /* SPI3_MISO */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ spi3_sleep_pins_a: spi3-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('H', 13, ANALOG)>, /* SPI3_SCK */
+ <STM32_PINMUX('D', 4, ANALOG)>, /* SPI3_MISO */
+ <STM32_PINMUX('F', 1, ANALOG)>; /* SPI3_MOSI */
+ };
+ };
+
+ /omit-if-no-ref/
spi5_pins_a: spi5-0 {
pins1 {
pinmux = <STM32_PINMUX('H', 7, AF6)>, /* SPI5_SCK */
@@ -288,6 +817,7 @@
};
};
+ /omit-if-no-ref/
spi5_sleep_pins_a: spi5-sleep-0 {
pins {
pinmux = <STM32_PINMUX('H', 7, ANALOG)>, /* SPI5_SCK */
@@ -296,6 +826,7 @@
};
};
+ /omit-if-no-ref/
stm32g0_intn_pins_a: stm32g0-intn-0 {
pins {
pinmux = <STM32_PINMUX('I', 2, GPIO)>;
@@ -303,6 +834,7 @@
};
};
+ /omit-if-no-ref/
uart4_pins_a: uart4-0 {
pins1 {
pinmux = <STM32_PINMUX('D', 6, AF8)>; /* UART4_TX */
@@ -316,6 +848,7 @@
};
};
+ /omit-if-no-ref/
uart4_idle_pins_a: uart4-idle-0 {
pins1 {
pinmux = <STM32_PINMUX('D', 6, ANALOG)>; /* UART4_TX */
@@ -326,6 +859,7 @@
};
};
+ /omit-if-no-ref/
uart4_sleep_pins_a: uart4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('D', 6, ANALOG)>, /* UART4_TX */
@@ -333,6 +867,84 @@
};
};
+ /omit-if-no-ref/
+ uart4_pins_b: uart4-1 {
+ pins1 {
+ pinmux = <STM32_PINMUX('A', 9, AF8)>; /* UART4_TX */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('D', 8, AF8)>; /* UART4_RX */
+ bias-pull-up;
+ };
+ };
+
+ /omit-if-no-ref/
+ uart4_idle_pins_b: uart4-idle-1 {
+ pins1 {
+ pinmux = <STM32_PINMUX('A', 9, ANALOG)>; /* UART4_TX */
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('D', 8, AF8)>; /* UART4_RX */
+ bias-pull-up;
+ };
+ };
+
+ /omit-if-no-ref/
+ uart4_sleep_pins_b: uart4-sleep-1 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 9, ANALOG)>, /* UART4_TX */
+ <STM32_PINMUX('D', 8, ANALOG)>; /* UART4_RX */
+ };
+ };
+
+ /omit-if-no-ref/
+ uart7_pins_a: uart7-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('H', 2, AF8)>, /* UART7_TX */
+ <STM32_PINMUX('B', 12, AF7)>; /* UART7_RTS */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 10, AF7)>, /* UART7_RX */
+ <STM32_PINMUX('G', 7, AF8)>; /* UART7_CTS_NSS */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ uart7_idle_pins_a: uart7-idle-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('H', 2, ANALOG)>, /* UART7_TX */
+ <STM32_PINMUX('G', 7, ANALOG)>; /* UART7_CTS_NSS */
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('B', 12, AF7)>; /* UART7_RTS */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins3 {
+ pinmux = <STM32_PINMUX('E', 10, AF7)>; /* UART7_RX */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ uart7_sleep_pins_a: uart7-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('H', 2, ANALOG)>, /* UART7_TX */
+ <STM32_PINMUX('B', 12, ANALOG)>, /* UART7_RTS */
+ <STM32_PINMUX('E', 10, ANALOG)>, /* UART7_RX */
+ <STM32_PINMUX('G', 7, ANALOG)>; /* UART7_CTS_NSS */
+ };
+ };
+
+ /omit-if-no-ref/
uart8_pins_a: uart8-0 {
pins1 {
pinmux = <STM32_PINMUX('E', 1, AF8)>; /* UART8_TX */
@@ -346,6 +958,7 @@
};
};
+ /omit-if-no-ref/
uart8_idle_pins_a: uart8-idle-0 {
pins1 {
pinmux = <STM32_PINMUX('E', 1, ANALOG)>; /* UART8_TX */
@@ -356,6 +969,7 @@
};
};
+ /omit-if-no-ref/
uart8_sleep_pins_a: uart8-sleep-0 {
pins {
pinmux = <STM32_PINMUX('E', 1, ANALOG)>, /* UART8_TX */
@@ -363,6 +977,7 @@
};
};
+ /omit-if-no-ref/
usart1_pins_a: usart1-0 {
pins1 {
pinmux = <STM32_PINMUX('C', 0, AF7)>, /* USART1_TX */
@@ -378,6 +993,7 @@
};
};
+ /omit-if-no-ref/
usart1_idle_pins_a: usart1-idle-0 {
pins1 {
pinmux = <STM32_PINMUX('C', 0, ANALOG)>, /* USART1_TX */
@@ -395,6 +1011,7 @@
};
};
+ /omit-if-no-ref/
usart1_sleep_pins_a: usart1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('C', 0, ANALOG)>, /* USART1_TX */
@@ -404,6 +1021,40 @@
};
};
+ /omit-if-no-ref/
+ usart1_pins_b: usart1-1 {
+ pins1 {
+ pinmux = <STM32_PINMUX('C', 0, AF7)>; /* USART1_TX */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('D', 14, AF7)>; /* USART1_RX */
+ bias-pull-up;
+ };
+ };
+
+ /omit-if-no-ref/
+ usart1_idle_pins_b: usart1-idle-1 {
+ pins1 {
+ pinmux = <STM32_PINMUX('C', 0, ANALOG)>; /* USART1_TX */
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('D', 14, AF7)>; /* USART1_RX */
+ bias-pull-up;
+ };
+ };
+
+ /omit-if-no-ref/
+ usart1_sleep_pins_b: usart1-sleep-1 {
+ pins {
+ pinmux = <STM32_PINMUX('C', 0, ANALOG)>, /* USART1_TX */
+ <STM32_PINMUX('D', 14, ANALOG)>; /* USART1_RX */
+ };
+ };
+
+ /omit-if-no-ref/
usart2_pins_a: usart2-0 {
pins1 {
pinmux = <STM32_PINMUX('H', 12, AF1)>, /* USART2_TX */
@@ -419,6 +1070,7 @@
};
};
+ /omit-if-no-ref/
usart2_idle_pins_a: usart2-idle-0 {
pins1 {
pinmux = <STM32_PINMUX('H', 12, ANALOG)>, /* USART2_TX */
@@ -436,6 +1088,7 @@
};
};
+ /omit-if-no-ref/
usart2_sleep_pins_a: usart2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('H', 12, ANALOG)>, /* USART2_TX */
@@ -444,4 +1097,48 @@
<STM32_PINMUX('E', 11, ANALOG)>; /* USART2_CTS_NSS */
};
};
+
+ /omit-if-no-ref/
+ usart2_pins_b: usart2-1 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 11, AF1)>, /* USART2_TX */
+ <STM32_PINMUX('A', 1, AF7)>; /* USART2_RTS */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('D', 15, AF1)>, /* USART2_RX */
+ <STM32_PINMUX('E', 15, AF3)>; /* USART2_CTS_NSS */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ usart2_idle_pins_b: usart2-idle-1 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 11, ANALOG)>, /* USART2_TX */
+ <STM32_PINMUX('E', 15, ANALOG)>; /* USART2_CTS_NSS */
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('A', 1, AF7)>; /* USART2_RTS */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins3 {
+ pinmux = <STM32_PINMUX('D', 15, AF1)>; /* USART2_RX */
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ usart2_sleep_pins_b: usart2-sleep-1 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 11, ANALOG)>, /* USART2_TX */
+ <STM32_PINMUX('A', 1, ANALOG)>, /* USART2_RTS */
+ <STM32_PINMUX('D', 15, ANALOG)>, /* USART2_RX */
+ <STM32_PINMUX('E', 15, ANALOG)>; /* USART2_CTS_NSS */
+ };
+ };
};
diff --git a/arch/arm/boot/dts/st/stm32mp131.dtsi b/arch/arm/boot/dts/st/stm32mp131.dtsi
index 6704ceef284d..e1a764d269d2 100644
--- a/arch/arm/boot/dts/st/stm32mp131.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp131.dtsi
@@ -979,6 +979,12 @@
ts_cal2: calib@5e {
reg = <0x5e 0x2>;
};
+ ethernet_mac1_address: mac1@e4 {
+ reg = <0xe4 0x6>;
+ };
+ ethernet_mac2_address: mac2@ea {
+ reg = <0xea 0x6>;
+ };
};
etzpc: bus@5c007000 {
@@ -1505,6 +1511,38 @@
status = "disabled";
};
+ ethernet1: ethernet@5800a000 {
+ compatible = "st,stm32mp13-dwmac", "snps,dwmac-4.20a";
+ reg = <0x5800a000 0x2000>;
+ reg-names = "stmmaceth";
+ interrupts-extended = <&intc GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 68 1>;
+ interrupt-names = "macirq", "eth_wake_irq";
+ clock-names = "stmmaceth",
+ "mac-clk-tx",
+ "mac-clk-rx",
+ "ethstp",
+ "eth-ck";
+ clocks = <&rcc ETH1MAC>,
+ <&rcc ETH1TX>,
+ <&rcc ETH1RX>,
+ <&rcc ETH1STP>,
+ <&rcc ETH1CK_K>;
+ st,syscon = <&syscfg 0x4 0xff0000>;
+ snps,mixed-burst;
+ snps,pbl = <2>;
+ snps,axi-config = <&stmmac_axi_config_1>;
+ snps,tso;
+ access-controllers = <&etzpc 48>;
+ status = "disabled";
+
+ stmmac_axi_config_1: stmmac-axi-config {
+ snps,blen = <0 0 0 0 16 8 4>;
+ snps,rd_osr_lmt = <0x7>;
+ snps,wr_osr_lmt = <0x7>;
+ };
+ };
+
usbphyc: usbphyc@5a006000 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/st/stm32mp133.dtsi b/arch/arm/boot/dts/st/stm32mp133.dtsi
index 3e394c8e58b9..73e470019ce4 100644
--- a/arch/arm/boot/dts/st/stm32mp133.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp133.dtsi
@@ -68,4 +68,35 @@
};
};
};
+
+ ethernet2: ethernet@5800e000 {
+ compatible = "st,stm32mp13-dwmac", "snps,dwmac-4.20a";
+ reg = <0x5800e000 0x2000>;
+ reg-names = "stmmaceth";
+ interrupts-extended = <&intc GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ clock-names = "stmmaceth",
+ "mac-clk-tx",
+ "mac-clk-rx",
+ "ethstp",
+ "eth-ck";
+ clocks = <&rcc ETH2MAC>,
+ <&rcc ETH2TX>,
+ <&rcc ETH2RX>,
+ <&rcc ETH2STP>,
+ <&rcc ETH2CK_K>;
+ st,syscon = <&syscfg 0x4 0xff000000>;
+ snps,mixed-burst;
+ snps,pbl = <2>;
+ snps,axi-config = <&stmmac_axi_config_2>;
+ snps,tso;
+ access-controllers = <&etzpc 49>;
+ status = "disabled";
+
+ stmmac_axi_config_2: stmmac-axi-config {
+ snps,blen = <0 0 0 0 16 8 4>;
+ snps,rd_osr_lmt = <0x7>;
+ snps,wr_osr_lmt = <0x7>;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts b/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts
new file mode 100644
index 000000000000..bacb70b4256b
--- /dev/null
+++ b/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts
@@ -0,0 +1,377 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) 2024 Marek Vasut <[email protected]>
+ *
+ * DHCOR STM32MP13 variant:
+ * DHCR-STM32MP135F-C100-R051-EE-F0409-SPI4-RTC-WBT-I-01LG
+ * DHCOR PCB number: 718-100 or newer
+ * DHSBC PCB number: 719-100 or newer
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/regulator/st,stm32mp13-regulator.h>
+#include "stm32mp135.dtsi"
+#include "stm32mp13xf.dtsi"
+#include "stm32mp13xx-dhcor-som.dtsi"
+
+/ {
+ model = "DH electronics STM32MP135F DHCOR DHSBC";
+ compatible = "dh,stm32mp135f-dhcor-dhsbc",
+ "dh,stm32mp135f-dhcor-som",
+ "st,stm32mp135";
+
+ aliases {
+ ethernet0 = &ethernet1;
+ ethernet1 = &ethernet2;
+ serial2 = &usart1;
+ serial3 = &usart2;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&adc_1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&adc1_pins_a &adc1_usb_cc_pins_b>;
+ vdda-supply = <&vdd_adc>;
+ vref-supply = <&vdd_adc>;
+ status = "okay";
+
+ adc1: adc@0 {
+ status = "okay";
+
+ /*
+ * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in2 & in11.
+ * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C:
+ * 5 * (5.1 + 47kOhms) * 5pF => 1.3us.
+ * Use arbitrary margin here (e.g. 5us).
+ *
+ * The pinmux pins must be set as ANALOG, use datasheet
+ * DS13483 Table 7. STM32MP135C/F ball definitions to
+ * find out which 'pin name' maps to which 'additional
+ * functions', which lists the mapping between pin and
+ * ADC channel. In this case, PA5 maps to ADC1_INP2 and
+ * PF13 maps to ADC1_INP11 .
+ */
+ channel@2 {
+ reg = <2>;
+ st,min-sample-time-ns = <5000>;
+ };
+
+ channel@11 {
+ reg = <11>;
+ st,min-sample-time-ns = <5000>;
+ };
+
+ /* Expansion connector: INP12:pin29 */
+ channel@12 {
+ reg = <12>;
+ st,min-sample-time-ns = <5000>;
+ };
+ };
+};
+
+&ethernet1 {
+ phy-handle = <&ethphy1>;
+ phy-mode = "rgmii-id";
+ pinctrl-0 = <&eth1_rgmii_pins_a>;
+ pinctrl-1 = <&eth1_rgmii_sleep_pins_a>;
+ pinctrl-names = "default", "sleep";
+ st,ext-phyclk;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+
+ ethphy1: ethernet-phy@1 {
+ /* RTL8211F */
+ compatible = "ethernet-phy-id001c.c916";
+ interrupt-parent = <&gpiog>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+ reg = <1>;
+ reset-assert-us = <15000>;
+ reset-deassert-us = <55000>;
+ reset-gpios = <&gpioa 11 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&ethernet2 {
+ phy-handle = <&ethphy2>;
+ phy-mode = "rgmii-id";
+ pinctrl-0 = <&eth2_rgmii_pins_a>;
+ pinctrl-1 = <&eth2_rgmii_sleep_pins_a>;
+ pinctrl-names = "default", "sleep";
+ st,ext-phyclk;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+
+ ethphy2: ethernet-phy@1 {
+ /* RTL8211F */
+ compatible = "ethernet-phy-id001c.c916";
+ interrupt-parent = <&gpiog>;
+ interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+ reg = <1>;
+ reset-assert-us = <15000>;
+ reset-deassert-us = <55000>;
+ reset-gpios = <&gpiog 8 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&gpioa {
+ gpio-line-names = "", "", "", "",
+ "", "DHSBC_USB_PWR_CC1", "", "",
+ "", "", "", "DHSBC_nETH1_RST",
+ "", "DHCOR_HW-CODING_0", "", "";
+};
+
+&gpiob {
+ gpio-line-names = "", "", "", "",
+ "", "", "", "DHCOR_BT_HOST_WAKE",
+ "", "", "", "",
+ "", "DHSBC_nTPM_CS", "", "";
+};
+
+&gpioc {
+ gpio-line-names = "", "", "", "DHSBC_USB_5V_MEAS",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "";
+};
+
+&gpiod {
+ gpio-line-names = "", "", "", "",
+ "", "DHCOR_RAM-CODING_0", "", "",
+ "", "DHCOR_RAM-CODING_1", "", "",
+ "", "", "", "";
+};
+
+&gpioe {
+ gpio-line-names = "", "", "", "",
+ "", "", "", "",
+ "", "DHSBC_nTPM_RST", "", "",
+ "DHSBC_nTPM_PIRQ", "", "DHCOR_WL_HOST_WAKE", "";
+};
+
+&gpiof {
+ gpio-line-names = "", "", "DHSBC_USB_PWR_nFLT", "",
+ "", "", "", "",
+ "", "", "", "",
+ "DHCOR_WL_REG_ON", "DHSBC_USB_PWR_CC2", "", "";
+};
+
+&gpiog {
+ gpio-line-names = "", "", "", "",
+ "", "", "", "",
+ "DHSBC_nETH2_RST", "DHCOR_BT_DEV_WAKE", "", "",
+ "DHSBC_ETH1_INTB", "", "", "DHSBC_ETH2_INTB";
+};
+
+&gpioi {
+ gpio-line-names = "DHCOR_RTC_nINT", "DHCOR_HW-CODING_1",
+ "DHCOR_BT_REG_ON", "DHCOR_PMIC_nINT",
+ "DHSBC_BOOT0", "DHSBC_BOOT1",
+ "DHSBC_BOOT2", "DHSBC_USB-C_DATA_VBUS";
+};
+
+&i2c1 { /* Expansion connector: SDA:pin27 SCL:pin28 */
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c1_pins_a>;
+ pinctrl-1 = <&i2c1_sleep_pins_a>;
+ i2c-scl-rising-time-ns = <96>;
+ i2c-scl-falling-time-ns = <3>;
+ clock-frequency = <400000>;
+ status = "okay";
+ /* spare dmas for other usage */
+ /delete-property/dmas;
+ /delete-property/dma-names;
+};
+
+&i2c5 { /* Expansion connector: SDA:pin3 SCL:pin5 */
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c5_pins_b>;
+ pinctrl-1 = <&i2c5_sleep_pins_b>;
+ i2c-scl-rising-time-ns = <96>;
+ i2c-scl-falling-time-ns = <3>;
+ clock-frequency = <400000>;
+ status = "okay";
+ /* spare dmas for other usage */
+ /delete-property/dmas;
+ /delete-property/dma-names;
+};
+
+&m_can1 { /* Expansion connector: TX:pin16 RX:pin18 */
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&m_can1_pins_a>;
+ pinctrl-1 = <&m_can1_sleep_pins_a>;
+ status = "okay";
+};
+
+&m_can2 { /* Expansion connector: TX:pin22 RX:pin26 */
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&m_can2_pins_a>;
+ pinctrl-1 = <&m_can2_sleep_pins_a>;
+ status = "okay";
+};
+
+&pwr_regulators {
+ vdd-supply = <&vdd>;
+ vdd_3v3_usbfs-supply = <&vdd_usb>;
+ status = "okay";
+};
+
+&sai1 { /* Expansion connector: SCK-A:pin12 FS-A:pin35 SD-A:pin38 SD-B:pin40 */
+ clocks = <&rcc SAI1>, <&rcc PLL3_Q>, <&rcc PLL3_R>;
+ clock-names = "pclk", "x8k", "x11k";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sai1a_pins_a &sai1b_pins_a>;
+ pinctrl-1 = <&sai1a_sleep_pins_a &sai1b_sleep_pins_a>;
+};
+
+&scmi_voltd {
+ status = "disabled";
+};
+
+&spi2 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&spi2_pins_a>;
+ pinctrl-1 = <&spi2_sleep_pins_a>;
+ cs-gpios = <&gpiob 13 0>;
+ status = "okay";
+
+ st33htph: tpm@0 {
+ compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi";
+ reg = <0>;
+ spi-max-frequency = <24000000>;
+ };
+};
+
+&spi3 { /* Expansion connector: MOSI:pin19 MISO:pin21 SCK:pin22 nCS:pin24 */
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&spi3_pins_a>;
+ pinctrl-1 = <&spi3_sleep_pins_a>;
+ cs-gpios = <&gpiof 3 0>;
+ status = "disabled";
+};
+
+&timers5 { /* Expansion connector: CH3:pin31 */
+ /delete-property/dmas;
+ /delete-property/dma-names;
+ status = "okay";
+
+ pwm {
+ pinctrl-0 = <&pwm5_pins_a>;
+ pinctrl-1 = <&pwm5_sleep_pins_a>;
+ pinctrl-names = "default", "sleep";
+ status = "okay";
+ };
+ timer@4 {
+ status = "okay";
+ };
+};
+
+&timers13 { /* Expansion connector: CH1:pin32 */
+ /delete-property/dmas;
+ /delete-property/dma-names;
+ status = "okay";
+
+ pwm {
+ pinctrl-0 = <&pwm13_pins_a>;
+ pinctrl-1 = <&pwm13_sleep_pins_a>;
+ pinctrl-names = "default", "sleep";
+ status = "okay";
+ };
+ timer@12 {
+ status = "okay";
+ };
+};
+
+&usart1 { /* Expansion connector: RX:pin33 TX:pin37 */
+ pinctrl-names = "default", "sleep", "idle";
+ pinctrl-0 = <&usart1_pins_b>;
+ pinctrl-1 = <&usart1_sleep_pins_b>;
+ pinctrl-2 = <&usart1_idle_pins_b>;
+ status = "okay";
+};
+
+&usart2 { /* Expansion connector: RX:pin10 TX:pin8 RTS:pin11 CTS:pin36 */
+ pinctrl-names = "default", "sleep", "idle";
+ pinctrl-0 = <&usart2_pins_b>;
+ pinctrl-1 = <&usart2_sleep_pins_b>;
+ pinctrl-2 = <&usart2_idle_pins_b>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usbh_ehci {
+ phys = <&usbphyc_port0>;
+ status = "okay";
+};
+
+&usbh_ohci {
+ phys = <&usbphyc_port0>;
+ status = "okay";
+};
+
+&usbotg_hs {
+ dr_mode = "peripheral";
+ phys = <&usbphyc_port1 0>;
+ phy-names = "usb2-phy";
+ usb33d-supply = <&usb33>;
+ status = "okay";
+};
+
+&usbphyc {
+ status = "okay";
+ vdda1v1-supply = <&reg11>;
+ vdda1v8-supply = <&reg18>;
+};
+
+&usbphyc_port0 {
+ phy-supply = <&vdd_usb>;
+ st,current-boost-microamp = <1000>;
+ st,decrease-hs-slew-rate;
+ st,tune-hs-dc-level = <2>;
+ st,enable-hs-rftime-reduction;
+ st,trim-hs-current = <11>;
+ st,trim-hs-impedance = <2>;
+ st,tune-squelch-level = <1>;
+ st,enable-hs-rx-gain-eq;
+ st,no-hs-ftime-ctrl;
+ st,no-lsfs-sc;
+ connector {
+ compatible = "usb-a-connector";
+ vbus-supply = <&vbus_sw>;
+ };
+};
+
+&usbphyc_port1 {
+ phy-supply = <&vdd_usb>;
+ st,current-boost-microamp = <1000>;
+ st,decrease-hs-slew-rate;
+ st,tune-hs-dc-level = <2>;
+ st,enable-hs-rftime-reduction;
+ st,trim-hs-current = <11>;
+ st,trim-hs-impedance = <2>;
+ st,tune-squelch-level = <1>;
+ st,enable-hs-rx-gain-eq;
+ st,no-hs-ftime-ctrl;
+ st,no-lsfs-sc;
+ connector {
+ compatible = "gpio-usb-b-connector", "usb-b-connector";
+ vbus-gpios = <&gpioi 7 GPIO_ACTIVE_HIGH>;
+ label = "Type-C";
+ self-powered;
+ type = "micro";
+ };
+};
diff --git a/arch/arm/boot/dts/st/stm32mp135f-dk.dts b/arch/arm/boot/dts/st/stm32mp135f-dk.dts
index 567e53ad285f..1af335a39993 100644
--- a/arch/arm/boot/dts/st/stm32mp135f-dk.dts
+++ b/arch/arm/boot/dts/st/stm32mp135f-dk.dts
@@ -19,6 +19,7 @@
compatible = "st,stm32mp135f-dk", "st,stm32mp135";
aliases {
+ ethernet0 = &ethernet1;
serial0 = &uart4;
serial1 = &usart1;
serial2 = &uart8;
@@ -29,6 +30,20 @@
stdout-path = "serial0:115200n8";
};
+ clocks {
+ clk_ext_camera: clk-ext-camera {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+
+ clk_mco1: clk-mco1 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+ };
+
memory@c0000000 {
device_type = "memory";
reg = <0xc0000000 0x20000000>;
@@ -141,6 +156,45 @@
status = "okay";
};
+&dcmipp {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&dcmipp_pins_a>;
+ pinctrl-1 = <&dcmipp_sleep_pins_a>;
+ status = "okay";
+
+ port {
+ dcmipp_0: endpoint {
+ remote-endpoint = <&mipid02_2>;
+ bus-width = <8>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pclk-sample = <0>;
+ };
+ };
+};
+
+&ethernet1 {
+ status = "okay";
+ pinctrl-0 = <&eth1_rmii_pins_a>;
+ pinctrl-1 = <&eth1_rmii_sleep_pins_a>;
+ pinctrl-names = "default", "sleep";
+ phy-mode = "rmii";
+ phy-handle = <&phy0_eth1>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+
+ phy0_eth1: ethernet-phy@0 {
+ compatible = "ethernet-phy-id0007.c131";
+ reg = <0>;
+ reset-gpios = <&mcp23017 9 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+ };
+};
+
&i2c1 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c1_pins_a>;
@@ -201,6 +255,76 @@
/* spare dmas for other usage */
/delete-property/dmas;
/delete-property/dma-names;
+
+ stmipi: csi2rx@14 {
+ compatible = "st,st-mipid02";
+ reg = <0x14>;
+ clocks = <&clk_mco1>;
+ clock-names = "xclk";
+ VDDE-supply = <&scmi_v1v8_periph>;
+ VDDIN-supply = <&scmi_v1v8_periph>;
+ reset-gpios = <&mcp23017 2 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+
+ mipid02_0: endpoint {
+ data-lanes = <1 2>;
+ lane-polarities = <0 0 0>;
+ remote-endpoint = <&gc2145_ep>;
+ };
+ };
+ port@2 {
+ reg = <2>;
+
+ mipid02_2: endpoint {
+ bus-width = <8>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pclk-sample = <0>;
+ remote-endpoint = <&dcmipp_0>;
+ };
+ };
+ };
+ };
+
+ gc2145: camera@3c {
+ compatible = "galaxycore,gc2145";
+ reg = <0x3c>;
+ clocks = <&clk_ext_camera>;
+ iovdd-supply = <&scmi_v3v3_sw>;
+ avdd-supply = <&scmi_v3v3_sw>;
+ dvdd-supply = <&scmi_v3v3_sw>;
+ powerdown-gpios = <&mcp23017 3 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
+ reset-gpios = <&mcp23017 4 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
+ status = "okay";
+
+ port {
+ gc2145_ep: endpoint {
+ remote-endpoint = <&mipid02_0>;
+ data-lanes = <1 2>;
+ link-frequencies = /bits/ 64 <120000000 192000000 240000000>;
+ };
+ };
+ };
+
+ goodix: goodix-ts@5d {
+ compatible = "goodix,gt911";
+ reg = <0x5d>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&goodix_pins_a>;
+ interrupt-parent = <&gpiof>;
+ interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+ AVDD28-supply = <&scmi_v3v3_sw>;
+ VDDIO-supply = <&scmi_v3v3_sw>;
+ touchscreen-size-x = <480>;
+ touchscreen-size-y = <272>;
+ status = "okay" ;
+ };
};
&iwdg2 {
@@ -273,6 +397,7 @@
/delete-property/dma-names;
status = "disabled";
pwm {
+ /* PWM output on pin 7 of the expansion connector (CN8.7) using TIM3_CH4 func */
pinctrl-0 = <&pwm3_pins_a>;
pinctrl-1 = <&pwm3_sleep_pins_a>;
pinctrl-names = "default", "sleep";
@@ -288,6 +413,7 @@
/delete-property/dma-names;
status = "disabled";
pwm {
+ /* PWM output on pin 31 of the expansion connector (CN8.31) using TIM4_CH2 func */
pinctrl-0 = <&pwm4_pins_a>;
pinctrl-1 = <&pwm4_sleep_pins_a>;
pinctrl-names = "default", "sleep";
@@ -303,6 +429,7 @@
/delete-property/dma-names;
status = "disabled";
pwm {
+ /* PWM output on pin 32 of the expansion connector (CN8.32) using TIM8_CH3 func */
pinctrl-0 = <&pwm8_pins_a>;
pinctrl-1 = <&pwm8_sleep_pins_a>;
pinctrl-names = "default", "sleep";
@@ -316,6 +443,7 @@
&timers14 {
status = "disabled";
pwm {
+ /* PWM output on pin 33 of the expansion connector (CN8.33) using TIM14_CH1 func */
pinctrl-0 = <&pwm14_pins_a>;
pinctrl-1 = <&pwm14_sleep_pins_a>;
pinctrl-names = "default", "sleep";
diff --git a/arch/arm/boot/dts/st/stm32mp13xx-dhcor-som.dtsi b/arch/arm/boot/dts/st/stm32mp13xx-dhcor-som.dtsi
new file mode 100644
index 000000000000..ddad6497775b
--- /dev/null
+++ b/arch/arm/boot/dts/st/stm32mp13xx-dhcor-som.dtsi
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) 2024 Marek Vasut <[email protected]>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
+#include <dt-bindings/regulator/st,stm32mp13-regulator.h>
+#include "stm32mp13-pinctrl.dtsi"
+
+/ {
+ model = "DH electronics STM32MP13xx DHCOR SoM";
+ compatible = "dh,stm32mp131a-dhcor-som",
+ "st,stm32mp131";
+
+ aliases {
+ mmc0 = &sdmmc2;
+ mmc1 = &sdmmc1;
+ serial0 = &uart4;
+ serial1 = &uart7;
+ rtc0 = &rv3032;
+ spi0 = &qspi;
+ };
+
+ memory@c0000000 {
+ device_type = "memory";
+ reg = <0xc0000000 0x20000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ optee@dd000000 {
+ reg = <0xdd000000 0x3000000>;
+ no-map;
+ };
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&gpiof 12 GPIO_ACTIVE_LOW>;
+ };
+
+ vin: vin {
+ compatible = "regulator-fixed";
+ regulator-name = "vin";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+};
+
+&i2c3 {
+ i2c-scl-rising-time-ns = <96>;
+ i2c-scl-falling-time-ns = <3>;
+ clock-frequency = <400000>;
+ status = "okay";
+ /* spare dmas for other usage */
+ /delete-property/dmas;
+ /delete-property/dma-names;
+
+ pmic: stpmic@33 {
+ compatible = "st,stpmic1";
+ reg = <0x33>;
+ interrupts-extended = <&gpioi 3 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ status = "okay";
+
+ regulators {
+ compatible = "st,stpmic1-regulators";
+
+ ldo1-supply = <&vin>;
+ ldo2-supply = <&vin>;
+ ldo3-supply = <&vin>;
+ ldo4-supply = <&vin>;
+ ldo5-supply = <&vin>;
+ ldo6-supply = <&vin>;
+ pwr_sw1-supply = <&bst_out>;
+ pwr_sw2-supply = <&bst_out>;
+
+ vddcpu: buck1 { /* VDD_CPU_1V2 */
+ regulator-name = "vddcpu";
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-always-on;
+ regulator-initial-mode = <0>;
+ regulator-over-current-protection;
+ };
+
+ vdd_ddr: buck2 { /* VDD_DDR_1V35 */
+ regulator-name = "vdd_ddr";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-initial-mode = <0>;
+ regulator-over-current-protection;
+ };
+
+ vdd: buck3 { /* VDD_3V3_1V8 */
+ regulator-name = "vdd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-initial-mode = <0>;
+ regulator-over-current-protection;
+ };
+
+ vddcore: buck4 { /* VDD_CORE_1V2 */
+ regulator-name = "vddcore";
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-always-on;
+ regulator-initial-mode = <0>;
+ regulator-over-current-protection;
+ };
+
+ vdd_adc: ldo1 { /* VDD_ADC_1V8 */
+ regulator-name = "vdd_adc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ interrupts = <IT_CURLIM_LDO1 0>;
+ };
+
+ vdd_ldo2: ldo2 { /* LDO2_OUT_1V8 */
+ regulator-name = "vdd_ldo2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ interrupts = <IT_CURLIM_LDO2 0>;
+ };
+
+ vdd_ldo3: ldo3 { /* LDO3_OUT */
+ regulator-name = "vdd_ldo3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ interrupts = <IT_CURLIM_LDO3 0>;
+ };
+
+ vdd_usb: ldo4 { /* VDD_USB_3V3 */
+ regulator-name = "vdd_usb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ interrupts = <IT_CURLIM_LDO4 0>;
+ };
+
+ vdd_sd: ldo5 { /* VDD_SD_3V3_1V8 */
+ regulator-name = "vdd_sd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ interrupts = <IT_CURLIM_LDO5 0>;
+ };
+
+ vdd_sd2: ldo6 { /* VDD_SD2_3V3_1V8 */
+ regulator-name = "vdd_sd2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ interrupts = <IT_CURLIM_LDO6 0>;
+ };
+
+ vref_ddr: vref_ddr { /* VREF_DDR_0V675 */
+ regulator-name = "vref_ddr";
+ regulator-always-on;
+ };
+
+ bst_out: boost { /* BST_OUT_5V2 */
+ regulator-name = "bst_out";
+ };
+
+ vbus_otg: pwr_sw1 {
+ regulator-name = "vbus_otg";
+ interrupts = <IT_OCP_OTG 0>;
+ };
+
+ vbus_sw: pwr_sw2 {
+ regulator-name = "vbus_sw";
+ interrupts = <IT_OCP_SWOUT 0>;
+ regulator-active-discharge = <1>;
+ };
+ };
+
+ onkey {
+ compatible = "st,stpmic1-onkey";
+ interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 1>;
+ interrupt-names = "onkey-falling", "onkey-rising";
+ status = "okay";
+ };
+
+ watchdog {
+ compatible = "st,stpmic1-wdt";
+ status = "disabled";
+ };
+ };
+
+ eeprom0: eeprom@50 {
+ compatible = "atmel,24c256"; /* ST M24256 */
+ reg = <0x50>;
+ pagesize = <64>;
+ };
+
+ rv3032: rtc@51 {
+ compatible = "microcrystal,rv3032";
+ reg = <0x51>;
+ interrupts-extended = <&gpioi 0 IRQ_TYPE_EDGE_FALLING>;
+ };
+};
+
+&iwdg2 {
+ timeout-sec = <32>;
+ status = "okay";
+};
+
+&qspi {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&qspi_clk_pins_a
+ &qspi_bk1_pins_a
+ &qspi_cs1_pins_a>;
+ pinctrl-1 = <&qspi_clk_sleep_pins_a
+ &qspi_bk1_sleep_pins_a
+ &qspi_cs1_sleep_pins_a>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ flash0: flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-rx-bus-width = <4>;
+ spi-max-frequency = <108000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
+/* Console UART */
+&uart4 {
+ pinctrl-names = "default", "sleep", "idle";
+ pinctrl-0 = <&uart4_pins_b>;
+ pinctrl-1 = <&uart4_sleep_pins_b>;
+ pinctrl-2 = <&uart4_idle_pins_b>;
+ /delete-property/dmas;
+ /delete-property/dma-names;
+ status = "okay";
+};
+
+/* Bluetooth */
+&uart7 {
+ pinctrl-names = "default", "sleep", "idle";
+ pinctrl-0 = <&uart7_pins_a>;
+ pinctrl-1 = <&uart7_sleep_pins_a>;
+ pinctrl-2 = <&uart7_idle_pins_a>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "infineon,cyw43439-bt", "brcm,bcm4329-bt";
+ max-speed = <3000000>;
+ device-wakeup-gpios = <&gpiog 9 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&gpioi 2 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+/* SDIO WiFi */
+&sdmmc1 {
+ pinctrl-names = "default", "opendrain", "sleep";
+ pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_clk_pins_a>;
+ pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_clk_pins_a>;
+ pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
+ bus-width = <4>;
+ cap-power-off-card;
+ keep-power-in-suspend;
+ non-removable;
+ st,neg-edge;
+ vmmc-supply = <&vdd>;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ status = "okay";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ brcmf: bcrmf@1 { /* muRata 1YN */
+ reg = <1>;
+ compatible = "infineon,cyw43439-fmac", "brcm,bcm4329-fmac";
+ interrupt-parent = <&gpioe>;
+ interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "host-wake";
+ };
+};
+
+/* eMMC */
+&sdmmc2 {
+ pinctrl-names = "default", "opendrain", "sleep";
+ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a &sdmmc2_clk_pins_a>;
+ pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a &sdmmc2_clk_pins_a>;
+ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>;
+ bus-width = <8>;
+ mmc-ddr-3_3v;
+ no-sd;
+ no-sdio;
+ non-removable;
+ st,neg-edge;
+ vmmc-supply = <&vdd>;
+ vqmmc-supply = <&vdd>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/st/stm32mp151.dtsi b/arch/arm/boot/dts/st/stm32mp151.dtsi
index 90c5c72c87ab..4f878ec102c1 100644
--- a/arch/arm/boot/dts/st/stm32mp151.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp151.dtsi
@@ -50,6 +50,7 @@
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
interrupt-parent = <&intc>;
+ arm,no-tick-in-suspend;
};
clocks {
diff --git a/arch/arm/boot/dts/st/stm32mp157a-dk1-scmi.dts b/arch/arm/boot/dts/st/stm32mp157a-dk1-scmi.dts
index 306e1bc2a514..847b360f02fc 100644
--- a/arch/arm/boot/dts/st/stm32mp157a-dk1-scmi.dts
+++ b/arch/arm/boot/dts/st/stm32mp157a-dk1-scmi.dts
@@ -62,6 +62,11 @@
reset-names = "mcu_rst", "hold_boot";
};
+&optee {
+ interrupt-parent = <&intc>;
+ interrupts = <GIC_PPI 15 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+};
+
&rcc {
compatible = "st,stm32mp1-rcc-secure", "syscon";
clock-names = "hse", "hsi", "csi", "lse", "lsi";
diff --git a/arch/arm/boot/dts/st/stm32mp157c-dk2-scmi.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2-scmi.dts
index 956da5f26c1c..43280289759d 100644
--- a/arch/arm/boot/dts/st/stm32mp157c-dk2-scmi.dts
+++ b/arch/arm/boot/dts/st/stm32mp157c-dk2-scmi.dts
@@ -68,6 +68,11 @@
reset-names = "mcu_rst", "hold_boot";
};
+&optee {
+ interrupt-parent = <&intc>;
+ interrupts = <GIC_PPI 15 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+};
+
&rcc {
compatible = "st,stm32mp1-rcc-secure", "syscon";
clock-names = "hse", "hsi", "csi", "lse", "lsi";
diff --git a/arch/arm/boot/dts/st/stm32mp157c-ed1-scmi.dts b/arch/arm/boot/dts/st/stm32mp157c-ed1-scmi.dts
index 8e4b0db198c2..6f27d794d270 100644
--- a/arch/arm/boot/dts/st/stm32mp157c-ed1-scmi.dts
+++ b/arch/arm/boot/dts/st/stm32mp157c-ed1-scmi.dts
@@ -67,6 +67,11 @@
reset-names = "mcu_rst", "hold_boot";
};
+&optee {
+ interrupt-parent = <&intc>;
+ interrupts = <GIC_PPI 15 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+};
+
&rcc {
compatible = "st,stm32mp1-rcc-secure", "syscon";
clock-names = "hse", "hsi", "csi", "lse", "lsi";
diff --git a/arch/arm/boot/dts/st/stm32mp157c-ev1-scmi.dts b/arch/arm/boot/dts/st/stm32mp157c-ev1-scmi.dts
index 72b9cab2d990..6ae391bffee5 100644
--- a/arch/arm/boot/dts/st/stm32mp157c-ev1-scmi.dts
+++ b/arch/arm/boot/dts/st/stm32mp157c-ev1-scmi.dts
@@ -72,6 +72,11 @@
reset-names = "mcu_rst", "hold_boot";
};
+&optee {
+ interrupt-parent = <&intc>;
+ interrupts = <GIC_PPI 15 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+};
+
&rcc {
compatible = "st,stm32mp1-rcc-secure", "syscon";
clock-names = "hse", "hsi", "csi", "lse", "lsi";
diff --git a/arch/arm/boot/dts/st/stm32mp157c-osd32mp1-red.dts b/arch/arm/boot/dts/st/stm32mp157c-osd32mp1-red.dts
index 527c33be66cc..36e6055b5665 100644
--- a/arch/arm/boot/dts/st/stm32mp157c-osd32mp1-red.dts
+++ b/arch/arm/boot/dts/st/stm32mp157c-osd32mp1-red.dts
@@ -147,11 +147,6 @@
status = "okay";
};
-&pwr_regulators {
- vdd-supply = <&vdd>;
- vdd_3v3_usbfs-supply = <&vdd_usb>;
-};
-
&rtc {
status = "okay";
};
@@ -211,11 +206,3 @@
&usbphyc {
status = "okay";
};
-
-&usbphyc_port0 {
- phy-supply = <&vdd_usb>;
-};
-
-&usbphyc_port1 {
- phy-supply = <&vdd_usb>;
-};
diff --git a/arch/arm/boot/dts/st/stm32mp15xc-lxa-tac.dtsi b/arch/arm/boot/dts/st/stm32mp15xc-lxa-tac.dtsi
index cfaf8adde319..c87fd96cbd91 100644
--- a/arch/arm/boot/dts/st/stm32mp15xc-lxa-tac.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp15xc-lxa-tac.dtsi
@@ -379,11 +379,6 @@ baseboard_eeprom: &sip_eeprom {
};
};
-&pwr_regulators {
- vdd-supply = <&vdd>;
- vdd_3v3_usbfs-supply = <&vdd_usb>;
-};
-
&rtc {
status = "okay";
};
@@ -590,14 +585,6 @@ baseboard_eeprom: &sip_eeprom {
status = "okay";
};
-&usbphyc_port0 {
- phy-supply = <&vdd_usb>;
-};
-
-&usbphyc_port1 {
- phy-supply = <&vdd_usb>;
-};
-
&vrefbuf {
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
diff --git a/arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi
index aeb71c41a734..2022a1fa31ca 100644
--- a/arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi
@@ -214,3 +214,16 @@
&rng1 {
status = "okay";
};
+
+&pwr_regulators {
+ vdd-supply = <&vdd>;
+ vdd_3v3_usbfs-supply = <&vdd_usb>;
+};
+
+&usbphyc_port0 {
+ phy-supply = <&vdd_usb>;
+};
+
+&usbphyc_port1 {
+ phy-supply = <&vdd_usb>;
+};
diff --git a/arch/arm/boot/dts/ti/davinci/da850-evm.dts b/arch/arm/boot/dts/ti/davinci/da850-evm.dts
index 6c5936278e75..1f5cd35f8b74 100644
--- a/arch/arm/boot/dts/ti/davinci/da850-evm.dts
+++ b/arch/arm/boot/dts/ti/davinci/da850-evm.dts
@@ -65,7 +65,7 @@
display-timings {
native-mode = <&timing0>;
- timing0: 480x272 {
+ timing0: timing-480x272 {
clock-frequency = <9000000>;
hactive = <480>;
vactive = <272>;
diff --git a/arch/arm/boot/dts/ti/omap/am335x-guardian.dts b/arch/arm/boot/dts/ti/omap/am335x-guardian.dts
index 56e5d954a490..4b070e634b28 100644
--- a/arch/arm/boot/dts/ti/omap/am335x-guardian.dts
+++ b/arch/arm/boot/dts/ti/omap/am335x-guardian.dts
@@ -74,7 +74,7 @@
pinctrl-1 = <&lcd_pins_sleep>;
display-timings {
- 320x240 {
+ timing-320x240 {
hactive = <320>;
vactive = <240>;
hback-porch = <68>;
diff --git a/arch/arm/boot/dts/ti/omap/am335x-pdu001.dts b/arch/arm/boot/dts/ti/omap/am335x-pdu001.dts
index f38f5bff2b96..17574d0d0525 100644
--- a/arch/arm/boot/dts/ti/omap/am335x-pdu001.dts
+++ b/arch/arm/boot/dts/ti/omap/am335x-pdu001.dts
@@ -67,7 +67,7 @@
};
display-timings {
- 240x320p16 {
+ timing-240x320p16 {
clock-frequency = <6500000>;
hactive = <240>;
vactive = <320>;
diff --git a/arch/arm/boot/dts/ti/omap/am335x-pepper.dts b/arch/arm/boot/dts/ti/omap/am335x-pepper.dts
index d5a4a21889d1..e7d561a527fd 100644
--- a/arch/arm/boot/dts/ti/omap/am335x-pepper.dts
+++ b/arch/arm/boot/dts/ti/omap/am335x-pepper.dts
@@ -202,7 +202,7 @@
};
display-timings {
native-mode = <&timing0>;
- timing0: 480x272 {
+ timing0: timing-480x272 {
clock-frequency = <18400000>;
hactive = <480>;
vactive = <272>;
diff --git a/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts b/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts
index eb1ec85aba28..e6a18954e449 100644
--- a/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts
+++ b/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts
@@ -196,7 +196,6 @@
extcon_usb1: extcon_usb1 {
compatible = "linux,extcon-usb-gpio";
- ti,enable-id-detection;
id-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
};
};
diff --git a/arch/arm/boot/dts/vt8500/vt8500-bv07.dts b/arch/arm/boot/dts/vt8500/vt8500-bv07.dts
index e9f55bd30bd4..38a2da5e2c5d 100644
--- a/arch/arm/boot/dts/vt8500/vt8500-bv07.dts
+++ b/arch/arm/boot/dts/vt8500/vt8500-bv07.dts
@@ -16,7 +16,7 @@
bits-per-pixel = <16>;
display-timings {
native-mode = <&timing0>;
- timing0: 800x480 {
+ timing0: timing-800x480 {
clock-frequency = <0>; /* unused but required */
hactive = <800>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/vt8500/vt8500.dtsi b/arch/arm/boot/dts/vt8500/vt8500.dtsi
index b7e09eff5bb2..f23cb5ee11ae 100644
--- a/arch/arm/boot/dts/vt8500/vt8500.dtsi
+++ b/arch/arm/boot/dts/vt8500/vt8500.dtsi
@@ -115,7 +115,7 @@
interrupts = <43>;
};
- uhci@d8007b00 {
+ usb@d8007b00 {
compatible = "platform-uhci";
reg = <0xd8007b00 0x200>;
interrupts = <43>;
diff --git a/arch/arm/boot/dts/vt8500/wm8505-ref.dts b/arch/arm/boot/dts/vt8500/wm8505-ref.dts
index 2d77c087676e..8ce9e2ef0a81 100644
--- a/arch/arm/boot/dts/vt8500/wm8505-ref.dts
+++ b/arch/arm/boot/dts/vt8500/wm8505-ref.dts
@@ -16,7 +16,7 @@
bits-per-pixel = <32>;
display-timings {
native-mode = <&timing0>;
- timing0: 800x480 {
+ timing0: timing-800x480 {
clock-frequency = <0>; /* unused but required */
hactive = <800>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/vt8500/wm8505.dtsi b/arch/arm/boot/dts/vt8500/wm8505.dtsi
index 168cd12b07bc..d9e1280372c5 100644
--- a/arch/arm/boot/dts/vt8500/wm8505.dtsi
+++ b/arch/arm/boot/dts/vt8500/wm8505.dtsi
@@ -213,7 +213,7 @@
interrupts = <1>;
};
- uhci@d8007300 {
+ usb@d8007300 {
compatible = "platform-uhci";
reg = <0xd8007300 0x200>;
interrupts = <0>;
diff --git a/arch/arm/boot/dts/vt8500/wm8650-mid.dts b/arch/arm/boot/dts/vt8500/wm8650-mid.dts
index f6a42149a0a0..7977b6c1e8eb 100644
--- a/arch/arm/boot/dts/vt8500/wm8650-mid.dts
+++ b/arch/arm/boot/dts/vt8500/wm8650-mid.dts
@@ -17,7 +17,7 @@
display-timings {
native-mode = <&timing0>;
- timing0: 800x480 {
+ timing0: timing-800x480 {
clock-frequency = <0>; /* unused but required */
hactive = <800>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/vt8500/wm8650.dtsi b/arch/arm/boot/dts/vt8500/wm8650.dtsi
index bc057b6f7d16..35d12d77efc0 100644
--- a/arch/arm/boot/dts/vt8500/wm8650.dtsi
+++ b/arch/arm/boot/dts/vt8500/wm8650.dtsi
@@ -185,7 +185,7 @@
interrupts = <43>;
};
- uhci@d8007b00 {
+ usb@d8007b00 {
compatible = "platform-uhci";
reg = <0xd8007b00 0x200>;
interrupts = <43>;
diff --git a/arch/arm/boot/dts/vt8500/wm8750.dtsi b/arch/arm/boot/dts/vt8500/wm8750.dtsi
index 33aeb37491f4..b292f85d4e69 100644
--- a/arch/arm/boot/dts/vt8500/wm8750.dtsi
+++ b/arch/arm/boot/dts/vt8500/wm8750.dtsi
@@ -257,13 +257,13 @@
interrupts = <26>;
};
- uhci@d8007b00 {
+ usb@d8007b00 {
compatible = "platform-uhci";
reg = <0xd8007b00 0x200>;
interrupts = <26>;
};
- uhci@d8008d00 {
+ usb@d8008d00 {
compatible = "platform-uhci";
reg = <0xd8008d00 0x200>;
interrupts = <26>;
diff --git a/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts b/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts
index c7a6fe0ce48f..5d409323b10c 100644
--- a/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts
+++ b/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts
@@ -28,7 +28,7 @@
bits-per-pixel = <16>;
display-timings {
native-mode = <&timing0>;
- timing0: 800x480 {
+ timing0: timing-800x480 {
clock-frequency = <0>; /* unused but required */
hactive = <800>;
vactive = <480>;
diff --git a/arch/arm/boot/dts/vt8500/wm8850.dtsi b/arch/arm/boot/dts/vt8500/wm8850.dtsi
index 65c9271050e6..c61717ebb4f1 100644
--- a/arch/arm/boot/dts/vt8500/wm8850.dtsi
+++ b/arch/arm/boot/dts/vt8500/wm8850.dtsi
@@ -244,13 +244,13 @@
interrupts = <26>;
};
- uhci@d8007b00 {
+ usb@d8007b00 {
compatible = "platform-uhci";
reg = <0xd8007b00 0x200>;
interrupts = <26>;
};
- uhci@d8008d00 {
+ usb@d8008d00 {
compatible = "platform-uhci";
reg = <0xd8008d00 0x200>;
interrupts = <26>;
diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
index 1d53aec4c836..6eabe2313c9a 100644
--- a/arch/arm/configs/at91_dt_defconfig
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -143,6 +143,7 @@ CONFIG_VIDEO_OV2640=m
CONFIG_VIDEO_OV7740=m
CONFIG_DRM=y
CONFIG_DRM_ATMEL_HLCDC=y
+CONFIG_DRM_MICROCHIP_LVDS_SERIALIZER=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_FB_ATMEL=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index cf2480dce285..b7c271ddf9c0 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -133,6 +133,7 @@ CONFIG_SMSC911X=y
# CONFIG_NET_VENDOR_STMICRO is not set
CONFIG_MICREL_PHY=y
CONFIG_AT803X_PHY=y
+CONFIG_DP83867_PHY=y
CONFIG_CAN_FLEXCAN=y
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
@@ -180,6 +181,7 @@ CONFIG_TOUCHSCREEN_SX8654=y
CONFIG_TOUCHSCREEN_COLIBRI_VF50=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_MMA8450=y
+CONFIG_INPUT_GPIO_BEEPER=m
CONFIG_SERIO_SERPORT=m
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_IMX=y
@@ -211,6 +213,7 @@ CONFIG_GPIO_SIOX=m
CONFIG_GPIO_VF610=y
CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_PCF857X=y
CONFIG_GPIO_BD71815=y
CONFIG_GPIO_STMPE=y
@@ -226,6 +229,7 @@ CONFIG_RN5T618_POWER=m
CONFIG_SENSORS_MC13783_ADC=y
CONFIG_SENSORS_GPIO_FAN=y
CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_SENSORS_LM75=m
CONFIG_SENSORS_PWM_FAN=y
CONFIG_SENSORS_SY7636A=y
CONFIG_THERMAL_STATISTICS=y
@@ -282,6 +286,9 @@ CONFIG_DRM_PANEL_LVDS=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
+CONFIG_DRM_DISPLAY_CONNECTOR=y
+CONFIG_DRM_LVDS_CODEC=m
+CONFIG_DRM_SII902X=y
CONFIG_DRM_TI_TFP410=y
CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
CONFIG_DRM_DW_HDMI_CEC=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 86bf057ac366..62734530a3d6 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -469,6 +469,7 @@ CONFIG_SPI_XILINX=y
CONFIG_SPI_SPIDEV=y
CONFIG_SPMI=y
CONFIG_PINCTRL_AS3722=y
+CONFIG_PINCTRL_MCP23S08=m
CONFIG_PINCTRL_MICROCHIP_SGPIO=y
CONFIG_PINCTRL_OCELOT=y
CONFIG_PINCTRL_PALMAS=y
diff --git a/arch/arm/configs/vexpress_defconfig b/arch/arm/configs/vexpress_defconfig
index 96ad442089bd..cdb6065e04fd 100644
--- a/arch/arm/configs/vexpress_defconfig
+++ b/arch/arm/configs/vexpress_defconfig
@@ -14,7 +14,6 @@ CONFIG_CPUSETS=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_PROFILING=y
CONFIG_ARCH_VEXPRESS=y
-CONFIG_ARCH_VEXPRESS_DCSCB=y
CONFIG_ARCH_VEXPRESS_TC2_PM=y
CONFIG_SMP=y
CONFIG_HAVE_ARM_ARCH_TIMER=y
diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h
index 44667bdb4707..9beb64d30586 100644
--- a/arch/arm/include/asm/cmpxchg.h
+++ b/arch/arm/include/asm/cmpxchg.h
@@ -5,6 +5,7 @@
#include <linux/irqflags.h>
#include <linux/prefetch.h>
#include <asm/barrier.h>
+#include <linux/cmpxchg-emu.h>
#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
/*
@@ -162,7 +163,11 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
prefetchw((const void *)ptr);
switch (size) {
-#ifndef CONFIG_CPU_V6 /* min ARCH >= ARMv6K */
+#ifdef CONFIG_CPU_V6 /* ARCH == ARMv6 */
+ case 1:
+ oldval = cmpxchg_emu_u8((volatile u8 *)ptr, old, new);
+ break;
+#else /* min ARCH > ARMv6 */
case 1:
do {
asm volatile("@ __cmpxchg1\n"
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 3676e82cf95c..9fb00973c608 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -37,7 +37,6 @@
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_VFORK
#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
/*
* Unimplemented (or alternatively implemented) syscalls
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 89a77e3f51d2..aaae31b8c4a5 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -78,8 +78,6 @@ obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o
obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o
obj-$(CONFIG_IWMMXT) += iwmmxt.o
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_xscale.o perf_event_v6.o \
- perf_event_v7.o
AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt
obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o
obj-$(CONFIG_VDSO) += vdso.o
diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c
index 8aa39db095d7..2c5155bd376b 100644
--- a/arch/arm/mach-davinci/pm.c
+++ b/arch/arm/mach-davinci/pm.c
@@ -61,7 +61,7 @@ static void davinci_pm_suspend(void)
/* Configure sleep count in deep sleep register */
val = __raw_readl(pm_config.deepsleep_reg);
- val &= ~DEEPSLEEP_SLEEPCOUNT_MASK,
+ val &= ~DEEPSLEEP_SLEEPCOUNT_MASK;
val |= pm_config.sleepcount;
__raw_writel(val, pm_config.deepsleep_reg);
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 1e4cd502340e..7695cfce01a1 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -7,6 +7,7 @@
#include <linux/clk-provider.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
+#include <linux/gpio-pxa.h>
#include <linux/platform_data/i2c-pxa.h>
#include <linux/soc/pxa/cpu.h>
@@ -17,6 +18,7 @@
#include <linux/platform_data/usb-ohci-pxa27x.h>
#include <linux/platform_data/mmp_dma.h>
+#include "mfp-pxa2xx.h"
#include "regs-ost.h"
#include "reset.h"
#include "devices.h"
@@ -46,7 +48,7 @@ struct platform_device pxa_device_pmu = {
.num_resources = 1,
};
-static struct resource pxamci_resources[] = {
+static const struct resource pxamci_resources[] = {
[0] = {
.start = 0x41100000,
.end = 0x41100fff,
@@ -59,22 +61,26 @@ static struct resource pxamci_resources[] = {
},
};
-static u64 pxamci_dmamask = 0xffffffffUL;
-
-struct platform_device pxa_device_mci = {
- .name = "pxa2xx-mci",
- .id = 0,
- .dev = {
- .dma_mask = &pxamci_dmamask,
- .coherent_dma_mask = 0xffffffff,
- },
- .num_resources = ARRAY_SIZE(pxamci_resources),
- .resource = pxamci_resources,
-};
-
-void __init pxa_set_mci_info(struct pxamci_platform_data *info)
+void __init pxa_set_mci_info(const struct pxamci_platform_data *info,
+ const struct property_entry *props)
{
- pxa_register_device(&pxa_device_mci, info);
+ const struct platform_device_info mci_info = {
+ .name = "pxa2xx-mci",
+ .id = 0,
+ .res = pxamci_resources,
+ .num_res = ARRAY_SIZE(pxamci_resources),
+ .data = info,
+ .size_data = sizeof(*info),
+ .dma_mask = 0xffffffffUL,
+ .properties = props,
+ };
+ struct platform_device *mci_dev;
+ int err;
+
+ mci_dev = platform_device_register_full(&mci_info);
+ err = PTR_ERR_OR_ZERO(mci_dev);
+ if (err)
+ pr_err("Unable to create mci device: %d\n", err);
}
static struct pxa2xx_udc_mach_info pxa_udc_info = {
@@ -627,6 +633,11 @@ struct platform_device pxa27x_device_pwm1 = {
};
#endif /* CONFIG_PXA27x || CONFIG_PXA3xx */
+#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
+const struct software_node pxa2xx_gpiochip_node = {
+ .name = "gpio-pxa",
+};
+
struct resource pxa_resource_gpio[] = {
{
.start = 0x40e00000,
@@ -650,11 +661,19 @@ struct resource pxa_resource_gpio[] = {
},
};
+static struct pxa_gpio_platform_data pxa2xx_gpio_info = {
+ .irq_base = PXA_GPIO_TO_IRQ(0),
+ .gpio_set_wake = gpio_set_wake,
+};
+
struct platform_device pxa25x_device_gpio = {
.name = "pxa25x-gpio",
.id = -1,
.num_resources = ARRAY_SIZE(pxa_resource_gpio),
.resource = pxa_resource_gpio,
+ .dev = {
+ .platform_data = &pxa2xx_gpio_info,
+ },
};
struct platform_device pxa27x_device_gpio = {
@@ -662,7 +681,11 @@ struct platform_device pxa27x_device_gpio = {
.id = -1,
.num_resources = ARRAY_SIZE(pxa_resource_gpio),
.resource = pxa_resource_gpio,
+ .dev = {
+ .platform_data = &pxa2xx_gpio_info,
+ },
};
+#endif /* CONFIG_PXA25x || CONFIG_PXA27x */
static struct resource pxa_dma_resource[] = {
[0] = {
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index 82c83939017a..72c556ff67db 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -4,7 +4,6 @@
struct mmp_dma_platdata;
extern struct platform_device pxa_device_pmu;
-extern struct platform_device pxa_device_mci;
extern struct platform_device pxa3xx_device_mci2;
extern struct platform_device pxa3xx_device_mci3;
extern struct platform_device pxa25x_device_udc;
@@ -53,8 +52,8 @@ extern struct platform_device pxa_device_asoc_ssp4;
extern struct platform_device pxa25x_device_gpio;
extern struct platform_device pxa27x_device_gpio;
-extern struct platform_device pxa3xx_device_gpio;
-extern struct platform_device pxa93x_device_gpio;
+
+extern const struct software_node pxa2xx_gpiochip_node;
void __init pxa_register_device(struct platform_device *dev, void *data);
void __init pxa2xx_set_dmac_info(struct mmp_dma_platdata *dma_pdata);
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index c9f0f62187bd..efa6faa62a2c 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -90,7 +90,7 @@ static struct pxamci_platform_data gumstix_mci_platform_data = {
static void __init gumstix_mmc_init(void)
{
- pxa_set_mci_info(&gumstix_mci_platform_data);
+ pxa_set_mci_info(&gumstix_mci_platform_data, NULL);
}
#else
static void __init gumstix_mmc_init(void)
@@ -100,26 +100,22 @@ static void __init gumstix_mmc_init(void)
#endif
#ifdef CONFIG_USB_PXA25X
-static struct gpiod_lookup_table gumstix_gpio_vbus_gpiod_table = {
- .dev_id = "gpio-vbus",
- .table = {
- GPIO_LOOKUP("gpio-pxa", GPIO_GUMSTIX_USB_GPIOn,
- "vbus", GPIO_ACTIVE_HIGH),
- GPIO_LOOKUP("gpio-pxa", GPIO_GUMSTIX_USB_GPIOx,
- "pullup", GPIO_ACTIVE_HIGH),
- { },
- },
+static const struct property_entry spitz_mci_props[] __initconst = {
+ PROPERTY_ENTRY_GPIO("vbus-gpios", &pxa2xx_gpiochip_node,
+ GPIO_GUMSTIX_USB_GPIOn, GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_GPIO("pullup-gpios", &pxa2xx_gpiochip_node,
+ GPIO_GUMSTIX_USB_GPIOx, GPIO_ACTIVE_HIGH),
+ { }
};
-static struct platform_device gumstix_gpio_vbus = {
+static const struct platform_device_info gumstix_gpio_vbus_info __initconst = {
.name = "gpio-vbus",
- .id = -1,
+ .id = PLATFORM_DEVID_NONE,
};
static void __init gumstix_udc_init(void)
{
- gpiod_add_lookup_table(&gumstix_gpio_vbus_gpiod_table);
- platform_device_register(&gumstix_gpio_vbus);
+ platform_device_register_full(&gumstix_gpio_vbus_info);
}
#else
static void gumstix_udc_init(void)
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 02712d24be82..03e34841fc00 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -178,12 +178,8 @@ void __init pxa25x_map_io(void)
pxa25x_get_clk_frequency_khz(1);
}
-static struct pxa_gpio_platform_data pxa25x_gpio_info __initdata = {
- .irq_base = PXA_GPIO_TO_IRQ(0),
- .gpio_set_wake = gpio_set_wake,
-};
-
static struct platform_device *pxa25x_devices[] __initdata = {
+ &pxa25x_device_gpio,
&pxa25x_device_udc,
&pxa_device_pmu,
&pxa_device_i2s,
@@ -243,8 +239,8 @@ static int __init pxa25x_init(void)
register_syscore_ops(&pxa2xx_mfp_syscore_ops);
if (!of_have_populated_dt()) {
+ software_node_register(&pxa2xx_gpiochip_node);
pxa2xx_set_dmac_info(&pxa25x_dma_pdata);
- pxa_register_device(&pxa25x_device_gpio, &pxa25x_gpio_info);
ret = platform_add_devices(pxa25x_devices,
ARRAY_SIZE(pxa25x_devices));
}
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index d71491e2e1d6..f8382477d629 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -276,12 +276,8 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info)
pxa_register_device(&pxa27x_device_i2c_power, info);
}
-static struct pxa_gpio_platform_data pxa27x_gpio_info __initdata = {
- .irq_base = PXA_GPIO_TO_IRQ(0),
- .gpio_set_wake = gpio_set_wake,
-};
-
static struct platform_device *devices[] __initdata = {
+ &pxa27x_device_gpio,
&pxa27x_device_udc,
&pxa_device_pmu,
&pxa_device_i2s,
@@ -345,8 +341,7 @@ static int __init pxa27x_init(void)
register_syscore_ops(&pxa2xx_mfp_syscore_ops);
if (!of_have_populated_dt()) {
- pxa_register_device(&pxa27x_device_gpio,
- &pxa27x_gpio_info);
+ software_node_register(&pxa2xx_gpiochip_node);
pxa2xx_set_dmac_info(&pxa27x_dma_pdata);
ret = platform_add_devices(devices,
ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 3c5f5a3cb480..452bf7aac1fa 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -14,6 +14,7 @@
#include <linux/gpio_keys.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
+#include <linux/gpio/property.h>
#include <linux/leds.h>
#include <linux/i2c.h>
#include <linux/platform_data/i2c-pxa.h>
@@ -28,6 +29,7 @@
#include <linux/input/matrix_keypad.h>
#include <linux/regulator/machine.h>
#include <linux/io.h>
+#include <linux/property.h>
#include <linux/reboot.h>
#include <linux/memblock.h>
@@ -128,6 +130,19 @@ static unsigned long spitz_pin_config[] __initdata = {
GPIO1_GPIO | WAKEUP_ON_EDGE_FALL, /* SPITZ_GPIO_RESET */
};
+static const struct software_node spitz_scoop_1_gpiochip_node = {
+ .name = "sharp-scoop.0",
+};
+
+/* Only on Spitz */
+static const struct software_node spitz_scoop_2_gpiochip_node = {
+ .name = "sharp-scoop.1",
+};
+
+/* Only on Akita */
+static const struct software_node akita_max7310_gpiochip_node = {
+ .name = "i2c-max7310",
+};
/******************************************************************************
* Scoop GPIO expander
@@ -452,35 +467,64 @@ static inline void spitz_keys_init(void) {}
* LEDs
******************************************************************************/
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
-static struct gpio_led spitz_gpio_leds[] = {
- {
- .name = "spitz:amber:charge",
- .default_trigger = "sharpsl-charge",
- .gpio = SPITZ_GPIO_LED_ORANGE,
- },
- {
- .name = "spitz:green:hddactivity",
- .default_trigger = "disk-activity",
- .gpio = SPITZ_GPIO_LED_GREEN,
- },
+static const struct software_node spitz_gpio_leds_node = {
+ .name = "spitz-leds",
};
-static struct gpio_led_platform_data spitz_gpio_leds_info = {
- .leds = spitz_gpio_leds,
- .num_leds = ARRAY_SIZE(spitz_gpio_leds),
+static const struct property_entry spitz_orange_led_props[] = {
+ PROPERTY_ENTRY_STRING("linux,default-trigger", "sharpsl-charge"),
+ PROPERTY_ENTRY_GPIO("gpios",
+ &spitz_scoop_1_gpiochip_node, 6, GPIO_ACTIVE_HIGH),
+ { }
};
-static struct platform_device spitz_led_device = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &spitz_gpio_leds_info,
- },
+static const struct software_node spitz_orange_led_node = {
+ .name = "spitz:amber:charge",
+ .parent = &spitz_gpio_leds_node,
+ .properties = spitz_orange_led_props,
+};
+
+static const struct property_entry spitz_green_led_props[] = {
+ PROPERTY_ENTRY_STRING("linux,default-trigger", "disk-activity"),
+ PROPERTY_ENTRY_GPIO("gpios",
+ &spitz_scoop_1_gpiochip_node, 0, GPIO_ACTIVE_HIGH),
+ { }
+};
+
+static const struct software_node spitz_green_led_node = {
+ .name = "spitz:green:hddactivity",
+ .parent = &spitz_gpio_leds_node,
+ .properties = spitz_green_led_props,
+};
+
+static const struct software_node *spitz_gpio_leds_swnodes[] = {
+ &spitz_gpio_leds_node,
+ &spitz_orange_led_node,
+ &spitz_green_led_node,
+ NULL
};
static void __init spitz_leds_init(void)
{
- platform_device_register(&spitz_led_device);
+ struct platform_device_info led_info = {
+ .name = "leds-gpio",
+ .id = PLATFORM_DEVID_NONE,
+ };
+ struct platform_device *led_dev;
+ int err;
+
+ err = software_node_register_node_group(spitz_gpio_leds_swnodes);
+ if (err) {
+ pr_err("failed to register LED software nodes: %d\n", err);
+ return;
+ }
+
+ led_info.fwnode = software_node_fwnode(&spitz_gpio_leds_node);
+
+ led_dev = platform_device_register_full(&led_info);
+ err = PTR_ERR_OR_ZERO(led_dev);
+ if (err)
+ pr_err("failed to create LED device: %d\n", err);
}
#else
static inline void spitz_leds_init(void) {}
@@ -490,53 +534,43 @@ static inline void spitz_leds_init(void) {}
* SSP Devices
******************************************************************************/
#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE)
-static void spitz_ads7846_wait_for_hsync(void)
-{
- while (gpio_get_value(SPITZ_GPIO_HSYNC))
- cpu_relax();
- while (!gpio_get_value(SPITZ_GPIO_HSYNC))
- cpu_relax();
-}
+static const struct property_entry spitz_ads7846_props[] = {
+ PROPERTY_ENTRY_STRING("compatible", "ti,ads7846"),
+ PROPERTY_ENTRY_U32("touchscreen-max-pressure", 1024),
+ PROPERTY_ENTRY_U16("ti,x-plate-ohms", 419),
+ PROPERTY_ENTRY_U16("ti,y-plate-ohms", 486),
+ PROPERTY_ENTRY_U16("ti,vref-delay-usecs", 100),
+ PROPERTY_ENTRY_GPIO("pendown-gpios", &pxa2xx_gpiochip_node,
+ SPITZ_GPIO_TP_INT, GPIO_ACTIVE_LOW),
+ PROPERTY_ENTRY_GPIO("ti,hsync-gpios", &pxa2xx_gpiochip_node,
+ SPITZ_GPIO_HSYNC, GPIO_ACTIVE_LOW),
+ { }
+};
-static struct ads7846_platform_data spitz_ads7846_info = {
- .model = 7846,
- .vref_delay_usecs = 100,
- .x_plate_ohms = 419,
- .y_plate_ohms = 486,
- .pressure_max = 1024,
- .wait_for_sync = spitz_ads7846_wait_for_hsync,
+static const struct software_node spitz_ads7846_swnode = {
+ .name = "ads7846",
+ .properties = spitz_ads7846_props,
};
-static struct gpiod_lookup_table spitz_ads7846_gpio_table = {
- .dev_id = "spi2.0",
- .table = {
- GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_TP_INT,
- "pendown", GPIO_ACTIVE_LOW),
- { }
- },
+static const struct property_entry spitz_lcdcon_props[] = {
+ PROPERTY_ENTRY_GPIO("BL_CONT-gpios",
+ &spitz_scoop_2_gpiochip_node, 6, GPIO_ACTIVE_LOW),
+ PROPERTY_ENTRY_GPIO("BL_ON-gpios",
+ &spitz_scoop_2_gpiochip_node, 7, GPIO_ACTIVE_HIGH),
+ { }
};
-static struct gpiod_lookup_table spitz_lcdcon_gpio_table = {
- .dev_id = "spi2.1",
- .table = {
- GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_BACKLIGHT_CONT,
- "BL_CONT", GPIO_ACTIVE_LOW),
- GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_BACKLIGHT_ON,
- "BL_ON", GPIO_ACTIVE_HIGH),
- { },
- },
+static const struct property_entry akita_lcdcon_props[] = {
+ PROPERTY_ENTRY_GPIO("BL_ON-gpios",
+ &akita_max7310_gpiochip_node, 3, GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_GPIO("BL_CONT-gpios",
+ &akita_max7310_gpiochip_node, 4, GPIO_ACTIVE_LOW),
+ { }
};
-static struct gpiod_lookup_table akita_lcdcon_gpio_table = {
- .dev_id = "spi2.1",
- .table = {
- GPIO_LOOKUP("gpio-pxa", AKITA_GPIO_BACKLIGHT_CONT,
- "BL_CONT", GPIO_ACTIVE_LOW),
- GPIO_LOOKUP("gpio-pxa", AKITA_GPIO_BACKLIGHT_ON,
- "BL_ON", GPIO_ACTIVE_HIGH),
- { },
- },
+static struct software_node spitz_lcdcon_node = {
+ .name = "spitz-lcdcon",
};
static struct corgi_lcd_platform_data spitz_lcdcon_info = {
@@ -553,7 +587,7 @@ static struct spi_board_info spitz_spi_devices[] = {
.max_speed_hz = 1200000,
.bus_num = 2,
.chip_select = 0,
- .platform_data = &spitz_ads7846_info,
+ .swnode = &spitz_ads7846_swnode,
.irq = PXA_GPIO_TO_IRQ(SPITZ_GPIO_TP_INT),
}, {
.modalias = "corgi-lcd",
@@ -561,6 +595,7 @@ static struct spi_board_info spitz_spi_devices[] = {
.bus_num = 2,
.chip_select = 1,
.platform_data = &spitz_lcdcon_info,
+ .swnode = &spitz_lcdcon_node,
}, {
.modalias = "max1111",
.max_speed_hz = 450000,
@@ -569,53 +604,40 @@ static struct spi_board_info spitz_spi_devices[] = {
},
};
-static struct gpiod_lookup_table spitz_spi_gpio_table = {
- .dev_id = "spi2",
- .table = {
- GPIO_LOOKUP_IDX("gpio-pxa", SPITZ_GPIO_ADS7846_CS, "cs", 0, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("gpio-pxa", SPITZ_GPIO_LCDCON_CS, "cs", 1, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("gpio-pxa", SPITZ_GPIO_MAX1111_CS, "cs", 2, GPIO_ACTIVE_LOW),
- { },
- },
+static const struct software_node_ref_args spitz_spi_gpio_refs[] = {
+ SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, SPITZ_GPIO_ADS7846_CS,
+ GPIO_ACTIVE_LOW),
+ SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, SPITZ_GPIO_LCDCON_CS,
+ GPIO_ACTIVE_LOW),
+ SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, SPITZ_GPIO_MAX1111_CS,
+ GPIO_ACTIVE_LOW),
};
static const struct property_entry spitz_spi_properties[] = {
- PROPERTY_ENTRY_U32("num-cs", 3),
+ PROPERTY_ENTRY_REF_ARRAY("gpios", spitz_spi_gpio_refs),
{ }
};
-static const struct software_node spitz_spi_node = {
+static const struct platform_device_info spitz_spi_device_info = {
+ .name = "pxa2xx-spi",
+ /* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1 */
+ .id = 2,
.properties = spitz_spi_properties,
};
static void __init spitz_spi_init(void)
{
struct platform_device *pd;
- int id = 2;
int err;
- if (machine_is_akita())
- gpiod_add_lookup_table(&akita_lcdcon_gpio_table);
- else
- gpiod_add_lookup_table(&spitz_lcdcon_gpio_table);
-
- gpiod_add_lookup_table(&spitz_ads7846_gpio_table);
- gpiod_add_lookup_table(&spitz_spi_gpio_table);
-
- /* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1 */
- pd = platform_device_alloc("pxa2xx-spi", id);
- if (pd == NULL) {
- pr_err("pxa2xx-spi: failed to allocate device id %d\n", id);
- } else {
- err = device_add_software_node(&pd->dev, &spitz_spi_node);
- if (err) {
- platform_device_put(pd);
- pr_err("pxa2xx-spi: failed to add software node\n");
- } else {
- platform_device_add(pd);
- }
- }
+ pd = platform_device_register_full(&spitz_spi_device_info);
+ err = PTR_ERR_OR_ZERO(pd);
+ if (err)
+ pr_err("pxa2xx-spi: failed to instantiate SPI controller: %d\n",
+ err);
+ spitz_lcdcon_node.properties = machine_is_akita() ?
+ akita_lcdcon_props : spitz_lcdcon_props;
spi_register_board_info(ARRAY_AND_SIZE(spitz_spi_devices));
}
#else
@@ -648,21 +670,17 @@ static struct pxamci_platform_data spitz_mci_platform_data = {
.setpower = spitz_mci_setpower,
};
-static struct gpiod_lookup_table spitz_mci_gpio_table = {
- .dev_id = "pxa2xx-mci.0",
- .table = {
- GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_nSD_DETECT,
- "cd", GPIO_ACTIVE_LOW),
- GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_nSD_WP,
- "wp", GPIO_ACTIVE_LOW),
- { },
- },
+static const struct property_entry spitz_mci_props[] __initconst = {
+ PROPERTY_ENTRY_GPIO("cd-gpios", &pxa2xx_gpiochip_node,
+ SPITZ_GPIO_nSD_DETECT, GPIO_ACTIVE_LOW),
+ PROPERTY_ENTRY_GPIO("wp-gpios", &pxa2xx_gpiochip_node,
+ SPITZ_GPIO_nSD_WP, GPIO_ACTIVE_LOW),
+ { }
};
static void __init spitz_mmc_init(void)
{
- gpiod_add_lookup_table(&spitz_mci_gpio_table);
- pxa_set_mci_info(&spitz_mci_platform_data);
+ pxa_set_mci_info(&spitz_mci_platform_data, spitz_mci_props);
}
#else
static inline void spitz_mmc_init(void) {}
@@ -961,30 +979,24 @@ static void __init spitz_i2c_init(void)
static inline void spitz_i2c_init(void) {}
#endif
-static struct gpiod_lookup_table spitz_audio_gpio_table = {
- .dev_id = "spitz-audio",
- .table = {
- GPIO_LOOKUP("sharp-scoop.0", SPITZ_GPIO_MUTE_L - SPITZ_SCP_GPIO_BASE,
- "mute-l", GPIO_ACTIVE_HIGH),
- GPIO_LOOKUP("sharp-scoop.0", SPITZ_GPIO_MUTE_R - SPITZ_SCP_GPIO_BASE,
- "mute-r", GPIO_ACTIVE_HIGH),
- GPIO_LOOKUP("sharp-scoop.1", SPITZ_GPIO_MIC_BIAS - SPITZ_SCP2_GPIO_BASE,
- "mic", GPIO_ACTIVE_HIGH),
- { },
- },
+static const struct property_entry spitz_audio_props[] = {
+ PROPERTY_ENTRY_GPIO("mute-l-gpios", &spitz_scoop_1_gpiochip_node, 3,
+ GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_GPIO("mute-r-gpios", &spitz_scoop_1_gpiochip_node, 4,
+ GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_GPIO("mic-gpios", &spitz_scoop_2_gpiochip_node, 8,
+ GPIO_ACTIVE_HIGH),
+ { }
};
-static struct gpiod_lookup_table akita_audio_gpio_table = {
- .dev_id = "spitz-audio",
- .table = {
- GPIO_LOOKUP("sharp-scoop.0", SPITZ_GPIO_MUTE_L - SPITZ_SCP_GPIO_BASE,
- "mute-l", GPIO_ACTIVE_HIGH),
- GPIO_LOOKUP("sharp-scoop.0", SPITZ_GPIO_MUTE_R - SPITZ_SCP_GPIO_BASE,
- "mute-r", GPIO_ACTIVE_HIGH),
- GPIO_LOOKUP("i2c-max7310", AKITA_GPIO_MIC_BIAS - AKITA_IOEXP_GPIO_BASE,
- "mic", GPIO_ACTIVE_HIGH),
- { },
- },
+static const struct property_entry akita_audio_props[] = {
+ PROPERTY_ENTRY_GPIO("mute-l-gpios", &spitz_scoop_1_gpiochip_node, 3,
+ GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_GPIO("mute-r-gpios", &spitz_scoop_1_gpiochip_node, 4,
+ GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_GPIO("mic-gpios", &akita_max7310_gpiochip_node, 2,
+ GPIO_ACTIVE_HIGH),
+ { }
};
/******************************************************************************
@@ -992,12 +1004,14 @@ static struct gpiod_lookup_table akita_audio_gpio_table = {
******************************************************************************/
static inline void spitz_audio_init(void)
{
- if (machine_is_akita())
- gpiod_add_lookup_table(&akita_audio_gpio_table);
- else
- gpiod_add_lookup_table(&spitz_audio_gpio_table);
-
- platform_device_register_simple("spitz-audio", -1, NULL, 0);
+ struct platform_device_info audio_info = {
+ .name = "spitz-audio",
+ .id = PLATFORM_DEVID_NONE,
+ .properties = machine_is_akita() ?
+ akita_audio_props : spitz_audio_props,
+ };
+
+ platform_device_register_full(&audio_info);
}
/******************************************************************************
@@ -1020,6 +1034,12 @@ static void spitz_restart(enum reboot_mode mode, const char *cmd)
static void __init spitz_init(void)
{
+ software_node_register(&spitz_scoop_1_gpiochip_node);
+ if (machine_is_akita())
+ software_node_register(&akita_max7310_gpiochip_node);
+ else
+ software_node_register(&spitz_scoop_2_gpiochip_node);
+
init_gpio_reset(SPITZ_GPIO_ON_RESET, 1, 0);
pm_power_off = spitz_poweroff;
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index 18d37f90cdfe..3ec810b6f1a7 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -8,35 +8,49 @@
* Copyright (C) 2010 Google, Inc.
*/
-#include <linux/property.h>
+#include <linux/err.h>
#include <linux/gpio/machine.h>
+#include <linux/gpio/property.h>
#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/property.h>
#include "board.h"
-static struct property_entry wifi_rfkill_prop[] __initdata = {
- PROPERTY_ENTRY_STRING("name", "wifi_rfkill"),
- PROPERTY_ENTRY_STRING("type", "wlan"),
- { },
+static const struct software_node tegra_gpiochip_node = {
+ .name = "tegra-gpio",
};
-static struct platform_device wifi_rfkill_device = {
- .name = "rfkill_gpio",
- .id = -1,
+static const struct property_entry wifi_rfkill_prop[] __initconst = {
+ PROPERTY_ENTRY_STRING("name", "wifi_rfkill"),
+ PROPERTY_ENTRY_STRING("type", "wlan"),
+ PROPERTY_ENTRY_GPIO("reset-gpios",
+ &tegra_gpiochip_node, 25, GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_GPIO("shutdown-gpios",
+ &tegra_gpiochip_node, 85, GPIO_ACTIVE_HIGH),
+ { }
};
-static struct gpiod_lookup_table wifi_gpio_lookup = {
- .dev_id = "rfkill_gpio",
- .table = {
- GPIO_LOOKUP("tegra-gpio", 25, "reset", 0),
- GPIO_LOOKUP("tegra-gpio", 85, "shutdown", 0),
- { },
- },
+static const struct platform_device_info wifi_rfkill_info __initconst = {
+ .name = "rfkill_gpio",
+ .id = PLATFORM_DEVID_NONE,
+ .properties = wifi_rfkill_prop,
};
void __init tegra_paz00_wifikill_init(void)
{
- device_create_managed_software_node(&wifi_rfkill_device.dev, wifi_rfkill_prop, NULL);
- gpiod_add_lookup_table(&wifi_gpio_lookup);
- platform_device_register(&wifi_rfkill_device);
+ struct platform_device *pd;
+ int err;
+
+ err = software_node_register(&tegra_gpiochip_node);
+ if (err) {
+ pr_err("failed to register %s node: %d\n",
+ tegra_gpiochip_node.name, err);
+ return;
+ }
+
+ pd = platform_device_register_full(&wifi_rfkill_info);
+ err = PTR_ERR_OR_ZERO(pd);
+ if (err)
+ pr_err("failed to register WiFi rfkill device: %d\n", err);
}
diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig
index e029270c2687..513618078440 100644
--- a/arch/arm/mach-versatile/Kconfig
+++ b/arch/arm/mach-versatile/Kconfig
@@ -278,15 +278,6 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
build a working kernel, you must also enable relevant core
tile support or Flattened Device Tree based support options.
-config ARCH_VEXPRESS_DCSCB
- bool "Dual Cluster System Control Block (DCSCB) support"
- depends on MCPM
- select ARM_CCI400_PORT_CTRL
- help
- Support for the Dual Cluster System Configuration Block (DCSCB).
- This is needed to provide CPU and cluster power management
- on RTSM implementing big.LITTLE.
-
config ARCH_VEXPRESS_SPC
bool "Versatile Express Serial Power Controller (SPC)"
select PM_OPP
diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile
index 27d712bcf1af..d819fb2fc450 100644
--- a/arch/arm/mach-versatile/Makefile
+++ b/arch/arm/mach-versatile/Makefile
@@ -16,9 +16,6 @@ obj-$(CONFIG_ARCH_REALVIEW) += realview.o
# vexpress
obj-$(CONFIG_ARCH_VEXPRESS) := v2m.o
-obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o
-CFLAGS_dcscb.o += -march=armv7-a
-CFLAGS_REMOVE_dcscb.o = -pg
obj-$(CONFIG_ARCH_VEXPRESS_SPC) += spc.o
CFLAGS_REMOVE_spc.o = -pg
obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o
diff --git a/arch/arm/mach-versatile/dcscb.c b/arch/arm/mach-versatile/dcscb.c
deleted file mode 100644
index d8797350996d..000000000000
--- a/arch/arm/mach-versatile/dcscb.c
+++ /dev/null
@@ -1,173 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * dcscb.c - Dual Cluster System Configuration Block
- *
- * Created by: Nicolas Pitre, May 2012
- * Copyright: (C) 2012-2013 Linaro Limited
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/of_address.h>
-#include <linux/vexpress.h>
-#include <linux/arm-cci.h>
-
-#include <asm/mcpm.h>
-#include <asm/proc-fns.h>
-#include <asm/cacheflush.h>
-#include <asm/cputype.h>
-#include <asm/cp15.h>
-
-#include "vexpress.h"
-
-#define RST_HOLD0 0x0
-#define RST_HOLD1 0x4
-#define SYS_SWRESET 0x8
-#define RST_STAT0 0xc
-#define RST_STAT1 0x10
-#define EAG_CFG_R 0x20
-#define EAG_CFG_W 0x24
-#define KFC_CFG_R 0x28
-#define KFC_CFG_W 0x2c
-#define DCS_CFG_R 0x30
-
-static void __iomem *dcscb_base;
-static int dcscb_allcpus_mask[2];
-
-static int dcscb_cpu_powerup(unsigned int cpu, unsigned int cluster)
-{
- unsigned int rst_hold, cpumask = (1 << cpu);
-
- pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
- if (cluster >= 2 || !(cpumask & dcscb_allcpus_mask[cluster]))
- return -EINVAL;
-
- rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
- rst_hold &= ~(cpumask | (cpumask << 4));
- writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
- return 0;
-}
-
-static int dcscb_cluster_powerup(unsigned int cluster)
-{
- unsigned int rst_hold;
-
- pr_debug("%s: cluster %u\n", __func__, cluster);
- if (cluster >= 2)
- return -EINVAL;
-
- /* remove cluster reset and add individual CPU's reset */
- rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
- rst_hold &= ~(1 << 8);
- rst_hold |= dcscb_allcpus_mask[cluster];
- writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
- return 0;
-}
-
-static void dcscb_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
-{
- unsigned int rst_hold;
-
- pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
- BUG_ON(cluster >= 2 || !((1 << cpu) & dcscb_allcpus_mask[cluster]));
-
- rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
- rst_hold |= (1 << cpu);
- writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
-}
-
-static void dcscb_cluster_powerdown_prepare(unsigned int cluster)
-{
- unsigned int rst_hold;
-
- pr_debug("%s: cluster %u\n", __func__, cluster);
- BUG_ON(cluster >= 2);
-
- rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
- rst_hold |= (1 << 8);
- writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
-}
-
-static void dcscb_cpu_cache_disable(void)
-{
- /* Disable and flush the local CPU cache. */
- v7_exit_coherency_flush(louis);
-}
-
-static void dcscb_cluster_cache_disable(void)
-{
- /* Flush all cache levels for this cluster. */
- v7_exit_coherency_flush(all);
-
- /*
- * A full outer cache flush could be needed at this point
- * on platforms with such a cache, depending on where the
- * outer cache sits. In some cases the notion of a "last
- * cluster standing" would need to be implemented if the
- * outer cache is shared across clusters. In any case, when
- * the outer cache needs flushing, there is no concurrent
- * access to the cache controller to worry about and no
- * special locking besides what is already provided by the
- * MCPM state machinery is needed.
- */
-
- /*
- * Disable cluster-level coherency by masking
- * incoming snoops and DVM messages:
- */
- cci_disable_port_by_cpu(read_cpuid_mpidr());
-}
-
-static const struct mcpm_platform_ops dcscb_power_ops = {
- .cpu_powerup = dcscb_cpu_powerup,
- .cluster_powerup = dcscb_cluster_powerup,
- .cpu_powerdown_prepare = dcscb_cpu_powerdown_prepare,
- .cluster_powerdown_prepare = dcscb_cluster_powerdown_prepare,
- .cpu_cache_disable = dcscb_cpu_cache_disable,
- .cluster_cache_disable = dcscb_cluster_cache_disable,
-};
-
-extern void dcscb_power_up_setup(unsigned int affinity_level);
-
-static int __init dcscb_init(void)
-{
- struct device_node *node;
- unsigned int cfg;
- int ret;
-
- if (!cci_probed())
- return -ENODEV;
-
- node = of_find_compatible_node(NULL, NULL, "arm,rtsm,dcscb");
- if (!node)
- return -ENODEV;
- dcscb_base = of_iomap(node, 0);
- of_node_put(node);
- if (!dcscb_base)
- return -EADDRNOTAVAIL;
- cfg = readl_relaxed(dcscb_base + DCS_CFG_R);
- dcscb_allcpus_mask[0] = (1 << (((cfg >> 16) >> (0 << 2)) & 0xf)) - 1;
- dcscb_allcpus_mask[1] = (1 << (((cfg >> 16) >> (1 << 2)) & 0xf)) - 1;
-
- ret = mcpm_platform_register(&dcscb_power_ops);
- if (!ret)
- ret = mcpm_sync_init(dcscb_power_up_setup);
- if (ret) {
- iounmap(dcscb_base);
- return ret;
- }
-
- pr_info("VExpress DCSCB support installed\n");
-
- /*
- * Future entries into the kernel can now go
- * through the cluster entry vectors.
- */
- vexpress_flags_set(__pa_symbol(mcpm_entry_point));
-
- return 0;
-}
-
-early_initcall(dcscb_init);
diff --git a/arch/arm/mach-versatile/dcscb_setup.S b/arch/arm/mach-versatile/dcscb_setup.S
deleted file mode 100644
index 92d1fd9d7f6a..000000000000
--- a/arch/arm/mach-versatile/dcscb_setup.S
+++ /dev/null
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Created by: Dave Martin, 2012-06-22
- * Copyright: (C) 2012-2013 Linaro Limited
- */
-
-#include <linux/linkage.h>
-
-
-ENTRY(dcscb_power_up_setup)
-
- cmp r0, #0 @ check affinity level
- beq 2f
-
-/*
- * Enable cluster-level coherency, in preparation for turning on the MMU.
- * The ACTLR SMP bit does not need to be set here, because cpu_resume()
- * already restores that.
- *
- * A15/A7 may not require explicit L2 invalidation on reset, dependent
- * on hardware integration decisions.
- * For now, this code assumes that L2 is either already invalidated,
- * or invalidation is not required.
- */
-
- b cci_enable_port_for_self
-
-2: @ Implementation-specific local CPU setup operations should go here,
- @ if any. In this case, there is nothing to do.
-
- bx lr
-
-ENDPROC(dcscb_power_up_setup)
diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
index 2ed7d229c8f9..23c98203c40f 100644
--- a/arch/arm/tools/syscall.tbl
+++ b/arch/arm/tools/syscall.tbl
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
#
# Linux system call numbers and entry vectors
#
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5d91259ee7b5..79a656a62cbc 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -5,6 +5,7 @@ config ARM64
select ACPI_CCA_REQUIRED if ACPI
select ACPI_GENERIC_GSI if ACPI
select ACPI_GTDT if ACPI
+ select ACPI_HOTPLUG_CPU if ACPI_PROCESSOR && HOTPLUG_CPU
select ACPI_IORT if ACPI
select ACPI_REDUCED_HARDWARE_ONLY if ACPI
select ACPI_MCFG if (ACPI && PCI)
@@ -381,7 +382,7 @@ config BROKEN_GAS_INST
config BUILTIN_RETURN_ADDRESS_STRIPS_PAC
bool
- # Clang's __builtin_return_adddress() strips the PAC since 12.0.0
+ # Clang's __builtin_return_address() strips the PAC since 12.0.0
# https://github.com/llvm/llvm-project/commit/2a96f47c5ffca84cd774ad402cacd137f4bf45e2
default y if CC_IS_CLANG
# GCC's __builtin_return_address() strips the PAC since 11.1.0,
@@ -1067,34 +1068,21 @@ config ARM64_ERRATUM_3117295
If unsure, say Y.
-config ARM64_WORKAROUND_SPECULATIVE_SSBS
- bool
-
config ARM64_ERRATUM_3194386
- bool "Cortex-X4: 3194386: workaround for MSR SSBS not self-synchronizing"
- select ARM64_WORKAROUND_SPECULATIVE_SSBS
+ bool "Cortex-{A720,X4,X925}/Neoverse-V3: workaround for MSR SSBS not self-synchronizing"
default y
help
- This option adds the workaround for ARM Cortex-X4 erratum 3194386.
+ This option adds the workaround for the following errata:
- On affected cores "MSR SSBS, #0" instructions may not affect
- subsequent speculative instructions, which may permit unexepected
- speculative store bypassing.
-
- Work around this problem by placing a speculation barrier after
- kernel changes to SSBS. The presence of the SSBS special-purpose
- register is hidden from hwcaps and EL0 reads of ID_AA64PFR1_EL1, such
- that userspace will use the PR_SPEC_STORE_BYPASS prctl to change
- SSBS.
-
- If unsure, say Y.
-
-config ARM64_ERRATUM_3312417
- bool "Neoverse-V3: 3312417: workaround for MSR SSBS not self-synchronizing"
- select ARM64_WORKAROUND_SPECULATIVE_SSBS
- default y
- help
- This option adds the workaround for ARM Neoverse-V3 erratum 3312417.
+ * ARM Cortex-A710 erratam 3324338
+ * ARM Cortex-A720 erratum 3456091
+ * ARM Cortex-X2 erratum 3324338
+ * ARM Cortex-X3 erratum 3324335
+ * ARM Cortex-X4 erratum 3194386
+ * ARM Cortex-X925 erratum 3324334
+ * ARM Neoverse N2 erratum 3324339
+ * ARM Neoverse V2 erratum 3324336
+ * ARM Neoverse-V3 erratum 3312417
On affected cores "MSR SSBS, #0" instructions may not affect
subsequent speculative instructions, which may permit unexepected
@@ -1108,7 +1096,6 @@ config ARM64_ERRATUM_3312417
If unsure, say Y.
-
config CAVIUM_ERRATUM_22375
bool "Cavium erratum 22375, 24313"
default y
@@ -1649,6 +1636,7 @@ config RODATA_FULL_DEFAULT_ENABLED
config ARM64_SW_TTBR0_PAN
bool "Emulate Privileged Access Never using TTBR0_EL1 switching"
+ depends on !KCSAN
help
Enabling this option prevents the kernel from accessing
user-space memory directly by pointing TTBR0_EL1 to a reserved
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index a52618073de2..d1461335e78f 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -207,7 +207,6 @@ if ARCH_NXP
config ARCH_LAYERSCAPE
bool "Freescale Layerscape SoC family"
- select EDAC_SUPPORT
help
This enables support for the Freescale Layerscape SoC family.
@@ -312,6 +311,8 @@ config ARCH_STM32
select STM32_EXTI
select ARM_SMC_MBOX
select ARM_SCMI_PROTOCOL
+ select REGULATOR
+ select REGULATOR_ARM_SCMI
select COMMON_CLK_SCMI
select STM32_FIREWALL
help
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index 30dd6347a929..21cd3a87f385 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
subdir-y += actions
+subdir-y += airoha
subdir-y += allwinner
subdir-y += altera
subdir-y += amazon
diff --git a/arch/arm64/boot/dts/airoha/Makefile b/arch/arm64/boot/dts/airoha/Makefile
new file mode 100644
index 000000000000..ebea112ce1d7
--- /dev/null
+++ b/arch/arm64/boot/dts/airoha/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+dtb-$(CONFIG_ARCH_AIROHA) += en7581-evb.dtb
diff --git a/arch/arm64/boot/dts/airoha/en7581-evb.dts b/arch/arm64/boot/dts/airoha/en7581-evb.dts
new file mode 100644
index 000000000000..cf58e43dd5b2
--- /dev/null
+++ b/arch/arm64/boot/dts/airoha/en7581-evb.dts
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/dts-v1/;
+
+/* Bootloader installs ATF here */
+/memreserve/ 0x80000000 0x200000;
+
+#include "en7581.dtsi"
+
+/ {
+ model = "Airoha EN7581 Evaluation Board";
+ compatible = "airoha,en7581-evb", "airoha,en7581";
+
+ aliases {
+ serial0 = &uart1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ linux,usable-memory-range = <0x0 0x80200000 0x0 0x1fe00000>;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x2 0x00000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/airoha/en7581.dtsi b/arch/arm64/boot/dts/airoha/en7581.dtsi
new file mode 100644
index 000000000000..55eb1762fb11
--- /dev/null
+++ b/arch/arm64/boot/dts/airoha/en7581.dtsi
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ npu-binary@84000000 {
+ no-map;
+ reg = <0x0 0x84000000 0x0 0xa00000>;
+ };
+
+ npu-flag@84b0000 {
+ no-map;
+ reg = <0x0 0x84b00000 0x0 0x100000>;
+ };
+
+ npu-pkt@85000000 {
+ no-map;
+ reg = <0x0 0x85000000 0x0 0x1a00000>;
+ };
+
+ npu-phyaddr@86b00000 {
+ no-map;
+ reg = <0x0 0x86b00000 0x0 0x100000>;
+ };
+
+ npu-rxdesc@86d00000 {
+ no-map;
+ reg = <0x0 0x86d00000 0x0 0x100000>;
+ };
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ 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 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x0>;
+ enable-method = "psci";
+ clock-frequency = <80000000>;
+ next-level-cache = <&l2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x1>;
+ enable-method = "psci";
+ clock-frequency = <80000000>;
+ next-level-cache = <&l2>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x2>;
+ enable-method = "psci";
+ clock-frequency = <80000000>;
+ next-level-cache = <&l2>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x3>;
+ enable-method = "psci";
+ clock-frequency = <80000000>;
+ next-level-cache = <&l2>;
+ };
+
+ l2: l2-cache {
+ compatible = "cache";
+ cache-size = <0x80000>;
+ cache-line-size = <64>;
+ cache-level = <2>;
+ cache-unified;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&gic>;
+ 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;
+
+ gic: interrupt-controller@9000000 {
+ compatible = "arm,gic-v3";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x0 0x09000000 0x0 0x20000>,
+ <0x0 0x09080000 0x0 0x80000>,
+ <0x0 0x09400000 0x0 0x2000>,
+ <0x0 0x09500000 0x0 0x2000>,
+ <0x0 0x09600000 0x0 0x20000>;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ uart1: serial@1fbf0000 {
+ compatible = "ns16550";
+ reg = <0x0 0x1fbf0000 0x0 0x30>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <1843200>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
index 596a25907432..709fe650a360 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
@@ -5,7 +5,7 @@
#include "sun50i-a64-sopine-baseboard.dts"
/ {
- model = "Pine64 LTS";
+ model = "Pine64 PINE A64 LTS";
compatible = "pine64,pine64-lts", "allwinner,sun50i-r18",
"allwinner,sun50i-a64";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
index b54099b654c8..026d843cd7e0 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
@@ -4,7 +4,7 @@
#include "sun50i-a64-pine64.dts"
/ {
- model = "Pine64+";
+ model = "Pine64 PINE A64+";
compatible = "pine64,pine64-plus", "allwinner,sun50i-a64";
/* TODO: Camera, touchscreen, etc. */
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
index 2accb5ddf783..09e71fd60785 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
@@ -9,7 +9,7 @@
#include <dt-bindings/gpio/gpio.h>
/ {
- model = "Pine64";
+ model = "Pine64 PINE A64";
compatible = "pine64,pine64", "allwinner,sun50i-a64";
aliases {
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
index 6c65d5bc16ba..379c2c8466f5 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
@@ -13,7 +13,7 @@
#include <dt-bindings/pwm/pwm.h>
/ {
- model = "Pinebook";
+ model = "Pine64 Pinebook";
compatible = "pine64,pinebook", "allwinner,sun50i-a64";
chassis-type = "laptop";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-early-adopter.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-early-adopter.dts
index 6265360ce623..86cc85eb3d48 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-early-adopter.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-early-adopter.dts
@@ -9,7 +9,7 @@
#include "sun50i-a64-pinetab.dts"
/ {
- model = "PineTab, Early Adopter's version";
+ model = "Pine64 PineTab Early Adopter";
compatible = "pine64,pinetab-early-adopter", "allwinner,sun50i-a64";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
index c6007df99938..f5fb1ee32dad 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
@@ -14,7 +14,7 @@
#include <dt-bindings/pwm/pwm.h>
/ {
- model = "PineTab, Development Sample";
+ model = "Pine64 PineTab Developer Sample";
compatible = "pine64,pinetab", "allwinner,sun50i-a64";
chassis-type = "tablet";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
index 5e66ce1a334f..be2347c8f267 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
@@ -8,7 +8,7 @@
#include "sun50i-a64-sopine.dtsi"
/ {
- model = "SoPine with baseboard";
+ model = "Pine64 SOPINE on Baseboard carrier board";
compatible = "pine64,sopine-baseboard", "pine64,sopine",
"allwinner,sun50i-a64";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index ce4aa44c3353..e868ca5ae753 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -51,10 +51,16 @@
device_type = "cpu";
reg = <0>;
enable-method = "psci";
- next-level-cache = <&L2>;
clocks = <&ccu CLK_CPUX>;
clock-names = "cpu";
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
};
cpu1: cpu@1 {
@@ -62,10 +68,16 @@
device_type = "cpu";
reg = <1>;
enable-method = "psci";
- next-level-cache = <&L2>;
clocks = <&ccu CLK_CPUX>;
clock-names = "cpu";
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
};
cpu2: cpu@2 {
@@ -73,10 +85,16 @@
device_type = "cpu";
reg = <2>;
enable-method = "psci";
- next-level-cache = <&L2>;
clocks = <&ccu CLK_CPUX>;
clock-names = "cpu";
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
};
cpu3: cpu@3 {
@@ -84,16 +102,25 @@
device_type = "cpu";
reg = <3>;
enable-method = "psci";
- next-level-cache = <&L2>;
clocks = <&ccu CLK_CPUX>;
clock-names = "cpu";
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
};
- L2: l2-cache {
+ l2_cache: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
+ cache-size = <0x80000>;
+ cache-line-size = <64>;
+ cache-sets = <512>;
};
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
index 66fe03910d5e..066fbeff8bfa 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
@@ -8,7 +8,7 @@
/delete-node/ &reg_gmac_3v3;
/ {
- model = "Pine H64 model B";
+ model = "Pine64 PINE H64 Model B";
compatible = "pine64,pine-h64-model-b", "allwinner,sun50i-h6";
wifi_pwrseq: pwrseq {
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 3910393be1f9..c8b275552872 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -9,7 +9,7 @@
#include <dt-bindings/gpio/gpio.h>
/ {
- model = "Pine H64 model A";
+ model = "Pine64 PINE H64 Model A";
compatible = "pine64,pine-h64", "allwinner,sun50i-h6";
aliases {
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index 8a8591c4e7dd..2301c59b41b1 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -29,6 +29,13 @@
clocks = <&ccu CLK_CPUX>;
clock-latency-ns = <244144>; /* 8 32k periods */
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
};
cpu1: cpu@1 {
@@ -39,6 +46,13 @@
clocks = <&ccu CLK_CPUX>;
clock-latency-ns = <244144>; /* 8 32k periods */
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
};
cpu2: cpu@2 {
@@ -49,6 +63,13 @@
clocks = <&ccu CLK_CPUX>;
clock-latency-ns = <244144>; /* 8 32k periods */
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
};
cpu3: cpu@3 {
@@ -59,6 +80,22 @@
clocks = <&ccu CLK_CPUX>;
clock-latency-ns = <244144>; /* 8 32k periods */
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
+ };
+
+ l2_cache: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0x80000>;
+ cache-line-size = <64>;
+ cache-sets = <512>;
};
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi
index aca22a7f0191..dd10aaf472b6 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi
@@ -11,7 +11,7 @@
opp-hz = /bits/ 64 <480000000>;
opp-microvolt = <900000>;
clock-latency-ns = <244144>; /* 8 32k periods */
- opp-supported-hw = <0x1f>;
+ opp-supported-hw = <0x3f>;
};
opp-600000000 {
@@ -25,7 +25,7 @@
opp-hz = /bits/ 64 <720000000>;
opp-microvolt = <900000>;
clock-latency-ns = <244144>; /* 8 32k periods */
- opp-supported-hw = <0x0d>;
+ opp-supported-hw = <0x2d>;
};
opp-792000000 {
@@ -50,8 +50,16 @@
opp-microvolt-speed2 = <950000>;
opp-microvolt-speed3 = <950000>;
opp-microvolt-speed4 = <1020000>;
+ opp-microvolt-speed5 = <900000>;
clock-latency-ns = <244144>; /* 8 32k periods */
- opp-supported-hw = <0x1f>;
+ opp-supported-hw = <0x3f>;
+ };
+
+ opp-1032000000 {
+ opp-hz = /bits/ 64 <1032000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x20>;
};
opp-1104000000 {
@@ -59,8 +67,9 @@
opp-microvolt-speed0 = <1000000>;
opp-microvolt-speed2 = <1000000>;
opp-microvolt-speed3 = <1000000>;
+ opp-microvolt-speed5 = <950000>;
clock-latency-ns = <244144>; /* 8 32k periods */
- opp-supported-hw = <0x0d>;
+ opp-supported-hw = <0x2d>;
};
opp-1200000000 {
@@ -70,8 +79,9 @@
opp-microvolt-speed2 = <1050000>;
opp-microvolt-speed3 = <1050000>;
opp-microvolt-speed4 = <1100000>;
+ opp-microvolt-speed5 = <1020000>;
clock-latency-ns = <244144>; /* 8 32k periods */
- opp-supported-hw = <0x1f>;
+ opp-supported-hw = <0x3f>;
};
opp-1320000000 {
@@ -85,15 +95,16 @@
opp-hz = /bits/ 64 <1416000000>;
opp-microvolt = <1100000>;
clock-latency-ns = <244144>; /* 8 32k periods */
- opp-supported-hw = <0x0d>;
+ opp-supported-hw = <0x2d>;
};
opp-1512000000 {
opp-hz = /bits/ 64 <1512000000>;
opp-microvolt-speed1 = <1100000>;
opp-microvolt-speed3 = <1100000>;
+ opp-microvolt-speed5 = <1160000>;
clock-latency-ns = <244144>; /* 8 32k periods */
- opp-supported-hw = <0x0a>;
+ opp-supported-hw = <0x2a>;
};
};
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
index 921d5f61d8d6..b29ce7321317 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -27,6 +27,13 @@
enable-method = "psci";
clocks = <&ccu CLK_CPUX>;
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
};
cpu1: cpu@1 {
@@ -36,6 +43,13 @@
enable-method = "psci";
clocks = <&ccu CLK_CPUX>;
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
};
cpu2: cpu@2 {
@@ -45,6 +59,13 @@
enable-method = "psci";
clocks = <&ccu CLK_CPUX>;
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
};
cpu3: cpu@3 {
@@ -54,6 +75,22 @@
enable-method = "psci";
clocks = <&ccu CLK_CPUX>;
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache>;
+ };
+
+ l2_cache: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0x40000>;
+ cache-line-size = <64>;
+ cache-sets = <256>;
};
};
@@ -113,6 +150,16 @@
#size-cells = <1>;
ranges = <0x0 0x0 0x0 0x40000000>;
+ crypto: crypto@1904000 {
+ compatible = "allwinner,sun50i-h616-crypto";
+ reg = <0x01904000 0x800>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CE>, <&ccu CLK_CE>,
+ <&ccu CLK_MBUS_CE>, <&rtc CLK_IOSC>;
+ clock-names = "bus", "mod", "ram", "trng";
+ resets = <&ccu RST_BUS_CE>;
+ };
+
syscon: syscon@3000000 {
compatible = "allwinner,sun50i-h616-system-control";
reg = <0x03000000 0x1000>;
@@ -306,6 +353,15 @@
#interrupt-cells = <3>;
};
+ iommu: iommu@30f0000 {
+ compatible = "allwinner,sun50i-h616-iommu";
+ reg = <0x030f0000 0x10000>;
+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_IOMMU>;
+ resets = <&ccu RST_BUS_IOMMU>;
+ #iommu-cells = <1>;
+ };
+
mmc0: mmc@4020000 {
compatible = "allwinner,sun50i-h616-mmc",
"allwinner,sun50i-a100-mmc";
@@ -589,6 +645,17 @@
status = "disabled";
};
+ gpadc: adc@5070000 {
+ compatible = "allwinner,sun50i-h616-gpadc",
+ "allwinner,sun20i-d1-gpadc";
+ reg = <0x05070000 0x400>;
+ clocks = <&ccu CLK_BUS_GPADC>;
+ resets = <&ccu RST_BUS_GPADC>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ #io-channel-cells = <1>;
+ };
+
ths: thermal-sensor@5070400 {
compatible = "allwinner,sun50i-h616-ths";
reg = <0x05070400 0x400>;
@@ -602,6 +669,16 @@
#thermal-sensor-cells = <1>;
};
+ lradc: lradc@5070800 {
+ compatible = "allwinner,sun50i-h616-lradc",
+ "allwinner,sun50i-r329-lradc";
+ reg = <0x05070800 0x400>;
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_KEYADC>;
+ resets = <&ccu RST_BUS_KEYADC>;
+ status = "disabled";
+ };
+
usbotg: usb@5100000 {
compatible = "allwinner,sun50i-h616-musb",
"allwinner,sun8i-h3-musb";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h64-remix-mini-pc.dts b/arch/arm64/boot/dts/allwinner/sun50i-h64-remix-mini-pc.dts
index c204dd43c726..ce90327e1b2e 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h64-remix-mini-pc.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h64-remix-mini-pc.dts
@@ -191,7 +191,7 @@
compatible = "x-powers,axp803";
reg = <0x3a3>;
interrupt-parent = <&r_intc>;
- interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_LOW>;
x-powers,drive-vbus-en;
vin1-supply = <&reg_vcc5v>;
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 ee30584b6ad7..afb49e65859f 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
@@ -6,7 +6,7 @@
/dts-v1/;
#include "sun50i-h616.dtsi"
-
+#include "sun50i-h616-cpu-opp.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -221,7 +221,7 @@
reg_dcdc1: dcdc1 {
regulator-always-on;
regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1100000>;
+ regulator-max-microvolt = <1160000>;
regulator-name = "vdd-cpu";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-h.dts b/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-h.dts
index 63036256917f..ff453336eab1 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-h.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-h.dts
@@ -9,6 +9,78 @@
/ {
model = "Anbernic RG35XX H";
compatible = "anbernic,rg35xx-h", "allwinner,sun50i-h700";
+
+ adc-joystick {
+ compatible = "adc-joystick";
+ io-channels = <&adc_mux 0>,
+ <&adc_mux 1>,
+ <&adc_mux 2>,
+ <&adc_mux 3>;
+ pinctrl-0 = <&joy_mux_pin>;
+ pinctrl-names = "default";
+ poll-interval = <60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ axis@0 {
+ reg = <0>;
+ abs-flat = <32>;
+ abs-fuzz = <32>;
+ abs-range = <4096 0>;
+ linux,code = <ABS_X>;
+ };
+
+ axis@1 {
+ reg = <1>;
+ abs-flat = <32>;
+ abs-fuzz = <32>;
+ abs-range = <0 4096>;
+ linux,code = <ABS_Y>;
+ };
+
+ axis@2 {
+ reg = <2>;
+ abs-flat = <32>;
+ abs-fuzz = <32>;
+ abs-range = <0 4096>;
+ linux,code = <ABS_RX>;
+ };
+
+ axis@3 {
+ reg = <3>;
+ abs-flat = <32>;
+ abs-fuzz = <32>;
+ abs-range = <4096 0>;
+ linux,code = <ABS_RY>;
+ };
+ };
+
+ adc_mux: adc-mux {
+ compatible = "io-channel-mux";
+ channels = "left_x", "left_y", "right_x", "right_y";
+ #io-channel-cells = <1>;
+ io-channels = <&gpadc 0>;
+ io-channel-names = "parent";
+ mux-controls = <&gpio_mux>;
+ settle-time-us = <100>;
+ };
+
+ gpio_mux: mux-controller {
+ compatible = "gpio-mux";
+ mux-gpios = <&pio 8 1 GPIO_ACTIVE_LOW>,
+ <&pio 8 2 GPIO_ACTIVE_LOW>;
+ #mux-control-cells = <0>;
+ };
+};
+
+&gpadc {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ channel@0 {
+ reg = <0>;
+ };
};
&gpio_keys_gamepad {
@@ -34,3 +106,10 @@
&ohci1 {
status = "okay";
};
+
+&pio {
+ joy_mux_pin: joy-mux-pin {
+ pins = "PI0";
+ function = "gpio_out";
+ };
+};
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
index cbbc53c47921..0def0b0daaf7 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
@@ -34,6 +34,7 @@
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "psci";
+ next-level-cache = <&l2_shared>;
reg = <0x0>;
};
@@ -41,6 +42,7 @@
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "psci";
+ next-level-cache = <&l2_shared>;
reg = <0x1>;
};
@@ -48,6 +50,7 @@
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "psci";
+ next-level-cache = <&l2_shared>;
reg = <0x2>;
};
@@ -55,8 +58,15 @@
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "psci";
+ next-level-cache = <&l2_shared>;
reg = <0x3>;
};
+
+ l2_shared: cache {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ };
};
firmware {
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
index 26173f0b0051..4eee777ef1a1 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
@@ -180,8 +180,6 @@
&qspi {
status = "okay";
flash@0 {
- #address-cells = <1>;
- #size-cells = <1>;
compatible = "micron,mt25qu02g", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <100000000>;
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts
index 81d0e914a77c..7c53cb9621e5 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts
@@ -169,8 +169,6 @@
&qspi {
status = "okay";
flash@0 {
- #address-cells = <1>;
- #size-cells = <1>;
compatible = "micron,mt25qu02g", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <100000000>;
diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 0f29517da5ec..29417f04f886 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -21,6 +21,8 @@ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-a311d-khadas-vim3.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-a311d-khadas-vim3-ts050.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-bananapi-cm4-cm4io.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-bananapi-cm4-mnt-reform2.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-g12b-dreambox-one.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-g12b-dreambox-two.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gsking-x.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking-pro.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking.dtb
@@ -62,6 +64,8 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc-v2.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-nexbox-a95x.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-vero4k.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxlx-s905l-p271.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxm-gt1-ultimate.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxm-khadas-vim2.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-gxm-mecool-kiii-pro.dtb
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
index 73ca1d7eed81..de10e7aebf21 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi
@@ -4,6 +4,7 @@
*/
#include "amlogic-a4-common.dtsi"
+#include <dt-bindings/power/amlogic,a4-pwrc.h>
/ {
cpus {
#address-cells = <2>;
@@ -37,4 +38,13 @@
enable-method = "psci";
};
};
+
+ sm: secure-monitor {
+ compatible = "amlogic,meson-gxbb-sm";
+
+ pwrc: power-controller {
+ compatible = "amlogic,a4-pwrc";
+ #power-domain-cells = <1>;
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi
index 32a754fe7990..f8fb060c49ae 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi
@@ -111,8 +111,7 @@
};
gpio_intc: interrupt-controller@4080 {
- compatible = "amlogic,meson-gpio-intc",
- "amlogic,c3-gpio-intc";
+ compatible = "amlogic,c3-gpio-intc", "amlogic,meson-gpio-intc";
reg = <0x0 0x4080 0x0 0x0020>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts b/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts
index 4bc30af05848..0d92f5253b64 100644
--- a/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-a1-ad402.dts
@@ -7,6 +7,7 @@
/dts-v1/;
#include "meson-a1.dtsi"
+#include <dt-bindings/thermal/thermal.h>
/ {
compatible = "amlogic,ad402", "amlogic,a1";
@@ -83,6 +84,50 @@
vin-supply = <&vddao_3v3>;
regulator-always-on;
};
+
+ thermal-zones {
+ soc_thermal: soc-thermal {
+ polling-delay = <1000>;
+ polling-delay-passive = <100>;
+ sustainable-power = <130>;
+
+ thermal-sensors = <&cpu_temp>;
+
+ trips {
+ soc_passive: soc-passive {
+ temperature = <70000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ soc_hot: soc-hot {
+ temperature = <85000>;
+ hysteresis = <5000>;
+ type = "hot";
+ };
+
+ soc_critical: soc-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+
+ soc_cooling_maps: cooling-maps {
+ map0 {
+ trip = <&soc_passive>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+
+ map1 {
+ trip = <&soc_hot>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
};
/* Bluetooth HCI H4 */
diff --git a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
index c03e207ea6c5..e5366d4239b1 100644
--- a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
@@ -28,6 +28,7 @@
reg = <0x0 0x0>;
enable-method = "psci";
next-level-cache = <&l2>;
+ #cooling-cells = <2>;
};
cpu1: cpu@1 {
@@ -36,6 +37,7 @@
reg = <0x0 0x1>;
enable-method = "psci";
next-level-cache = <&l2>;
+ #cooling-cells = <2>;
};
l2: l2-cache0 {
@@ -398,6 +400,17 @@
power-domains = <&pwrc PWRC_USB_ID>;
};
+ cpu_temp: temperature-sensor@4c00 {
+ compatible = "amlogic,a1-cpu-thermal";
+ reg = <0x0 0x4c00 0x0 0x50>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc_periphs CLKID_TS>;
+ assigned-clocks = <&clkc_periphs CLKID_TS>;
+ assigned-clock-rates = <500000>;
+ #thermal-sensor-cells = <0>;
+ amlogic,ao-secure = <&sec_AO>;
+ };
+
hwrng: rng@5118 {
compatible = "amlogic,meson-rng";
reg = <0x0 0x5118 0x0 0x4>;
@@ -419,7 +432,7 @@
clock-names = "fixpll_in", "hifipll_in";
};
- sd_emmc: sd@10000 {
+ sd_emmc: mmc@10000 {
compatible = "amlogic,meson-axg-mmc";
reg = <0x0 0x10000 0x0 0x800>;
interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
@@ -453,7 +466,6 @@
assigned-clocks = <&clkc_periphs CLKID_USB_BUS>;
assigned-clock-rates = <64000000>;
resets = <&reset RESET_USBCTRL>;
- reset-name = "usb_ctrl";
dr_mode = "otg";
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index 6d12b760b90f..e9b22868983d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -25,10 +25,10 @@
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
sound-name-prefix = "TDM_A";
- clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>,
- <&clkc_audio AUD_CLKID_MST_A_SCLK>,
- <&clkc_audio AUD_CLKID_MST_A_LRCLK>;
- clock-names = "mclk", "sclk", "lrclk";
+ clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_A_LRCLK>,
+ <&clkc_audio AUD_CLKID_MST_A_MCLK>;
+ clock-names = "sclk", "lrclk", "mclk";
status = "disabled";
};
@@ -36,10 +36,10 @@
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
sound-name-prefix = "TDM_B";
- clocks = <&clkc_audio AUD_CLKID_MST_B_MCLK>,
- <&clkc_audio AUD_CLKID_MST_B_SCLK>,
- <&clkc_audio AUD_CLKID_MST_B_LRCLK>;
- clock-names = "mclk", "sclk", "lrclk";
+ clocks = <&clkc_audio AUD_CLKID_MST_B_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_B_LRCLK>,
+ <&clkc_audio AUD_CLKID_MST_B_MCLK>;
+ clock-names = "sclk", "lrclk", "mclk";
status = "disabled";
};
@@ -47,10 +47,10 @@
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
sound-name-prefix = "TDM_C";
- clocks = <&clkc_audio AUD_CLKID_MST_C_MCLK>,
- <&clkc_audio AUD_CLKID_MST_C_SCLK>,
- <&clkc_audio AUD_CLKID_MST_C_LRCLK>;
- clock-names = "mclk", "sclk", "lrclk";
+ clocks = <&clkc_audio AUD_CLKID_MST_C_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_C_LRCLK>,
+ <&clkc_audio AUD_CLKID_MST_C_MCLK>;
+ clock-names = "sclk", "lrclk", "mclk";
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
index b058ed78faf0..d08c97797010 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
@@ -215,6 +215,11 @@
#sound-dai-cells = <0>;
status = "disabled";
+ assigned-clocks = <&clkc CLKID_HDMI_SEL>,
+ <&clkc CLKID_HDMI>;
+ assigned-clock-parents = <&xtal>, <0>;
+ assigned-clock-rates = <0>, <24000000>;
+
/* VPU VENC Input */
hdmi_tx_venc_port: port@0 {
reg = <0>;
@@ -987,7 +992,7 @@
mux {
groups = "spdif_out_h";
function = "spdif_out";
- drive-strength-microamp = <500>;
+ drive-strength-microamp = <3000>;
bias-disable;
};
};
@@ -996,7 +1001,7 @@
mux {
groups = "spdif_out_a11";
function = "spdif_out";
- drive-strength-microamp = <500>;
+ drive-strength-microamp = <3000>;
bias-disable;
};
};
@@ -1005,7 +1010,7 @@
mux {
groups = "spdif_out_a13";
function = "spdif_out";
- drive-strength-microamp = <500>;
+ drive-strength-microamp = <3000>;
bias-disable;
};
};
@@ -1741,9 +1746,6 @@
compatible = "amlogic,meson-gx-ao-sysctrl",
"simple-mfd", "syscon";
reg = <0x0 0x0 0x0 0x100>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x0 0x0 0x0 0x0 0x0 0x100>;
clkc_AO: clock-controller {
compatible = "amlogic,meson-g12a-aoclkc";
@@ -1752,278 +1754,278 @@
clocks = <&xtal>, <&clkc CLKID_CLK81>;
clock-names = "xtal", "mpeg-clk";
};
+ };
- ao_pinctrl: pinctrl {
- compatible = "amlogic,meson-g12a-aobus-pinctrl";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ ao_pinctrl: pinctrl@14 {
+ compatible = "amlogic,meson-g12a-aobus-pinctrl";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ gpio_ao: bank@14 {
+ reg = <0x0 0x14 0x0 0x8>,
+ <0x0 0x1c 0x0 0x8>,
+ <0x0 0x24 0x0 0x14>;
+ reg-names = "mux",
+ "ds",
+ "gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&ao_pinctrl 0 0 15>;
+ };
- gpio_ao: bank@14 {
- reg = <0x0 0x14 0x0 0x8>,
- <0x0 0x1c 0x0 0x8>,
- <0x0 0x24 0x0 0x14>;
- reg-names = "mux",
- "ds",
- "gpio";
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&ao_pinctrl 0 0 15>;
+ i2c_ao_sck_pins: i2c_ao_sck_pins {
+ mux {
+ groups = "i2c_ao_sck";
+ function = "i2c_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
};
+ };
- i2c_ao_sck_pins: i2c_ao_sck_pins {
- mux {
- groups = "i2c_ao_sck";
- function = "i2c_ao";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
+ i2c_ao_sda_pins: i2c_ao_sda {
+ mux {
+ groups = "i2c_ao_sda";
+ function = "i2c_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
};
+ };
- i2c_ao_sda_pins: i2c_ao_sda {
- mux {
- groups = "i2c_ao_sda";
- function = "i2c_ao";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
+ i2c_ao_sck_e_pins: i2c_ao_sck_e {
+ mux {
+ groups = "i2c_ao_sck_e";
+ function = "i2c_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
};
+ };
- i2c_ao_sck_e_pins: i2c_ao_sck_e {
- mux {
- groups = "i2c_ao_sck_e";
- function = "i2c_ao";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
+ i2c_ao_sda_e_pins: i2c_ao_sda_e {
+ mux {
+ groups = "i2c_ao_sda_e";
+ function = "i2c_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
};
+ };
- i2c_ao_sda_e_pins: i2c_ao_sda_e {
- mux {
- groups = "i2c_ao_sda_e";
- function = "i2c_ao";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
+ mclk0_ao_pins: mclk0-ao {
+ mux {
+ groups = "mclk0_ao";
+ function = "mclk0_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
};
+ };
- mclk0_ao_pins: mclk0-ao {
- mux {
- groups = "mclk0_ao";
- function = "mclk0_ao";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
+ tdm_ao_b_din0_pins: tdm-ao-b-din0 {
+ mux {
+ groups = "tdm_ao_b_din0";
+ function = "tdm_ao_b";
+ bias-disable;
};
+ };
- tdm_ao_b_din0_pins: tdm-ao-b-din0 {
- mux {
- groups = "tdm_ao_b_din0";
- function = "tdm_ao_b";
- bias-disable;
- };
+ spdif_ao_out_pins: spdif-ao-out {
+ mux {
+ groups = "spdif_ao_out";
+ function = "spdif_ao_out";
+ drive-strength-microamp = <3000>;
+ bias-disable;
};
+ };
- spdif_ao_out_pins: spdif-ao-out {
- mux {
- groups = "spdif_ao_out";
- function = "spdif_ao_out";
- drive-strength-microamp = <500>;
- bias-disable;
- };
+ tdm_ao_b_din1_pins: tdm-ao-b-din1 {
+ mux {
+ groups = "tdm_ao_b_din1";
+ function = "tdm_ao_b";
+ bias-disable;
};
+ };
- tdm_ao_b_din1_pins: tdm-ao-b-din1 {
- mux {
- groups = "tdm_ao_b_din1";
- function = "tdm_ao_b";
- bias-disable;
- };
+ tdm_ao_b_din2_pins: tdm-ao-b-din2 {
+ mux {
+ groups = "tdm_ao_b_din2";
+ function = "tdm_ao_b";
+ bias-disable;
};
+ };
- tdm_ao_b_din2_pins: tdm-ao-b-din2 {
- mux {
- groups = "tdm_ao_b_din2";
- function = "tdm_ao_b";
- bias-disable;
- };
+ tdm_ao_b_dout0_pins: tdm-ao-b-dout0 {
+ mux {
+ groups = "tdm_ao_b_dout0";
+ function = "tdm_ao_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
};
+ };
- tdm_ao_b_dout0_pins: tdm-ao-b-dout0 {
- mux {
- groups = "tdm_ao_b_dout0";
- function = "tdm_ao_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
+ tdm_ao_b_dout1_pins: tdm-ao-b-dout1 {
+ mux {
+ groups = "tdm_ao_b_dout1";
+ function = "tdm_ao_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
};
+ };
- tdm_ao_b_dout1_pins: tdm-ao-b-dout1 {
- mux {
- groups = "tdm_ao_b_dout1";
- function = "tdm_ao_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
- };
-
- tdm_ao_b_dout2_pins: tdm-ao-b-dout2 {
- mux {
- groups = "tdm_ao_b_dout2";
- function = "tdm_ao_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
+ tdm_ao_b_dout2_pins: tdm-ao-b-dout2 {
+ mux {
+ groups = "tdm_ao_b_dout2";
+ function = "tdm_ao_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
};
+ };
- tdm_ao_b_fs_pins: tdm-ao-b-fs {
- mux {
- groups = "tdm_ao_b_fs";
- function = "tdm_ao_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
+ tdm_ao_b_fs_pins: tdm-ao-b-fs {
+ mux {
+ groups = "tdm_ao_b_fs";
+ function = "tdm_ao_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
};
+ };
- tdm_ao_b_sclk_pins: tdm-ao-b-sclk {
- mux {
- groups = "tdm_ao_b_sclk";
- function = "tdm_ao_b";
- bias-disable;
- drive-strength-microamp = <3000>;
- };
+ tdm_ao_b_sclk_pins: tdm-ao-b-sclk {
+ mux {
+ groups = "tdm_ao_b_sclk";
+ function = "tdm_ao_b";
+ bias-disable;
+ drive-strength-microamp = <3000>;
};
+ };
- tdm_ao_b_slv_fs_pins: tdm-ao-b-slv-fs {
- mux {
- groups = "tdm_ao_b_slv_fs";
- function = "tdm_ao_b";
- bias-disable;
- };
+ tdm_ao_b_slv_fs_pins: tdm-ao-b-slv-fs {
+ mux {
+ groups = "tdm_ao_b_slv_fs";
+ function = "tdm_ao_b";
+ bias-disable;
};
+ };
- tdm_ao_b_slv_sclk_pins: tdm-ao-b-slv-sclk {
- mux {
- groups = "tdm_ao_b_slv_sclk";
- function = "tdm_ao_b";
- bias-disable;
- };
+ tdm_ao_b_slv_sclk_pins: tdm-ao-b-slv-sclk {
+ mux {
+ groups = "tdm_ao_b_slv_sclk";
+ function = "tdm_ao_b";
+ bias-disable;
};
+ };
- uart_ao_a_pins: uart-a-ao {
- mux {
- groups = "uart_ao_a_tx",
- "uart_ao_a_rx";
- function = "uart_ao_a";
- bias-disable;
- };
+ uart_ao_a_pins: uart-a-ao {
+ mux {
+ groups = "uart_ao_a_tx",
+ "uart_ao_a_rx";
+ function = "uart_ao_a";
+ bias-disable;
};
+ };
- uart_ao_a_cts_rts_pins: uart-ao-a-cts-rts {
- mux {
- groups = "uart_ao_a_cts",
- "uart_ao_a_rts";
- function = "uart_ao_a";
- bias-disable;
- };
+ uart_ao_a_cts_rts_pins: uart-ao-a-cts-rts {
+ mux {
+ groups = "uart_ao_a_cts",
+ "uart_ao_a_rts";
+ function = "uart_ao_a";
+ bias-disable;
};
+ };
- uart_ao_b_2_3_pins: uart-ao-b-2-3 {
- mux {
- groups = "uart_ao_b_tx_2",
- "uart_ao_b_rx_3";
- function = "uart_ao_b";
- bias-disable;
- };
+ uart_ao_b_2_3_pins: uart-ao-b-2-3 {
+ mux {
+ groups = "uart_ao_b_tx_2",
+ "uart_ao_b_rx_3";
+ function = "uart_ao_b";
+ bias-disable;
};
+ };
- uart_ao_b_8_9_pins: uart-ao-b-8-9 {
- mux {
- groups = "uart_ao_b_tx_8",
- "uart_ao_b_rx_9";
- function = "uart_ao_b";
- bias-disable;
- };
+ uart_ao_b_8_9_pins: uart-ao-b-8-9 {
+ mux {
+ groups = "uart_ao_b_tx_8",
+ "uart_ao_b_rx_9";
+ function = "uart_ao_b";
+ bias-disable;
};
+ };
- uart_ao_b_cts_rts_pins: uart-ao-b-cts-rts {
- mux {
- groups = "uart_ao_b_cts",
- "uart_ao_b_rts";
- function = "uart_ao_b";
- bias-disable;
- };
+ uart_ao_b_cts_rts_pins: uart-ao-b-cts-rts {
+ mux {
+ groups = "uart_ao_b_cts",
+ "uart_ao_b_rts";
+ function = "uart_ao_b";
+ bias-disable;
};
+ };
- pwm_a_e_pins: pwm-a-e {
- mux {
- groups = "pwm_a_e";
- function = "pwm_a_e";
- bias-disable;
- };
+ pwm_a_e_pins: pwm-a-e {
+ mux {
+ groups = "pwm_a_e";
+ function = "pwm_a_e";
+ bias-disable;
};
+ };
- pwm_ao_a_pins: pwm-ao-a {
- mux {
- groups = "pwm_ao_a";
- function = "pwm_ao_a";
- bias-disable;
- };
+ pwm_ao_a_pins: pwm-ao-a {
+ mux {
+ groups = "pwm_ao_a";
+ function = "pwm_ao_a";
+ bias-disable;
};
+ };
- pwm_ao_b_pins: pwm-ao-b {
- mux {
- groups = "pwm_ao_b";
- function = "pwm_ao_b";
- bias-disable;
- };
+ pwm_ao_b_pins: pwm-ao-b {
+ mux {
+ groups = "pwm_ao_b";
+ function = "pwm_ao_b";
+ bias-disable;
};
+ };
- pwm_ao_c_4_pins: pwm-ao-c-4 {
- mux {
- groups = "pwm_ao_c_4";
- function = "pwm_ao_c";
- bias-disable;
- };
+ pwm_ao_c_4_pins: pwm-ao-c-4 {
+ mux {
+ groups = "pwm_ao_c_4";
+ function = "pwm_ao_c";
+ bias-disable;
};
+ };
- pwm_ao_c_6_pins: pwm-ao-c-6 {
- mux {
- groups = "pwm_ao_c_6";
- function = "pwm_ao_c";
- bias-disable;
- };
+ pwm_ao_c_6_pins: pwm-ao-c-6 {
+ mux {
+ groups = "pwm_ao_c_6";
+ function = "pwm_ao_c";
+ bias-disable;
};
+ };
- pwm_ao_d_5_pins: pwm-ao-d-5 {
- mux {
- groups = "pwm_ao_d_5";
- function = "pwm_ao_d";
- bias-disable;
- };
+ pwm_ao_d_5_pins: pwm-ao-d-5 {
+ mux {
+ groups = "pwm_ao_d_5";
+ function = "pwm_ao_d";
+ bias-disable;
};
+ };
- pwm_ao_d_10_pins: pwm-ao-d-10 {
- mux {
- groups = "pwm_ao_d_10";
- function = "pwm_ao_d";
- bias-disable;
- };
+ pwm_ao_d_10_pins: pwm-ao-d-10 {
+ mux {
+ groups = "pwm_ao_d_10";
+ function = "pwm_ao_d";
+ bias-disable;
};
+ };
- pwm_ao_d_e_pins: pwm-ao-d-e {
- mux {
- groups = "pwm_ao_d_e";
- function = "pwm_ao_d";
- };
+ pwm_ao_d_e_pins: pwm-ao-d-e {
+ mux {
+ groups = "pwm_ao_d_e";
+ function = "pwm_ao_d";
};
+ };
- remote_input_ao_pins: remote-input-ao {
- mux {
- groups = "remote_ao_input";
- function = "remote_ao_input";
- bias-disable;
- };
+ remote_input_ao_pins: remote-input-ao {
+ mux {
+ groups = "remote_ao_input";
+ function = "remote_ao_input";
+ bias-disable;
};
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12.dtsi
index e732df3f3114..664912d1beaa 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12.dtsi
@@ -363,6 +363,10 @@
power-domains = <&pwrc PWRC_G12A_ETH_ID>;
};
+&hdmi_tx {
+ power-domains = <&pwrc PWRC_G12A_VPU_ID>;
+};
+
&vpu {
power-domains = <&pwrc PWRC_G12A_VPU_ID>;
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
index 3da7922d83f1..0e239939ade6 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
@@ -24,7 +24,6 @@
compatible = "simple-audio-amplifier";
enable-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
VCC-supply = <&vcc_5v>;
- #sound-dai-cells = <0>;
sound-name-prefix = "10U2";
};
@@ -374,6 +373,7 @@
};
&acodec {
+ AVDD-supply = <&vddao_1v8>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi.dtsi
index 4b8db872bbf3..6a346cb86a53 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi.dtsi
@@ -44,13 +44,6 @@
reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>;
};
- fan0: pwm-fan {
- compatible = "pwm-fan";
- #cooling-cells = <2>;
- cooling-levels = <0 120 170 220>;
- pwms = <&pwm_cd 1 40000 0>;
- };
-
hdmi-connector {
compatible = "hdmi-connector";
type = "a";
@@ -374,13 +367,6 @@
clock-names = "clkin0";
};
-&pwm_cd {
- status = "okay";
- pinctrl-0 = <&pwm_d_x6_pins>;
- pinctrl-names = "default";
- pwm-gpios = <&gpio GPIOAO_10 GPIO_ACTIVE_HIGH>;
-};
-
&pwm_ef {
status = "okay";
pinctrl-0 = <&pwm_e_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-one.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-one.dts
new file mode 100644
index 000000000000..ecfa1c683dde
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-one.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Christian Hewitt <[email protected]>
+ */
+
+/dts-v1/;
+
+#include "meson-g12b-dreambox.dtsi"
+
+/ {
+ compatible = "dream,dreambox-one", "amlogic,s922x", "amlogic,g12b";
+ model = "Dreambox One";
+};
+
+&sd_emmc_a {
+ sd-uhs-sdr12;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-two.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-two.dts
new file mode 100644
index 000000000000..df0d71983c3d
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-two.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Christian Hewitt <[email protected]>
+ */
+
+/dts-v1/;
+
+#include "meson-g12b-dreambox.dtsi"
+
+/ {
+ compatible = "dream,dreambox-two", "amlogic,s922x", "amlogic,g12b";
+ model = "Dreambox Two";
+};
+
+&sd_emmc_a {
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi
new file mode 100644
index 000000000000..3a24c2411552
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2021 Christian Hewitt <[email protected]>
+ */
+
+#include "meson-g12b-w400.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
+
+/ {
+ cvbs-connector {
+ status = "disabled";
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&gpio GPIOA_11 GPIO_ACTIVE_LOW>;
+ clocks = <&wifi32k>;
+ clock-names = "ext_clock";
+ };
+
+ spdif_dit: audio-codec-1 {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dit";
+ status = "okay";
+ sound-name-prefix = "DIT";
+ };
+
+ sound {
+ compatible = "amlogic,axg-sound-card";
+ model = "DREAMBOX";
+ audio-aux-devs = <&tdmout_b>;
+ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1",
+ "TDMOUT_B IN 1", "FRDDR_B OUT 1",
+ "TDMOUT_B IN 2", "FRDDR_C OUT 1",
+ "TDM_B Playback", "TDMOUT_B OUT",
+ "SPDIFOUT_A IN 0", "FRDDR_A OUT 3",
+ "SPDIFOUT_A IN 1", "FRDDR_B OUT 3",
+ "SPDIFOUT_A IN 2", "FRDDR_C OUT 3";
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ dai-link-0 {
+ sound-dai = <&frddr_a>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&frddr_b>;
+ };
+
+ dai-link-2 {
+ sound-dai = <&frddr_c>;
+ };
+
+ /* 8ch hdmi interface */
+ dai-link-3 {
+ sound-dai = <&tdmif_b>;
+ dai-format = "i2s";
+ dai-tdm-slot-tx-mask-0 = <1 1>;
+ dai-tdm-slot-tx-mask-1 = <1 1>;
+ dai-tdm-slot-tx-mask-2 = <1 1>;
+ dai-tdm-slot-tx-mask-3 = <1 1>;
+ mclk-fs = <256>;
+
+ codec {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
+ };
+ };
+
+ /* spdif hdmi or toslink interface */
+ dai-link-4 {
+ sound-dai = <&spdifout_a>;
+
+ codec-0 {
+ sound-dai = <&spdif_dit>;
+ };
+
+ codec-1 {
+ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_A>;
+ };
+ };
+
+ /* spdif hdmi interface */
+ dai-link-5 {
+ sound-dai = <&spdifout_b>;
+
+ codec {
+ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_B>;
+ };
+ };
+
+ /* hdmi glue */
+ dai-link-6 {
+ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+};
+
+&arb {
+ status = "okay";
+};
+
+&frddr_a {
+ status = "okay";
+};
+
+&frddr_b {
+ status = "okay";
+};
+
+&frddr_c {
+ status = "okay";
+};
+
+&ir {
+ linux,rc-map-name = "rc-dreambox";
+};
+
+&saradc {
+ status = "okay";
+ vref-supply = <&vddao_1v8>;
+};
+
+&spdifout_a {
+ pinctrl-0 = <&spdif_out_h_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&spdifout_b {
+ status = "okay";
+};
+
+&tdmif_b {
+ status = "okay";
+};
+
+&tdmout_b {
+ status = "okay";
+};
+
+&tohdmitx {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts
index 890f5bfebb03..8445701100d0 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts
@@ -33,6 +33,13 @@
reg = <0x0 0x0 0x0 0x80000000>;
};
+ fan0: pwm-fan {
+ compatible = "pwm-fan";
+ #cooling-cells = <2>;
+ cooling-levels = <0 64 128 192 255>;
+ pwms = <&pwm_AO_ab 0 40000 0>;
+ };
+
gpio-keys-polled {
compatible = "gpio-keys-polled";
poll-interval = <100>;
@@ -286,6 +293,23 @@
clock-latency = <50000>;
};
+&cpu_thermal {
+ trips {
+ cpu_active: cpu-active {
+ temperature = <70000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map2 {
+ trip = <&cpu_active>;
+ cooling-device = <&fan0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+};
+
&frddr_a {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index c431986e6a33..c37cc6b036cd 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -408,6 +408,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/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 12ef6e81c8bd..ed00e67e6923 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -311,10 +311,16 @@
<&reset RESET_HDMI_SYSTEM_RESET>,
<&reset RESET_HDMI_TX>;
reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
- clocks = <&clkc CLKID_HDMI_PCLK>,
- <&clkc CLKID_CLK81>,
+ clocks = <&clkc CLKID_HDMI>,
+ <&clkc CLKID_HDMI_PCLK>,
<&clkc CLKID_GCLK_VENCI_INT0>;
clock-names = "isfr", "iahb", "venci";
+ power-domains = <&pwrc PWRC_GXBB_VPU_ID>;
+
+ assigned-clocks = <&clkc CLKID_HDMI_SEL>,
+ <&clkc CLKID_HDMI>;
+ assigned-clock-parents = <&xtal>, <0>;
+ assigned-clock-rates = <0>, <24000000>;
};
&sysctrl {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts
new file mode 100644
index 000000000000..de996e930b82
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2024 Christian Hewitt <[email protected]>
+ */
+
+/dts-v1/;
+
+#include "meson-gxl-s905x-p212.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/sound/meson-aiu.h>
+
+/ {
+ compatible = "osmc,vero4k", "amlogic,s905x", "amlogic,meson-gxl";
+ model = "OSMC Vero 4K";
+
+ reserved-memory {
+ /* 32 MiB reserved for ARM Trusted Firmware (BL32) */
+ secmon_reserved_bl32: secmon@5300000 {
+ reg = <0x0 0x05300000 0x0 0x2000000>;
+ no-map;
+ };
+ };
+
+ gpio-keys-polled {
+ compatible = "gpio-keys-polled";
+ poll-interval = <20>;
+
+ button {
+ label = "power";
+ linux,code = <KEY_POWER>;
+ gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-standby {
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_POWER;
+ gpios = <&gpio GPIODV_24 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ panic-indicator;
+ };
+ };
+
+ dio2133: analog-amplifier {
+ compatible = "simple-audio-amplifier";
+ sound-name-prefix = "AU2";
+ VCC-supply = <&hdmi_5v>;
+ enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
+ };
+
+ spdif_dit: audio-codec-0 {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dit";
+ sound-name-prefix = "DIT";
+ };
+
+ cvbs-connector {
+ compatible = "composite-video-connector";
+
+ port {
+ cvbs_connector_in: endpoint {
+ remote-endpoint = <&cvbs_vdac_out>;
+ };
+ };
+ };
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_tmds_out>;
+ };
+ };
+ };
+
+ sound {
+ compatible = "amlogic,gx-sound-card";
+ model = "VERO4K";
+ audio-aux-devs = <&dio2133>;
+ audio-widgets = "Line", "Lineout";
+ audio-routing = "AU2 INL", "ACODEC LOLP",
+ "AU2 INR", "ACODEC LORP",
+ "AU2 INL", "ACODEC LOLN",
+ "AU2 INR", "ACODEC LORN",
+ "Lineout", "AU2 OUTL",
+ "Lineout", "AU2 OUTR";
+ assigned-clocks = <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>,
+ <&clkc CLKID_MPLL2>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ dai-link-0 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>;
+ };
+
+ dai-link-2 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
+ dai-format = "i2s";
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
+ };
+
+ codec-1 {
+ sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
+ };
+ };
+
+ dai-link-3 {
+ sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>;
+
+ codec-0 {
+ sound-dai = <&spdif_dit>;
+ };
+ };
+
+ dai-link-4 {
+ sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
+
+ codec-0 {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+
+ dai-link-5 {
+ sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
+
+ codec-0 {
+ sound-dai = <&acodec>;
+ };
+ };
+ };
+};
+
+&acodec {
+ AVDD-supply = <&vddio_ao18>;
+ status = "okay";
+};
+
+&aiu {
+ status = "okay";
+ pinctrl-0 = <&spdif_out_h_pins>;
+ pinctrl-names = "default";
+};
+
+&cec_AO {
+ status = "okay";
+ pinctrl-0 = <&ao_cec_pins>;
+ pinctrl-names = "default";
+ hdmi-phandle = <&hdmi_tx>;
+};
+
+&cvbs_vdac_port {
+ cvbs_vdac_out: endpoint {
+ remote-endpoint = <&cvbs_connector_in>;
+ };
+};
+
+&ethmac {
+ phy-mode = "rmii";
+ phy-handle = <&internal_phy>;
+};
+
+&hdmi_tx {
+ status = "okay";
+ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+ pinctrl-names = "default";
+ hdmi-supply = <&hdmi_5v>;
+};
+
+&hdmi_tx_tmds_port {
+ hdmi_tx_tmds_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+};
+
+&internal_phy {
+ pinctrl-0 = <&eth_link_led_pins>, <&eth_act_led_pins>;
+ pinctrl-names = "default";
+};
+
+/* This UART is brought out to the DB9 connector */
+&uart_AO {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index 17bcfa4702e1..f58d1790de1c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -323,10 +323,16 @@
<&reset RESET_HDMI_SYSTEM_RESET>,
<&reset RESET_HDMI_TX>;
reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
- clocks = <&clkc CLKID_HDMI_PCLK>,
- <&clkc CLKID_CLK81>,
+ clocks = <&clkc CLKID_HDMI>,
+ <&clkc CLKID_HDMI_PCLK>,
<&clkc CLKID_GCLK_VENCI_INT0>;
clock-names = "isfr", "iahb", "venci";
+ power-domains = <&pwrc PWRC_GXBB_VPU_ID>;
+
+ assigned-clocks = <&clkc CLKID_HDMI_SEL>,
+ <&clkc CLKID_HDMI>;
+ assigned-clock-parents = <&xtal>, <0>;
+ assigned-clock-rates = <0>, <24000000>;
};
&sysctrl {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxlx-s905l-p271.dts b/arch/arm64/boot/dts/amlogic/meson-gxlx-s905l-p271.dts
new file mode 100644
index 000000000000..1221f4545130
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-gxlx-s905l-p271.dts
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2024 Christian Hewitt <[email protected]>
+ */
+
+/dts-v1/;
+
+#include "meson-gxl-s905x.dtsi"
+#include "meson-gx-p23x-q20x.dtsi"
+
+/ {
+ compatible = "amlogic,p271", "amlogic,s905l", "amlogic,meson-gxlx";
+ model = "Amlogic Meson GXLX (S905L) P271 Development Board";
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x40000000>;
+ };
+
+ sound {
+ model = "P271";
+ };
+};
+
+&apb {
+ mali: gpu@c0000 {
+ /* Mali 450-MP2 */
+ interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
+ <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>,
+ <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "gp", "gpmmu", "pp", "pmu",
+ "pp0", "ppmmu0", "pp1", "ppmmu1";
+ };
+};
+
+&saradc {
+ compatible = "amlogic,meson-gxlx-saradc", "amlogic,meson-saradc";
+};
+
+&usb {
+ dr_mode = "host";
+};
+
+&vdec {
+ compatible = "amlogic,gxlx-vdec", "amlogic,gx-vdec";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
index 10896f9df682..b686eacb9662 100644
--- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
@@ -312,6 +312,160 @@
};
};
+ pwm_a_pins1: pwm-a-pins1 {
+ mux {
+ groups = "pwm_a_d";
+ function = "pwm_a";
+ };
+ };
+
+ pwm_a_pins2: pwm-a-pins2 {
+ mux {
+ groups = "pwm_a_x";
+ function = "pwm_a";
+ };
+ };
+
+ pwm_b_pins1: pwm-b-pins1 {
+ mux {
+ groups = "pwm_b_d";
+ function = "pwm_b";
+ };
+ };
+
+ pwm_b_pins2: pwm-b-pins2 {
+ mux {
+ groups = "pwm_b_x";
+ function = "pwm_b";
+ };
+ };
+
+ pwm_c_pins1: pwm-c-pins1 {
+ mux {
+ groups = "pwm_c_d";
+ function = "pwm_c";
+ };
+ };
+
+ pwm_c_pins2: pwm-c-pins2 {
+ mux {
+ groups = "pwm_c_x";
+ function = "pwm_c";
+ };
+ };
+
+ pwm_d_pins1: pwm-d-pins1 {
+ mux {
+ groups = "pwm_d_d";
+ function = "pwm_d";
+ };
+ };
+
+ pwm_d_pins2: pwm-d-pins2 {
+ mux {
+ groups = "pwm_d_h";
+ function = "pwm_d";
+ };
+ };
+
+ pwm_e_pins1: pwm-e-pins1 {
+ mux {
+ groups = "pwm_e_x";
+ function = "pwm_e";
+ };
+ };
+
+ pwm_e_pins2: pwm-e-pins2 {
+ mux {
+ groups = "pwm_e_z";
+ function = "pwm_e";
+ };
+ };
+
+ pwm_f_pins1: pwm-f-pins1 {
+ mux {
+ groups = "pwm_f_x";
+ function = "pwm_f";
+ };
+ };
+
+ pwm_f_pins2: pwm-f-pins2 {
+ mux {
+ groups = "pwm_f_z";
+ function = "pwm_f";
+ };
+ };
+
+ pwm_g_pins1: pwm-g-pins1 {
+ mux {
+ groups = "pwm_g_d";
+ function = "pwm_g";
+ };
+ };
+
+ pwm_g_pins2: pwm-g-pins2 {
+ mux {
+ groups = "pwm_g_z";
+ function = "pwm_g";
+ };
+ };
+
+ pwm_h_pins: pwm-h-pins {
+ mux {
+ groups = "pwm_h";
+ function = "pwm_h";
+ };
+ };
+
+ pwm_i_pins1: pwm-i-pins1 {
+ mux {
+ groups = "pwm_i_d";
+ function = "pwm_i";
+ };
+ };
+
+ pwm_i_pins2: pwm-i-pins2 {
+ mux {
+ groups = "pwm_i_h";
+ function = "pwm_i";
+ };
+ };
+
+ pwm_j_pins: pwm-j-pins {
+ mux {
+ groups = "pwm_j";
+ function = "pwm_j";
+ };
+ };
+
+ pwm_a_hiz_pins: pwm-a-hiz-pins {
+ mux {
+ groups = "pwm_a_hiz";
+ function = "pwm_a_hiz";
+ };
+ };
+
+ pwm_b_hiz_pins: pwm-b-hiz-pins {
+ mux {
+ groups = "pwm_b_hiz";
+ function = "pwm_b_hiz";
+ };
+ };
+
+ pwm_c_hiz_pins: pwm-c-hiz-pins {
+ mux {
+ groups = "pwm_c_hiz";
+ function = "pwm_c_hiz";
+ };
+ };
+
+ pwm_g_hiz_pins: pwm-g-hiz-pins {
+ mux {
+ groups = "pwm_g_hiz";
+ function = "pwm_g_hiz";
+ };
+ };
+
spicc0_pins_x: spicc0-pins_x {
mux {
groups = "spi_a_mosi_x",
@@ -399,6 +553,51 @@
status = "disabled";
};
+ pwm_ab: pwm@58000 {
+ compatible = "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,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,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,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,meson-s4-pwm";
+ reg = <0x0 0x60000 0x0 0x24>;
+ clocks = <&clkc_periphs CLKID_PWM_I>,
+ <&clkc_periphs CLKID_PWM_J>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
i2c0: i2c@66000 {
compatible = "amlogic,meson-axg-i2c";
reg = <0x0 0x66000 0x0 0x20>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
index 643f94d9d08e..97e4b52066dc 100644
--- a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
@@ -17,10 +17,10 @@
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
sound-name-prefix = "TDM_A";
- clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>,
- <&clkc_audio AUD_CLKID_MST_A_SCLK>,
- <&clkc_audio AUD_CLKID_MST_A_LRCLK>;
- clock-names = "mclk", "sclk", "lrclk";
+ clocks = <&clkc_audio AUD_CLKID_MST_A_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_A_LRCLK>,
+ <&clkc_audio AUD_CLKID_MST_A_MCLK>;
+ clock-names = "sclk", "lrclk", "mclk";
status = "disabled";
};
@@ -28,10 +28,10 @@
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
sound-name-prefix = "TDM_B";
- clocks = <&clkc_audio AUD_CLKID_MST_B_MCLK>,
- <&clkc_audio AUD_CLKID_MST_B_SCLK>,
- <&clkc_audio AUD_CLKID_MST_B_LRCLK>;
- clock-names = "mclk", "sclk", "lrclk";
+ clocks = <&clkc_audio AUD_CLKID_MST_B_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_B_LRCLK>,
+ <&clkc_audio AUD_CLKID_MST_B_MCLK>;
+ clock-names = "sclk", "lrclk", "mclk";
status = "disabled";
};
@@ -39,10 +39,10 @@
compatible = "amlogic,axg-tdm-iface";
#sound-dai-cells = <0>;
sound-name-prefix = "TDM_C";
- clocks = <&clkc_audio AUD_CLKID_MST_C_MCLK>,
- <&clkc_audio AUD_CLKID_MST_C_SCLK>,
- <&clkc_audio AUD_CLKID_MST_C_LRCLK>;
- clock-names = "mclk", "sclk", "lrclk";
+ clocks = <&clkc_audio AUD_CLKID_MST_C_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_C_LRCLK>,
+ <&clkc_audio AUD_CLKID_MST_C_MCLK>;
+ clock-names = "sclk", "lrclk", "mclk";
status = "disabled";
};
@@ -275,8 +275,7 @@
};
tdmin_a: audio-controller@300 {
- compatible = "amlogic,sm1-tdmin",
- "amlogic,axg-tdmin";
+ compatible = "amlogic,sm1-tdmin";
reg = <0x0 0x300 0x0 0x40>;
sound-name-prefix = "TDMIN_A";
resets = <&clkc_audio AUD_RESET_TDMIN_A>;
@@ -291,8 +290,7 @@
};
tdmin_b: audio-controller@340 {
- compatible = "amlogic,sm1-tdmin",
- "amlogic,axg-tdmin";
+ compatible = "amlogic,sm1-tdmin";
reg = <0x0 0x340 0x0 0x40>;
sound-name-prefix = "TDMIN_B";
resets = <&clkc_audio AUD_RESET_TDMIN_B>;
@@ -307,8 +305,7 @@
};
tdmin_c: audio-controller@380 {
- compatible = "amlogic,sm1-tdmin",
- "amlogic,axg-tdmin";
+ compatible = "amlogic,sm1-tdmin";
reg = <0x0 0x380 0x0 0x40>;
sound-name-prefix = "TDMIN_C";
resets = <&clkc_audio AUD_RESET_TDMIN_C>;
@@ -323,8 +320,7 @@
};
tdmin_lb: audio-controller@3c0 {
- compatible = "amlogic,sm1-tdmin",
- "amlogic,axg-tdmin";
+ compatible = "amlogic,sm1-tdmin";
reg = <0x0 0x3c0 0x0 0x40>;
sound-name-prefix = "TDMIN_LB";
resets = <&clkc_audio AUD_RESET_TDMIN_LB>;
@@ -339,7 +335,7 @@
};
spdifin: audio-controller@400 {
- compatible = "amlogic,g12a-spdifin",
+ compatible = "amlogic,sm1-spdifin",
"amlogic,axg-spdifin";
reg = <0x0 0x400 0x0 0x30>;
#sound-dai-cells = <0>;
@@ -353,7 +349,7 @@
};
spdifout_a: audio-controller@480 {
- compatible = "amlogic,g12a-spdifout",
+ compatible = "amlogic,sm1-spdifout",
"amlogic,axg-spdifout";
reg = <0x0 0x480 0x0 0x50>;
#sound-dai-cells = <0>;
@@ -518,6 +514,10 @@
"amlogic,meson-gpio-intc";
};
+&hdmi_tx {
+ power-domains = <&pwrc PWRC_SM1_VPU_ID>;
+};
+
&pcie {
power-domains = <&pwrc PWRC_SM1_PCIE_ID>;
};
diff --git a/arch/arm64/boot/dts/apm/apm-merlin.dts b/arch/arm64/boot/dts/apm/apm-merlin.dts
index 6e05cf1a3df6..b1160780a2a6 100644
--- a/arch/arm64/boot/dts/apm/apm-merlin.dts
+++ b/arch/arm64/boot/dts/apm/apm-merlin.dts
@@ -32,7 +32,7 @@
};
poweroff_mbox: poweroff_mbox@10548000 {
- compatible = "syscon";
+ compatible = "apm,merlin-poweroff-mailbox", "syscon";
reg = <0x0 0x10548000 0x0 0x30>;
};
diff --git a/arch/arm64/boot/dts/apm/apm-mustang.dts b/arch/arm64/boot/dts/apm/apm-mustang.dts
index e7644cddf06f..2ef658796746 100644
--- a/arch/arm64/boot/dts/apm/apm-mustang.dts
+++ b/arch/arm64/boot/dts/apm/apm-mustang.dts
@@ -32,7 +32,7 @@
};
poweroff_mbox: poweroff_mbox@10548000 {
- compatible = "syscon";
+ compatible = "apm,mustang-poweroff-mailbox", "syscon";
reg = <0x0 0x10548000 0x0 0x30>;
};
diff --git a/arch/arm64/boot/dts/arm/corstone1000-fvp.dts b/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
index 901a7fc83307..abd013562995 100644
--- a/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
+++ b/arch/arm64/boot/dts/arm/corstone1000-fvp.dts
@@ -21,7 +21,7 @@
reg-io-width = <2>;
};
- vmmc_v3_3d: fixed_v3_3d {
+ vmmc_v3_3d: regulator-vmmc {
compatible = "regulator-fixed";
regulator-name = "vmmc_supply";
regulator-min-microvolt = <3300000>;
diff --git a/arch/arm64/boot/dts/arm/corstone1000.dtsi b/arch/arm64/boot/dts/arm/corstone1000.dtsi
index 6ad7829f9e28..bb9b96fb5314 100644
--- a/arch/arm64/boot/dts/arm/corstone1000.dtsi
+++ b/arch/arm64/boot/dts/arm/corstone1000.dtsi
@@ -60,14 +60,14 @@
cache-sets = <1024>;
};
- refclk100mhz: refclk100mhz {
+ refclk100mhz: clock-100000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <100000000>;
clock-output-names = "apb_pclk";
};
- smbclk: refclk24mhzx2 {
+ smbclk: clock-48000000 {
/* Reference 24MHz clock x 2 */
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -83,7 +83,7 @@
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
};
- uartclk: uartclk {
+ uartclk: clock-50000000 {
/* UART clock - 50MHz */
compatible = "fixed-clock";
#clock-cells = <0>;
diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dtsi b/arch/arm64/boot/dts/arm/foundation-v8.dtsi
index 7b41537731a6..93f1e7c026b8 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dtsi
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dtsi
@@ -99,21 +99,21 @@
timeout-sec = <30>;
};
- v2m_clk24mhz: clk24mhz {
+ v2m_clk24mhz: clock-24000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>;
clock-output-names = "v2m:clk24mhz";
};
- v2m_refclk1mhz: refclk1mhz {
+ v2m_refclk1mhz: clock-1000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1000000>;
clock-output-names = "v2m:refclk1mhz";
};
- v2m_refclk32khz: refclk32khz {
+ v2m_refclk32khz: clock-32768 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi
index 98ed2b329ed6..055764d0b9e5 100644
--- a/arch/arm64/boot/dts/arm/juno-base.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-base.dtsi
@@ -663,7 +663,6 @@
dma-coherent;
/* The SMMU is only really of interest to bare-metal hypervisors */
/* iommus = <&smmu_gpu 0>; */
- status = "disabled";
};
sram: sram@2e000000 {
diff --git a/arch/arm64/boot/dts/arm/juno-clocks.dtsi b/arch/arm64/boot/dts/arm/juno-clocks.dtsi
index 2870b5eeb198..6d7d88e9591a 100644
--- a/arch/arm64/boot/dts/arm/juno-clocks.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-clocks.dtsi
@@ -8,35 +8,35 @@
*/
/ {
/* SoC fixed clocks */
- soc_uartclk: refclk7372800hz {
+ soc_uartclk: clock-7372800 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <7372800>;
clock-output-names = "juno:uartclk";
};
- soc_usb48mhz: clk48mhz {
+ soc_usb48mhz: clock-48000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <48000000>;
clock-output-names = "clk48mhz";
};
- soc_smc50mhz: clk50mhz {
+ soc_smc50mhz: clock-50000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <50000000>;
clock-output-names = "smc_clk";
};
- soc_refclk100mhz: refclk100mhz {
+ soc_refclk100mhz: clock-100000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <100000000>;
clock-output-names = "apb_pclk";
};
- soc_faxiclk: refclk400mhz {
+ soc_faxiclk: clock-400000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <400000000>;
diff --git a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
index be42932f7e21..ffa4ba4f1fbc 100644
--- a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
@@ -8,35 +8,35 @@
*/
/ {
- mb_clk24mhz: clk24mhz {
+ mb_clk24mhz: clock-24000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>;
clock-output-names = "juno_mb:clk24mhz";
};
- mb_clk25mhz: clk25mhz {
+ mb_clk25mhz: clock-25000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <25000000>;
clock-output-names = "juno_mb:clk25mhz";
};
- v2m_refclk1mhz: refclk1mhz {
+ v2m_refclk1mhz: clock-1000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1000000>;
clock-output-names = "juno_mb:refclk1mhz";
};
- v2m_refclk32khz: refclk32khz {
+ v2m_refclk32khz: clock-32768 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
clock-output-names = "juno_mb:refclk32khz";
};
- mb_fixed_3v3: mcc-sb-3v3 {
+ mb_fixed_3v3: regulator-3v3 {
compatible = "regulator-fixed";
regulator-name = "MCC_SB_3V3";
regulator-min-microvolt = <3300000>;
@@ -158,7 +158,8 @@
};
apbregs@10000 {
- compatible = "syscon", "simple-mfd";
+ compatible = "arm,juno-fpga-apb-regs",
+ "syscon", "simple-mfd";
reg = <0x010000 0x1000>;
ranges = <0x0 0x10000 0x1000>;
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
index ba8beef3fe99..66b1b74d27dc 100644
--- a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
+++ b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
@@ -8,28 +8,28 @@
* VEMotherBoard.lisa
*/
/ {
- v2m_clk24mhz: clk24mhz {
+ v2m_clk24mhz: clock-24000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>;
clock-output-names = "v2m:clk24mhz";
};
- v2m_refclk1mhz: refclk1mhz {
+ v2m_refclk1mhz: clock-1000000 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1000000>;
clock-output-names = "v2m:refclk1mhz";
};
- v2m_refclk32khz: refclk32khz {
+ v2m_refclk32khz: clock-32768 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
clock-output-names = "v2m:refclk32khz";
};
- v2m_fixed_3v3: v2m-3v3 {
+ v2m_fixed_3v3: regulator-3v3 {
compatible = "regulator-fixed";
regulator-name = "3V3";
regulator-min-microvolt = <3300000>;
@@ -41,7 +41,7 @@
compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
- v2m_oscclk1: oscclk1 {
+ v2m_oscclk1: clock-controller {
/* CLCD clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 1>;
diff --git a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
index 9115c99d0dc0..a0e1fa83eafa 100644
--- a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
+++ b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
@@ -111,7 +111,7 @@
compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
- smbclk: smclk {
+ smbclk: clock-controller {
/* SMC clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 4>;
@@ -120,7 +120,7 @@
clock-output-names = "smclk";
};
- volt-vio {
+ regulator-vio {
/* VIO to expansion board above */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 0>;
@@ -130,7 +130,7 @@
regulator-always-on;
};
- volt-12v {
+ regulator-12v {
/* 12V from power connector J6 */
compatible = "arm,vexpress-volt";
arm,vexpress-sysreg,func = <2 1>;
diff --git a/arch/arm64/boot/dts/exynos/exynos850.dtsi b/arch/arm64/boot/dts/exynos/exynos850.dtsi
index 0706c8534ceb..f1c8b4613cbc 100644
--- a/arch/arm64/boot/dts/exynos/exynos850.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos850.dtsi
@@ -416,6 +416,14 @@
interrupts = <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>;
};
+ trng: rng@12081400 {
+ compatible = "samsung,exynos850-trng";
+ reg = <0x12081400 0x100>;
+ clocks = <&cmu_core CLK_GOUT_SSS_ACLK>,
+ <&cmu_core CLK_GOUT_SSS_PCLK>;
+ clock-names = "secss", "pclk";
+ };
+
pinctrl_hsi: pinctrl@13430000 {
compatible = "samsung,exynos850-pinctrl";
reg = <0x13430000 0x1000>;
diff --git a/arch/arm64/boot/dts/exynos/google/gs101-oriole.dts b/arch/arm64/boot/dts/exynos/google/gs101-oriole.dts
index 5e8ffe065081..387fb779bd29 100644
--- a/arch/arm64/boot/dts/exynos/google/gs101-oriole.dts
+++ b/arch/arm64/boot/dts/exynos/google/gs101-oriole.dts
@@ -131,9 +131,9 @@
};
&usbdrd31 {
- status = "okay";
vdd10-supply = <&reg_placeholder>;
vdd33-supply = <&reg_placeholder>;
+ status = "okay";
};
&usbdrd31_dwc3 {
@@ -145,6 +145,13 @@
};
&usbdrd31_phy {
+ /* TODO: Update these once PMIC is implemented */
+ pll-supply = <&reg_placeholder>;
+ dvdd-usb20-supply = <&reg_placeholder>;
+ vddh-usb20-supply = <&reg_placeholder>;
+ vdd33-usb20-supply = <&reg_placeholder>;
+ vdda-usbdp-supply = <&reg_placeholder>;
+ vddh-usbdp-supply = <&reg_placeholder>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/exynos/google/gs101.dtsi b/arch/arm64/boot/dts/exynos/google/gs101.dtsi
index a66e996666b8..eadb8822e6d4 100644
--- a/arch/arm64/boot/dts/exynos/google/gs101.dtsi
+++ b/arch/arm64/boot/dts/exynos/google/gs101.dtsi
@@ -213,9 +213,9 @@
pmu-3 {
compatible = "arm,dsu-pmu";
- interrupts = <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH 0>;
cpus = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>,
<&cpu4>, <&cpu5>, <&cpu6>, <&cpu7>;
+ interrupts = <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH 0>;
};
psci {
@@ -288,6 +288,8 @@
compatible = "google,gs101-mct",
"samsung,exynos4210-mct";
reg = <0x10050000 0x800>;
+ clocks = <&ext_24_5m>, <&cmu_misc CLK_GOUT_MISC_MCT_PCLK>;
+ clock-names = "fin_pll", "mct";
interrupts = <GIC_SPI 753 IRQ_TYPE_LEVEL_HIGH 0>,
<GIC_SPI 754 IRQ_TYPE_LEVEL_HIGH 0>,
<GIC_SPI 755 IRQ_TYPE_LEVEL_HIGH 0>,
@@ -300,17 +302,15 @@
<GIC_SPI 762 IRQ_TYPE_LEVEL_HIGH 0>,
<GIC_SPI 763 IRQ_TYPE_LEVEL_HIGH 0>,
<GIC_SPI 764 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&ext_24_5m>, <&cmu_misc CLK_GOUT_MISC_MCT_PCLK>;
- clock-names = "fin_pll", "mct";
};
watchdog_cl0: watchdog@10060000 {
compatible = "google,gs101-wdt";
reg = <0x10060000 0x100>;
- interrupts = <GIC_SPI 765 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&cmu_misc CLK_GOUT_MISC_WDT_CLUSTER0_PCLK>,
<&ext_24_5m>;
clock-names = "watchdog", "watchdog_src";
+ interrupts = <GIC_SPI 765 IRQ_TYPE_LEVEL_HIGH 0>;
samsung,syscon-phandle = <&pmu_system_controller>;
samsung,cluster-index = <0>;
status = "disabled";
@@ -319,10 +319,10 @@
watchdog_cl1: watchdog@10070000 {
compatible = "google,gs101-wdt";
reg = <0x10070000 0x100>;
- interrupts = <GIC_SPI 766 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&cmu_misc CLK_GOUT_MISC_WDT_CLUSTER1_PCLK>,
<&ext_24_5m>;
clock-names = "watchdog", "watchdog_src";
+ interrupts = <GIC_SPI 766 IRQ_TYPE_LEVEL_HIGH 0>;
samsung,syscon-phandle = <&pmu_system_controller>;
samsung,cluster-index = <1>;
status = "disabled";
@@ -776,12 +776,12 @@
compatible = "google,gs101-hsi2c",
"samsung,exynosautov9-hsi2c";
reg = <0x10970000 0xc0>;
- interrupts = <GIC_SPI 642 IRQ_TYPE_LEVEL_HIGH 0>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&cmu_peric0 CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_7>,
<&cmu_peric0 CLK_GOUT_PERIC0_PERIC0_TOP0_PCLK_7>;
clock-names = "hsi2c", "hsi2c_pclk";
+ interrupts = <GIC_SPI 642 IRQ_TYPE_LEVEL_HIGH 0>;
pinctrl-0 = <&hsi2c8_bus>;
pinctrl-names = "default";
status = "disabled";
@@ -831,10 +831,10 @@
serial_0: serial@10a00000 {
compatible = "google,gs101-uart";
reg = <0x10a00000 0xc0>;
- interrupts = <GIC_SPI 634 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&cmu_peric0 CLK_GOUT_PERIC0_PERIC0_TOP1_PCLK_0>,
<&cmu_peric0 CLK_GOUT_PERIC0_PERIC0_TOP1_IPCLK_0>;
clock-names = "uart", "clk_uart_baud0";
+ interrupts = <GIC_SPI 634 IRQ_TYPE_LEVEL_HIGH 0>;
pinctrl-0 = <&uart0_bus>;
pinctrl-names = "default";
samsung,uart-fifosize = <256>;
@@ -1157,12 +1157,12 @@
compatible = "google,gs101-hsi2c",
"samsung,exynosautov9-hsi2c";
reg = <0x10d50000 0xc0>;
- interrupts = <GIC_SPI 655 IRQ_TYPE_LEVEL_HIGH 0>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&cmu_peric1 CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_5>,
<&cmu_peric1 CLK_GOUT_PERIC1_PERIC1_TOP0_PCLK_5>;
clock-names = "hsi2c", "hsi2c_pclk";
+ interrupts = <GIC_SPI 655 IRQ_TYPE_LEVEL_HIGH 0>;
pinctrl-0 = <&hsi2c12_bus>;
pinctrl-names = "default";
status = "disabled";
@@ -1277,13 +1277,14 @@
<&cmu_hsi0 CLK_GOUT_HSI0_UASC_HSI0_CTRL_PCLK>,
<&cmu_hsi0 CLK_GOUT_HSI0_USB31DRD_I_USBDPPHY_SCL_APB_PCLK>;
clock-names = "phy", "ref", "ctrl_aclk", "ctrl_pclk", "scl_pclk";
- samsung,pmu-syscon = <&pmu_system_controller>;
#phy-cells = <1>;
+ samsung,pmu-syscon = <&pmu_system_controller>;
status = "disabled";
};
usbdrd31: usb@11110000 {
compatible = "google,gs101-dwusb3";
+ ranges = <0x0 0x11110000 0x10000>;
clocks = <&cmu_hsi0 CLK_GOUT_HSI0_USB31DRD_BUS_CLK_EARLY>,
<&cmu_hsi0 CLK_GOUT_HSI0_USB31DRD_I_USB31DRD_SUSPEND_CLK_26>,
<&cmu_hsi0 CLK_GOUT_HSI0_UASC_HSI0_LINK_ACLK>,
@@ -1291,14 +1292,13 @@
clock-names = "bus_early", "susp_clk", "link_aclk", "link_pclk";
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0x0 0x11110000 0x10000>;
status = "disabled";
usbdrd31_dwc3: usb@0 {
compatible = "snps,dwc3";
+ reg = <0x0 0x10000>;
clocks = <&cmu_hsi0 CLK_GOUT_HSI0_USB31DRD_I_USB31DRD_REF_CLK_40>;
clock-names = "ref";
- reg = <0x0 0x10000>;
interrupts = <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH 0>;
phys = <&usbdrd31_phy 0>, <&usbdrd31_phy 1>;
phy-names = "usb2-phy", "usb3-phy";
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index bd443c2bc5a4..f04c22b7de72 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -114,6 +114,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-evkb.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-icore-mx8mm-ctouch2.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-icore-mx8mm-edimm2.2.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-iot-gateway.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-innocomm-wb15-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-kontron-bl.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-kontron-bl-osm-s.dtb
@@ -177,6 +178,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-skov-revb-hdmi.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-skov-revb-lt6.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-skov-revb-mi1010ait-1cp1.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mp-ras314.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw71xx-2x.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw72xx-2x.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw73xx-2x.dtb
@@ -191,6 +193,9 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-wifi-dev.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
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-mx8-dlvds-lcd1.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
dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl-lvds.dtb
@@ -231,11 +236,13 @@ dtb-$(CONFIG_ARCH_MXC) += imx8qxp-colibri-iris-v2.dtb
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
dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93-phyboard-segin.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxca.dtb
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-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
@@ -263,6 +270,14 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw73xx-0x-rs485.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw74xx-imx219.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw74xx-rpidsi.dtb
+imx8mm-phygate-tauri-l-rs232-rs232-dtbs := imx8mm-phygate-tauri-l.dtb imx8mm-phygate-tauri-l-rs232-rs232.dtbo
+imx8mm-phygate-tauri-l-rs232-cts-rts-dtbs := imx8mm-phygate-tauri-l.dtb imx8mm-phygate-tauri-l-rs232-rts-cts.dtbo
+imx8mm-phygate-tauri-l-rs232-rs485-dtbs := imx8mm-phygate-tauri-l.dtb imx8mm-phygate-tauri-l-rs232-rs485.dtbo
+
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-phygate-tauri-l-rs232-rs232.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-phygate-tauri-l-rs232-cts-rts.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-phygate-tauri-l-rs232-rs485.dtb
+
dtb-$(CONFIG_ARCH_S32) += s32g274a-evb.dtb
dtb-$(CONFIG_ARCH_S32) += s32g274a-rdb2.dtb
dtb-$(CONFIG_ARCH_S32) += s32g399a-rdb3.dtb
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index a0f7bbd691a0..e61ea7e0737e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -74,15 +74,15 @@
timer {
compatible = "arm,armv8-timer";
- interrupts = <1 13 IRQ_TYPE_LEVEL_LOW>,/* Physical Secure PPI */
- <1 14 IRQ_TYPE_LEVEL_LOW>,/* Physical Non-Secure PPI */
- <1 11 IRQ_TYPE_LEVEL_LOW>,/* Virtual PPI */
- <1 10 IRQ_TYPE_LEVEL_LOW>;/* Hypervisor PPI */
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,/* Physical Secure PPI */
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,/* Physical Non-Secure PPI */
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,/* Virtual PPI */
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;/* Hypervisor PPI */
};
pmu {
compatible = "arm,cortex-a53-pmu";
- interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
};
gic: interrupt-controller@1400000 {
@@ -93,7 +93,7 @@
<0x0 0x1402000 0 0x2000>, /* GICC */
<0x0 0x1404000 0 0x2000>, /* GICH */
<0x0 0x1406000 0 0x2000>; /* GICV */
- interrupts = <1 9 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
};
reboot {
@@ -156,10 +156,10 @@
status = "disabled";
};
- esdhc0: esdhc@1560000 {
+ esdhc0: mmc@1560000 {
compatible = "fsl,ls1012a-esdhc", "fsl,esdhc";
reg = <0x0 0x1560000 0x0 0x10000>;
- interrupts = <0 62 0x4>;
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
voltage-ranges = <1800 1800 3300 3300>;
@@ -175,10 +175,10 @@
big-endian;
};
- esdhc1: esdhc@1580000 {
+ esdhc1: mmc@1580000 {
compatible = "fsl,ls1012a-esdhc", "fsl,esdhc";
reg = <0x0 0x1580000 0x0 0x10000>;
- interrupts = <0 65 0x4>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
voltage-ranges = <1800 1800 3300 3300>;
@@ -305,7 +305,7 @@
tmu: tmu@1f00000 {
compatible = "fsl,qoriq-tmu";
reg = <0x0 0x1f00000 0x0 0x10000>;
- interrupts = <0 33 0x4>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x60062>;
fsl,tmu-calibration =
<0x00000000 0x00000025>,
@@ -355,7 +355,7 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2180000 0x0 0x10000>;
- interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
scl-gpios = <&gpio0 2 0>;
@@ -367,7 +367,7 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2190000 0x0 0x10000>;
- interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
scl-gpios = <&gpio0 13 0>;
@@ -379,7 +379,7 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2100000 0x0 0x10000>;
- interrupts = <0 64 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "dspi";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
@@ -391,7 +391,7 @@
duart0: serial@21c0500 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x00 0x21c0500 0x0 0x100>;
- interrupts = <0 54 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
status = "disabled";
@@ -400,16 +400,16 @@
duart1: serial@21c0600 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x00 0x21c0600 0x0 0x100>;
- interrupts = <0 54 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
status = "disabled";
};
gpio0: gpio@2300000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1021a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
- interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -417,9 +417,9 @@
};
gpio1: gpio@2310000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1021a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2310000 0x0 0x10000>;
- interrupts = <0 67 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -430,7 +430,7 @@
compatible = "fsl,ls1012a-wdt",
"fsl,imx21-wdt";
reg = <0x0 0x2ad0000 0x0 0x10000>;
- interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL QORIQ_CLK_PLL_DIV(1)>;
big-endian;
};
@@ -439,7 +439,7 @@
#sound-dai-cells = <0>;
compatible = "fsl,vf610-sai";
reg = <0x0 0x2b50000 0x0 0x10000>;
- interrupts = <0 148 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>,
<&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -449,9 +449,9 @@
<&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
- dma-names = "tx", "rx";
- dmas = <&edma0 1 47>,
- <&edma0 1 46>;
+ dma-names = "rx", "tx";
+ dmas = <&edma0 1 46>,
+ <&edma0 1 47>;
status = "disabled";
};
@@ -459,7 +459,7 @@
#sound-dai-cells = <0>;
compatible = "fsl,vf610-sai";
reg = <0x0 0x2b60000 0x0 0x10000>;
- interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>,
<&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -469,9 +469,9 @@
<&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
- dma-names = "tx", "rx";
- dmas = <&edma0 1 45>,
- <&edma0 1 44>;
+ dma-names = "rx", "tx";
+ dmas = <&edma0 1 44>,
+ <&edma0 1 45>;
status = "disabled";
};
@@ -481,8 +481,8 @@
reg = <0x0 0x2c00000 0x0 0x10000>,
<0x0 0x2c10000 0x0 0x10000>,
<0x0 0x2c20000 0x0 0x10000>;
- interrupts = <0 103 IRQ_TYPE_LEVEL_HIGH>,
- <0 103 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "edma-tx", "edma-err";
dma-channels = <32>;
big-endian;
@@ -496,12 +496,11 @@
usb0: usb@2f00000 {
compatible = "snps,dwc3";
reg = <0x0 0x2f00000 0x0 0x10000>;
- interrupts = <0 60 0x4>;
+ interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
snps,quirk-frame-length-adjustment = <0x20>;
snps,dis_rxdet_inp3_quirk;
snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
- snps,host-vbus-glitches;
};
sata: sata@3200000 {
@@ -509,7 +508,7 @@
reg = <0x0 0x3200000 0x0 0x10000>,
<0x0 0x20140520 0x0 0x4>;
reg-names = "ahci", "sata-ecc";
- interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
dma-coherent;
@@ -519,7 +518,7 @@
usb1: usb@8600000 {
compatible = "fsl-usb2-dr-v2.5", "fsl-usb2-dr";
reg = <0x0 0x8600000 0x0 0x1000>;
- interrupts = <0 139 0x4>;
+ interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
phy_type = "ulpi";
};
@@ -528,7 +527,7 @@
compatible = "fsl,ls1012a-msi";
reg = <0x0 0x1572000 0x0 0x8>;
msi-controller;
- interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
};
pcie1: pcie@3400000 {
@@ -536,9 +535,9 @@
reg = <0x00 0x03400000 0x0 0x00100000>, /* controller registers */
<0x40 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <0 118 0x4>, /* controller interrupt */
- <0 117 0x4>; /* PME interrupt */
- interrupt-names = "aer", "pme";
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "pme", "aer";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -563,7 +562,7 @@
#fsl,rcpm-wakeup-cells = <1>;
};
- ftm_alarm0: timer@29d0000 {
+ ftm_alarm0: rtc@29d0000 {
compatible = "fsl,ls1012a-ftm-alarm";
reg = <0x0 0x29d0000 0x0 0x10000>;
fsl,rcpm-wakeup = <&rcpm 0x20000>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
index ecd2c1ea177f..757a34ba7da3 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
@@ -201,6 +201,37 @@
#address-cells = <1>;
#size-cells = <0>;
+ i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0>;
+
+ /* Atmel AT24C512C-XHD­B: 64 KB EEPROM */
+ eeprom@50 {
+ compatible = "atmel,24c512";
+ reg = <0x50>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ /* AT24C04C 512-byte DDR4 SPD EEPROM */
+ /* Documentation says 0x51, but must be even and i2cdetect says 0x52 */
+ eeprom@52 {
+ compatible = "atmel,24c04";
+ reg = <0x52>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ /* Atmel AT24C02C-XHM­B: 256-byte EEPROM */
+ eeprom@57 {
+ compatible = "atmel,24c02";
+ reg = <0x57>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+ };
+
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
index 70b8731029c4..6b6e3ee950e5 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
@@ -155,7 +155,7 @@
};
thermal-zones {
- ddr-controller {
+ ddr-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 0>;
@@ -175,7 +175,7 @@
};
};
- core-cluster {
+ core-cluster-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 1>;
@@ -674,7 +674,7 @@
};
pcie_ep1: pcie-ep@3400000 {
- compatible = "fsl,ls1028a-pcie-ep","fsl,ls-pcie-ep";
+ compatible = "fsl,ls1028a-pcie-ep";
reg = <0x00 0x03400000 0x0 0x00100000
0x80 0x00000000 0x8 0x00000000>;
reg-names = "regs", "addr_space";
@@ -713,7 +713,7 @@
};
pcie_ep2: pcie-ep@3500000 {
- compatible = "fsl,ls1028a-pcie-ep","fsl,ls-pcie-ep";
+ compatible = "fsl,ls1028a-pcie-ep";
reg = <0x00 0x03500000 0x0 0x00100000
0x88 0x00000000 0x8 0x00000000>;
reg-names = "regs", "addr_space";
@@ -828,6 +828,7 @@
<GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "qdma-error", "qdma-queue0",
"qdma-queue1", "qdma-queue2", "qdma-queue3";
+ #dma-cells = <1>;
dma-channels = <8>;
block-number = <1>;
block-offset = <0x10000>;
@@ -859,8 +860,8 @@
malidp0: display@f080000 {
compatible = "arm,mali-dp500";
reg = <0x0 0xf080000 0x0 0x10000>;
- interrupts = <0 222 IRQ_TYPE_LEVEL_HIGH>,
- <0 223 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "DE", "SE";
clocks = <&dpclk>,
<&clockgen QORIQ_CLK_HWACCEL 2>,
@@ -902,9 +903,9 @@
<&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(2)>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
- dma-names = "tx", "rx";
- dmas = <&edma0 1 4>,
- <&edma0 1 3>;
+ dma-names = "rx", "tx";
+ dmas = <&edma0 1 3>,
+ <&edma0 1 4>;
fsl,sai-asynchronous;
status = "disabled";
};
@@ -923,9 +924,9 @@
<&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(2)>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
- dma-names = "tx", "rx";
- dmas = <&edma0 1 6>,
- <&edma0 1 5>;
+ dma-names = "rx", "tx";
+ dmas = <&edma0 1 5>,
+ <&edma0 1 6>;
fsl,sai-asynchronous;
status = "disabled";
};
@@ -944,9 +945,9 @@
<&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(2)>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
- dma-names = "tx", "rx";
- dmas = <&edma0 1 8>,
- <&edma0 1 7>;
+ dma-names = "rx", "tx";
+ dmas = <&edma0 1 7>,
+ <&edma0 1 8>;
fsl,sai-asynchronous;
status = "disabled";
};
@@ -965,9 +966,9 @@
<&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(2)>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
- dma-names = "tx", "rx";
- dmas = <&edma0 1 10>,
- <&edma0 1 9>;
+ dma-names = "rx", "tx";
+ dmas = <&edma0 1 9>,
+ <&edma0 1 10>;
fsl,sai-asynchronous;
status = "disabled";
};
@@ -986,9 +987,9 @@
<&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(2)>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
- dma-names = "tx", "rx";
- dmas = <&edma0 1 12>,
- <&edma0 1 11>;
+ dma-names = "rx", "tx";
+ dmas = <&edma0 1 11>,
+ <&edma0 1 12>;
fsl,sai-asynchronous;
status = "disabled";
};
@@ -1007,9 +1008,9 @@
<&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(2)>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
- dma-names = "tx", "rx";
- dmas = <&edma0 1 14>,
- <&edma0 1 13>;
+ dma-names = "rx", "tx";
+ dmas = <&edma0 1 13>,
+ <&edma0 1 14>;
fsl,sai-asynchronous;
status = "disabled";
};
@@ -1024,7 +1025,7 @@
tmu: tmu@1f80000 {
compatible = "fsl,qoriq-tmu";
reg = <0x0 0x1f80000 0x0 0x10000>;
- interrupts = <0 23 0x4>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x70061>;
fsl,tmu-calibration =
<0x00000000 0x00000024>,
@@ -1325,7 +1326,7 @@
little-endian;
};
- ftm_alarm0: timer@2800000 {
+ ftm_alarm0: rtc@2800000 {
compatible = "fsl,ls1028a-ftm-alarm";
reg = <0x0 0x2800000 0x0 0x10000>;
fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0 0x0>;
@@ -1333,7 +1334,7 @@
status = "disabled";
};
- ftm_alarm1: timer@2810000 {
+ ftm_alarm1: rtc@2810000 {
compatible = "fsl,ls1028a-ftm-alarm";
reg = <0x0 0x2810000 0x0 0x10000>;
fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0 0x0>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
index dda27ed7aaf2..11b1356e95d5 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
@@ -64,7 +64,7 @@
0x2 0x0 0x0 0x7fb00000 0x00000100>;
status = "okay";
- nor@0,0 {
+ flash@0,0 {
compatible = "cfi-flash";
reg = <0x0 0x0 0x8000000>;
big-endian;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
index 26f8540cb101..c4532c809f0a 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
@@ -71,7 +71,7 @@
0x1 0x0 0x0 0x7e800000 0x00010000
0x2 0x0 0x0 0x7fb00000 0x00000100>;
- nor@0,0 {
+ flash@0,0 {
compatible = "cfi-flash";
#address-cells = <1>;
#size-cells = <1>;
@@ -104,6 +104,12 @@
compatible = "n25q128a13", "jedec,spi-nor"; /* 16MB */
reg = <0>;
spi-max-frequency = <1000000>; /* input clock */
+ /*
+ * Standard CS timing properties replace the deprecated vendor
+ * variants below.
+ */
+ spi-cs-setup-delay-ns = <100>;
+ spi-cs-hold-delay-ns = <100>;
fsl,spi-cs-sck-delay = <100>;
fsl,spi-sck-cs-delay = <100>;
};
@@ -112,6 +118,12 @@
compatible = "maxim,ds26522";
reg = <2>;
spi-max-frequency = <2000000>;
+ /*
+ * Standard CS timing properties replace the deprecated vendor
+ * variants below.
+ */
+ spi-cs-setup-delay-ns = <100>;
+ spi-cs-hold-delay-ns = <50>;
fsl,spi-cs-sck-delay = <100>;
fsl,spi-sck-cs-delay = <50>;
};
@@ -120,6 +132,12 @@
compatible = "maxim,ds26522";
reg = <3>;
spi-max-frequency = <2000000>;
+ /*
+ * Standard CS timing properties replace the deprecated vendor
+ * variants below.
+ */
+ spi-cs-setup-delay-ns = <100>;
+ spi-cs-hold-delay-ns = <50>;
fsl,spi-cs-sck-delay = <100>;
fsl,spi-sck-cs-delay = <50>;
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 8ee6d8c0ef61..17f4e3171120 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -154,7 +154,7 @@
};
thermal-zones {
- ddr-controller {
+ ddr-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 0>;
@@ -174,7 +174,7 @@
};
};
- serdes {
+ serdes-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 1>;
@@ -194,7 +194,7 @@
};
};
- fman {
+ fman-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 2>;
@@ -214,7 +214,7 @@
};
};
- core-cluster {
+ core-cluster-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 3>;
@@ -245,7 +245,7 @@
};
};
- sec {
+ sec-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 4>;
@@ -268,19 +268,19 @@
timer {
compatible = "arm,armv8-timer";
- interrupts = <1 13 0xf08>, /* Physical Secure PPI */
- <1 14 0xf08>, /* Physical Non-Secure PPI */
- <1 11 0xf08>, /* Virtual PPI */
- <1 10 0xf08>; /* Hypervisor PPI */
+ 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)>;
fsl,erratum-a008585;
};
pmu {
compatible = "arm,cortex-a53-pmu";
- interrupts = <0 106 0x4>,
- <0 107 0x4>,
- <0 95 0x4>,
- <0 97 0x4>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
interrupt-affinity = <&cpu0>,
<&cpu1>,
<&cpu2>,
@@ -295,7 +295,7 @@
<0x0 0x1402000 0 0x2000>, /* GICC */
<0x0 0x1404000 0 0x2000>, /* GICH */
<0x0 0x1406000 0 0x2000>; /* GICV */
- interrupts = <1 9 0xf08>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
};
soc: soc {
@@ -352,7 +352,7 @@
#size-cells = <1>;
ranges = <0x0 0x00 0x1700000 0x100000>;
reg = <0x00 0x1700000 0x0 0x100000>;
- interrupts = <0 75 0x4>;
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
dma-coherent;
sec_jr0: jr@10000 {
@@ -360,7 +360,7 @@
"fsl,sec-v5.0-job-ring",
"fsl,sec-v4.0-job-ring";
reg = <0x10000 0x10000>;
- interrupts = <0 71 0x4>;
+ interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
};
sec_jr1: jr@20000 {
@@ -368,7 +368,7 @@
"fsl,sec-v5.0-job-ring",
"fsl,sec-v4.0-job-ring";
reg = <0x20000 0x10000>;
- interrupts = <0 72 0x4>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
};
sec_jr2: jr@30000 {
@@ -376,7 +376,7 @@
"fsl,sec-v5.0-job-ring",
"fsl,sec-v4.0-job-ring";
reg = <0x30000 0x10000>;
- interrupts = <0 73 0x4>;
+ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
};
sec_jr3: jr@40000 {
@@ -384,7 +384,7 @@
"fsl,sec-v5.0-job-ring",
"fsl,sec-v4.0-job-ring";
reg = <0x40000 0x10000>;
- interrupts = <0 74 0x4>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
};
};
@@ -405,7 +405,7 @@
ifc: memory-controller@1530000 {
compatible = "fsl,ifc";
reg = <0x0 0x1530000 0x0 0x10000>;
- interrupts = <0 43 0x4>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
};
qspi: spi@1550000 {
@@ -415,7 +415,7 @@
reg = <0x0 0x1550000 0x0 0x10000>,
<0x0 0x40000000 0x0 0x4000000>;
reg-names = "QuadSPI", "QuadSPI-memory";
- interrupts = <0 99 0x4>;
+ interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "qspi_en", "qspi";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>,
@@ -424,10 +424,10 @@
status = "disabled";
};
- esdhc: esdhc@1560000 {
+ esdhc: mmc@1560000 {
compatible = "fsl,ls1043a-esdhc", "fsl,esdhc";
reg = <0x0 0x1560000 0x0 0x10000>;
- interrupts = <0 62 0x4>;
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <0>;
voltage-ranges = <1800 1800 3300 3300>;
sdhci,auto-cmd12;
@@ -438,14 +438,14 @@
ddr: memory-controller@1080000 {
compatible = "fsl,qoriq-memory-controller";
reg = <0x0 0x1080000 0x0 0x1000>;
- interrupts = <0 144 0x4>;
+ interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
big-endian;
};
tmu: tmu@1f00000 {
compatible = "fsl,qoriq-tmu";
reg = <0x0 0x1f00000 0x0 0x10000>;
- interrupts = <0 33 0x4>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x70062>;
fsl,tmu-calibration =
<0x00000000 0x00000023>,
@@ -505,11 +505,11 @@
memory-region = <&bman_fbpr>;
};
- bportals: bman-portals@508000000 {
+ bportals: bman-portals-bus@508000000 {
ranges = <0x0 0x5 0x08000000 0x8000000>;
};
- qportals: qman-portals@500000000 {
+ qportals: qman-portals-bus@500000000 {
ranges = <0x0 0x5 0x00000000 0x8000000>;
};
@@ -518,7 +518,7 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2100000 0x0 0x10000>;
- interrupts = <0 64 0x4>;
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "dspi";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
@@ -532,8 +532,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2180000 0x0 0x10000>;
- interrupts = <0 56 0x4>;
- clock-names = "i2c";
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
dmas = <&edma0 1 38>,
@@ -547,8 +547,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2190000 0x0 0x10000>;
- interrupts = <0 57 0x4>;
- clock-names = "i2c";
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
scl-gpios = <&gpio4 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
@@ -560,8 +560,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x21a0000 0x0 0x10000>;
- interrupts = <0 58 0x4>;
- clock-names = "i2c";
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
scl-gpios = <&gpio4 10 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
@@ -573,8 +573,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x21b0000 0x0 0x10000>;
- interrupts = <0 59 0x4>;
- clock-names = "i2c";
+ interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
scl-gpios = <&gpio4 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
@@ -584,7 +584,7 @@
duart0: serial@21c0500 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x00 0x21c0500 0x0 0x100>;
- interrupts = <0 54 0x4>;
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
};
@@ -592,7 +592,7 @@
duart1: serial@21c0600 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x00 0x21c0600 0x0 0x100>;
- interrupts = <0 54 0x4>;
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
};
@@ -600,7 +600,7 @@
duart2: serial@21d0500 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x0 0x21d0500 0x0 0x100>;
- interrupts = <0 55 0x4>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
};
@@ -608,7 +608,7 @@
duart3: serial@21d0600 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x0 0x21d0600 0x0 0x100>;
- interrupts = <0 55 0x4>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
};
@@ -616,7 +616,7 @@
gpio1: gpio@2300000 {
compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
- interrupts = <0 66 0x4>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -626,7 +626,7 @@
gpio2: gpio@2310000 {
compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2310000 0x0 0x10000>;
- interrupts = <0 67 0x4>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -636,7 +636,7 @@
gpio3: gpio@2320000 {
compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2320000 0x0 0x10000>;
- interrupts = <0 68 0x4>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -646,7 +646,7 @@
gpio4: gpio@2330000 {
compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2330000 0x0 0x10000>;
- interrupts = <0 134 0x4>;
+ interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -721,7 +721,7 @@
lpuart0: serial@2950000 {
compatible = "fsl,ls1021a-lpuart";
reg = <0x0 0x2950000 0x0 0x1000>;
- interrupts = <0 48 0x4>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_SYSCLK 0>;
clock-names = "ipg";
status = "disabled";
@@ -730,7 +730,7 @@
lpuart1: serial@2960000 {
compatible = "fsl,ls1021a-lpuart";
reg = <0x0 0x2960000 0x0 0x1000>;
- interrupts = <0 49 0x4>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
clock-names = "ipg";
@@ -740,7 +740,7 @@
lpuart2: serial@2970000 {
compatible = "fsl,ls1021a-lpuart";
reg = <0x0 0x2970000 0x0 0x1000>;
- interrupts = <0 50 0x4>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
clock-names = "ipg";
@@ -750,7 +750,7 @@
lpuart3: serial@2980000 {
compatible = "fsl,ls1021a-lpuart";
reg = <0x0 0x2980000 0x0 0x1000>;
- interrupts = <0 51 0x4>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
clock-names = "ipg";
@@ -760,7 +760,7 @@
lpuart4: serial@2990000 {
compatible = "fsl,ls1021a-lpuart";
reg = <0x0 0x2990000 0x0 0x1000>;
- interrupts = <0 52 0x4>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
clock-names = "ipg";
@@ -770,7 +770,7 @@
lpuart5: serial@29a0000 {
compatible = "fsl,ls1021a-lpuart";
reg = <0x0 0x29a0000 0x0 0x1000>;
- interrupts = <0 53 0x4>;
+ interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
clock-names = "ipg";
@@ -780,10 +780,9 @@
wdog0: watchdog@2ad0000 {
compatible = "fsl,ls1043a-wdt", "fsl,imx21-wdt";
reg = <0x0 0x2ad0000 0x0 0x10000>;
- interrupts = <0 83 0x4>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
- clock-names = "wdog";
big-endian;
};
@@ -793,8 +792,8 @@
reg = <0x0 0x2c00000 0x0 0x10000>,
<0x0 0x2c10000 0x0 0x10000>,
<0x0 0x2c20000 0x0 0x10000>;
- interrupts = <0 103 0x4>,
- <0 103 0x4>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "edma-tx", "edma-err";
dma-channels = <32>;
big-endian;
@@ -805,7 +804,7 @@
QORIQ_CLK_PLL_DIV(1)>;
};
- aux_bus: aux_bus {
+ aux_bus: aux-bus {
#address-cells = <2>;
#size-cells = <2>;
compatible = "simple-bus";
@@ -815,7 +814,7 @@
usb0: usb@2f00000 {
compatible = "snps,dwc3";
reg = <0x0 0x2f00000 0x0 0x10000>;
- interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
snps,quirk-frame-length-adjustment = <0x20>;
snps,dis_rxdet_inp3_quirk;
@@ -827,7 +826,7 @@
usb1: usb@3000000 {
compatible = "snps,dwc3";
reg = <0x0 0x3000000 0x0 0x10000>;
- interrupts = <0 61 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
snps,quirk-frame-length-adjustment = <0x20>;
snps,dis_rxdet_inp3_quirk;
@@ -839,7 +838,7 @@
usb2: usb@3100000 {
compatible = "snps,dwc3";
reg = <0x0 0x3100000 0x0 0x10000>;
- interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
snps,quirk-frame-length-adjustment = <0x20>;
snps,dis_rxdet_inp3_quirk;
@@ -853,7 +852,7 @@
reg = <0x0 0x3200000 0x0 0x10000>,
<0x0 0x20140520 0x0 0x4>;
reg-names = "ahci", "sata-ecc";
- interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(1)>;
dma-coherent;
@@ -864,21 +863,21 @@
compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1571000 0x0 0x8>;
msi-controller;
- interrupts = <0 116 0x4>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
};
msi2: msi-controller2@1572000 {
compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1572000 0x0 0x8>;
msi-controller;
- interrupts = <0 126 0x4>;
+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
};
msi3: msi-controller3@1573000 {
compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1573000 0x0 0x8>;
msi-controller;
- interrupts = <0 160 0x4>;
+ interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>;
};
pcie1: pcie@3400000 {
@@ -886,8 +885,8 @@
reg = <0x00 0x03400000 0x0 0x00100000>, /* controller registers */
<0x40 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <0 117 IRQ_TYPE_LEVEL_HIGH>,
- <0 118 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "pme", "aer";
#address-cells = <3>;
#size-cells = <2>;
@@ -913,8 +912,8 @@
reg = <0x00 0x03500000 0x0 0x00100000>, /* controller registers */
<0x48 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <0 127 IRQ_TYPE_LEVEL_HIGH>,
- <0 128 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "pme", "aer";
#address-cells = <3>;
#size-cells = <2>;
@@ -940,8 +939,8 @@
reg = <0x00 0x03600000 0x0 0x00100000>, /* controller registers */
<0x50 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <0 161 IRQ_TYPE_LEVEL_HIGH>,
- <0 162 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "pme", "aer";
#address-cells = <3>;
#size-cells = <2>;
@@ -974,6 +973,7 @@
<GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "qdma-error", "qdma-queue0",
"qdma-queue1", "qdma-queue2", "qdma-queue3";
+ #dma-cells = <1>;
dma-channels = <8>;
block-number = <1>;
block-offset = <0x10000>;
@@ -989,7 +989,7 @@
#fsl,rcpm-wakeup-cells = <1>;
};
- ftm_alarm0: timer@29d0000 {
+ ftm_alarm0: rtc@29d0000 {
compatible = "fsl,ls1043a-ftm-alarm";
reg = <0x0 0x29d0000 0x0 0x10000>;
fsl,rcpm-wakeup = <&rcpm 0x20000>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts
index 3b0ed9305f2b..e5296e51f656 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts
@@ -151,7 +151,7 @@
0x2 0x0 0x0 0x7fb00000 0x00000100>;
status = "okay";
- nor@0,0 {
+ flash@0,0 {
compatible = "cfi-flash";
reg = <0x0 0x0 0x8000000>;
big-endian;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 754a64be739c..200e52622f99 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -122,7 +122,7 @@
};
thermal-zones {
- ddr-controller {
+ ddr-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 0>;
@@ -142,7 +142,7 @@
};
};
- serdes {
+ serdes-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 1>;
@@ -162,7 +162,7 @@
};
};
- fman {
+ fman-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 2>;
@@ -182,7 +182,7 @@
};
};
- core-cluster {
+ core-cluster-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 3>;
@@ -213,7 +213,7 @@
};
};
- sec {
+ sec-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 4>;
@@ -308,7 +308,7 @@
status = "disabled";
};
- esdhc: esdhc@1560000 {
+ esdhc: mmc@1560000 {
compatible = "fsl,ls1046a-esdhc", "fsl,esdhc";
reg = <0x0 0x1560000 0x0 0x10000>;
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
@@ -409,11 +409,11 @@
};
- qportals: qman-portals@500000000 {
+ qportals: qman-portals-bus@500000000 {
ranges = <0x0 0x5 0x00000000 0x8000000>;
};
- bportals: bman-portals@508000000 {
+ bportals: bman-portals-bus@508000000 {
ranges = <0x0 0x5 0x08000000 0x8000000>;
};
@@ -441,7 +441,7 @@
tmu: tmu@1f00000 {
compatible = "fsl,qoriq-tmu";
reg = <0x0 0x1f00000 0x0 0x10000>;
- interrupts = <0 33 0x4>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x70062>;
fsl,tmu-calibration =
/* Calibration data group 1 */
@@ -589,7 +589,7 @@
};
gpio0: gpio@2300000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1046a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
@@ -599,7 +599,7 @@
};
gpio1: gpio@2310000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1046a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2310000 0x0 0x10000>;
interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
@@ -609,7 +609,7 @@
};
gpio2: gpio@2320000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1046a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2320000 0x0 0x10000>;
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
@@ -619,7 +619,7 @@
};
gpio3: gpio@2330000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls1046a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2330000 0x0 0x10000>;
interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
@@ -715,7 +715,7 @@
QORIQ_CLK_PLL_DIV(2)>;
};
- aux_bus: aux_bus {
+ aux_bus: aux-bus {
#address-cells = <2>;
#size-cells = <2>;
compatible = "simple-bus";
@@ -801,9 +801,9 @@
reg = <0x00 0x03400000 0x0 0x00100000>, /* controller registers */
<0x40 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */
- <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; /* PME interrupt */
- interrupt-names = "aer", "pme";
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "pme", "aer";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -840,9 +840,9 @@
reg = <0x00 0x03500000 0x0 0x00100000>, /* controller registers */
<0x48 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */
- <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; /* PME interrupt */
- interrupt-names = "aer", "pme";
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "pme", "aer";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -879,9 +879,9 @@
reg = <0x00 0x03600000 0x0 0x00100000>, /* controller registers */
<0x50 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */
- <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>; /* PME interrupt */
- interrupt-names = "aer", "pme";
+ interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "pme", "aer";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -925,6 +925,7 @@
<GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "qdma-error", "qdma-queue0",
"qdma-queue1", "qdma-queue2", "qdma-queue3";
+ #dma-cells = <1>;
dma-channels = <8>;
block-number = <1>;
block-offset = <0x10000>;
@@ -940,7 +941,7 @@
#fsl,rcpm-wakeup-cells = <1>;
};
- ftm_alarm0: timer@29d0000 {
+ ftm_alarm0: rtc@29d0000 {
compatible = "fsl,ls1046a-ftm-alarm";
reg = <0x0 0x29d0000 0x0 0x10000>;
fsl,rcpm-wakeup = <&rcpm 0x20000>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
index aa52ff73ff9e..d238a8440a81 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
@@ -113,7 +113,7 @@
3 0 0x5 0x20000000 0x00010000>;
status = "okay";
- nor@0,0 {
+ flash@0,0 {
compatible = "cfi-flash";
reg = <0x0 0x0 0x8000000>;
bank-width = <2>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index 604bf88d70b3..8ce4b6aae79d 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -118,7 +118,7 @@
<0x0 0x0c0c0000 0 0x2000>, /* GICC */
<0x0 0x0c0d0000 0 0x1000>, /* GICH */
<0x0 0x0c0e0000 0 0x20000>; /* GICV */
- interrupts = <1 9 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
@@ -131,7 +131,7 @@
};
thermal-zones {
- core-cluster {
+ core-cluster-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 0>;
@@ -166,7 +166,7 @@
};
};
- soc {
+ soc-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 1>;
@@ -183,10 +183,10 @@
timer {
compatible = "arm,armv8-timer";
- interrupts = <1 13 IRQ_TYPE_LEVEL_LOW>,/* Physical Secure PPI */
- <1 14 IRQ_TYPE_LEVEL_LOW>,/* Physical Non-Secure PPI */
- <1 11 IRQ_TYPE_LEVEL_LOW>,/* Virtual PPI */
- <1 10 IRQ_TYPE_LEVEL_LOW>;/* Hypervisor PPI */
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,/* Physical Secure PPI */
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,/* Physical Non-Secure PPI */
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,/* Virtual PPI */
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;/* Hypervisor PPI */
};
pmu {
@@ -280,7 +280,7 @@
tmu: tmu@1f80000 {
compatible = "fsl,qoriq-tmu";
reg = <0x0 0x1f80000 0x0 0x10000>;
- interrupts = <0 23 0x4>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x70062>;
fsl,tmu-calibration =
/* Calibration data group 1 */
@@ -347,7 +347,7 @@
reg = <0x0 0x21c0500 0x0 0x100>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
- interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
@@ -356,14 +356,14 @@
reg = <0x0 0x21c0600 0x0 0x100>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
- interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
gpio0: gpio@2300000 {
compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
- interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
little-endian;
gpio-controller;
#gpio-cells = <2>;
@@ -374,7 +374,7 @@
gpio1: gpio@2310000 {
compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2310000 0x0 0x10000>;
- interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
little-endian;
gpio-controller;
#gpio-cells = <2>;
@@ -385,7 +385,7 @@
gpio2: gpio@2320000 {
compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2320000 0x0 0x10000>;
- interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
little-endian;
gpio-controller;
#gpio-cells = <2>;
@@ -396,7 +396,7 @@
gpio3: gpio@2330000 {
compatible = "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2330000 0x0 0x10000>;
- interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
little-endian;
gpio-controller;
#gpio-cells = <2>;
@@ -407,7 +407,7 @@
ifc: memory-controller@2240000 {
compatible = "fsl,ifc";
reg = <0x0 0x2240000 0x0 0x20000>;
- interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
little-endian;
#address-cells = <2>;
#size-cells = <1>;
@@ -419,7 +419,7 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2000000 0x0 0x10000>;
- interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(8)>;
status = "disabled";
@@ -430,7 +430,7 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2010000 0x0 0x10000>;
- interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(8)>;
status = "disabled";
@@ -441,7 +441,7 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2020000 0x0 0x10000>;
- interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(8)>;
status = "disabled";
@@ -452,7 +452,7 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2030000 0x0 0x10000>;
- interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(8)>;
status = "disabled";
@@ -474,10 +474,10 @@
status = "disabled";
};
- esdhc: esdhc@2140000 {
+ esdhc: mmc@2140000 {
compatible = "fsl,ls1088a-esdhc", "fsl,esdhc";
reg = <0x0 0x2140000 0x0 0x10000>;
- interrupts = <0 28 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <0>;
clocks = <&clockgen QORIQ_CLK_HWACCEL 1>;
voltage-ranges = <1800 1800 3300 3300>;
@@ -490,7 +490,7 @@
usb0: usb@3100000 {
compatible = "snps,dwc3";
reg = <0x0 0x3100000 0x0 0x10000>;
- interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
snps,quirk-frame-length-adjustment = <0x20>;
snps,dis_rxdet_inp3_quirk;
@@ -501,7 +501,7 @@
usb1: usb@3110000 {
compatible = "snps,dwc3";
reg = <0x0 0x3110000 0x0 0x10000>;
- interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
snps,quirk-frame-length-adjustment = <0x20>;
snps,dis_rxdet_inp3_quirk;
@@ -514,7 +514,7 @@
reg = <0x0 0x3200000 0x0 0x10000>,
<0x7 0x100520 0x0 0x4>;
reg-names = "ahci", "sata-ecc";
- interrupts = <0 133 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
dma-coherent;
@@ -565,7 +565,7 @@
reg = <0x00 0x03400000 0x0 0x00100000>, /* controller registers */
<0x20 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
interrupt-names = "aer";
#address-cells = <3>;
#size-cells = <2>;
@@ -604,7 +604,7 @@
reg = <0x00 0x03500000 0x0 0x00100000>, /* controller registers */
<0x28 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <0 113 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
interrupt-names = "aer";
#address-cells = <3>;
#size-cells = <2>;
@@ -642,7 +642,7 @@
reg = <0x00 0x03600000 0x0 0x00100000>, /* controller registers */
<0x30 0x00000000 0x0 0x00002000>; /* configuration space */
reg-names = "regs", "config";
- interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
interrupt-names = "aer";
#address-cells = <3>;
#size-cells = <2>;
@@ -880,7 +880,7 @@
};
};
- cluster1_core0_watchdog: wdt@c000000 {
+ cluster1_core0_watchdog: watchdog@c000000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc000000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -890,7 +890,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster1_core1_watchdog: wdt@c010000 {
+ cluster1_core1_watchdog: watchdog@c010000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc010000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -900,7 +900,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster1_core2_watchdog: wdt@c020000 {
+ cluster1_core2_watchdog: watchdog@c020000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc020000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -910,7 +910,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster1_core3_watchdog: wdt@c030000 {
+ cluster1_core3_watchdog: watchdog@c030000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc030000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -920,7 +920,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster2_core0_watchdog: wdt@c100000 {
+ cluster2_core0_watchdog: watchdog@c100000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc100000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -930,7 +930,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster2_core1_watchdog: wdt@c110000 {
+ cluster2_core1_watchdog: watchdog@c110000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc110000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -940,7 +940,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster2_core2_watchdog: wdt@c120000 {
+ cluster2_core2_watchdog: watchdog@c120000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc120000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -950,7 +950,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster2_core3_watchdog: wdt@c130000 {
+ cluster2_core3_watchdog: watchdog@c130000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc130000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -1040,7 +1040,7 @@
little-endian;
};
- ftm_alarm0: timer@2800000 {
+ ftm_alarm0: rtc@2800000 {
compatible = "fsl,ls1088a-ftm-alarm";
reg = <0x0 0x2800000 0x0 0x10000>;
fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 8352197cea6f..e9bc1f4fa13c 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -15,7 +15,7 @@
/ {
pmu {
compatible = "arm,cortex-a57-pmu";
- interrupts = <1 7 0x8>; /* PMU PPI, Level low type */
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
index 245bbd615c81..60c422560e33 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
@@ -15,7 +15,7 @@
/ {
pmu {
compatible = "arm,cortex-a72-pmu";
- interrupts = <1 7 0x8>; /* PMU PPI, Level low type */
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi
index e2c94da6d6e8..9178cd61c786 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi
@@ -43,7 +43,7 @@
0x2 0x0 0x5 0x30000000 0x00010000
0x3 0x0 0x5 0x20000000 0x00010000>;
- nor@0,0 {
+ flash@0,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
index 537cecb13dd0..69cd05a30b85 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
@@ -21,7 +21,7 @@
0x2 0x0 0x5 0x30000000 0x00010000
0x3 0x0 0x5 0x20000000 0x00010000>;
- nor@0,0 {
+ flash@0,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
index ccba0a135b24..bde89de2576e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
@@ -58,7 +58,7 @@
#size-cells = <2>;
ranges;
interrupt-controller;
- interrupts = <1 9 0x4>;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
its: msi-controller@6020000 {
compatible = "arm,gic-v3-its";
@@ -80,7 +80,7 @@
};
thermal-zones {
- ddr-controller1 {
+ ddr-ctrl1-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 1>;
@@ -94,7 +94,7 @@
};
};
- ddr-controller2 {
+ ddr-ctrl2-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 2>;
@@ -108,7 +108,7 @@
};
};
- ddr-controller3 {
+ ddr-ctrl3-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 3>;
@@ -122,7 +122,7 @@
};
};
- core-cluster1 {
+ core-cluster1-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 4>;
@@ -151,7 +151,7 @@
};
};
- core-cluster2 {
+ core-cluster2-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 5>;
@@ -180,7 +180,7 @@
};
};
- core-cluster3 {
+ core-cluster3-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 6>;
@@ -209,7 +209,7 @@
};
};
- core-cluster4 {
+ core-cluster4-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 7>;
@@ -241,10 +241,10 @@
timer: timer {
compatible = "arm,armv8-timer";
- interrupts = <1 13 4>, /* Physical Secure PPI, active-low */
- <1 14 4>, /* Physical Non-Secure PPI, active-low */
- <1 11 4>, /* Virtual PPI, active-low */
- <1 10 4>; /* Hypervisor PPI, active-low */
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>, /* Physical Secure PPI */
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>, /* Physical Non-Secure PPI */
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>, /* Virtual PPI */
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>; /* Hypervisor PPI */
};
psci {
@@ -314,7 +314,7 @@
tmu: tmu@1f80000 {
compatible = "fsl,qoriq-tmu";
reg = <0x0 0x1f80000 0x0 0x10000>;
- interrupts = <0 23 0x4>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
fsl,tmu-calibration =
<0x00000000 0x00000026>,
@@ -362,7 +362,7 @@
reg = <0x0 0x21c0500 0x0 0x100>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
- interrupts = <0 32 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
};
serial1: serial@21c0600 {
@@ -370,7 +370,7 @@
reg = <0x0 0x21c0600 0x0 0x100>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
- interrupts = <0 32 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
};
serial2: serial@21d0500 {
@@ -378,7 +378,7 @@
reg = <0x0 0x21d0500 0x0 0x100>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
- interrupts = <0 33 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
};
serial3: serial@21d0600 {
@@ -386,10 +386,10 @@
reg = <0x0 0x21d0600 0x0 0x100>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
- interrupts = <0 33 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
};
- cluster1_core0_watchdog: wdt@c000000 {
+ cluster1_core0_watchdog: watchdog@c000000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc000000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -399,7 +399,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster1_core1_watchdog: wdt@c010000 {
+ cluster1_core1_watchdog: watchdog@c010000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc010000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -409,7 +409,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster2_core0_watchdog: wdt@c100000 {
+ cluster2_core0_watchdog: watchdog@c100000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc100000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -419,7 +419,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster2_core1_watchdog: wdt@c110000 {
+ cluster2_core1_watchdog: watchdog@c110000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc110000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -429,7 +429,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster3_core0_watchdog: wdt@c200000 {
+ cluster3_core0_watchdog: watchdog@c200000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc200000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -439,7 +439,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster3_core1_watchdog: wdt@c210000 {
+ cluster3_core1_watchdog: watchdog@c210000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc210000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -449,7 +449,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster4_core0_watchdog: wdt@c300000 {
+ cluster4_core0_watchdog: watchdog@c300000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc300000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -459,7 +459,7 @@
clock-names = "wdog_clk", "apb_pclk";
};
- cluster4_core1_watchdog: wdt@c310000 {
+ cluster4_core1_watchdog: watchdog@c310000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0 0xc310000 0x0 0x1000>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
@@ -883,48 +883,48 @@
#iommu-cells = <1>;
stream-match-mask = <0x7C00>;
dma-coherent;
- interrupts = <0 13 4>, /* global secure fault */
- <0 14 4>, /* combined secure interrupt */
- <0 15 4>, /* global non-secure fault */
- <0 16 4>, /* combined non-secure interrupt */
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>, /* global secure fault */
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>, /* combined secure interrupt */
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>, /* global non-secure fault */
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>, /* combined non-secure interrupt */
/* performance counter interrupts 0-7 */
- <0 211 4>, <0 212 4>,
- <0 213 4>, <0 214 4>,
- <0 215 4>, <0 216 4>,
- <0 217 4>, <0 218 4>,
+ <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>,
/* per context interrupt, 64 interrupts */
- <0 146 4>, <0 147 4>,
- <0 148 4>, <0 149 4>,
- <0 150 4>, <0 151 4>,
- <0 152 4>, <0 153 4>,
- <0 154 4>, <0 155 4>,
- <0 156 4>, <0 157 4>,
- <0 158 4>, <0 159 4>,
- <0 160 4>, <0 161 4>,
- <0 162 4>, <0 163 4>,
- <0 164 4>, <0 165 4>,
- <0 166 4>, <0 167 4>,
- <0 168 4>, <0 169 4>,
- <0 170 4>, <0 171 4>,
- <0 172 4>, <0 173 4>,
- <0 174 4>, <0 175 4>,
- <0 176 4>, <0 177 4>,
- <0 178 4>, <0 179 4>,
- <0 180 4>, <0 181 4>,
- <0 182 4>, <0 183 4>,
- <0 184 4>, <0 185 4>,
- <0 186 4>, <0 187 4>,
- <0 188 4>, <0 189 4>,
- <0 190 4>, <0 191 4>,
- <0 192 4>, <0 193 4>,
- <0 194 4>, <0 195 4>,
- <0 196 4>, <0 197 4>,
- <0 198 4>, <0 199 4>,
- <0 200 4>, <0 201 4>,
- <0 202 4>, <0 203 4>,
- <0 204 4>, <0 205 4>,
- <0 206 4>, <0 207 4>,
- <0 208 4>, <0 209 4>;
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>, <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>, <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 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>,
+ <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
};
dspi: spi@2100000 {
@@ -933,18 +933,18 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2100000 0x0 0x10000>;
- interrupts = <0 26 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
clock-names = "dspi";
spi-num-chipselects = <5>;
};
- esdhc: esdhc@2140000 {
+ esdhc: mmc@2140000 {
status = "disabled";
compatible = "fsl,ls2080a-esdhc", "fsl,esdhc";
reg = <0x0 0x2140000 0x0 0x10000>;
- interrupts = <0 28 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(2)>;
voltage-ranges = <1800 1800 3300 3300>;
@@ -956,7 +956,7 @@
gpio0: gpio@2300000 {
compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
- interrupts = <0 36 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
little-endian;
#gpio-cells = <2>;
@@ -967,7 +967,7 @@
gpio1: gpio@2310000 {
compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2310000 0x0 0x10000>;
- interrupts = <0 36 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
little-endian;
#gpio-cells = <2>;
@@ -978,7 +978,7 @@
gpio2: gpio@2320000 {
compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2320000 0x0 0x10000>;
- interrupts = <0 37 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
little-endian;
#gpio-cells = <2>;
@@ -989,7 +989,7 @@
gpio3: gpio@2330000 {
compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2330000 0x0 0x10000>;
- interrupts = <0 37 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
little-endian;
#gpio-cells = <2>;
@@ -1003,8 +1003,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2000000 0x0 0x10000>;
- interrupts = <0 34 0x4>; /* Level high type */
- clock-names = "i2c";
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
};
@@ -1015,8 +1015,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2010000 0x0 0x10000>;
- interrupts = <0 34 0x4>; /* Level high type */
- clock-names = "i2c";
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
};
@@ -1027,8 +1027,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2020000 0x0 0x10000>;
- interrupts = <0 35 0x4>; /* Level high type */
- clock-names = "i2c";
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
};
@@ -1039,8 +1039,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0 0x2030000 0x0 0x10000>;
- interrupts = <0 35 0x4>; /* Level high type */
- clock-names = "i2c";
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
};
@@ -1048,7 +1048,7 @@
ifc: memory-controller@2240000 {
compatible = "fsl,ifc";
reg = <0x0 0x2240000 0x0 0x20000>;
- interrupts = <0 21 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
little-endian;
#address-cells = <2>;
#size-cells = <1>;
@@ -1077,7 +1077,7 @@
pcie1: pcie@3400000 {
compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie";
reg-names = "regs", "config";
- interrupts = <0 108 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "intr";
#address-cells = <3>;
#size-cells = <2>;
@@ -1099,7 +1099,7 @@
pcie2: pcie@3500000 {
compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie";
reg-names = "regs", "config";
- interrupts = <0 113 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "intr";
#address-cells = <3>;
#size-cells = <2>;
@@ -1121,7 +1121,7 @@
pcie3: pcie@3600000 {
compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie";
reg-names = "regs", "config";
- interrupts = <0 118 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "intr";
#address-cells = <3>;
#size-cells = <2>;
@@ -1143,7 +1143,7 @@
pcie4: pcie@3700000 {
compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie";
reg-names = "regs", "config";
- interrupts = <0 123 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "intr";
#address-cells = <3>;
#size-cells = <2>;
@@ -1166,7 +1166,7 @@
status = "disabled";
compatible = "fsl,ls2080a-ahci";
reg = <0x0 0x3200000 0x0 0x10000>;
- interrupts = <0 133 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
dma-coherent;
@@ -1176,7 +1176,7 @@
status = "disabled";
compatible = "fsl,ls2080a-ahci";
reg = <0x0 0x3210000 0x0 0x10000>;
- interrupts = <0 136 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(4)>;
dma-coherent;
@@ -1192,7 +1192,7 @@
usb0: usb@3100000 {
compatible = "snps,dwc3";
reg = <0x0 0x3100000 0x0 0x10000>;
- interrupts = <0 80 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
snps,quirk-frame-length-adjustment = <0x20>;
snps,dis_rxdet_inp3_quirk;
@@ -1203,7 +1203,7 @@
usb1: usb@3110000 {
compatible = "snps,dwc3";
reg = <0x0 0x3110000 0x0 0x10000>;
- interrupts = <0 81 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
snps,quirk-frame-length-adjustment = <0x20>;
snps,dis_rxdet_inp3_quirk;
@@ -1215,7 +1215,7 @@
ccn@4000000 {
compatible = "arm,ccn-504";
reg = <0x0 0x04000000 0x0 0x01000000>;
- interrupts = <0 12 4>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
};
rcpm: power-controller@1e34040 {
@@ -1225,7 +1225,7 @@
little-endian;
};
- ftm_alarm0: timer@2800000 {
+ ftm_alarm0: rtc@2800000 {
compatible = "fsl,ls208xa-ftm-alarm";
reg = <0x0 0x2800000 0x0 0x10000>;
fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0>;
@@ -1236,14 +1236,14 @@
ddr1: memory-controller@1080000 {
compatible = "fsl,qoriq-memory-controller";
reg = <0x0 0x1080000 0x0 0x1000>;
- interrupts = <0 17 0x4>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
little-endian;
};
ddr2: memory-controller@1090000 {
compatible = "fsl,qoriq-memory-controller";
reg = <0x0 0x1090000 0x0 0x1000>;
- interrupts = <0 18 0x4>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
little-endian;
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
index 96055593204a..26c7ca31e22e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
@@ -449,7 +449,7 @@
};
thermal-zones {
- cluster6-7 {
+ cluster6-7-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 0>;
@@ -492,7 +492,7 @@
};
};
- ddr-cluster5 {
+ ddr-cluster5-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 1>;
@@ -512,7 +512,7 @@
};
};
- wriop {
+ wriop-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 2>;
@@ -532,7 +532,7 @@
};
};
- dce-qbman-hsio2 {
+ dce-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 3>;
@@ -552,7 +552,7 @@
};
};
- ccn-dpaa-tbu {
+ ccn-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 4>;
@@ -572,7 +572,7 @@
};
};
- cluster4-hsio3 {
+ cluster4-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 5>;
@@ -592,7 +592,7 @@
};
};
- cluster2-3 {
+ cluster2-3-thermal {
polling-delay-passive = <1000>;
polling-delay = <5000>;
thermal-sensors = <&tmu 6>;
@@ -745,7 +745,7 @@
#size-cells = <0>;
reg = <0x0 0x2000000 0x0 0x10000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "i2c";
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(16)>;
pinctrl-names = "default", "gpio";
@@ -761,7 +761,7 @@
#size-cells = <0>;
reg = <0x0 0x2010000 0x0 0x10000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "i2c";
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(16)>;
pinctrl-names = "default", "gpio";
@@ -777,7 +777,7 @@
#size-cells = <0>;
reg = <0x0 0x2020000 0x0 0x10000>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "i2c";
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(16)>;
pinctrl-names = "default", "gpio";
@@ -793,7 +793,7 @@
#size-cells = <0>;
reg = <0x0 0x2030000 0x0 0x10000>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "i2c";
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(16)>;
pinctrl-names = "default", "gpio";
@@ -809,7 +809,7 @@
#size-cells = <0>;
reg = <0x0 0x2040000 0x0 0x10000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "i2c";
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(16)>;
pinctrl-names = "default", "gpio";
@@ -825,7 +825,7 @@
#size-cells = <0>;
reg = <0x0 0x2050000 0x0 0x10000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "i2c";
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(16)>;
pinctrl-names = "default", "gpio";
@@ -841,7 +841,7 @@
#size-cells = <0>;
reg = <0x0 0x2060000 0x0 0x10000>;
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "i2c";
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(16)>;
pinctrl-names = "default", "gpio";
@@ -857,7 +857,7 @@
#size-cells = <0>;
reg = <0x0 0x2070000 0x0 0x10000>;
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "i2c";
+ clock-names = "ipg";
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(16)>;
pinctrl-names = "default", "gpio";
@@ -925,10 +925,10 @@
status = "disabled";
};
- esdhc0: esdhc@2140000 {
- compatible = "fsl,esdhc";
+ esdhc0: mmc@2140000 {
+ compatible = "fsl,ls2080a-esdhc", "fsl,esdhc";
reg = <0x0 0x2140000 0x0 0x10000>;
- interrupts = <0 28 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(2)>;
dma-coherent;
@@ -939,10 +939,10 @@
status = "disabled";
};
- esdhc1: esdhc@2150000 {
- compatible = "fsl,esdhc";
+ esdhc1: mmc@2150000 {
+ compatible = "fsl,ls2080a-esdhc", "fsl,esdhc";
reg = <0x0 0x2150000 0x0 0x10000>;
- interrupts = <0 63 0x4>; /* Level high type */
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
QORIQ_CLK_PLL_DIV(2)>;
dma-coherent;
@@ -1027,7 +1027,7 @@
};
gpio0: gpio@2300000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
@@ -1038,7 +1038,7 @@
};
gpio1: gpio@2310000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2310000 0x0 0x10000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
@@ -1049,7 +1049,7 @@
};
gpio2: gpio@2320000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2320000 0x0 0x10000>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
@@ -1060,7 +1060,7 @@
};
gpio3: gpio@2330000 {
- compatible = "fsl,qoriq-gpio";
+ compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2330000 0x0 0x10000>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
@@ -1085,7 +1085,7 @@
little-endian;
};
- ftm_alarm0: timer@2800000 {
+ ftm_alarm0: rtc@2800000 {
compatible = "fsl,lx2160a-ftm-alarm";
reg = <0x0 0x2800000 0x0 0x10000>;
fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0 0x0>;
@@ -1702,8 +1702,8 @@
pinmux_i2crv: pinmux@70010012c {
compatible = "pinctrl-single";
reg = <0x00000007 0x0010012c 0x0 0xc>;
- #address-cells = <2>;
- #size-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
pinctrl-single,bit-per-mux;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0x7>;
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi
index 897cbb7b6742..ff5df0fed9e9 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi
@@ -447,7 +447,6 @@ audio_subsys: bus@59000000 {
<&lsio_mu13 2 1>,
<&lsio_mu13 3 0>,
<&lsio_mu13 3 1>;
- memory-region = <&dsp_reserved>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-cm41.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-cm41.dtsi
new file mode 100644
index 000000000000..d715f2a6b037
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-cm41.dtsi
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ * Dong Aisheng <[email protected]>
+ */
+
+#include <dt-bindings/firmware/imx/rsrc.h>
+#include <dt-bindings/clock/imx8-lpcg.h>
+
+cm41_ipg_clk: clock-cm41-ipg {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <132000000>;
+ clock-output-names = "cm41_ipg_clk";
+};
+
+cm41_subsys: bus@38000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x38000000 0x0 0x38000000 0x4000000>;
+ interrupt-parent = <&cm41_intmux>;
+
+ cm41_i2c: i2c@3b230000 {
+ compatible = "fsl,imx8qxp-lpi2c", "fsl,imx7ulp-lpi2c";
+ reg = <0x3b230000 0x1000>;
+ interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cm41_i2c_lpcg IMX_LPCG_CLK_0>,
+ <&cm41_i2c_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_M4_1_I2C IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ power-domains = <&pd IMX_SC_R_M4_1_I2C>;
+ status = "disabled";
+ };
+
+ cm41_intmux: intmux@3b400000 {
+ compatible = "fsl,imx-intmux";
+ reg = <0x3b400000 0x1000>;
+ 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 39 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&cm41_ipg_clk>;
+ clock-names = "ipg";
+ power-domains = <&pd IMX_SC_R_M4_1_INTMUX>;
+ status = "disabled";
+ };
+
+ cm41_i2c_lpcg: clock-controller@3b630000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x3b630000 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&clk IMX_SC_R_M4_1_I2C IMX_SC_PM_CLK_PER>,
+ <&cm41_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "cm41_lpcg_i2c_clk",
+ "cm41_lpcg_i2c_ipg_clk";
+ power-domains = <&pd IMX_SC_R_M4_1_I2C>;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
index 4aaf5a0c1ed8..a4a10ce03bfe 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
@@ -28,6 +28,13 @@ conn_ipg_clk: clock-conn-ipg {
clock-output-names = "conn_ipg_clk";
};
+conn_bch_clk: clock-conn-bch {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <400000000>;
+ clock-output-names = "conn_bch_clk";
+};
+
conn_subsys: bus@5b000000 {
compatible = "simple-bus";
#address-cells = <1>;
@@ -302,4 +309,66 @@ conn_subsys: bus@5b000000 {
"usb3_aclk";
power-domains = <&pd IMX_SC_R_USB_2_PHY>;
};
+
+ rawnand_0_lpcg: clock-controller@5b290000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5b290000 0x4>;
+ #clock-cells = <1>;
+ clocks = <&clk IMX_SC_R_NAND IMX_SC_PM_CLK_PER>,
+ <&clk IMX_SC_R_NAND IMX_SC_PM_CLK_MST_BUS>,
+ <&conn_axi_clk>,
+ <&conn_axi_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_1>,
+ <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_5>;
+ clock-output-names = "gpmi_bch",
+ "gpmi_io",
+ "gpmi_apb",
+ "gpmi_bch_apb";
+ power-domains = <&pd IMX_SC_R_NAND>;
+ };
+
+ rawnand_4_lpcg: clock-controller@5b290004 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5b290004 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&conn_axi_clk>;
+ clock-indices = <IMX_LPCG_CLK_4>;
+ clock-output-names = "apbhdma_hclk";
+ power-domains = <&pd IMX_SC_R_NAND>;
+ };
+
+ dma_apbh: dma-controller@5b810000 {
+ compatible = "fsl,imx8qxp-dma-apbh", "fsl,imx28-dma-apbh";
+ reg = <0x5b810000 0x2000>;
+ interrupts = <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ dma-channels = <4>;
+ clocks = <&rawnand_4_lpcg IMX_LPCG_CLK_0>;
+ power-domains = <&pd IMX_SC_R_NAND>;
+ };
+
+ gpmi: nand-controller@5b812000{
+ compatible = "fsl,imx8qxp-gpmi-nand";
+ reg = <0x5b812000 0x2000>, <0x5b814000 0x2000>;
+ reg-names = "gpmi-nand", "bch";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "bch";
+ clocks = <&rawnand_0_lpcg IMX_LPCG_CLK_1>,
+ <&rawnand_0_lpcg IMX_LPCG_CLK_4>,
+ <&rawnand_0_lpcg IMX_LPCG_CLK_0>,
+ <&rawnand_0_lpcg IMX_LPCG_CLK_5>;
+ clock-names = "gpmi_io", "gpmi_apb",
+ "gpmi_bch", "gpmi_bch_apb";
+ dmas = <&dma_apbh 0>;
+ dma-names = "rx-tx";
+ power-domains = <&pd IMX_SC_R_NAND>;
+ assigned-clocks = <&clk IMX_SC_R_NAND IMX_SC_PM_CLK_MST_BUS>;
+ assigned-clock-rates = <50000000>;
+ status = "disabled";
+ };
};
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
index 2412ab145c06..1a74ac3ee4ee 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
@@ -24,6 +24,19 @@
stdout-path = &lpuart0;
};
+ imx8dxl-cm4 {
+ compatible = "fsl,imx8qxp-cm4";
+ clocks = <&clk_dummy>;
+ 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,resource-id = <IMX_SC_R_M4_0_PID0>;
+ fsl,entry-address = <0x34fe0000>;
+ };
+
+
memory@80000000 {
device_type = "memory";
reg = <0x00000000 0x80000000 0 0x40000000>;
@@ -51,6 +64,37 @@
alloc-ranges = <0 0x98000000 0 0x14000000>;
linux,cma-default;
};
+
+ vdev0vring0: memory0@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-rsc-table@900ff000 {
+ reg = <0 0x900ff000 0 0x1000>;
+ no-map;
+ };
+
+ vdevbuffer: memory-vdevbuffer@90400000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90400000 0 0x100000>;
+ no-map;
+ };
};
m2_uart1_sel: regulator-m2uart1sel {
@@ -137,6 +181,76 @@
enable-active-high;
regulator-always-on;
};
+
+ bt_sco_codec: audio-codec-bt {
+ compatible = "linux,bt-sco";
+ #sound-dai-cells = <1>;
+ };
+
+ 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 = <&sai0>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <16>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&bt_sco_codec 1>;
+ };
+ };
+
+ sound-wm8960-1 {
+ compatible = "fsl,imx-audio-wm8960";
+ model = "wm8960-audio";
+ audio-cpu = <&sai1>;
+ audio-codec = <&wm8960_1>;
+ audio-asrc = <&asrc0>;
+ audio-routing = "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT1", "Mic Jack",
+ "Mic Jack", "MICB";
+ };
+
+ sound-wm8960-2 {
+ compatible = "fsl,imx-audio-wm8960";
+ model = "wm8960-audio-2";
+ audio-cpu = <&sai2>;
+ audio-codec = <&wm8960_2>;
+ audio-routing = "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT1", "Mic Jack",
+ "Mic Jack", "MICB";
+ };
+
+ sound-wm8960-3 {
+ compatible = "fsl,imx-audio-wm8960";
+ model = "wm8960-audio-3";
+ audio-cpu = <&sai3>;
+ audio-codec = <&wm8960_3>;
+ audio-routing = "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT1", "Mic Jack",
+ "Mic Jack", "MICB";
+ };
};
&adc0 {
@@ -144,6 +258,11 @@
status = "okay";
};
+&asrc0 {
+ fsl,asrc-rate = <48000>;
+ status = "okay";
+};
+
&eqos {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_eqos>;
@@ -271,6 +390,78 @@
};
};
+ i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1>;
+
+ wm8960_1: audio-codec@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ clocks = <&mclkout1_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>,
+ <&mclkout1_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <786432000>,
+ <49152000>,
+ <12288000>,
+ <12288000>;
+ wlf,shared-lrclk;
+ wlf,hp-cfg = <2 2 3>;
+ wlf,gpio-cfg = <1 3>;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x2>;
+
+ wm8960_2: audio-codec@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ clocks = <&mclkout1_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>,
+ <&mclkout1_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <786432000>,
+ <49152000>,
+ <12288000>,
+ <12288000>;
+ wlf,shared-lrclk;
+ wlf,hp-cfg = <2 2 3>;
+ wlf,gpio-cfg = <1 3>;
+ };
+ };
+
+ i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x3>;
+
+ wm8960_3: audio-codec@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ clocks = <&mclkout1_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>,
+ <&mclkout1_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <786432000>,
+ <49152000>,
+ <12288000>,
+ <12288000>;
+ wlf,shared-lrclk;
+ wlf,hp-cfg = <2 2 3>;
+ wlf,gpio-cfg = <1 3>;
+ };
+ };
+
i2c@4 {
#address-cells = <1>;
#size-cells = <0>;
@@ -358,6 +549,10 @@
status = "okay";
};
+&lsio_mu5 {
+ status = "okay";
+};
+
&flexcan2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan2>;
@@ -390,6 +585,53 @@
status = "okay";
};
+&sai0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai0>;
+ #sound-dai-cells = <0>;
+ 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>;
+ status = "okay";
+};
+
+&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>;
+ status = "okay";
+};
+
+&sai2 {
+ 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>,
+ <&sai2_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2>;
+ fsl,sai-asynchronous;
+ status = "okay";
+};
+
+&sai3 {
+ 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>,
+ <&sai3_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai3>;
+ fsl,sai-asynchronous;
+ status = "okay";
+};
+
&thermal_zones {
pmic-thermal {
polling-delay-passive = <250>;
@@ -632,6 +874,41 @@
>;
};
+ pinctrl_sai0: sai0grp {
+ fsl,pins = <
+ IMX8DXL_SPI0_CS0_ADMA_SAI0_RXD 0x06000060
+ IMX8DXL_SPI0_CS1_ADMA_SAI0_RXC 0x06000040
+ IMX8DXL_SPI0_SCK_ADMA_SAI0_TXC 0x06000060
+ IMX8DXL_SPI0_SDI_ADMA_SAI0_TXD 0x06000060
+ IMX8DXL_SPI0_SDO_ADMA_SAI0_TXFS 0x06000040
+ >;
+ };
+
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ IMX8DXL_FLEXCAN0_RX_ADMA_SAI1_TXC 0x06000040
+ IMX8DXL_FLEXCAN0_TX_ADMA_SAI1_TXFS 0x06000040
+ IMX8DXL_FLEXCAN1_RX_ADMA_SAI1_TXD 0x06000060
+ IMX8DXL_FLEXCAN1_TX_ADMA_SAI1_RXD 0x06000060
+ >;
+ };
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ IMX8DXL_SNVS_TAMPER_OUT3_ADMA_SAI2_RXC 0x06000040
+ IMX8DXL_SNVS_TAMPER_IN0_ADMA_SAI2_RXFS 0x06000040
+ IMX8DXL_SNVS_TAMPER_OUT4_ADMA_SAI2_RXD 0x06000060
+ >;
+ };
+
+ pinctrl_sai3: sai3grp {
+ fsl,pins = <
+ IMX8DXL_SNVS_TAMPER_IN1_ADMA_SAI3_RXC 0x06000040
+ IMX8DXL_SNVS_TAMPER_IN3_ADMA_SAI3_RXFS 0x06000040
+ IMX8DXL_SNVS_TAMPER_IN2_ADMA_SAI3_RXD 0x06000060
+ >;
+ };
+
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
IMX8DXL_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
index 5d012c95222f..72434529f78e 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
@@ -3,6 +3,63 @@
* Copyright 2019~2020, 2022 NXP
*/
+/delete-node/ &asrc1;
+/delete-node/ &asrc1_lpcg;
+/delete-node/ &adc1;
+/delete-node/ &adc1_lpcg;
+/delete-node/ &amix;
+/delete-node/ &amix_lpcg;
+/delete-node/ &edma1;
+/delete-node/ &esai0;
+/delete-node/ &esai0_lpcg;
+/delete-node/ &sai4;
+/delete-node/ &sai4_lpcg;
+/delete-node/ &sai5;
+/delete-node/ &sai5_lpcg;
+
+&acm {
+ compatible = "fsl,imx8dxl-acm";
+ power-domains = <&pd IMX_SC_R_AUDIO_CLK_0>,
+ <&pd IMX_SC_R_AUDIO_CLK_1>,
+ <&pd IMX_SC_R_MCLK_OUT_0>,
+ <&pd IMX_SC_R_MCLK_OUT_1>,
+ <&pd IMX_SC_R_AUDIO_PLL_0>,
+ <&pd IMX_SC_R_AUDIO_PLL_1>,
+ <&pd IMX_SC_R_ASRC_0>,
+ <&pd IMX_SC_R_SAI_0>,
+ <&pd IMX_SC_R_SAI_1>,
+ <&pd IMX_SC_R_SAI_2>,
+ <&pd IMX_SC_R_SAI_3>,
+ <&pd IMX_SC_R_SPDIF_0>,
+ <&pd IMX_SC_R_MQS_0>;
+ clocks = <&aud_rec0_lpcg IMX_LPCG_CLK_0>,
+ <&aud_rec1_lpcg IMX_LPCG_CLK_0>,
+ <&aud_pll_div0_lpcg IMX_LPCG_CLK_0>,
+ <&aud_pll_div1_lpcg IMX_LPCG_CLK_0>,
+ <&clk_ext_aud_mclk0>,
+ <&clk_ext_aud_mclk1>,
+ <&clk_spdif0_rx>,
+ <&clk_sai0_rx_bclk>,
+ <&clk_sai0_tx_bclk>,
+ <&clk_sai1_rx_bclk>,
+ <&clk_sai1_tx_bclk>,
+ <&clk_sai2_rx_bclk>,
+ <&clk_sai3_rx_bclk>;
+ clock-names = "aud_rec_clk0_lpcg_clk",
+ "aud_rec_clk1_lpcg_clk",
+ "aud_pll_div_clk0_lpcg_clk",
+ "aud_pll_div_clk1_lpcg_clk",
+ "ext_aud_mclk0",
+ "ext_aud_mclk1",
+ "spdif0_rx",
+ "sai0_rx_bclk",
+ "sai0_tx_bclk",
+ "sai1_rx_bclk",
+ "sai1_tx_bclk",
+ "sai2_rx_bclk",
+ "sai3_rx_bclk";
+};
+
&audio_ipg_clk {
clock-frequency = <160000000>;
};
@@ -177,3 +234,24 @@
&lpspi3 {
interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
};
+
+&sai0 {
+ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&sai1 {
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&sai2 {
+ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&sai3 {
+ interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&spdif0 {
+ interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>, /* rx */
+ <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>; /* tx */
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
index 6d13e4fafb76..1e02b04494e9 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
@@ -108,6 +108,13 @@
};
+&dma_apbh {
+ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+};
+
&enet0_lpcg {
clocks = <&conn_enet0_root_clk>,
<&conn_enet0_root_clk>,
@@ -127,6 +134,10 @@
assigned-clock-rates = <125000000>;
};
+&gpmi {
+ interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+};
+
&usdhc1 {
compatible = "fsl,imx8dxl-usdhc", "fsl,imx8qxp-usdhc";
interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
index 90d1901df2b1..930e14fec423 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
@@ -400,7 +400,7 @@
pinctrl-0 = <&pinctrl_typec1>;
reg = <0x50>;
interrupt-parent = <&gpio2>;
- interrupts = <11 8>;
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
status = "okay";
typec1_con: connector {
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-iot-gateway.dts b/arch/arm64/boot/dts/freescale/imx8mm-iot-gateway.dts
new file mode 100644
index 000000000000..370558a8ba46
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-iot-gateway.dts
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+//
+// Copyright 2020 CompuLab
+
+#include "imx8mm-ucm-som.dtsi"
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+/ {
+ model = "CompuLab i.MX8MM IoT Gateway";
+ compatible = "compulab,imx8mm-iot-gateway", "compulab,imx8mm-ucm-som", "fsl,imx8mm";
+
+ regulator-usbhub-ena {
+ compatible = "regulator-fixed";
+ regulator-name = "usbhub_ena";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio4 28 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ regulator-usbhub-rst {
+ compatible = "regulator-fixed";
+ regulator-name = "usbhub_rst";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ regulator-uart1-mode {
+ compatible = "regulator-fixed";
+ regulator-name = "uart1_mode";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio4 26 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ regulator-uart1-duplex {
+ compatible = "regulator-fixed";
+ regulator-name = "uart1_duplex";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ regulator-uart1-shdn {
+ compatible = "regulator-fixed";
+ regulator-name = "uart1_shdn";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio5 5 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ regulator-uart1-trmen {
+ compatible = "regulator-fixed";
+ regulator-name = "uart1_trmen";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio4 25 GPIO_ACTIVE_LOW>;
+ regulator-always-on;
+ };
+
+ regulator-usdhc2-v {
+ compatible = "regulator-fixed";
+ regulator-name = "usdhc2_v";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ regulator-mpcie2-rst {
+ compatible = "regulator-fixed";
+ regulator-name = "mpcie2_rst";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ regulator-mpcie2lora-dis {
+ compatible = "regulator-fixed";
+ regulator-name = "mpcie2lora_dis";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ pcie0_refclk: clock-pcie0-refclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ eeprom@54 {
+ compatible = "atmel,24c08";
+ reg = <0x54>;
+ pagesize = <16>;
+ };
+};
+
+&ecspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1 &pinctrl_ecspi1_cs>;
+ cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&pcie_phy {
+ fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
+ fsl,tx-deemph-gen1 = <0x2d>;
+ fsl,tx-deemph-gen2 = <0xf>;
+ fsl,clkreq-unsupported;
+ clocks = <&pcie0_refclk>;
+ clock-names = "ref";
+ status = "okay";
+};
+
+&pcie0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie0>;
+ reset-gpio = <&gpio3 20 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&usbotg1 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usbotg2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dr_mode = "host";
+ usb-role-switch;
+ status = "okay";
+
+ usbhub@1 {
+ compatible = "usb424,9514";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb9514>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet: ethernet@1 {
+ compatible = "usb424,ec00";
+ reg = <1>;
+ };
+ };
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <4>;
+ mmc-ddr-1_8v;
+ non-removable;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* mPCIe2 */
+ MX8MM_IOMUXC_SAI5_RXD0_GPIO3_IO21 0x140
+ MX8MM_IOMUXC_SAI5_RXD1_GPIO3_IO22 0x140
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK 0x82
+ MX8MM_IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI 0x82
+ MX8MM_IOMUXC_ECSPI1_MISO_ECSPI1_MISO 0x82
+ >;
+ };
+
+ pinctrl_ecspi1_cs: ecspi1csgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x40000
+ >;
+ };
+
+ pinctrl_pcie0: pcie0grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXC_GPIO3_IO20 0x140
+ >;
+ };
+
+ pinctrl_usb9514: usb9514grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x140 /* USB_PS_EN */
+ MX8MM_IOMUXC_SAI5_RXD3_GPIO3_IO24 0x140 /* HUB_RSTn */
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs232.dtso b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs232.dtso
new file mode 100644
index 000000000000..bf3e04651ba0
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs232.dtso
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2021 PHYTEC Messtechnik GmbH
+ * Author: Jens Lang <[email protected]>
+ *
+ * Tauri-L 2 x RS232:
+ * - GPIO3_20 uart4_rs485_en needs to be driven low (inactive)
+ */
+
+#include <dt-bindings/clock/imx8mm-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+ compatible = "phytec,imx8mm-phygate-tauri-l";
+
+};
+
+&gpio3 {
+ pinctrl-names = "default";
+ pinctrcl-0 = <&pinctrl_gpio3_hog>;
+
+ uart4_rs485_en {
+ gpio-hog;
+ gpios = <20 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "uart4_rs485_en";
+ };
+};
+
+/* UART2 - RS232 */
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART2>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ status = "okay";
+};
+
+/* UART4 - RS232 */
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART4>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_gpio3_hog: gpio3hoggrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXC_GPIO3_IO20 0x49
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x00
+ MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x00
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART4_RXD_UART4_DCE_RX 0x49
+ MX8MM_IOMUXC_UART4_TXD_UART4_DCE_TX 0x49
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs485.dtso b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs485.dtso
new file mode 100644
index 000000000000..f4448cde0407
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs485.dtso
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2021 PHYTEC Messtechnik GmbH
+ * Author: Jens Lang <[email protected]>
+ *
+ * Tauri-L RS232 + RS485:
+ * - GPIO3_20 uart4_rs485_en needs to be driven high (active)
+ * - GPIO3_25 RS485_DE Driver enable
+ */
+
+#include <dt-bindings/clock/imx8mm-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+ compatible = "phytec,imx8mm-phygate-tauri-l";
+
+};
+
+&gpio3 {
+ pinctrl-names = "default";
+ pinctrcl-0 = <&pinctrl_gpio3_hog>;
+
+ uart4_rs485_en {
+ gpio-hog;
+ gpios = <20 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "uart4_rs485_en";
+ };
+};
+
+/* UART2 - RS232 */
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART2>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ status = "okay";
+};
+
+/* UART4 - RS485 */
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART4>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ rts-gpios = <&gpio3 25 GPIO_ACTIVE_HIGH>;
+ linux,rs485-enabled-at-boot-time;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_gpio3_hog: gpio3hoggrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXC_GPIO3_IO20 0x49
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x00
+ MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x00
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART4_RXD_UART4_DCE_RX 0x49
+ MX8MM_IOMUXC_UART4_TXD_UART4_DCE_TX 0x49
+ MX8MM_IOMUXC_SAI5_MCLK_GPIO3_IO25 0x49
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rts-cts.dtso b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rts-cts.dtso
new file mode 100644
index 000000000000..107f743fbb1c
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rts-cts.dtso
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2023 PHYTEC Messtechnik GmbH
+ * Author: Jens Lang <[email protected]>
+ *
+ * Tauri-L RS232 with RTS/CTS hardware flow control:
+ * - UART4_TX becomes RTS
+ * - UART4_RX becomes CTS
+ */
+
+#include <dt-bindings/clock/imx8mm-clock.h>
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+
+&{/} {
+ compatible = "phytec,imx8mm-phygate-tauri-l";
+
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART2>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x00
+ MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x00
+ MX8MM_IOMUXC_UART4_RXD_UART2_DCE_CTS_B 0x00
+ MX8MM_IOMUXC_UART4_TXD_UART2_DCE_RTS_B 0x00
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts
index 27a902569e2a..ba6ce3c7f477 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts
@@ -7,6 +7,7 @@
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/leds/common.h>
+#include <dt-bindings/phy/phy-imx8-pcie.h>
#include "imx8mm-phycore-som.dtsi"
/ {
@@ -185,6 +186,15 @@
status = "okay";
};
+&pcie_phy {
+ clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
+ fsl,clkreq-unsupported;
+ fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_OUTPUT>;
+ fsl,tx-deemph-gen1 = <0x2d>;
+ fsl,tx-deemph-gen2 = <0xf>;
+ status = "okay";
+};
+
&pwm1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm1>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi
index 8c0c6e715924..ca0205b9019e 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi
@@ -62,11 +62,15 @@
flash0: flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
- #address-cells = <1>;
- #size-cells = <1>;
spi-max-frequency = <84000000>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-ucm-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-ucm-som.dtsi
new file mode 100644
index 000000000000..d3b21203c5f4
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-ucm-som.dtsi
@@ -0,0 +1,679 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+//
+// Copyright 2018 CompuLab
+
+/dts-v1/;
+
+#include "imx8mm.dtsi"
+#include <dt-bindings/leds/common.h>
+
+/ {
+ aliases {
+ rtc0 = &rtc_i2c;
+ rtc1 = &snvs_rtc;
+ mmc0 = &usdhc3;
+ };
+
+ chosen {
+ stdout-path = &uart3;
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 3000000 0>;
+ brightness-levels = <0 255>;
+ num-interpolated-steps = <255>;
+ default-brightness-level = <222>;
+ status = "okay";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_led>;
+
+ heartbeat-led {
+ function = LED_FUNCTION_STATUS;
+ gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ pmic_osc: clock-pmic {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "pmic_osc";
+ };
+
+ wlreg_on: regulator-wlreg-on {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ regulator-always-on;
+ status = "okay";
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2-vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ startup-delay-us = <100>;
+ off-on-delay-us = <12000>;
+ };
+
+ regulator-usdhc3rst {
+ compatible = "regulator-fixed";
+ regulator-name = "usdhc3_rst";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+ regulator-always-on;
+ enable-active-high;
+ };
+
+ regulator-fec1rst {
+ compatible = "regulator-fixed";
+ regulator-name = "fec1_rst";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ regulator-always-on;
+ enable-active-high;
+ startup-delay-us = <500>;
+ regulator-boot-on;
+ };
+};
+
+&A53_0 {
+ arm-supply = <&buck2>;
+};
+
+&cpu_alert0 {
+ temperature = <105000>;
+};
+
+&cpu_crit0 {
+ temperature = <115000>;
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ pmic@4b {
+ reg = <0x4b>;
+ compatible = "rohm,bd71837";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pmic>;
+ #clock-cells = <0>;
+ clocks = <&pmic_osc>;
+ clock-names = "osc";
+ clock-output-names = "pmic_clk";
+ interrupt-parent = <&gpio1>;
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ rohm,reset-snvs-powered;
+
+ regulators {
+ buck1: BUCK1 {
+ regulator-name = "buck1";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ };
+
+ buck2: BUCK2 {
+ regulator-name = "buck2";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ rohm,dvs-run-voltage = <1000000>;
+ rohm,dvs-idle-voltage = <900000>;
+ };
+
+ buck3: BUCK3 {
+ regulator-name = "buck3";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck4: BUCK4 {
+ regulator-name = "buck4";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck5: BUCK5 {
+ regulator-name = "buck5";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck6: BUCK6 {
+ regulator-name = "buck6";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck7: BUCK7 {
+ regulator-name = "buck7";
+ regulator-min-microvolt = <1605000>;
+ regulator-max-microvolt = <1995000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck8: BUCK8 {
+ regulator-name = "buck8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1: LDO1 {
+ regulator-name = "ldo1";
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2: LDO2 {
+ regulator-name = "ldo2";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3: LDO3 {
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo4: LDO4 {
+ regulator-name = "ldo4";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo5: LDO5 {
+ regulator-name = "ldo5";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo6: LDO6 {
+ regulator-name = "ldo6";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo7: LDO7 {
+ regulator-name = "ldo7";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c08";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+
+ rtc_i2c: rtc@69 {
+ compatible = "abracon,ab1805";
+ reg = <0x69>;
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "disabled";
+};
+
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_backlight>;
+ status = "okay";
+};
+
+&sai2 {
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2>;
+ assigned-clocks = <&clk IMX8MM_CLK_SAI2>;
+ assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <49152000>;
+ clocks = <&clk IMX8MM_CLK_SAI2_IPG>, <&clk IMX8MM_CLK_DUMMY>,
+ <&clk IMX8MM_CLK_SAI2_ROOT>, <&clk IMX8MM_CLK_DUMMY>,
+ <&clk IMX8MM_CLK_DUMMY>, <&clk IMX8MM_AUDIO_PLL1_OUT>,
+ <&clk IMX8MM_AUDIO_PLL2_OUT>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k", "pll11k";
+ fsl,sai-asynchronous;
+ status = "okay";
+};
+
+&snvs {
+ status = "okay";
+};
+
+&snvs_pwrkey {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART1>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ status = "disabled";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART2>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ status = "disabled";
+};
+
+&uart3 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ status = "okay";
+};
+
+&uart4 { /* bluetooth */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART4>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ uart-has-rtscts;
+ status = "disabled";
+
+ bluetooth {
+ compatible = "brcm,bcm4330-bt";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_bt>;
+ max-speed = <3000000>;
+ device-wakeup-gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>;
+ host-wakeup-gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&usbotg1 {
+ dr_mode = "otg";
+ hnp-disable;
+ srp-disable;
+ disable-over-current;
+ status = "disabled";
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ hnp-disable;
+ srp-disable;
+ disable-over-current;
+ status = "disabled";
+};
+
+&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>;
+ non-removable;
+};
+
+&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_LOW>;
+ wp-gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+ no-1-8-v;
+ bus-width = <4>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ no-1-8-v;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_1>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x19
+ MX8MM_IOMUXC_NAND_READY_B_GPIO3_IO16 0x190
+ >;
+ };
+
+ pinctrl_bt: bt0grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_DATA4_GPIO2_IO6 0x19 /* BT_REG_ON */
+ MX8MM_IOMUXC_SD1_DATA5_GPIO2_IO7 0x19 /* BT_DEV_WU */
+ MX8MM_IOMUXC_SD1_DATA6_GPIO2_IO8 0x19 /* BT_HST_WU */
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO 0x3
+ MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ >;
+ };
+
+ pinctrl_gpio_led: gpioledgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x19
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
+ >;
+ };
+
+ pinctrl_pwm_backlight: pwmbacklightgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO13_PWM2_OUT 0x03
+ >;
+ };
+
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI2_MCLK_SAI2_MCLK 0xd6
+ MX8MM_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC 0xd6
+ MX8MM_IOMUXC_SAI2_RXFS_SAI2_RX_SYNC 0xd6
+ MX8MM_IOMUXC_SAI2_TXC_SAI2_TX_BCLK 0xd6
+ MX8MM_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0 0xd6
+ MX8MM_IOMUXC_SAI2_RXD0_SAI2_RX_DATA0 0xd6
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140
+ MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
+ MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART3_RXD_UART3_DCE_RX 0x49
+ MX8MM_IOMUXC_UART3_TXD_UART3_DCE_TX 0x49
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI2_MISO_UART4_DCE_CTS_B 0x140
+ MX8MM_IOMUXC_ECSPI2_MOSI_UART4_DCE_TX 0x140
+ MX8MM_IOMUXC_ECSPI2_SS0_UART4_DCE_RTS_B 0x140
+ MX8MM_IOMUXC_ECSPI2_SCLK_UART4_DCE_RX 0x140
+ >;
+ };
+
+ pinctrl_usdhc1_gpio: usdhc1grpgpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_RESET_B_GPIO2_IO10 0x41
+ >;
+ };
+
+ 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
+ MX8MM_IOMUXC_GPIO1_IO03_USDHC1_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhzgrp {
+ 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
+ MX8MM_IOMUXC_GPIO1_IO03_USDHC1_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhzgrp {
+ 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
+ MX8MM_IOMUXC_GPIO1_IO03_USDHC1_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2grpgpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x41
+ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41
+ MX8MM_IOMUXC_SD2_WP_GPIO2_IO20 0x00
+ >;
+ };
+
+ 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
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x194
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d4
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d4
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d4
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x196
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d6
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d6
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d6
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x40000190
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d0
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d0
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d0
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d0
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d0
+ MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d0
+ MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d0
+ MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d0
+ MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d0
+ MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x190
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp100mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x40000194
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d4
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d4
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d4
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d4
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d4
+ MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d4
+ MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d4
+ MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d4
+ MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d4
+ MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x194
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp200mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x40000196
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d6
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d6
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d6
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d6
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d6
+ MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d6
+ MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d6
+ MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d6
+ MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d6
+ MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x196
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
index de7f67a4ff2a..36803b038cd5 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
@@ -5,6 +5,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/leds/common.h>
#include <dt-bindings/net/ti-dp83867.h>
/ {
@@ -113,6 +114,25 @@
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
rx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_AMBER>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
};
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
index 35ae0faa815b..136cb30df03a 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
@@ -364,8 +364,6 @@
interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
index c11260c26d0b..1d56f2a6c06a 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
@@ -314,8 +314,6 @@
interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
index db1737bf637d..45470160f98f 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
@@ -280,8 +280,6 @@
interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
index 05489a31e7fd..ef951bc9f0dd 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
@@ -330,8 +330,6 @@
interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
index 98544741ce17..5fa395914191 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
@@ -228,15 +228,16 @@
pinctrl-0 = <&pinctrl_ecspi2>;
};
-/* Verdin CAN_1 (On-module) */
+/* On-module SPI */
&ecspi3 {
#address-cells = <1>;
#size-cells = <0>;
- cs-gpios = <&gpio5 25 GPIO_ACTIVE_LOW>;
+ cs-gpios = <&gpio5 25 GPIO_ACTIVE_LOW>, <&gpio4 19 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ecspi3>;
+ pinctrl-0 = <&pinctrl_ecspi3>, <&pinctrl_tpm_spi_cs>;
status = "okay";
+ /* Verdin CAN_1 */
can1: can@0 {
compatible = "microchip,mcp251xfd";
clocks = <&clk40m>;
@@ -246,6 +247,12 @@
reg = <0>;
spi-max-frequency = <8500000>;
};
+
+ verdin_som_tpm: tpm@1 {
+ compatible = "atmel,attpm20p", "tcg,tpm_tis-spi";
+ reg = <0x1>;
+ spi-max-frequency = <36000000>;
+ };
};
/* Verdin ETH_1 (On-module PHY) */
@@ -548,7 +555,7 @@
/* Verdin I2C_2_DSI */
&i2c2 {
- clock-frequency = <10000>;
+ clock-frequency = <400000>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
pinctrl-1 = <&pinctrl_i2c2_gpio>;
@@ -808,8 +815,7 @@
pinctrl-0 = <&pinctrl_gpio1>, <&pinctrl_gpio2>,
<&pinctrl_gpio3>, <&pinctrl_gpio4>,
<&pinctrl_gpio7>, <&pinctrl_gpio8>,
- <&pinctrl_gpio_hog1>, <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>,
- <&pinctrl_pmic_tpm_ena>;
+ <&pinctrl_gpio_hog1>, <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>;
pinctrl_can1_int: can1intgrp {
fsl,pins =
@@ -1111,7 +1117,7 @@
};
/* control signal for optional ATTPM20P or SE050 */
- pinctrl_pmic_tpm_ena: pmictpmenagrp {
+ pinctrl_tpm_spi_cs: tpmspicsgrp {
fsl,pins =
<MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19 0x106>; /* PMIC_TPM_ENA */
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi
index fb24b9aa1b93..e68a3fd73e17 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi
@@ -60,11 +60,15 @@
flash0: flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
- #address-cells = <1>;
- #size-cells = <1>;
spi-max-frequency = <84000000>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
index 0b1fa04f1d67..72004ab6bda5 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
@@ -312,8 +312,6 @@
interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts b/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts
index e5d3901f2913..17e2c19d8455 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts
@@ -302,10 +302,18 @@
adv_bridge: hdmi@3d {
compatible = "adi,adv7535";
- reg = <0x3d>, <0x3c>, <0x3e>, <0x3f>;
- reg-names = "main", "cec", "edid", "packet";
+ reg = <0x3d>;
+ reg-names = "main";
+ interrupt-parent = <&gpio4>;
+ interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
adi,dsi-lanes = <4>;
#sound-dai-cells = <0>;
+ avdd-supply = <&buck5>;
+ dvdd-supply = <&buck5>;
+ pvdd-supply = <&buck5>;
+ a2vdd-supply = <&buck5>;
+ v1p2-supply = <&buck5>;
+ v3p3-supply = <&buck4>;
ports {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-beacon-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-beacon-som.dtsi
index 8be251b69378..15f7ab58db36 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-beacon-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-beacon-som.dtsi
@@ -71,7 +71,6 @@
mtl_rx_setup: rx-queues-config {
snps,rx-queues-to-use = <5>;
- snps,rx-sched-sp;
queue0 {
snps,dcb-algorithm;
@@ -106,7 +105,6 @@
mtl_tx_setup: tx-queues-config {
snps,tx-queues-to-use = <5>;
- snps,tx-sched-sp;
queue0 {
snps,dcb-algorithm;
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts b/arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts
index 9b8f97a84e61..af02af9e5334 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts
@@ -20,6 +20,18 @@
stdout-path = &uart2;
};
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ label = "hdmi";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_out>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -94,6 +106,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";
@@ -239,6 +273,10 @@
status = "okay";
};
+&lcdif3 {
+ status = "okay";
+};
+
&snvs_pwrkey {
status = "okay";
};
@@ -356,6 +394,15 @@
>;
};
+ pinctrl_hdmi: hdmigrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_HDMI_DDC_SCL__HDMIMIX_HDMI_SCL 0x1c3
+ MX8MP_IOMUXC_HDMI_DDC_SDA__HDMIMIX_HDMI_SDA 0x1c3
+ MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x19
+ MX8MP_IOMUXC_HDMI_CEC__HDMIMIX_HDMI_CEC 0x19
+ >;
+ };
+
pinctrl_i2c1: i2c1grp {
fsl,pins = <
MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x400001c2
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts
index 3b1c940860e0..ebdf13e97b4e 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts
@@ -69,6 +69,18 @@
};
};
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ label = "X38";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_out>;
+ };
+ };
+ };
+
led {
compatible = "gpio-leds";
@@ -184,6 +196,33 @@
status = "okay";
};
+&hdmi_pvi {
+ status = "okay";
+};
+
+&hdmi_tx {
+ ddc-i2c-bus = <&i2c5>;
+ 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";
+};
+
+&lcdif3 {
+ status = "okay";
+};
+
&pcie_phy {
clock-names = "ref";
clocks = <&hsio_blk_ctrl>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts
index ac7ec7533a3c..ef012e8365b1 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts
@@ -75,6 +75,18 @@
};
};
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ label = "X28";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_out>;
+ };
+ };
+ };
+
led {
compatible = "gpio-leds";
@@ -248,6 +260,33 @@
status = "okay";
};
+&hdmi_pvi {
+ status = "okay";
+};
+
+&hdmi_tx {
+ ddc-i2c-bus = <&i2cmuxed1>;
+ 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";
+};
+
+&lcdif3 {
+ status = "okay";
+};
+
&pcie_phy {
clocks = <&pcieclk 1>;
clock-names = "ref";
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi
index f5115f9e8c47..a90e28c07e3f 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi
@@ -78,6 +78,11 @@
cpu-supply = <&buck2>;
};
+&audio_blk_ctrl {
+ assigned-clocks = <&clk IMX8MP_AUDIO_PLL1>;
+ assigned-clock-rates = <393216000>;
+};
+
&ecspi1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi1>;
@@ -105,14 +110,14 @@
#size-cells = <0>;
/* Up to one of these two PHYs may be populated. */
- ethphy0f: ethernet-phy@0 { /* SMSC LAN8740Ai */
+ ethphy0f: ethernet-phy@1 { /* SMSC LAN8740Ai */
compatible = "ethernet-phy-id0007.c110",
"ethernet-phy-ieee802.3-c22";
interrupt-parent = <&gpio3>;
interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
pinctrl-0 = <&pinctrl_ethphy0>;
pinctrl-names = "default";
- reg = <0>;
+ reg = <1>;
reset-assert-us = <1000>;
reset-deassert-us = <1000>;
reset-gpios = <&ioexp 4 GPIO_ACTIVE_LOW>;
@@ -151,14 +156,14 @@
#size-cells = <0>;
/* Up to one PHY may be populated. */
- ethphy1f: ethernet-phy@1 { /* SMSC LAN8740Ai */
+ ethphy1f: ethernet-phy@2 { /* SMSC LAN8740Ai */
compatible = "ethernet-phy-id0007.c110",
"ethernet-phy-ieee802.3-c22";
interrupt-parent = <&gpio4>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
pinctrl-0 = <&pinctrl_ethphy1>;
pinctrl-names = "default";
- reg = <1>;
+ reg = <2>;
reset-assert-us = <1000>;
reset-deassert-us = <1000>;
reset-gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-mx8-dlvds-lcd1.dtso b/arch/arm64/boot/dts/freescale/imx8mp-evk-mx8-dlvds-lcd1.dtso
new file mode 100644
index 000000000000..1b71890d43d5
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-mx8-dlvds-lcd1.dtso
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2024 NXP
+ */
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+ panel-lvds {
+ compatible = "koe,tx26d202vm0bwa";
+ backlight = <&backlight_lvds>;
+ power-supply = <&reg_vext_3v3>;
+
+ panel-timing {
+ clock-frequency = <148500000>;
+ hactive = <1920>;
+ vactive = <1200>;
+ hfront-porch = <130>;
+ hback-porch = <70>;
+ hsync-len = <30>;
+ vfront-porch = <5>;
+ vback-porch = <5>;
+ vsync-len = <5>;
+ de-active = <1>;
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dual-lvds-odd-pixels;
+
+ panel_in_odd: endpoint {
+ remote-endpoint = <&ldb_lvds_ch0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dual-lvds-even-pixels;
+
+ panel_in_even: endpoint {
+ remote-endpoint = <&ldb_lvds_ch1>;
+ };
+ };
+ };
+ };
+};
+
+&backlight_lvds {
+ status = "okay";
+};
+
+&lcdif2 {
+ status = "okay";
+};
+
+&lvds_bridge {
+ status = "okay";
+
+ ports {
+ port@1 {
+ ldb_lvds_ch0: endpoint {
+ remote-endpoint = <&panel_in_odd>;
+ };
+ };
+
+ port@2 {
+ ldb_lvds_ch1: endpoint {
+ remote-endpoint = <&panel_in_even>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
index 8be5b2a57f27..938347704136 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
@@ -16,6 +16,16 @@
stdout-path = &uart2;
};
+ backlight_lvds: backlight-lvds {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 100000 0>;
+ brightness-levels = <0 100>;
+ num-interpolated-steps = <100>;
+ default-brightness-level = <100>;
+ power-supply = <&reg_per_12v>;
+ status = "disabled";
+ };
+
hdmi-connector {
compatible = "hdmi-connector";
label = "hdmi";
@@ -96,6 +106,15 @@
enable-active-high;
};
+ reg_per_12v: regulator-per-12v {
+ compatible = "regulator-fixed";
+ regulator-name = "PER_12V";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ gpio = <&pca6416 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
reg_usdhc2_vmmc: regulator-usdhc2 {
compatible = "regulator-fixed";
pinctrl-names = "default";
@@ -114,6 +133,11 @@
regulator-max-microvolt = <3300000>;
};
+ audio_codec_bt_sco: audio-codec-bt-sco {
+ compatible = "linux,bt-sco";
+ #sound-dai-cells = <1>;
+ };
+
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "wm8960-audio";
@@ -145,6 +169,25 @@
};
+ 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 = <&sai2>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <16>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&audio_codec_bt_sco 1>;
+ };
+ };
+
sound-hdmi {
compatible = "fsl,imx-audio-hdmi";
model = "audio-hdmi";
@@ -166,6 +209,19 @@
};
};
+ sound-xcvr {
+ compatible = "fsl,imx-audio-card";
+ model = "imx-audio-xcvr";
+
+ pri-dai-link {
+ link-name = "XCVR PCM";
+
+ cpu {
+ sound-dai = <&xcvr>;
+ };
+ };
+ };
+
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
@@ -251,7 +307,6 @@
mtl_tx_setup: tx-queues-config {
snps,tx-queues-to-use = <5>;
- snps,tx-sched-sp;
queue0 {
snps,dcb-algorithm;
@@ -608,6 +663,17 @@
status = "okay";
};
+&sai2 {
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2>;
+ assigned-clocks = <&clk IMX8MP_CLK_SAI2>;
+ assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <12288000>;
+ fsl,sai-mclk-direction-output;
+ status = "okay";
+};
+
&sai3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3>;
@@ -694,7 +760,15 @@
status = "okay";
};
+&xcvr {
+ #sound-dai-cells = <0>;
+ status = "okay";
+};
+
&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
pinctrl_audio_pwr_reg: audiopwrreggrp {
fsl,pins = <
MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0xd6
@@ -784,6 +858,12 @@
>;
};
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x40000010
+ >;
+ };
+
pinctrl_i2c1: i2c1grp {
fsl,pins = <
MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x400001c2
@@ -880,6 +960,15 @@
>;
};
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_SAI2_TX_BCLK 0xd6
+ MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_SYNC 0xd6
+ MX8MP_IOMUXC_SAI2_TXD0__AUDIOMIX_SAI2_TX_DATA00 0xd6
+ MX8MP_IOMUXC_SAI2_RXD0__AUDIOMIX_SAI2_RX_DATA00 0xd6
+ >;
+ };
+
pinctrl_sai3: sai3grp {
fsl,pins = <
MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_SYNC 0xd6
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-msc-sm2s-ep1.dts b/arch/arm64/boot/dts/freescale/imx8mp-msc-sm2s-ep1.dts
index da4b1807c275..83194ea7cb81 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-msc-sm2s-ep1.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-msc-sm2s-ep1.dts
@@ -46,6 +46,24 @@
};
};
+&hdmi_pvi {
+ status = "okay";
+};
+
+&hdmi_tx {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi>;
+ status = "okay";
+};
+
+&hdmi_tx_phy {
+ status = "okay";
+};
+
+&lcdif3 {
+ status = "okay";
+};
+
&i2c1 {
sgtl5000: audio-codec@a {
compatible = "fsl,sgtl5000";
@@ -92,6 +110,15 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_smarc_gpio>;
+ 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_CEC__HDMIMIX_HDMI_CEC 0x10
+ MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x10
+ >;
+ };
+
pinctrl_sai2: sai2grp {
fsl,pins = <
MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_SYNC 0xd6
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314.dts b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314.dts
new file mode 100644
index 000000000000..d7fd9d36f824
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314.dts
@@ -0,0 +1,906 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright (c) 2023-2024 TQ-Systems GmbH <[email protected]>,
+ * D-82229 Seefeld, Germany.
+ * Author: Martin Schmiedel
+ * Author: Alexander Stein
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+#include <dt-bindings/pwm/pwm.h>
+#include "imx8mp-tqma8mpql.dtsi"
+
+/ {
+ model = "TQ-Systems i.MX8MPlus TQMa8MPxL on MBa8MP-RAS314";
+ compatible = "tq,imx8mp-tqma8mpql-mba8mp-ras314", "tq,imx8mp-tqma8mpql", "fsl,imx8mp";
+ chassis-type = "embedded";
+
+ chosen {
+ stdout-path = &uart4;
+ };
+
+ aliases {
+ mmc0 = &usdhc3;
+ mmc1 = &usdhc2;
+ mmc2 = &usdhc1;
+ rtc0 = &pcf85063;
+ rtc1 = &snvs_rtc;
+ };
+
+ /* X8 */
+ backlight_lvds: backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_backlight>;
+ pwms = <&pwm2 0 5000000 0>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <7>;
+ power-supply = <&reg_vcc_12v0>;
+ enable-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
+ status = "disabled";
+ };
+
+ /* X7 + X8 */
+ display: display {
+ /*
+ * Display is not fixed, so compatible has to be added from
+ * DT overlay
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lvdsdisplay>;
+ power-supply = <&reg_vcc_3v3>;
+ enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+ backlight = <&backlight_lvds>;
+ status = "disabled";
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpioled>;
+
+ led-1 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <0>;
+ gpios = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-2 {
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <1>;
+ gpios = <&gpio4 19 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ label = "X9";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_out>;
+ };
+ };
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ startup-delay-us = <100>;
+ off-on-delay-us = <12000>;
+ };
+
+ reg_vcc_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "V_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_vcc_5v0: regulator-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "V_5V0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_vcc_12v0: regulator-12v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "V_12V";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0 0x38000000>;
+ alloc-ranges = <0 0x40000000 0 0xB0000000>;
+ linux,cma-default;
+ };
+ };
+
+ rfkill {
+ compatible = "rfkill-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rfkill>;
+ label = "rfkill-pcie-wlan";
+ radio-type = "wlan";
+ shutdown-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+ };
+
+ sound {
+ compatible = "fsl,imx-audio-tlv320aic32x4";
+ model = "tq-mba8mp-ras314";
+ audio-cpu = <&sai5>;
+ audio-codec = <&tlv320aic3x04>;
+ audio-routing =
+ "IN3_L", "Mic Jack",
+ "Mic Jack", "Mic Bias",
+ "Headphone Jack", "HPL",
+ "Headphone Jack", "HPR";
+ };
+};
+
+&ecspi3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi3>;
+ cs-gpios = <&gpio5 25 GPIO_ACTIVE_LOW>, <&gpio1 6 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&eqos {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_eqos>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy3>;
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy3: ethernet-phy@3 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_eqos_phy>;
+ reset-gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <500000>;
+ reset-deassert-us = <50000>;
+ enet-phy-lane-no-swap;
+ interrupt-parent = <&gpio4>;
+ interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ ti,dp83867-rxctrl-strap-quirk;
+ ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
+ };
+ };
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec_phy>;
+ reset-gpios = <&gpio4 0 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <500000>;
+ reset-deassert-us = <50000>;
+ enet-phy-lane-no-swap;
+ interrupt-parent = <&gpio4>;
+ interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ ti,dp83867-rxctrl-strap-quirk;
+ ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
+ };
+ };
+};
+
+&gpio1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio1>;
+
+ gpio-line-names = "WIFI_PMIC_EN", "LVDS_RESET#", "", "",
+ "", "", "GPIO8", "",
+ "", "", "", "",
+ "", "", "GPIO12", "GPIO13",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "";
+
+ wifi-pmic-en-hog {
+ gpio-hog;
+ gpios = <0 0>;
+ output-high;
+ line-name = "WIFI_PMIC_EN";
+ };
+};
+
+&gpio2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio2>;
+
+ gpio-line-names = "GPIO22", "GPIO23", "GPIO24", "GPIO25",
+ "GPIO26", "GPIO27", "CAM_GPIO1", "CAM_GPIO2",
+ "", "", "GPIO1", "GPIO0",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "";
+};
+
+&gpio3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio3>;
+
+ gpio-line-names = "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "TEMP_EVENT#", "", "", "",
+ "", "", "", "",
+ "", "", "", "";
+};
+
+&gpio4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio4>;
+
+ gpio-line-names = "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "HDMI_OC#", "GPIO14", "GPIO15", "GPIO16",
+ "GPIO17", "PCIE_WAKE#", "GPIO19", "GPIO20",
+ "PCIE_PERST#", "", "", "";
+
+ pewake-hog {
+ gpio-hog;
+ gpios = <25 0>;
+ input;
+ line-name = "PCIE_WAKE#";
+ };
+};
+
+&gpio5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio5>, <&pinctrl_gpt1_gpio>,
+ <&pinctrl_gpt2_gpio>, <&pinctrl_gpt3_gpio>;
+
+ gpio-line-names = "", "GPIO18", "", "GPIO3",
+ "GPIO2", "GPIO21", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "GPIO5", "GPIO6",
+ "", "", "GPIO11", "GPIO10",
+ "GPIO9", "GPIO7", "", "GPIO4",
+ "", "", "", "";
+};
+
+&gpt1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpt1>;
+ status = "disabled";
+};
+
+&gpt2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpt2>;
+ status = "disabled";
+};
+
+&gpt3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpt3>;
+ status = "disabled";
+};
+
+&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";
+};
+
+/* X5 + X6 Camera & Display interface */
+&i2c2 {
+ clock-frequency = <384000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+};
+
+/* X1 ID_I2C */
+&i2c3 {
+ clock-frequency = <384000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio2 10 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio2 11 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <384000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ pinctrl-1 = <&pinctrl_i2c4_gpio>;
+ scl-gpios = <&gpio5 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ tlv320aic3x04: audio-codec@18 {
+ compatible = "ti,tlv320aic32x4";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tlv320aic3x04>;
+ reg = <0x18>;
+ clock-names = "mclk";
+ clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI5_MCLK1>;
+ reset-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
+ iov-supply = <&reg_vcc_3v3>;
+ ldoin-supply = <&reg_vcc_3v3>;
+ };
+};
+
+/* X1 I2C */
+&i2c5 {
+ clock-frequency = <384000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c5>;
+ pinctrl-1 = <&pinctrl_i2c5_gpio>;
+ scl-gpios = <&gpio5 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 4 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+};
+
+/* X1 I2C on GPIO24/GPIO25 */
+&i2c6 {
+ clock-frequency = <384000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c6>;
+ pinctrl-1 = <&pinctrl_i2c6_gpio>;
+ scl-gpios = <&gpio2 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio2 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "disabled";
+};
+
+&lcdif3 {
+ status = "okay";
+};
+
+&pcf85063 {
+ /* RTC_EVENT# is connected on MBa8MP-RAS314 */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcf85063>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
+};
+
+&pcie_phy {
+ clocks = <&hsio_blk_ctrl>;
+ clock-names = "ref";
+ fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_OUTPUT>;
+ status = "okay";
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie>;
+ reset-gpios = <&gpio4 28 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm2>;
+ status = "disabled";
+};
+
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3>;
+ status = "okay";
+};
+
+&pwm4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm4>;
+ status = "okay";
+};
+
+&sai5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai5>;
+ assigned-clocks = <&clk IMX8MP_CLK_SAI5>;
+ assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <12288000>;
+ fsl,sai-mclk-direction-output;
+ status = "okay";
+};
+
+&snvs_pwrkey {
+ status = "okay";
+};
+
+/* X1 UART1 */
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ uart-has-rtscts;
+ assigned-clocks = <&clk IMX8MP_CLK_UART1>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_80M>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ uart-has-rtscts;
+ assigned-clocks = <&clk IMX8MP_CLK_UART2>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_80M>;
+ status = "okay";
+
+ bluetooth {
+ compatible = "nxp,88w8987-bt";
+ };
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ assigned-clocks = <&clk IMX8MP_CLK_UART3>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_80M>;
+ status = "okay";
+};
+
+&uart4 {
+ /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+&usb3_0 {
+ fsl,disable-port-power-control;
+ status = "okay";
+};
+
+&usb3_1 {
+ fsl,disable-port-power-control;
+ fsl,permanently-attached;
+ status = "okay";
+};
+
+&usb3_phy0 {
+ vbus-supply = <&reg_vcc_5v0>;
+ status = "okay";
+};
+
+&usb3_phy1 {
+ vbus-supply = <&reg_vcc_5v0>;
+ status = "okay";
+};
+
+&usb_dwc3_0 {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbhub>;
+ status = "okay";
+
+ hub_2_0: hub@1 {
+ compatible = "usb451,8142";
+ reg = <1>;
+ peer-hub = <&hub_3_0>;
+ reset-gpios = <&gpio5 26 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&reg_vcc_3v3>;
+ };
+
+ hub_3_0: hub@2 {
+ compatible = "usb451,8140";
+ reg = <2>;
+ peer-hub = <&hub_2_0>;
+ reset-gpios = <&gpio5 26 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&reg_vcc_3v3>;
+ };
+};
+
+/* X1 SD card on GPIO22-GPIO27 */
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ disable-wp;
+ bus-width = <4>;
+ status = "disabled";
+};
+
+&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_LOW>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ no-mmc;
+ no-sdio;
+ disable-wp;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_backlight: backlightgrp {
+ fsl,pins = <MX8MP_IOMUXC_GPIO1_IO03__GPIO1_IO03 0x14>;
+ };
+
+ pinctrl_ecspi3: ecspi3grp {
+ fsl,pins = <MX8MP_IOMUXC_UART1_RXD__ECSPI3_SCLK 0x140>,
+ <MX8MP_IOMUXC_UART1_TXD__ECSPI3_MOSI 0x140>,
+ <MX8MP_IOMUXC_UART2_RXD__ECSPI3_MISO 0x1c0>,
+ <MX8MP_IOMUXC_UART2_TXD__GPIO5_IO25 0x140>,
+ <MX8MP_IOMUXC_GPIO1_IO06__GPIO1_IO06 0x140>;
+ };
+
+ pinctrl_ecspi3_gpio: ecspi3gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_UART1_RXD__GPIO5_IO22 0x80>,
+ <MX8MP_IOMUXC_UART1_TXD__GPIO5_IO23 0x80>,
+ <MX8MP_IOMUXC_UART2_RXD__GPIO5_IO24 0x80>,
+ <MX8MP_IOMUXC_UART2_TXD__GPIO5_IO25 0x80>,
+ <MX8MP_IOMUXC_GPIO1_IO06__GPIO1_IO06 0x80>;
+ };
+
+ pinctrl_eqos: eqosgrp {
+ fsl,pins = <MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC 0x40000044>,
+ <MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO 0x40000044>,
+ <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_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x90>,
+ <MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x90>,
+ <MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0 0x12>,
+ <MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1 0x12>,
+ <MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2 0x12>,
+ <MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3 0x12>,
+ <MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x12>,
+ <MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x14>;
+ };
+
+ pinctrl_eqos_phy: eqosphygrp {
+ fsl,pins = <MX8MP_IOMUXC_SAI1_RXD0__GPIO4_IO02 0x100>,
+ <MX8MP_IOMUXC_SAI1_RXD1__GPIO4_IO03 0x1c0>;
+ };
+
+ pinctrl_fec: fecgrp {
+ fsl,pins = <MX8MP_IOMUXC_SAI1_RXD2__ENET1_MDC 0x40000044>,
+ <MX8MP_IOMUXC_SAI1_RXD3__ENET1_MDIO 0x40000044>,
+ <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 0x12>,
+ <MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1 0x12>,
+ <MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2 0x12>,
+ <MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3 0x12>,
+ <MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL 0x12>,
+ <MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC 0x14>;
+ };
+
+ pinctrl_fec_phy: fecphygrp {
+ fsl,pins = <MX8MP_IOMUXC_SAI1_RXFS__GPIO4_IO00 0x100>,
+ <MX8MP_IOMUXC_SAI1_RXC__GPIO4_IO01 0x1c0>;
+ };
+
+ pinctrl_gpioled: gpioledgrp {
+ fsl,pins = <MX8MP_IOMUXC_SAI1_TXD6__GPIO4_IO18 0x14>,
+ <MX8MP_IOMUXC_SAI1_TXD7__GPIO4_IO19 0x14>;
+ };
+
+ pinctrl_gpio1: gpio1grp {
+ fsl,pins = <MX8MP_IOMUXC_GPIO1_IO00__GPIO1_IO00 0x14>,
+ <MX8MP_IOMUXC_GPIO1_IO01__GPIO1_IO01 0x14>;
+ };
+
+ pinctrl_gpio2: gpio2grp {
+ fsl,pins = <MX8MP_IOMUXC_SD1_CLK__GPIO2_IO00 0x94>,
+ <MX8MP_IOMUXC_SD1_CMD__GPIO2_IO01 0x94>,
+ <MX8MP_IOMUXC_SD1_DATA0__GPIO2_IO02 0x94>,
+ <MX8MP_IOMUXC_SD1_DATA1__GPIO2_IO03 0x94>,
+ <MX8MP_IOMUXC_SD1_DATA2__GPIO2_IO04 0x94>,
+ <MX8MP_IOMUXC_SD1_DATA3__GPIO2_IO05 0x94>,
+ <MX8MP_IOMUXC_SD1_DATA4__GPIO2_IO06 0x94>,
+ <MX8MP_IOMUXC_SD1_DATA5__GPIO2_IO07 0x94>;
+ };
+
+ pinctrl_gpio3: gpio3grp {
+ fsl,pins = <MX8MP_IOMUXC_SAI5_RXC__GPIO3_IO20 0x180>;
+ };
+
+ pinctrl_gpio4: gpio4grp {
+ fsl,pins = <MX8MP_IOMUXC_SAI1_MCLK__GPIO4_IO20 0x80>,
+ /* PCIE_WAKE# */
+ <MX8MP_IOMUXC_SAI2_TXC__GPIO4_IO25 0x180>,
+ <MX8MP_IOMUXC_SAI2_TXD0__GPIO4_IO26 0x94>,
+ <MX8MP_IOMUXC_SAI2_MCLK__GPIO4_IO27 0x94>;
+ };
+
+ pinctrl_gpio5: gpio5grp {
+ fsl,pins = <MX8MP_IOMUXC_SAI3_TXD__GPIO5_IO01 0x80>,
+ <MX8MP_IOMUXC_SPDIF_EXT_CLK__GPIO5_IO05 0x80>;
+ };
+
+ pinctrl_hdmi: hdmigrp {
+ fsl,pins = <MX8MP_IOMUXC_HDMI_DDC_SCL__HDMIMIX_HDMI_SCL 0x400001c2>,
+ <MX8MP_IOMUXC_HDMI_DDC_SDA__HDMIMIX_HDMI_SDA 0x400001c2>,
+ <MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x40000010>,
+ <MX8MP_IOMUXC_HDMI_CEC__HDMIMIX_HDMI_CEC 0x40000154>;
+ };
+
+ pinctrl_gpt1: gpt1grp {
+ fsl,pins = <MX8MP_IOMUXC_UART3_TXD__GPT1_CLK 0x14>;
+ };
+
+ pinctrl_gpt1_gpio: gpt1gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_UART3_TXD__GPIO5_IO27 0x80>;
+ };
+
+ pinctrl_gpt2: gpt2grp {
+ fsl,pins = <MX8MP_IOMUXC_I2C3_SCL__GPT2_CLK 0x14>;
+ };
+
+ pinctrl_gpt2_gpio: gpt2gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_I2C3_SCL__GPIO5_IO18 0x80>;
+ };
+
+ pinctrl_gpt3: gpt3grp {
+ fsl,pins = <MX8MP_IOMUXC_I2C3_SDA__GPT3_CLK 0x14>;
+ };
+
+ pinctrl_gpt3_gpio: gpt3gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_I2C3_SDA__GPIO5_IO19 0x80>;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001e2>,
+ <MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x400001e2>;
+ };
+
+ pinctrl_i2c2_gpio: i2c2-gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_I2C2_SCL__GPIO5_IO16 0x400001e2>,
+ <MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17 0x400001e2>;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <MX8MP_IOMUXC_SD1_RESET_B__I2C3_SCL 0x400001e2>,
+ <MX8MP_IOMUXC_SD1_STROBE__I2C3_SDA 0x400001e2>;
+ };
+
+ pinctrl_i2c3_gpio: i2c3-gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_SD1_RESET_B__GPIO2_IO10 0x400001e2>,
+ <MX8MP_IOMUXC_SD1_STROBE__GPIO2_IO11 0x400001e2>;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <MX8MP_IOMUXC_ECSPI2_MISO__I2C4_SCL 0x400001e2>,
+ <MX8MP_IOMUXC_ECSPI2_SS0__I2C4_SDA 0x400001e2>;
+ };
+
+ pinctrl_i2c4_gpio: i2c4-gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_ECSPI2_MISO__GPIO5_IO12 0x400001e2>,
+ <MX8MP_IOMUXC_ECSPI2_SS0__GPIO5_IO13 0x400001e2>;
+ };
+
+ pinctrl_i2c5: i2c5grp {
+ fsl,pins = <MX8MP_IOMUXC_SPDIF_TX__I2C5_SCL 0x400001e2>,
+ <MX8MP_IOMUXC_SPDIF_RX__I2C5_SDA 0x400001e2>;
+ };
+
+ pinctrl_i2c5_gpio: i2c5-gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_SPDIF_TX__GPIO5_IO03 0x400001e2>,
+ <MX8MP_IOMUXC_SPDIF_RX__GPIO5_IO04 0x400001e2>;
+ };
+
+ pinctrl_i2c6: i2c6grp {
+ fsl,pins = <MX8MP_IOMUXC_SD1_DATA0__I2C6_SCL 0x400001e2>,
+ <MX8MP_IOMUXC_SD1_DATA1__I2C6_SDA 0x400001e2>;
+ };
+
+ pinctrl_i2c6_gpio: i2c6-gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_SD1_DATA0__GPIO2_IO02 0x400001e2>,
+ <MX8MP_IOMUXC_SD1_DATA1__GPIO2_IO03 0x400001e2>;
+ };
+
+ pinctrl_pcf85063: pcf85063grp {
+ fsl,pins = <MX8MP_IOMUXC_SAI5_RXFS__GPIO3_IO19 0x80>;
+ };
+
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <MX8MP_IOMUXC_I2C4_SCL__PCIE_CLKREQ_B 0x60>,
+ <MX8MP_IOMUXC_SAI3_RXFS__GPIO4_IO28 0x94>;
+ };
+
+ pinctrl_lvdsdisplay: lvdsdisplaygrp {
+ fsl,pins = <MX8MP_IOMUXC_GPIO1_IO07__GPIO1_IO07 0x10>;
+ };
+
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <MX8MP_IOMUXC_GPIO1_IO09__PWM2_OUT 0x14>;
+ };
+
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <MX8MP_IOMUXC_GPIO1_IO14__PWM3_OUT 0x14>;
+ };
+
+ pinctrl_pwm3_gpio: pwm3grpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_GPIO1_IO14__GPIO1_IO14 0x80>;
+ };
+
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <MX8MP_IOMUXC_GPIO1_IO15__PWM4_OUT 0x14>;
+ };
+
+ pinctrl_pwm4_gpio: pwm4grpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_GPIO1_IO15__GPIO1_IO15 0x80>;
+ };
+
+ pinctrl_rfkill: rfkillgrp {
+ fsl,pins = <MX8MP_IOMUXC_SAI3_MCLK__GPIO5_IO02 0x14>;
+ };
+
+ pinctrl_sai5: sai5grp {
+ fsl,pins = <MX8MP_IOMUXC_SAI5_MCLK__AUDIOMIX_SAI5_MCLK 0x94>,
+ <MX8MP_IOMUXC_SAI5_RXD0__AUDIOMIX_SAI5_RX_DATA00 0x94>,
+ <MX8MP_IOMUXC_SAI5_RXD3__AUDIOMIX_SAI5_TX_DATA00 0x94>,
+ <MX8MP_IOMUXC_SAI5_RXD1__AUDIOMIX_SAI5_TX_SYNC 0x94>,
+ <MX8MP_IOMUXC_SAI5_RXD2__AUDIOMIX_SAI5_TX_BCLK 0x94>;
+ };
+
+ pinctrl_tlv320aic3x04: tlv320aic3x04grp {
+ fsl,pins = <MX8MP_IOMUXC_ECSPI2_MOSI__GPIO5_IO11 0x180>;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <MX8MP_IOMUXC_SAI2_RXFS__UART1_DCE_TX 0x14>,
+ <MX8MP_IOMUXC_SAI2_RXC__UART1_DCE_RX 0x14>,
+ <MX8MP_IOMUXC_SAI2_RXD0__UART1_DTE_CTS 0x14>,
+ <MX8MP_IOMUXC_SAI2_TXFS__UART1_DTE_RTS 0x14>;
+ };
+
+ pinctrl_uart1_gpio: uart1gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21 0x80>,
+ <MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x80>,
+ <MX8MP_IOMUXC_SAI2_RXD0__GPIO4_IO23 0x80>,
+ <MX8MP_IOMUXC_SAI2_TXFS__GPIO4_IO24 0x80>;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <MX8MP_IOMUXC_SAI3_TXC__UART2_DCE_TX 0x14>,
+ <MX8MP_IOMUXC_SAI3_TXFS__UART2_DCE_RX 0x14>,
+ <MX8MP_IOMUXC_SAI3_RXD__UART2_DCE_RTS 0x14>,
+ <MX8MP_IOMUXC_SAI3_RXC__UART2_DCE_CTS 0x14>;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <MX8MP_IOMUXC_SD1_DATA6__UART3_DCE_TX 0x140>,
+ <MX8MP_IOMUXC_SD1_DATA7__UART3_DCE_RX 0x140>;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <MX8MP_IOMUXC_UART4_TXD__UART4_DCE_TX 0x140>,
+ <MX8MP_IOMUXC_UART4_RXD__UART4_DCE_RX 0x140>;
+ };
+
+ pinctrl_usbhub: usbhubgrp {
+ fsl,pins = <MX8MP_IOMUXC_UART3_RXD__GPIO5_IO26 0x10>;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x192>,
+ <MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x1d2>,
+ <MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x1d2>,
+ <MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d2>,
+ <MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d2>,
+ <MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d2>;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x192>,
+ <MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d2>,
+ <MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d2>,
+ <MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d2>,
+ <MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d2>,
+ <MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d2>,
+ <MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0>;
+ };
+
+ 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 0xc0>;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ 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 0xc0>;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2-gpiogrp {
+ fsl,pins = <MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12 0x1c0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts
index c51ed7d991d1..ae64731266f3 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts
@@ -222,11 +222,6 @@
#size-cells = <2>;
ranges;
- ocram: ocram@900000 {
- no-map;
- reg = <0 0x900000 0 0x70000>;
- };
-
/* global autoconfigured region for contiguous allocations */
linux,cma {
compatible = "shared-dma-pool";
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi
index ebc29a950ba9..336785a9fba8 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi
@@ -45,12 +45,16 @@
flash0: flash@0 {
reg = <0>;
- #address-cells = <1>;
- #size-cells = <1>;
compatible = "jedec,spi-nor";
spi-max-frequency = <80000000>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi
index 560c68e4da6d..6c75a5ecf56b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi
@@ -5,6 +5,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/leds/common.h>
#include <dt-bindings/net/ti-dp83867.h>
/ {
@@ -102,6 +103,25 @@
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
rx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_AMBER>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
};
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
index a77e9a44d9fa..d765b7972841 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
@@ -9,6 +9,7 @@
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/phy/phy-imx8-pcie.h>
+#include <dt-bindings/net/ti-dp83867.h>
#include "imx8mp.dtsi"
@@ -225,6 +226,29 @@
ethphy0: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0x0>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ rx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_AMBER>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
};
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi
index 6e6b9c2c4640..fbcd93e33aea 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi
@@ -4,6 +4,18 @@
*/
/ {
+ native-hdmi-connector {
+ compatible = "hdmi-connector";
+ label = "X21";
+ type = "a";
+
+ port {
+ native_hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_out>;
+ };
+ };
+ };
+
sound {
compatible = "simple-audio-card";
simple-audio-card,bitclock-master = <&codec_dai>;
@@ -94,6 +106,27 @@
pinctrl-0 = <&pinctrl_ctrl_sleep_moci>;
};
+/* Verdin HDMI_1 */
+&hdmi_pvi {
+ status = "okay";
+};
+
+&hdmi_tx {
+ status = "okay";
+
+ ports {
+ port@1 {
+ hdmi_tx_out: endpoint {
+ remote-endpoint = <&native_hdmi_connector_in>;
+ };
+ };
+ };
+};
+
+&hdmi_tx_phy {
+ status = "okay";
+};
+
/* Current measurement into module VCC */
&hwmon {
status = "okay";
@@ -139,6 +172,10 @@
status = "okay";
};
+&lcdif3 {
+ status = "okay";
+};
+
/* Verdin PCIE_1 */
&pcie {
vpcie-supply = <&reg_pcie>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi
index 42ed44a11711..09733fea036d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi
@@ -4,6 +4,18 @@
*/
/ {
+ native-hdmi-connector {
+ compatible = "hdmi-connector";
+ label = "X37";
+ type = "a";
+
+ port {
+ native_hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_out>;
+ };
+ };
+ };
+
reg_eth2phy: regulator-eth2phy {
compatible = "regulator-fixed";
enable-active-high;
@@ -103,6 +115,27 @@
vcc-supply = <&reg_1p8v>;
};
+/* Verdin HDMI_1 */
+&hdmi_pvi {
+ status = "okay";
+};
+
+&hdmi_tx {
+ status = "okay";
+
+ ports {
+ port@1 {
+ hdmi_tx_out: endpoint {
+ remote-endpoint = <&native_hdmi_connector_in>;
+ };
+ };
+ };
+};
+
+&hdmi_tx_phy {
+ status = "okay";
+};
+
/* Current measurement into module VCC */
&hwmon {
status = "okay";
@@ -141,6 +174,10 @@
status = "okay";
};
+&lcdif3 {
+ status = "okay";
+};
+
/* Verdin PCIE_1 */
&pcie {
status = "okay";
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-mallow.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-mallow.dtsi
index 1d15f7449c58..3a40338cf2d8 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-mallow.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-mallow.dtsi
@@ -11,6 +11,18 @@
#include <dt-bindings/leds/common.h>
/ {
+ native-hdmi-connector {
+ compatible = "hdmi-connector";
+ label = "X14";
+ type = "a";
+
+ port {
+ native_hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_out>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -91,6 +103,27 @@
status = "okay";
};
+/* Verdin HDMI_1 */
+&hdmi_pvi {
+ status = "okay";
+};
+
+&hdmi_tx {
+ status = "okay";
+
+ ports {
+ port@1 {
+ hdmi_tx_out: endpoint {
+ remote-endpoint = <&native_hdmi_connector_in>;
+ };
+ };
+ };
+};
+
+&hdmi_tx_phy {
+ status = "okay";
+};
+
/* Temperature sensor on Mallow */
&hwmon_temp {
compatible = "ti,tmp1075";
@@ -117,6 +150,10 @@
status = "okay";
};
+&lcdif3 {
+ status = "okay";
+};
+
/* Verdin PCIE_1 */
&pcie {
status = "okay";
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi.dtsi
index 91d597391b7c..2ee91f31e7f0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi.dtsi
@@ -41,8 +41,7 @@
pinctrl-0 = <&pinctrl_gpio1>, <&pinctrl_gpio2>,
<&pinctrl_gpio3>, <&pinctrl_gpio4>,
<&pinctrl_gpio7>, <&pinctrl_gpio8>,
- <&pinctrl_gpio_hog1>, <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>,
- <&pinctrl_hdmi_hog>;
+ <&pinctrl_gpio_hog1>, <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>;
};
/*
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi
index ef94f9a57e20..efcab00c0142 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi
@@ -55,8 +55,7 @@
pinctrl-0 = <&pinctrl_gpio1>, <&pinctrl_gpio2>,
<&pinctrl_gpio3>, <&pinctrl_gpio4>,
<&pinctrl_gpio7>, <&pinctrl_gpio8>,
- <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>, <&pinctrl_gpio_hog4>,
- <&pinctrl_hdmi_hog>;
+ <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>, <&pinctrl_gpio_hog4>;
};
/* On-module Bluetooth */
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi
index a7b261ff3e4c..533b7fe218ce 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi
@@ -6,6 +6,18 @@
#include <dt-bindings/leds/common.h>
/ {
+ native-hdmi-connector {
+ compatible = "hdmi-connector";
+ label = "J15";
+ type = "a";
+
+ port {
+ native_hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_out>;
+ };
+ };
+ };
+
/* Carrier Board Supply +V1.8 */
reg_1p8v: regulator-1p8v {
compatible = "regulator-fixed";
@@ -105,6 +117,27 @@
pinctrl-0 = <&pinctrl_ctrl_sleep_moci>;
};
+/* Verdin HDMI_1 */
+&hdmi_pvi {
+ status = "okay";
+};
+
+&hdmi_tx {
+ status = "okay";
+
+ ports {
+ port@1 {
+ hdmi_tx_out: endpoint {
+ remote-endpoint = <&native_hdmi_connector_in>;
+ };
+ };
+ };
+};
+
+&hdmi_tx_phy {
+ status = "okay";
+};
+
&hwmon_temp {
status = "okay";
};
@@ -127,6 +160,10 @@
status = "okay";
};
+&lcdif3 {
+ status = "okay";
+};
+
/* Verdin PCIE_1 */
&pcie {
status = "okay";
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
index aef4bef4bccd..d23a3942174d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
@@ -241,7 +241,6 @@
mtl_rx_setup: rx-queues-config {
snps,rx-queues-to-use = <5>;
- snps,rx-sched-sp;
queue0 {
snps,dcb-algorithm;
@@ -276,7 +275,6 @@
mtl_tx_setup: tx-queues-config {
snps,tx-queues-to-use = <5>;
- snps,tx-sched-sp;
queue0 {
snps,dcb-algorithm;
@@ -457,6 +455,13 @@
"SODIMM_44";
};
+/* Verdin HDMI_1 */
+&hdmi_tx {
+ ddc-i2c-bus = <&i2c5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi>;
+};
+
/* On-module I2C */
&i2c1 {
clock-frequency = <400000>;
@@ -650,8 +655,7 @@
/* Verdin I2C_2_DSI */
&i2c2 {
- /* Lower frequency to avoid DDC/EDID issues with certain displays/screens. */
- clock-frequency = <10000>;
+ clock-frequency = <400000>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
pinctrl-1 = <&pinctrl_i2c2_gpio>;
@@ -1117,10 +1121,10 @@
<MX8MP_IOMUXC_SAI1_RXFS__GPIO4_IO00 0x1c4>; /* SODIMM 252 */
};
- pinctrl_hdmi_hog: hdmihoggrp {
+ pinctrl_hdmi: hdmigrp {
fsl,pins =
- <MX8MP_IOMUXC_HDMI_CEC__HDMIMIX_HDMI_CEC 0x40000019>, /* SODIMM 63 */
- <MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x40000019>; /* SODIMM 61 */
+ <MX8MP_IOMUXC_HDMI_CEC__HDMIMIX_HDMI_CEC 0x140>, /* SODIMM 63 */
+ <MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x180>; /* SODIMM 61 */
};
/* On-module I2C */
diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index b92abb5a5c53..603dfe80216f 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -789,6 +789,23 @@
reg = <IMX8MP_POWER_DOMAIN_USB2_PHY>;
};
+ pgc_mlmix: power-domain@4 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MP_POWER_DOMAIN_MLMIX>;
+ clocks = <&clk IMX8MP_CLK_ML_AXI>,
+ <&clk IMX8MP_CLK_ML_AHB>,
+ <&clk IMX8MP_CLK_NPU_ROOT>;
+ assigned-clocks = <&clk IMX8MP_CLK_ML_CORE>,
+ <&clk IMX8MP_CLK_ML_AXI>,
+ <&clk IMX8MP_CLK_ML_AHB>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>,
+ <&clk IMX8MP_SYS_PLL1_800M>,
+ <&clk IMX8MP_SYS_PLL1_800M>;
+ assigned-clock-rates = <800000000>,
+ <800000000>,
+ <300000000>;
+ };
+
pgc_audio: power-domain@5 {
#power-domain-cells = <0>;
reg = <IMX8MP_POWER_DOMAIN_AUDIOMIX>;
@@ -821,6 +838,12 @@
assigned-clock-rates = <800000000>, <400000000>;
};
+ pgc_vpumix: power-domain@8 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MP_POWER_DOMAIN_VPUMIX>;
+ clocks = <&clk IMX8MP_CLK_VPU_ROOT>;
+ };
+
pgc_gpu3d: power-domain@9 {
#power-domain-cells = <0>;
reg = <IMX8MP_POWER_DOMAIN_GPU3D>;
@@ -836,6 +859,28 @@
<&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
};
+ pgc_vpu_g1: power-domain@11 {
+ #power-domain-cells = <0>;
+ power-domains = <&pgc_vpumix>;
+ reg = <IMX8MP_POWER_DOMAIN_VPU_G1>;
+ clocks = <&clk IMX8MP_CLK_VPU_G1_ROOT>;
+ };
+
+ pgc_vpu_g2: power-domain@12 {
+ #power-domain-cells = <0>;
+ power-domains = <&pgc_vpumix>;
+ reg = <IMX8MP_POWER_DOMAIN_VPU_G2>;
+ clocks = <&clk IMX8MP_CLK_VPU_G2_ROOT>;
+
+ };
+
+ pgc_vpu_vc8000e: power-domain@13 {
+ #power-domain-cells = <0>;
+ power-domains = <&pgc_vpumix>;
+ reg = <IMX8MP_POWER_DOMAIN_VPU_VC8000E>;
+ clocks = <&clk IMX8MP_CLK_VPU_VC8KE_ROOT>;
+ };
+
pgc_hdmimix: power-domain@14 {
#power-domain-cells = <0>;
reg = <IMX8MP_POWER_DOMAIN_HDMIMIX>;
@@ -873,50 +918,6 @@
reg = <IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP>;
clocks = <&clk IMX8MP_CLK_MEDIA_ISP_ROOT>;
};
-
- pgc_vpumix: power-domain@19 {
- #power-domain-cells = <0>;
- reg = <IMX8MP_POWER_DOMAIN_VPUMIX>;
- clocks = <&clk IMX8MP_CLK_VPU_ROOT>;
- };
-
- pgc_vpu_g1: power-domain@20 {
- #power-domain-cells = <0>;
- power-domains = <&pgc_vpumix>;
- reg = <IMX8MP_POWER_DOMAIN_VPU_G1>;
- clocks = <&clk IMX8MP_CLK_VPU_G1_ROOT>;
- };
-
- pgc_vpu_g2: power-domain@21 {
- #power-domain-cells = <0>;
- power-domains = <&pgc_vpumix>;
- reg = <IMX8MP_POWER_DOMAIN_VPU_G2>;
- clocks = <&clk IMX8MP_CLK_VPU_G2_ROOT>;
- };
-
- pgc_vpu_vc8000e: power-domain@22 {
- #power-domain-cells = <0>;
- power-domains = <&pgc_vpumix>;
- reg = <IMX8MP_POWER_DOMAIN_VPU_VC8000E>;
- clocks = <&clk IMX8MP_CLK_VPU_VC8KE_ROOT>;
- };
-
- pgc_mlmix: power-domain@24 {
- #power-domain-cells = <0>;
- reg = <IMX8MP_POWER_DOMAIN_MLMIX>;
- clocks = <&clk IMX8MP_CLK_ML_AXI>,
- <&clk IMX8MP_CLK_ML_AHB>,
- <&clk IMX8MP_CLK_NPU_ROOT>;
- assigned-clocks = <&clk IMX8MP_CLK_ML_CORE>,
- <&clk IMX8MP_CLK_ML_AXI>,
- <&clk IMX8MP_CLK_ML_AHB>;
- assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>,
- <&clk IMX8MP_SYS_PLL1_800M>,
- <&clk IMX8MP_SYS_PLL1_800M>;
- assigned-clock-rates = <800000000>,
- <800000000>,
- <300000000>;
- };
};
};
};
@@ -1540,6 +1541,31 @@
dma-names = "tx";
status = "disabled";
};
+
+ xcvr: xcvr@30cc0000 {
+ compatible = "fsl,imx8mp-xcvr";
+ reg = <0x30cc0000 0x800>,
+ <0x30cc0800 0x400>,
+ <0x30cc0c00 0x080>,
+ <0x30cc0e00 0x080>;
+ reg-names = "ram", "regs", "rxfifo",
+ "txfifo";
+ interrupts = /* XCVR IRQ 0 */
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
+ /* XCVR IRQ 1 */
+ <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
+ /* XCVR PHY - SPDIF wakeup IRQ */
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_EARC_IPG>,
+ <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_EARC_PHY>,
+ <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SPBA2_ROOT>,
+ <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_AUDPLL_ROOT>;
+ clock-names = "ipg", "phy", "spba", "pll_ipg";
+ dmas = <&sdma2 30 2 0>, <&sdma2 31 2 0>;
+ dma-names = "rx", "tx";
+ resets = <&audio_blk_ctrl 0>;
+ status = "disabled";
+ };
};
sdma3: dma-controller@30e00000 {
@@ -1568,6 +1594,7 @@
compatible = "fsl,imx8mp-audio-blk-ctrl";
reg = <0x30e20000 0x10000>;
#clock-cells = <1>;
+ #reset-cells = <1>;
clocks = <&clk IMX8MP_CLK_AUDIO_ROOT>,
<&clk IMX8MP_CLK_SAI1>,
<&clk IMX8MP_CLK_SAI2>,
@@ -1579,6 +1606,9 @@
"sai1", "sai2", "sai3",
"sai5", "sai6", "sai7";
power-domains = <&pgc_audio>;
+ assigned-clocks = <&clk IMX8MP_AUDIO_PLL1>,
+ <&clk IMX8MP_AUDIO_PLL2>;
+ assigned-clock-rates = <393216000>, <361267200>;
};
};
@@ -1946,7 +1976,7 @@
};
irqsteer_hdmi: interrupt-controller@32fc2000 {
- compatible = "fsl,imx-irqsteer";
+ compatible = "fsl,imx8mp-irqsteer", "fsl,imx-irqsteer";
reg = <0x32fc2000 0x1000>;
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
index ffb5fe61630d..1b39514d5c12 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
@@ -45,7 +45,6 @@
gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
linux,code = <KEY_VOLUMEDOWN>;
debounce-interval = <50>;
- wakeup-source;
};
key-vol-up {
@@ -53,7 +52,6 @@
gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
linux,code = <KEY_VOLUMEUP>;
debounce-interval = <50>;
- wakeup-source;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi
index 5ca6b2252546..01e5092e4c40 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi
@@ -251,11 +251,15 @@
flash0: flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
- #address-cells = <1>;
- #size-cells = <1>;
spi-max-frequency = <84000000>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
index 6e05361c1ffb..778741dbbb33 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
@@ -40,12 +40,99 @@
enable-active-high;
};
+ reg_fec2_supply: regulator-fec2-nvcc {
+ compatible = "regulator-fixed";
+ regulator-name = "fec2_nvcc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&max7322 0 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can01_en: regulator-can01-gen {
+ compatible = "regulator-fixed";
+ regulator-name = "can01-en";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pca6416 3 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can2_en: regulator-can2-gen {
+ compatible = "regulator-fixed";
+ regulator-name = "can2-en";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pca6416 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can01_stby: regulator-can01-stby {
+ compatible = "regulator-fixed";
+ regulator-name = "can01-stby";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pca6416 5 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&reg_can01_en>;
+ };
+
+ reg_can2_stby: regulator-can2-stby {
+ compatible = "regulator-fixed";
+ regulator-name = "can2-stby";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pca6416 6 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&reg_can2_en>;
+ };
+
reg_vref_1v8: regulator-adc-vref {
compatible = "regulator-fixed";
regulator-name = "vref_1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
+
+ bt_sco_codec: audio-codec-bt {
+ compatible = "linux,bt-sco";
+ #sound-dai-cells = <1>;
+ };
+
+ 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 = <&sai0>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <16>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&bt_sco_codec 1>;
+ };
+ };
+
+ sound-wm8960 {
+ compatible = "fsl,imx-audio-wm8960";
+ model = "wm8960-audio";
+ audio-cpu = <&sai1>;
+ audio-codec = <&wm8960>;
+ hp-det-gpio = <&lsio_gpio0 31 GPIO_ACTIVE_HIGH>;
+ audio-routing = "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT1", "Mic Jack",
+ "Mic Jack", "MICB";
+ };
};
&adc0 {
@@ -55,6 +142,78 @@
status = "okay";
};
+&amix {
+ status = "okay";
+};
+
+&asrc0 {
+ fsl,asrc-rate = <48000>;
+ status = "okay";
+};
+
+&cm41_i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cm41_i2c>;
+ status = "okay";
+
+ pca6416: gpio@20 {
+ compatible = "ti,tca6416";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+};
+
+&cm41_intmux {
+ status = "okay";
+};
+
+&i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c0>;
+ status = "okay";
+
+ accelerometer@19 {
+ compatible = "st,lsm303agr-accel";
+ reg = <0x19>;
+ };
+
+ gyrometer@20 {
+ compatible = "nxp,fxas21002c";
+ reg = <0x20>;
+ };
+
+ light-sensor@44 {
+ compatible = "isil,isl29023";
+ reg = <0x44>;
+ interrupt-parent = <&lsio_gpio4>;
+ interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
+ };
+
+ pressure-sensor@60 {
+ compatible = "fsl,mpl3115";
+ reg = <0x60>;
+ };
+
+ max7322: gpio@68 {
+ compatible = "maxim,max7322";
+ reg = <0x68>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gyrometer@69 {
+ compatible = "st,l3g4200d-gyro";
+ reg = <0x69>;
+ };
+};
+
&i2c1 {
#address-cells = <1>;
#size-cells = <0>;
@@ -65,6 +224,42 @@
scl-gpios = <&lsio_gpio0 14 GPIO_ACTIVE_HIGH>;
sda-gpios = <&lsio_gpio0 15 GPIO_ACTIVE_HIGH>;
status = "okay";
+
+ wm8960: audio-codec@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ 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>;
+ wlf,shared-lrclk;
+ wlf,hp-cfg = <2 2 3>;
+ wlf,gpio-cfg = <1 3>;
+ };
+};
+
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can01_stby>;
+ status = "okay";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can01_stby>;
+ status = "okay";
+};
+
+&flexcan3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan3>;
+ xceiver-supply = <&reg_can2_stby>;
+ status = "okay";
};
&lpuart0 {
@@ -100,6 +295,14 @@
};
};
+&lsio_mu5 {
+ status = "okay";
+};
+
+&lsio_mu6 {
+ status = "okay";
+};
+
&flexspi0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexspi0>;
@@ -140,6 +343,19 @@
};
};
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec2>;
+ phy-mode = "rgmii-txid";
+ phy-handle = <&ethphy1>;
+ phy-supply = <&reg_fec2_supply>;
+ nvmem-cells = <&fec_mac1>;
+ nvmem-cell-names = "mac-address";
+ rx-internal-delay-ps = <2000>;
+ fsl,magic-packet;
+ status = "okay";
+};
+
&usdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1>;
@@ -160,7 +376,71 @@
status = "okay";
};
+&sai0 {
+ #sound-dai-cells = <0>;
+ 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_4>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai0>;
+ status = "okay";
+};
+
+&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_4>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1>;
+ status = "okay";
+};
+
+&sai6 {
+ assigned-clocks = <&acm IMX_ADMA_ACM_SAI6_MCLK_SEL>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_MST_BUS>,
+ <&sai6_lpcg IMX_LPCG_CLK_4>;
+ assigned-clock-parents = <&aud_pll_div1_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <0>, <786432000>, <98304000>, <12288000>, <98304000>;
+ fsl,sai-asynchronous;
+ status = "okay";
+};
+
+&sai7 {
+ assigned-clocks = <&acm IMX_ADMA_ACM_SAI7_MCLK_SEL>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_MST_BUS>,
+ <&sai7_lpcg IMX_LPCG_CLK_4>;
+ assigned-clock-parents = <&aud_pll_div1_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <0>, <786432000>, <98304000>, <12288000>, <98304000>;
+ fsl,sai-asynchronous;
+ status = "okay";
+};
+
&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ IMX8QM_MCLK_OUT0_AUD_ACM_MCLK_OUT0 0x0600004c
+ IMX8QM_SCU_GPIO0_03_LSIO_GPIO0_IO31 0x0600004c
+ >;
+ };
+
+ pinctrl_i2c0: i2c0grp {
+ fsl,pins = <
+ IMX8QM_HDMI_TX0_TS_SCL_DMA_I2C0_SCL 0x06000021
+ IMX8QM_HDMI_TX0_TS_SDA_DMA_I2C0_SDA 0x06000021
+ >;
+ };
+
pinctrl_i2c1: i2c1grp {
fsl,pins = <
IMX8QM_GPT0_CLK_DMA_I2C1_SCL 0x0600004c
@@ -181,6 +461,13 @@
>;
};
+ pinctrl_cm41_i2c: cm41i2cgrp {
+ fsl,pins = <
+ IMX8QM_M41_I2C0_SDA_M41_I2C0_SDA 0x0600004c
+ IMX8QM_M41_I2C0_SCL_M41_I2C0_SCL 0x0600004c
+ >;
+ };
+
pinctrl_fec1: fec1grp {
fsl,pins = <
IMX8QM_ENET0_MDC_CONN_ENET0_MDC 0x06000020
@@ -235,6 +522,45 @@
>;
};
+ pinctrl_fec2: fec2grp {
+ fsl,pins = <
+ IMX8QM_COMP_CTL_GPIO_1V8_3V3_ENET_ENETA_PAD 0x000014a0
+ IMX8QM_ENET1_RGMII_TX_CTL_CONN_ENET1_RGMII_TX_CTL 0x00000060
+ IMX8QM_ENET1_RGMII_TXC_CONN_ENET1_RGMII_TXC 0x00000060
+ IMX8QM_ENET1_RGMII_TXD0_CONN_ENET1_RGMII_TXD0 0x00000060
+ IMX8QM_ENET1_RGMII_TXD1_CONN_ENET1_RGMII_TXD1 0x00000060
+ IMX8QM_ENET1_RGMII_TXD2_CONN_ENET1_RGMII_TXD2 0x00000060
+ IMX8QM_ENET1_RGMII_TXD3_CONN_ENET1_RGMII_TXD3 0x00000060
+ IMX8QM_ENET1_RGMII_RXC_CONN_ENET1_RGMII_RXC 0x00000060
+ IMX8QM_ENET1_RGMII_RX_CTL_CONN_ENET1_RGMII_RX_CTL 0x00000060
+ IMX8QM_ENET1_RGMII_RXD0_CONN_ENET1_RGMII_RXD0 0x00000060
+ IMX8QM_ENET1_RGMII_RXD1_CONN_ENET1_RGMII_RXD1 0x00000060
+ IMX8QM_ENET1_RGMII_RXD2_CONN_ENET1_RGMII_RXD2 0x00000060
+ IMX8QM_ENET1_RGMII_RXD3_CONN_ENET1_RGMII_RXD3 0x00000060
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan0grp {
+ fsl,pins = <
+ IMX8QM_FLEXCAN0_TX_DMA_FLEXCAN0_TX 0x21
+ IMX8QM_FLEXCAN0_RX_DMA_FLEXCAN0_RX 0x21
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan1grp {
+ fsl,pins = <
+ IMX8QM_FLEXCAN1_TX_DMA_FLEXCAN1_TX 0x21
+ IMX8QM_FLEXCAN1_RX_DMA_FLEXCAN1_RX 0x21
+ >;
+ };
+
+ pinctrl_flexcan3: flexcan3grp {
+ fsl,pins = <
+ IMX8QM_FLEXCAN2_TX_DMA_FLEXCAN2_TX 0x21
+ IMX8QM_FLEXCAN2_RX_DMA_FLEXCAN2_RX 0x21
+ >;
+ };
+
pinctrl_lpuart0: lpuart0grp {
fsl,pins = <
IMX8QM_UART0_RX_DMA_UART0_RX 0x06000020
@@ -256,6 +582,24 @@
>;
};
+ pinctrl_sai0: sai0grp {
+ fsl,pins = <
+ IMX8QM_SPI0_CS1_AUD_SAI0_TXC 0x0600004c
+ IMX8QM_SPI2_CS1_AUD_SAI0_TXFS 0x0600004c
+ IMX8QM_SAI1_RXFS_AUD_SAI0_RXD 0x0600004c
+ IMX8QM_SAI1_RXC_AUD_SAI0_TXD 0x0600006c
+ >;
+ };
+
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ IMX8QM_SAI1_RXD_AUD_SAI1_RXD 0x06000040
+ IMX8QM_SAI1_TXFS_AUD_SAI1_TXFS 0x06000040
+ IMX8QM_SAI1_TXD_AUD_SAI1_TXD 0x06000060
+ IMX8QM_SAI1_TXC_AUD_SAI1_TXC 0x06000040
+ >;
+ };
+
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-audio.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-audio.dtsi
new file mode 100644
index 000000000000..3036af49fc85
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-audio.dtsi
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ * Dong Aisheng <[email protected]>
+ */
+
+/delete-node/ &acm;
+/delete-node/ &sai4;
+/delete-node/ &sai5;
+/delete-node/ &sai4_lpcg;
+/delete-node/ &sai5_lpcg;
+
+&amix {
+ dais = <&sai6>, <&sai7>;
+};
+
+&asrc0 {
+ clocks = <&asrc0_lpcg IMX_LPCG_CLK_0>,
+ <&asrc0_lpcg IMX_LPCG_CLK_2>,
+ <&aud_pll_div0_lpcg IMX_LPCG_CLK_0>,
+ <&aud_pll_div1_lpcg IMX_LPCG_CLK_0>,
+ <&acm IMX_ADMA_ACM_AUD_CLK0_SEL>,
+ <&acm IMX_ADMA_ACM_AUD_CLK1_SEL>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ power-domains = <&pd IMX_SC_R_ASRC_0>;
+};
+
+&asrc0_lpcg {
+ clocks = <&audio_ipg_clk>,
+ <&audio_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_2>;
+ clock-output-names = "asrc0_lpcg_ipg_clk", "asrc0_lpcg_mem_clk";
+};
+
+&asrc1 {
+ clocks = <&asrc1_lpcg IMX_LPCG_CLK_0>,
+ <&asrc1_lpcg IMX_LPCG_CLK_2>,
+ <&aud_pll_div0_lpcg IMX_LPCG_CLK_0>,
+ <&aud_pll_div1_lpcg IMX_LPCG_CLK_0>,
+ <&acm IMX_ADMA_ACM_AUD_CLK0_SEL>,
+ <&acm IMX_ADMA_ACM_AUD_CLK1_SEL>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ power-domains = <&pd IMX_SC_R_ASRC_1>;
+};
+
+&asrc1_lpcg {
+ clocks = <&audio_ipg_clk>, <&audio_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_2>;
+ clock-output-names = "asrc1_lpcg_ipg_clk", "asrc1_lpcg_mem_clk";
+};
+
+&audio_subsys {
+
+ sai4: sai@59080000 {
+ compatible = "fsl,imx8qm-sai";
+ reg = <0x59080000 0x10000>;
+ interrupts = <GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sai4_lpcg IMX_LPCG_CLK_0>,
+ <&clk_dummy>,
+ <&sai4_lpcg IMX_LPCG_CLK_4>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dma-names = "rx";
+ dmas = <&edma0 18 0 1>;
+ fsl,dataline = <0 0xf 0x0>;
+ power-domains = <&pd IMX_SC_R_SAI_4>;
+ status = "disabled";
+ };
+
+ sai5: sai@59090000 {
+ compatible = "fsl,imx8qm-sai";
+ reg = <0x59090000 0x10000>;
+ interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sai5_lpcg IMX_LPCG_CLK_0>,
+ <&clk_dummy>,
+ <&sai5_lpcg IMX_LPCG_CLK_4>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dma-names = "tx";
+ dmas = <&edma0 19 0 0>;
+ fsl,dataline = <0 0x0 0xf>;
+ power-domains = <&pd IMX_SC_R_SAI_5>;
+ status = "disabled";
+ };
+
+ sai4_lpcg: clock-controller@59480000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x59480000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&acm IMX_ADMA_ACM_SAI4_MCLK_SEL>,
+ <&audio_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "sai4_lpcg_mclk", "sai4_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_SAI_4>;
+ status = "disabled";
+ };
+
+ sai5_lpcg: clock-controller@59490000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x59490000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&acm IMX_ADMA_ACM_SAI5_MCLK_SEL>,
+ <&audio_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "sai5_lpcg_mclk", "sai5_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_SAI_5>;
+ status = "disabled";
+ };
+
+ esai1: esai@59810000 {
+ compatible = "fsl,imx8qm-esai";
+ reg = <0x59810000 0x10000>;
+ interrupts = <GIC_SPI 411 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&esai1_lpcg IMX_LPCG_CLK_0>,
+ <&esai1_lpcg IMX_LPCG_CLK_4>,
+ <&esai1_lpcg IMX_LPCG_CLK_0>,
+ <&clk_dummy>;
+ clock-names = "core", "extal", "fsys", "spba";
+ dmas = <&edma1 6 0 1>, <&edma1 7 0 0>;
+ dma-names = "rx", "tx";
+ power-domains = <&pd IMX_SC_R_ESAI_1>;
+ status = "disabled";
+ };
+
+ sai6: sai@59820000 {
+ compatible = "fsl,imx8qm-sai";
+ reg = <0x59820000 0x10000>;
+ interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sai6_lpcg IMX_LPCG_CLK_0>,
+ <&clk_dummy>,
+ <&sai6_lpcg IMX_LPCG_CLK_4>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dma-names = "rx", "tx";
+ dmas = <&edma1 8 0 1>, <&edma1 9 0 0>;
+ power-domains = <&pd IMX_SC_R_SAI_6>;
+ status = "disabled";
+ };
+
+ sai7: sai@59830000 {
+ compatible = "fsl,imx8qm-sai";
+ reg = <0x59830000 0x10000>;
+ interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sai7_lpcg IMX_LPCG_CLK_0>,
+ <&clk_dummy>,
+ <&sai7_lpcg IMX_LPCG_CLK_4>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dma-names = "tx";
+ dmas = <&edma1 10 0 0>;
+ power-domains = <&pd IMX_SC_R_SAI_7>;
+ status = "disabled";
+ };
+
+ esai1_lpcg: clock-controller@59c10000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x59c10000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&acm IMX_ADMA_ACM_ESAI1_MCLK_SEL>,
+ <&audio_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "esai1_lpcg_extal_clk", "esai1_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_ESAI_1>;
+ };
+
+ sai6_lpcg: clock-controller@59c20000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x59c20000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&acm IMX_ADMA_ACM_SAI6_MCLK_SEL>,
+ <&audio_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "sai6_lpcg_mclk", "sai6_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_SAI_6>;
+ };
+
+ sai7_lpcg: clock-controller@59c30000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x59c30000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&acm IMX_ADMA_ACM_SAI7_MCLK_SEL>,
+ <&audio_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "sai7_lpcg_mclk", "sai7_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_SAI_7>;
+ };
+
+ acm: acm@59e00000 {
+ compatible = "fsl,imx8qm-acm";
+ reg = <0x59e00000 0x1d0000>;
+ #clock-cells = <1>;
+ power-domains = <&pd IMX_SC_R_AUDIO_CLK_0>,
+ <&pd IMX_SC_R_AUDIO_CLK_1>,
+ <&pd IMX_SC_R_MCLK_OUT_0>,
+ <&pd IMX_SC_R_MCLK_OUT_1>,
+ <&pd IMX_SC_R_AUDIO_PLL_0>,
+ <&pd IMX_SC_R_AUDIO_PLL_1>,
+ <&pd IMX_SC_R_ASRC_0>,
+ <&pd IMX_SC_R_ASRC_1>,
+ <&pd IMX_SC_R_ESAI_0>,
+ <&pd IMX_SC_R_ESAI_1>,
+ <&pd IMX_SC_R_SAI_0>,
+ <&pd IMX_SC_R_SAI_1>,
+ <&pd IMX_SC_R_SAI_2>,
+ <&pd IMX_SC_R_SAI_3>,
+ <&pd IMX_SC_R_SAI_4>,
+ <&pd IMX_SC_R_SAI_5>,
+ <&pd IMX_SC_R_SAI_6>,
+ <&pd IMX_SC_R_SAI_7>,
+ <&pd IMX_SC_R_SPDIF_0>,
+ <&pd IMX_SC_R_SPDIF_1>,
+ <&pd IMX_SC_R_MQS_0>;
+ clocks = <&aud_rec0_lpcg IMX_LPCG_CLK_0>,
+ <&aud_rec1_lpcg IMX_LPCG_CLK_0>,
+ <&aud_pll_div0_lpcg IMX_LPCG_CLK_0>,
+ <&aud_pll_div1_lpcg IMX_LPCG_CLK_0>,
+ <&clk_mlb_clk>,
+ <&clk_hdmi_rx_mclk>,
+ <&clk_ext_aud_mclk0>,
+ <&clk_ext_aud_mclk1>,
+ <&clk_esai0_rx_clk>,
+ <&clk_esai0_rx_hf_clk>,
+ <&clk_esai0_tx_clk>,
+ <&clk_esai0_tx_hf_clk>,
+ <&clk_esai1_rx_clk>,
+ <&clk_esai1_rx_hf_clk>,
+ <&clk_esai1_tx_clk>,
+ <&clk_esai1_tx_hf_clk>,
+ <&clk_spdif0_rx>,
+ <&clk_spdif0_rx>,
+ <&clk_sai0_rx_bclk>,
+ <&clk_sai0_tx_bclk>,
+ <&clk_sai1_rx_bclk>,
+ <&clk_sai1_tx_bclk>,
+ <&clk_sai2_rx_bclk>,
+ <&clk_sai3_rx_bclk>,
+ <&clk_sai4_rx_bclk>,
+ <&clk_sai5_rx_bclk>,
+ <&clk_sai6_rx_bclk>;
+ clock-names = "aud_rec_clk0_lpcg_clk",
+ "aud_rec_clk1_lpcg_clk",
+ "aud_pll_div_clk0_lpcg_clk",
+ "aud_pll_div_clk1_lpcg_clk",
+ "mlb_clk",
+ "hdmi_rx_mclk",
+ "ext_aud_mclk0",
+ "ext_aud_mclk1",
+ "esai0_rx_clk",
+ "esai0_rx_hf_clk",
+ "esai0_tx_clk",
+ "esai0_tx_hf_clk",
+ "esai1_rx_clk",
+ "esai1_rx_hf_clk",
+ "esai1_tx_clk",
+ "esai1_tx_hf_clk",
+ "spdif0_rx",
+ "spdif1_rx",
+ "sai0_rx_bclk",
+ "sai0_tx_bclk",
+ "sai1_rx_bclk",
+ "sai1_tx_bclk",
+ "sai2_rx_bclk",
+ "sai3_rx_bclk",
+ "sai4_rx_bclk",
+ "sai5_tx_bclk",
+ "sai6_rx_bclk";
+ };
+};
+
+&dsp_lpcg {
+ status = "disabled";
+};
+
+&dsp_ram_lpcg {
+ status = "disabled";
+};
+
+/* edma2 called in imx8qm RM with the same address in edma0 of imx8qxp */
+&edma0{
+ reg = <0x591f0000 0x150000>;
+ dma-channels = <20>;
+ dma-channel-mask = <0>;
+ interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>, /* asrc0 */
+ <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 410 IRQ_TYPE_LEVEL_HIGH>, /* esai0 */
+ <GIC_SPI 410 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>, /* spdif0 */
+ <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 461 IRQ_TYPE_LEVEL_HIGH>, /* spdif1 */
+ <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>, /* sai0 */
+ <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>, /* sai1 */
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>, /* sai2 */
+ <GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH>, /* sai3 */
+ <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>, /* sai4 */
+ <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>; /* sai5 */
+ power-domains = <&pd IMX_SC_R_DMA_2_CH0>,
+ <&pd IMX_SC_R_DMA_2_CH1>,
+ <&pd IMX_SC_R_DMA_2_CH2>,
+ <&pd IMX_SC_R_DMA_2_CH3>,
+ <&pd IMX_SC_R_DMA_2_CH4>,
+ <&pd IMX_SC_R_DMA_2_CH5>,
+ <&pd IMX_SC_R_DMA_2_CH6>,
+ <&pd IMX_SC_R_DMA_2_CH7>,
+ <&pd IMX_SC_R_DMA_2_CH8>,
+ <&pd IMX_SC_R_DMA_2_CH9>,
+ <&pd IMX_SC_R_DMA_2_CH10>,
+ <&pd IMX_SC_R_DMA_2_CH11>,
+ <&pd IMX_SC_R_DMA_2_CH12>,
+ <&pd IMX_SC_R_DMA_2_CH13>,
+ <&pd IMX_SC_R_DMA_2_CH14>,
+ <&pd IMX_SC_R_DMA_2_CH15>,
+ <&pd IMX_SC_R_DMA_2_CH16>,
+ <&pd IMX_SC_R_DMA_2_CH17>,
+ <&pd IMX_SC_R_DMA_2_CH18>,
+ <&pd IMX_SC_R_DMA_2_CH19>;
+};
+
+/* edma3 called in imx8qm RM with the same address in edma1 of imx8qxp */
+&edma1{
+ reg = <0x599f0000 0xc0000>;
+ dma-channels = <11>;
+ dma-channel-mask = <0xc0>;
+ interrupts = <GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH>, /* asrc1 */
+ <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 385 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 387 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* no used */
+ <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* no used */
+ <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>, /* sai6 */
+ <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>; /* sai7 */
+ power-domains = <&pd IMX_SC_R_DMA_3_CH0>,
+ <&pd IMX_SC_R_DMA_3_CH1>,
+ <&pd IMX_SC_R_DMA_3_CH2>,
+ <&pd IMX_SC_R_DMA_3_CH3>,
+ <&pd IMX_SC_R_DMA_3_CH4>,
+ <&pd IMX_SC_R_DMA_3_CH5>,
+ <&pd IMX_SC_R_DMA_3_CH6>,
+ <&pd IMX_SC_R_DMA_3_CH7>,
+ <&pd IMX_SC_R_DMA_3_CH8>,
+ <&pd IMX_SC_R_DMA_3_CH9>,
+ <&pd IMX_SC_R_DMA_3_CH10>;
+};
+
+&esai0 {
+ clocks = <&esai0_lpcg IMX_LPCG_CLK_0>,
+ <&esai0_lpcg IMX_LPCG_CLK_4>,
+ <&esai0_lpcg IMX_LPCG_CLK_0>,
+ <&clk_dummy>;
+ power-domains = <&pd IMX_SC_R_ESAI_0>;
+};
+
+&esai0_lpcg {
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "esai0_lpcg_extal_clk", "esai0_lpcg_ipg_clk";
+};
+
+&mqs0_lpcg {
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "mqs0_lpcg_mclk", "mqs0_lpcg_ipg_clk";
+};
+
+&sai0 {
+ clocks = <&sai0_lpcg IMX_LPCG_CLK_0>,
+ <&clk_dummy>,
+ <&sai0_lpcg IMX_LPCG_CLK_4>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ power-domains = <&pd IMX_SC_R_SAI_0>;
+};
+
+&sai0_lpcg {
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "sai0_lpcg_mclk", "sai0_lpcg_ipg_clk";
+};
+
+&sai1 {
+ clocks = <&sai1_lpcg IMX_LPCG_CLK_0>,
+ <&clk_dummy>,
+ <&sai1_lpcg IMX_LPCG_CLK_4>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ power-domains = <&pd IMX_SC_R_SAI_1>;
+};
+
+&sai1_lpcg {
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "sai1_lpcg_mclk", "sai1_lpcg_ipg_clk";
+};
+
+&sai2 {
+ clocks = <&sai2_lpcg IMX_LPCG_CLK_0>,
+ <&clk_dummy>,
+ <&sai2_lpcg IMX_LPCG_CLK_4>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ power-domains = <&pd IMX_SC_R_SAI_2>;
+};
+
+&sai2_lpcg {
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "sai2_lpcg_mclk", "sai2_lpcg_ipg_clk";
+};
+
+&sai3 {
+ clocks = <&sai3_lpcg IMX_LPCG_CLK_0>,
+ <&clk_dummy>,
+ <&sai3_lpcg IMX_LPCG_CLK_4>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ power-domains = <&pd IMX_SC_R_SAI_3>;
+};
+
+&sai3_lpcg {
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_0>;
+ clock-output-names = "sai3_lpcg_mclk", "sai3_lpcg_ipg_clk";
+};
+
+&spdif0 {
+ clocks = <&spdif0_lpcg IMX_LPCG_CLK_4>, /* core */
+ <&clk_dummy>, /* rxtx0 */
+ <&spdif0_lpcg IMX_LPCG_CLK_5>, /* rxtx1 */
+ <&clk_dummy>, /* rxtx2 */
+ <&clk_dummy>, /* rxtx3 */
+ <&clk_dummy>, /* rxtx4 */
+ <&audio_ipg_clk>, /* rxtx5 */
+ <&clk_dummy>, /* rxtx6 */
+ <&clk_dummy>, /* rxtx7 */
+ <&clk_dummy>; /* spba */
+ power-domains = <&pd IMX_SC_R_SPDIF_0>;
+};
+
+&spdif0_lpcg {
+ clock-indices = <IMX_LPCG_CLK_5>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "spdif0_lpcg_tx_clk", "spdif0_lpcg_gclkw";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm.dtsi b/arch/arm64/boot/dts/freescale/imx8qm.dtsi
index b3d01677b70c..61986e0639e5 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm.dtsi
@@ -333,6 +333,21 @@
compatible = "fsl,imx8qxp-sc-rtc";
};
+ ocotp: ocotp {
+ compatible = "fsl,imx8qm-scu-ocotp";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ read-only;
+
+ fec_mac0: mac@1c4 {
+ reg = <0x1c4 6>;
+ };
+
+ fec_mac1: mac@1c6 {
+ reg = <0x1c6 6>;
+ };
+ };
+
tsens: thermal-sensor {
compatible = "fsl,imx8qxp-sc-thermal", "fsl,imx-sc-thermal";
#thermal-sensor-cells = <1>;
@@ -461,8 +476,95 @@
};
};
+ clk_dummy: clock-dummy {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "clk_dummy";
+ };
+
+ clk_esai1_rx_clk: clock-esai1-rx {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "esai1_rx_clk";
+ };
+
+ clk_esai1_rx_hf_clk: clock-esai1-rx-hf {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "esai1_rx_hf_clk";
+ };
+
+ clk_esai1_tx_clk: clock-esai1-tx {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "esai1_tx_clk";
+ };
+
+ clk_esai1_tx_hf_clk: clock-esai1-tx-hf {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "esai1_tx_hf_clk";
+ };
+
+ clk_hdmi_rx_mclk: clock-hdmi-rx-mclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "hdmi-rx-mclk";
+ };
+
+ clk_mlb_clk: clock-mlb-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "mlb_clk";
+ };
+
+ clk_sai5_rx_bclk: clock-sai5-rx-bclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "sai5_rx_bclk";
+ };
+
+ clk_sai5_tx_bclk: clock-sai5-tx-bclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "sai5_tx_bclk";
+ };
+
+ clk_sai6_rx_bclk: clock-sai6-rx-bclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "sai6_rx_bclk";
+ };
+
+ clk_sai6_tx_bclk: clock-sai6-tx-bclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "sai6_tx_bclk";
+ };
+
+ clk_spdif1_rx: clock-spdif1-rx {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "spdif1_rx";
+ };
+
/* sorted in register address */
+ #include "imx8-ss-cm41.dtsi"
+ #include "imx8-ss-audio.dtsi"
#include "imx8-ss-vpu.dtsi"
+ #include "imx8-ss-gpu0.dtsi"
#include "imx8-ss-img.dtsi"
#include "imx8-ss-dma.dtsi"
#include "imx8-ss-conn.dtsi"
@@ -473,3 +575,4 @@
#include "imx8qm-ss-dma.dtsi"
#include "imx8qm-ss-conn.dtsi"
#include "imx8qm-ss-lsio.dtsi"
+#include "imx8qm-ss-audio.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
index cee13e58762c..936ba5ecdcac 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
@@ -63,6 +63,7 @@
};
&dsp {
+ memory-region = <&dsp_reserved>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
index bd98eff4d685..a15987f49e8d 100644
--- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
@@ -97,89 +97,6 @@
status = "okay";
};
-&mu1 {
- status = "okay";
-};
-
-&mu2 {
- status = "okay";
-};
-
-&lpi2c3 {
- #address-cells = <1>;
- #size-cells = <0>;
- clock-frequency = <400000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_lpi2c3>;
- status = "okay";
-
- ptn5110: tcpc@50 {
- compatible = "nxp,ptn5110", "tcpci";
- reg = <0x50>;
- interrupt-parent = <&gpio3>;
- interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
-
- typec1_con: 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>;
- };
- };
- };
- };
- };
-
- ptn5110_2: tcpc@51 {
- compatible = "nxp,ptn5110", "tcpci";
- reg = <0x51>;
- interrupt-parent = <&gpio3>;
- interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
-
- typec2_con: 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>;
-
- typec2_dr_sw: endpoint {
- remote-endpoint = <&usb2_drd_sw>;
- };
- };
- };
- };
- };
-};
-
&eqos {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_eqos>;
@@ -228,81 +145,6 @@
};
};
-&lpuart1 { /* console */
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart1>;
- status = "okay";
-};
-
-&lpuart5 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart5>;
- status = "okay";
-};
-
-&usbotg1 {
- dr_mode = "otg";
- hnp-disable;
- srp-disable;
- adp-disable;
- usb-role-switch;
- disable-over-current;
- samsung,picophy-pre-emp-curr-control = <3>;
- samsung,picophy-dc-vol-level-adjust = <7>;
- status = "okay";
-
- port {
- usb1_drd_sw: endpoint {
- remote-endpoint = <&typec1_dr_sw>;
- };
- };
-};
-
-&usbotg2 {
- dr_mode = "otg";
- hnp-disable;
- srp-disable;
- adp-disable;
- usb-role-switch;
- disable-over-current;
- samsung,picophy-pre-emp-curr-control = <3>;
- samsung,picophy-dc-vol-level-adjust = <7>;
- status = "okay";
-
- port {
- usb2_drd_sw: endpoint {
- remote-endpoint = <&typec2_dr_sw>;
- };
- };
-};
-
-&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";
-};
-
-&usdhc2 {
- pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
- pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
- pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
- pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
- pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_usdhc2_gpio_sleep>;
- cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>;
- vmmc-supply = <&reg_usdhc2_vmmc>;
- bus-width = <4>;
- status = "okay";
- no-mmc;
-};
-
-&wdog3 {
- status = "okay";
-};
-
&lpi2c2 {
#address-cells = <1>;
#size-cells = <0>;
@@ -402,11 +244,79 @@
};
&lpi2c3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lpi2c3>;
status = "okay";
+ ptn5110: tcpc@50 {
+ compatible = "nxp,ptn5110", "tcpci";
+ reg = <0x50>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+
+ typec1_con: 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>;
+ };
+ };
+ };
+ };
+ };
+
+ ptn5110_2: tcpc@51 {
+ compatible = "nxp,ptn5110", "tcpci";
+ reg = <0x51>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+
+ typec2_con: 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>;
+
+ typec2_dr_sw: endpoint {
+ remote-endpoint = <&usb2_drd_sw>;
+ };
+ };
+ };
+ };
+ };
+
pcf2131: rtc@53 {
compatible = "nxp,pcf2131";
reg = <0x53>;
@@ -415,6 +325,89 @@
};
};
+&lpuart1 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&lpuart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5>;
+ status = "okay";
+};
+
+&mu1 {
+ status = "okay";
+};
+
+&mu2 {
+ status = "okay";
+};
+
+&usbotg1 {
+ dr_mode = "otg";
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+ usb-role-switch;
+ disable-over-current;
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ status = "okay";
+
+ port {
+ usb1_drd_sw: endpoint {
+ remote-endpoint = <&typec1_dr_sw>;
+ };
+ };
+};
+
+&usbotg2 {
+ dr_mode = "otg";
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+ usb-role-switch;
+ disable-over-current;
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ status = "okay";
+
+ port {
+ usb2_drd_sw: endpoint {
+ remote-endpoint = <&typec2_dr_sw>;
+ };
+ };
+};
+
+&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";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_usdhc2_gpio_sleep>;
+ cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ bus-width = <4>;
+ status = "okay";
+ no-mmc;
+};
+
+&wdog3 {
+ status = "okay";
+};
+
&iomuxc {
pinctrl_eqos: eqosgrp {
fsl,pins = <
diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts
new file mode 100644
index 000000000000..950dece83c24
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts
@@ -0,0 +1,492 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright 2024 NXP
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/usb/pd.h>
+#include "imx93.dtsi"
+
+/ {
+ model = "NXP i.MX93 9x9 Quick Start Board";
+ compatible = "fsl,imx93-9x9-qsb", "fsl,imx93";
+
+ chosen {
+ stdout-path = &lpuart1;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0 0x10000000>;
+ linux,cma-default;
+ };
+
+ vdev0vring0: vdev0vring0@a4000000 {
+ reg = <0 0xa4000000 0 0x8000>;
+ no-map;
+ };
+
+ vdev0vring1: vdev0vring1@a4008000 {
+ reg = <0 0xa4008000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring0: vdev1vring0@a4010000 {
+ reg = <0 0xa4010000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring1: vdev1vring1@a4018000 {
+ reg = <0 0xa4018000 0 0x8000>;
+ no-map;
+ };
+
+ rsc_table: rsc-table@2021e000 {
+ reg = <0 0x2021e000 0 0x1000>;
+ no-map;
+ };
+
+ vdevbuffer: vdevbuffer@a4020000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0xa4020000 0 0x100000>;
+ no-map;
+ };
+
+ };
+
+ reg_vref_1v8: regulator-adc-vref {
+ compatible = "regulator-fixed";
+ regulator-name = "VREF_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_rpi_3v3: regulator-rpi {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_RPI_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pcal6524 21 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ off-on-delay-us = <12000>;
+ };
+};
+
+&adc1 {
+ vref-supply = <&reg_vref_1v8>;
+ status = "okay";
+};
+
+&cm33 {
+ mbox-names = "tx", "rx", "rxdb";
+ mboxes = <&mu1 0 1>,
+ <&mu1 1 1>,
+ <&mu1 3 1>;
+ memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>,
+ <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>;
+ status = "okay";
+};
+
+&eqos {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_eqos>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy1>;
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <5000000>;
+
+ ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ eee-broken-1000t;
+ reset-gpios = <&pcal6524 15 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <80000>;
+ realtek,clkout-disable;
+ };
+ };
+};
+
+&lpi2c1 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c1>;
+ status = "okay";
+
+ ptn5110: tcpc@50 {
+ compatible = "nxp,ptn5110", "tcpci";
+ reg = <0x50>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+
+ typec1_con: 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>;
+ };
+ };
+ };
+ };
+ };
+
+ rtc@53 {
+ compatible = "nxp,pcf2131";
+ reg = <0x53>;
+ interrupt-parent = <&pcal6524>;
+ interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+ };
+};
+
+&lpi2c2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c2>;
+ status = "okay";
+
+ pcal6524: gpio@22 {
+ compatible = "nxp,pcal6524";
+ reg = <0x22>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcal6524>;
+ };
+
+ pmic@25 {
+ compatible = "nxp,pca9451a";
+ reg = <0x25>;
+ interrupt-parent = <&pcal6524>;
+ interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
+
+ regulators {
+ buck1: BUCK1 {
+ regulator-name = "BUCK1";
+ regulator-min-microvolt = <650000>;
+ regulator-max-microvolt = <2237500>;
+ 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>;
+ };
+
+ 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;
+ };
+
+ 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;
+ };
+ };
+ };
+};
+
+&lpuart1 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&mu1 {
+ status = "okay";
+};
+
+&mu2 {
+ status = "okay";
+};
+
+&usbotg1 {
+ dr_mode = "otg";
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+ usb-role-switch;
+ disable-over-current;
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ status = "okay";
+
+ port {
+ usb1_drd_sw: endpoint {
+ remote-endpoint = <&typec1_dr_sw>;
+ };
+ };
+};
+
+&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";
+};
+
+&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 = <&gpio3 0 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ bus-width = <4>;
+ no-mmc;
+ status = "okay";
+};
+
+&wdog3 {
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_eqos: eqosgrp {
+ fsl,pins = <
+ MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x57e
+ MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x57e
+ MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x57e
+ MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e
+ MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e
+ MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e
+ MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x58e
+ MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e
+ MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x57e
+ MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x57e
+ MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x57e
+ MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x57e
+ MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x58e
+ MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x57e
+ >;
+ };
+
+ pinctrl_lpi2c1: lpi2c1grp {
+ fsl,pins = <
+ MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e
+ MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e
+ >;
+ };
+
+ pinctrl_lpi2c2: lpi2c2grp {
+ fsl,pins = <
+ MX93_PAD_I2C2_SCL__LPI2C2_SCL 0x40000b9e
+ MX93_PAD_I2C2_SDA__LPI2C2_SDA 0x40000b9e
+ >;
+ };
+
+ pinctrl_pcal6524: pcal6524grp {
+ fsl,pins = <
+ MX93_PAD_CCM_CLKO1__GPIO3_IO26 0x31e
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX93_PAD_UART1_RXD__LPUART1_RX 0x31e
+ MX93_PAD_UART1_TXD__LPUART1_TX 0x31e
+ >;
+ };
+
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX93_PAD_DAP_TDO_TRACESWO__LPUART5_TX 0x31e
+ MX93_PAD_DAP_TDI__LPUART5_RX 0x31e
+ MX93_PAD_DAP_TMS_SWDIO__LPUART5_RTS_B 0x31e
+ MX93_PAD_DAP_TCLK_SWCLK__LPUART5_CTS_B 0x31e
+ >;
+ };
+
+ /* need to config the SION for data and cmd pad, refer to ERR052021 */
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX93_PAD_SD1_CLK__USDHC1_CLK 0x1582
+ MX93_PAD_SD1_CMD__USDHC1_CMD 0x40001382
+ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x40001382
+ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x40001382
+ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x40001382
+ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x40001382
+ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x40001382
+ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x40001382
+ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x40001382
+ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x40001382
+ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x1582
+ >;
+ };
+
+ /* need to config the SION for data and cmd pad, refer to ERR052021 */
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+ fsl,pins = <
+ MX93_PAD_SD1_CLK__USDHC1_CLK 0x158e
+ MX93_PAD_SD1_CMD__USDHC1_CMD 0x4000138e
+ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000138e
+ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x4000138e
+ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x4000138e
+ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x4000138e
+ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x4000138e
+ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x4000138e
+ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x4000138e
+ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x4000138e
+ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x158e
+ >;
+ };
+
+ /* need to config the SION for data and cmd pad, refer to ERR052021 */
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <
+ MX93_PAD_SD1_CLK__USDHC1_CLK 0x15fe
+ MX93_PAD_SD1_CMD__USDHC1_CMD 0x400013fe
+ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x400013fe
+ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x400013fe
+ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x400013fe
+ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x400013fe
+ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x400013fe
+ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x400013fe
+ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x400013fe
+ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x400013fe
+ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe
+ >;
+ };
+
+ pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp {
+ fsl,pins = <
+ MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+ fsl,pins = <
+ MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e
+ >;
+ };
+
+ /* need to config the SION for data and cmd pad, refer to ERR052021 */
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX93_PAD_SD2_CLK__USDHC2_CLK 0x1582
+ MX93_PAD_SD2_CMD__USDHC2_CMD 0x40001382
+ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x40001382
+ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x40001382
+ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x40001382
+ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x40001382
+ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e
+ >;
+ };
+
+ /* need to config the SION for data and cmd pad, refer to ERR052021 */
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX93_PAD_SD2_CLK__USDHC2_CLK 0x158e
+ MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000138e
+ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e
+ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e
+ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e
+ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e
+ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e
+ >;
+ };
+
+ /* need to config the SION for data and cmd pad, refer to ERR052021 */
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX93_PAD_SD2_CLK__USDHC2_CLK 0x15fe
+ MX93_PAD_SD2_CMD__USDHC2_CMD 0x400013fe
+ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x400013fe
+ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x400013fe
+ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x400013fe
+ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x400013fe
+ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts
index af795ecf678b..852dd3d2eac7 100644
--- a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts
@@ -303,6 +303,32 @@
reg = <0x1c>;
};
+ ptn5110: usb-typec@50 {
+ compatible = "nxp,ptn5110", "tcpci";
+ reg = <0x50>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_typec>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+
+ connector {
+ compatible = "usb-c-connector";
+ label = "X17";
+ power-role = "dual";
+ data-role = "dual";
+ try-power-role = "sink";
+ typec-power-opmode = "default";
+ pd-disable;
+ self-powered;
+
+ port {
+ typec_con_hs: endpoint {
+ remote-endpoint = <&typec_hs>;
+ };
+ };
+ };
+ };
+
eeprom2: eeprom@54 {
compatible = "nxp,se97b", "atmel,24c02";
reg = <0x54>;
@@ -371,18 +397,6 @@
"WLAN_PERST#", "12V_EN";
/*
- * Controls the on board USB Hub reset which is low
- * active as reset signal. The output-low states, the
- * signal is inactive, e.g. no reset
- */
- usb-reset-hog {
- gpio-hog;
- gpios = <2 GPIO_ACTIVE_LOW>;
- output-low;
- line-name = "USB_RESET#";
- };
-
- /*
* Controls the WiFi card PD pin which is low active
* as power down signal. The output-high states, the signal
* is active, e.g. card is powered down
@@ -492,6 +506,41 @@
status = "okay";
};
+&usbotg1 {
+ dr_mode = "otg";
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+ usb-role-switch;
+ disable-over-current;
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ status = "okay";
+
+ port {
+ typec_hs: endpoint {
+ remote-endpoint = <&typec_con_hs>;
+ };
+ };
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ disable-over-current;
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ status = "okay";
+
+ hub_2_0: hub@1 {
+ compatible = "usb424,2517";
+ reg = <1>;
+ reset-gpios = <&expander1 2 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&reg_3v3>;
+ };
+};
+
&usdhc2 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2_hs>, <&pinctrl_usdhc2_gpio>;
diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
index eb3f4cfb6986..da8f19a646a9 100644
--- a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts
@@ -252,6 +252,32 @@
reg = <0x1c>;
};
+ ptn5110: usb-typec@50 {
+ compatible = "nxp,ptn5110", "tcpci";
+ reg = <0x50>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_typec>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+
+ connector {
+ compatible = "usb-c-connector";
+ label = "X17";
+ power-role = "dual";
+ data-role = "dual";
+ try-power-role = "sink";
+ typec-power-opmode = "default";
+ pd-disable;
+ self-powered;
+
+ port {
+ typec_con_hs: endpoint {
+ remote-endpoint = <&typec_hs>;
+ };
+ };
+ };
+ };
+
eeprom2: eeprom@54 {
compatible = "nxp,se97b", "atmel,24c02";
reg = <0x54>;
@@ -433,6 +459,41 @@
pinctrl-0 = <&pinctrl_tpm5>;
};
+&usbotg1 {
+ dr_mode = "otg";
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+ usb-role-switch;
+ disable-over-current;
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ status = "okay";
+
+ port {
+ typec_hs: endpoint {
+ remote-endpoint = <&typec_con_hs>;
+ };
+ };
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ disable-over-current;
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ status = "okay";
+
+ hub_2_0: hub@1 {
+ compatible = "usb424,2517";
+ reg = <1>;
+ reset-gpios = <&expander1 2 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&reg_3v3>;
+ };
+};
+
&usdhc2 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2_hs>, <&pinctrl_usdhc2_gpio>;
diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi b/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi
index 9d2328c185c9..edbd8cad35bc 100644
--- a/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi
@@ -75,6 +75,12 @@
spi-max-frequency = <62000000>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts b/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts
new file mode 100644
index 000000000000..d14a54ab4fd4
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2024 NXP
+ */
+
+/dts-v1/;
+
+#include "imx95.dtsi"
+
+/ {
+ model = "NXP i.MX95 19X19 board";
+ compatible = "fsl,imx95-19x19-evk", "fsl,imx95";
+
+ aliases {
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ serial0 = &lpuart1;
+ };
+
+ chosen {
+ stdout-path = &lpuart1;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0 0x80000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ linux_cma: linux,cma {
+ compatible = "shared-dma-pool";
+ alloc-ranges = <0 0x80000000 0 0x7f000000>;
+ size = <0 0x3c000000>;
+ linux,cma-default;
+ reusable;
+ };
+ };
+
+ reg_m2_pwr: regulator-m2-pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "M.2-power";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&i2c7_pcal6524 20 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_pcie0: regulator-pcie {
+ compatible = "regulator-fixed";
+ regulator-name = "PCIE_WLAN_EN";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&reg_m2_pwr>;
+ gpio = <&i2c7_pcal6524 6 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_slot_pwr: regulator-slot-pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "PCIe slot-power";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&i2c7_pcal6524 14 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+ regulator-name = "VDD_SD2_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ off-on-delay-us = <12000>;
+ };
+};
+
+&lpi2c7 {
+ clock-frequency = <1000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c7>;
+ status = "okay";
+
+ i2c7_pcal6524: i2c7-gpio@22 {
+ compatible = "nxp,pcal6524";
+ reg = <0x22>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c7_pcal6524>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&lpuart1 {
+ /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&mu7 {
+ status = "okay";
+};
+
+&pcie0 {
+ pinctrl-0 = <&pinctrl_pcie0>;
+ pinctrl-names = "default";
+ reset-gpio = <&i2c7_pcal6524 5 GPIO_ACTIVE_LOW>;
+ vpcie-supply = <&reg_pcie0>;
+ status = "okay";
+};
+
+&pcie1 {
+ pinctrl-0 = <&pinctrl_pcie1>;
+ pinctrl-names = "default";
+ reset-gpio = <&i2c7_pcal6524 16 GPIO_ACTIVE_LOW>;
+ vpcie-supply = <&reg_slot_pwr>;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ pinctrl-3 = <&pinctrl_usdhc1>;
+ bus-width = <8>;
+ non-removable;
+ no-sdio;
+ no-sd;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-3 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&wdog3 {
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&scmi_iomuxc {
+ pinctrl_i2c7_pcal6524: i2c7pcal6524grp {
+ fsl,pins = <
+ IMX95_PAD_GPIO_IO36__GPIO5_IO_BIT16 0x31e
+ >;
+ };
+
+ pinctrl_lpi2c7: lpi2c7grp {
+ fsl,pins = <
+ IMX95_PAD_GPIO_IO08__LPI2C7_SDA 0x40000b9e
+ IMX95_PAD_GPIO_IO09__LPI2C7_SCL 0x40000b9e
+ >;
+ };
+
+ pinctrl_pcie0: pcie0grp {
+ fsl,pins = <
+ IMX95_PAD_GPIO_IO32__HSIOMIX_TOP_PCIE1_CLKREQ_B 0x4000031e
+ >;
+ };
+
+ pinctrl_pcie1: pcie1grp {
+ fsl,pins = <
+ IMX95_PAD_GPIO_IO35__HSIOMIX_TOP_PCIE2_CLKREQ_B 0x4000031e
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ IMX95_PAD_UART1_RXD__AONMIX_TOP_LPUART1_RX 0x31e
+ IMX95_PAD_UART1_TXD__AONMIX_TOP_LPUART1_TX 0x31e
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ IMX95_PAD_SD1_CLK__USDHC1_CLK 0x158e
+ IMX95_PAD_SD1_CMD__USDHC1_CMD 0x138e
+ IMX95_PAD_SD1_DATA0__USDHC1_DATA0 0x138e
+ IMX95_PAD_SD1_DATA1__USDHC1_DATA1 0x138e
+ IMX95_PAD_SD1_DATA2__USDHC1_DATA2 0x138e
+ IMX95_PAD_SD1_DATA3__USDHC1_DATA3 0x138e
+ IMX95_PAD_SD1_DATA4__USDHC1_DATA4 0x138e
+ IMX95_PAD_SD1_DATA5__USDHC1_DATA5 0x138e
+ IMX95_PAD_SD1_DATA6__USDHC1_DATA6 0x138e
+ IMX95_PAD_SD1_DATA7__USDHC1_DATA7 0x138e
+ IMX95_PAD_SD1_STROBE__USDHC1_STROBE 0x158e
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+ fsl,pins = <
+ IMX95_PAD_SD1_CLK__USDHC1_CLK 0x158e
+ IMX95_PAD_SD1_CMD__USDHC1_CMD 0x138e
+ IMX95_PAD_SD1_DATA0__USDHC1_DATA0 0x138e
+ IMX95_PAD_SD1_DATA1__USDHC1_DATA1 0x138e
+ IMX95_PAD_SD1_DATA2__USDHC1_DATA2 0x138e
+ IMX95_PAD_SD1_DATA3__USDHC1_DATA3 0x138e
+ IMX95_PAD_SD1_DATA4__USDHC1_DATA4 0x138e
+ IMX95_PAD_SD1_DATA5__USDHC1_DATA5 0x138e
+ IMX95_PAD_SD1_DATA6__USDHC1_DATA6 0x138e
+ IMX95_PAD_SD1_DATA7__USDHC1_DATA7 0x138e
+ IMX95_PAD_SD1_STROBE__USDHC1_STROBE 0x158e
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <
+ IMX95_PAD_SD1_CLK__USDHC1_CLK 0x15fe
+ IMX95_PAD_SD1_CMD__USDHC1_CMD 0x13fe
+ IMX95_PAD_SD1_DATA0__USDHC1_DATA0 0x13fe
+ IMX95_PAD_SD1_DATA1__USDHC1_DATA1 0x13fe
+ IMX95_PAD_SD1_DATA2__USDHC1_DATA2 0x13fe
+ IMX95_PAD_SD1_DATA3__USDHC1_DATA3 0x13fe
+ IMX95_PAD_SD1_DATA4__USDHC1_DATA4 0x13fe
+ IMX95_PAD_SD1_DATA5__USDHC1_DATA5 0x13fe
+ IMX95_PAD_SD1_DATA6__USDHC1_DATA6 0x13fe
+ IMX95_PAD_SD1_DATA7__USDHC1_DATA7 0x13fe
+ IMX95_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe
+ >;
+ };
+
+ pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp {
+ fsl,pins = <
+ IMX95_PAD_SD2_RESET_B__GPIO3_IO_BIT7 0x31e
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+ fsl,pins = <
+ IMX95_PAD_SD2_CD_B__GPIO3_IO_BIT0 0x31e
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ IMX95_PAD_SD2_CLK__USDHC2_CLK 0x158e
+ IMX95_PAD_SD2_CMD__USDHC2_CMD 0x138e
+ IMX95_PAD_SD2_DATA0__USDHC2_DATA0 0x138e
+ IMX95_PAD_SD2_DATA1__USDHC2_DATA1 0x138e
+ IMX95_PAD_SD2_DATA2__USDHC2_DATA2 0x138e
+ IMX95_PAD_SD2_DATA3__USDHC2_DATA3 0x138e
+ IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ IMX95_PAD_SD2_CLK__USDHC2_CLK 0x158e
+ IMX95_PAD_SD2_CMD__USDHC2_CMD 0x138e
+ IMX95_PAD_SD2_DATA0__USDHC2_DATA0 0x138e
+ IMX95_PAD_SD2_DATA1__USDHC2_DATA1 0x138e
+ IMX95_PAD_SD2_DATA2__USDHC2_DATA2 0x138e
+ IMX95_PAD_SD2_DATA3__USDHC2_DATA3 0x138e
+ IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ IMX95_PAD_SD2_CLK__USDHC2_CLK 0x15fe
+ IMX95_PAD_SD2_CMD__USDHC2_CMD 0x13fe
+ IMX95_PAD_SD2_DATA0__USDHC2_DATA0 0x13fe
+ IMX95_PAD_SD2_DATA1__USDHC2_DATA1 0x13fe
+ IMX95_PAD_SD2_DATA2__USDHC2_DATA2 0x13fe
+ IMX95_PAD_SD2_DATA3__USDHC2_DATA3 0x13fe
+ IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx95-clock.h b/arch/arm64/boot/dts/freescale/imx95-clock.h
new file mode 100644
index 000000000000..e1f91203e794
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx95-clock.h
@@ -0,0 +1,187 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+/*
+ * Copyright 2024 NXP
+ */
+
+#ifndef __CLOCK_IMX95_H
+#define __CLOCK_IMX95_H
+
+/* The index should match i.MX95 SCMI Firmware */
+#define IMX95_CLK_32K 1
+#define IMX95_CLK_24M 2
+#define IMX95_CLK_FRO 3
+#define IMX95_CLK_SYSPLL1_VCO 4
+#define IMX95_CLK_SYSPLL1_PFD0_UNGATED 5
+#define IMX95_CLK_SYSPLL1_PFD0 6
+#define IMX95_CLK_SYSPLL1_PFD0_DIV2 7
+#define IMX95_CLK_SYSPLL1_PFD1_UNGATED 8
+#define IMX95_CLK_SYSPLL1_PFD1 9
+#define IMX95_CLK_SYSPLL1_PFD1_DIV2 10
+#define IMX95_CLK_SYSPLL1_PFD2_UNGATED 11
+#define IMX95_CLK_SYSPLL1_PFD2 12
+#define IMX95_CLK_SYSPLL1_PFD2_DIV2 13
+#define IMX95_CLK_AUDIOPLL1_VCO 14
+#define IMX95_CLK_AUDIOPLL1 15
+#define IMX95_CLK_AUDIOPLL2_VCO 16
+#define IMX95_CLK_AUDIOPLL2 17
+#define IMX95_CLK_VIDEOPLL1_VCO 18
+#define IMX95_CLK_VIDEOPLL1 19
+#define IMX95_CLK_RESERVED20 20
+#define IMX95_CLK_RESERVED21 21
+#define IMX95_CLK_RESERVED22 22
+#define IMX95_CLK_RESERVED23 23
+#define IMX95_CLK_ARMPLL_VCO 24
+#define IMX95_CLK_ARMPLL_PFD0_UNGATED 25
+#define IMX95_CLK_ARMPLL_PFD0 26
+#define IMX95_CLK_ARMPLL_PFD1_UNGATED 27
+#define IMX95_CLK_ARMPLL_PFD1 28
+#define IMX95_CLK_ARMPLL_PFD2_UNGATED 29
+#define IMX95_CLK_ARMPLL_PFD2 30
+#define IMX95_CLK_ARMPLL_PFD3_UNGATED 31
+#define IMX95_CLK_ARMPLL_PFD3 32
+#define IMX95_CLK_DRAMPLL_VCO 33
+#define IMX95_CLK_DRAMPLL 34
+#define IMX95_CLK_HSIOPLL_VCO 35
+#define IMX95_CLK_HSIOPLL 36
+#define IMX95_CLK_LDBPLL_VCO 37
+#define IMX95_CLK_LDBPLL 38
+#define IMX95_CLK_EXT1 39
+#define IMX95_CLK_EXT2 40
+
+#define IMX95_CCM_NUM_CLK_SRC 41
+
+#define IMX95_CLK_ADC (IMX95_CCM_NUM_CLK_SRC + 0)
+#define IMX95_CLK_TMU (IMX95_CCM_NUM_CLK_SRC + 1)
+#define IMX95_CLK_BUSAON (IMX95_CCM_NUM_CLK_SRC + 2)
+#define IMX95_CLK_CAN1 (IMX95_CCM_NUM_CLK_SRC + 3)
+#define IMX95_CLK_I3C1 (IMX95_CCM_NUM_CLK_SRC + 4)
+#define IMX95_CLK_I3C1SLOW (IMX95_CCM_NUM_CLK_SRC + 5)
+#define IMX95_CLK_LPI2C1 (IMX95_CCM_NUM_CLK_SRC + 6)
+#define IMX95_CLK_LPI2C2 (IMX95_CCM_NUM_CLK_SRC + 7)
+#define IMX95_CLK_LPSPI1 (IMX95_CCM_NUM_CLK_SRC + 8)
+#define IMX95_CLK_LPSPI2 (IMX95_CCM_NUM_CLK_SRC + 9)
+#define IMX95_CLK_LPTMR1 (IMX95_CCM_NUM_CLK_SRC + 10)
+#define IMX95_CLK_LPUART1 (IMX95_CCM_NUM_CLK_SRC + 11)
+#define IMX95_CLK_LPUART2 (IMX95_CCM_NUM_CLK_SRC + 12)
+#define IMX95_CLK_M33 (IMX95_CCM_NUM_CLK_SRC + 13)
+#define IMX95_CLK_M33SYSTICK (IMX95_CCM_NUM_CLK_SRC + 14)
+#define IMX95_CLK_MQS1 (IMX95_CCM_NUM_CLK_SRC + 15)
+#define IMX95_CLK_PDM (IMX95_CCM_NUM_CLK_SRC + 16)
+#define IMX95_CLK_SAI1 (IMX95_CCM_NUM_CLK_SRC + 17)
+#define IMX95_CLK_SENTINEL (IMX95_CCM_NUM_CLK_SRC + 18)
+#define IMX95_CLK_TPM2 (IMX95_CCM_NUM_CLK_SRC + 19)
+#define IMX95_CLK_TSTMR1 (IMX95_CCM_NUM_CLK_SRC + 20)
+#define IMX95_CLK_CAMAPB (IMX95_CCM_NUM_CLK_SRC + 21)
+#define IMX95_CLK_CAMAXI (IMX95_CCM_NUM_CLK_SRC + 22)
+#define IMX95_CLK_CAMCM0 (IMX95_CCM_NUM_CLK_SRC + 23)
+#define IMX95_CLK_CAMISI (IMX95_CCM_NUM_CLK_SRC + 24)
+#define IMX95_CLK_MIPIPHYCFG (IMX95_CCM_NUM_CLK_SRC + 25)
+#define IMX95_CLK_MIPIPHYPLLBYPASS (IMX95_CCM_NUM_CLK_SRC + 26)
+#define IMX95_CLK_MIPIPHYPLLREF (IMX95_CCM_NUM_CLK_SRC + 27)
+#define IMX95_CLK_MIPITESTBYTE (IMX95_CCM_NUM_CLK_SRC + 28)
+#define IMX95_CLK_A55 (IMX95_CCM_NUM_CLK_SRC + 29)
+#define IMX95_CLK_A55MTRBUS (IMX95_CCM_NUM_CLK_SRC + 30)
+#define IMX95_CLK_A55PERIPH (IMX95_CCM_NUM_CLK_SRC + 31)
+#define IMX95_CLK_DRAMALT (IMX95_CCM_NUM_CLK_SRC + 32)
+#define IMX95_CLK_DRAMAPB (IMX95_CCM_NUM_CLK_SRC + 33)
+#define IMX95_CLK_DISPAPB (IMX95_CCM_NUM_CLK_SRC + 34)
+#define IMX95_CLK_DISPAXI (IMX95_CCM_NUM_CLK_SRC + 35)
+#define IMX95_CLK_DISPDP (IMX95_CCM_NUM_CLK_SRC + 36)
+#define IMX95_CLK_DISPOCRAM (IMX95_CCM_NUM_CLK_SRC + 37)
+#define IMX95_CLK_DISPUSB31 (IMX95_CCM_NUM_CLK_SRC + 38)
+#define IMX95_CLK_DISP1PIX (IMX95_CCM_NUM_CLK_SRC + 39)
+#define IMX95_CLK_DISP2PIX (IMX95_CCM_NUM_CLK_SRC + 40)
+#define IMX95_CLK_DISP3PIX (IMX95_CCM_NUM_CLK_SRC + 41)
+#define IMX95_CLK_GPUAPB (IMX95_CCM_NUM_CLK_SRC + 42)
+#define IMX95_CLK_GPU (IMX95_CCM_NUM_CLK_SRC + 43)
+#define IMX95_CLK_HSIOACSCAN480M (IMX95_CCM_NUM_CLK_SRC + 44)
+#define IMX95_CLK_HSIOACSCAN80M (IMX95_CCM_NUM_CLK_SRC + 45)
+#define IMX95_CLK_HSIO (IMX95_CCM_NUM_CLK_SRC + 46)
+#define IMX95_CLK_HSIOPCIEAUX (IMX95_CCM_NUM_CLK_SRC + 47)
+#define IMX95_CLK_HSIOPCIETEST160M (IMX95_CCM_NUM_CLK_SRC + 48)
+#define IMX95_CLK_HSIOPCIETEST400M (IMX95_CCM_NUM_CLK_SRC + 49)
+#define IMX95_CLK_HSIOPCIETEST500M (IMX95_CCM_NUM_CLK_SRC + 50)
+#define IMX95_CLK_HSIOUSBTEST50M (IMX95_CCM_NUM_CLK_SRC + 51)
+#define IMX95_CLK_HSIOUSBTEST60M (IMX95_CCM_NUM_CLK_SRC + 52)
+#define IMX95_CLK_BUSM7 (IMX95_CCM_NUM_CLK_SRC + 53)
+#define IMX95_CLK_M7 (IMX95_CCM_NUM_CLK_SRC + 54)
+#define IMX95_CLK_M7SYSTICK (IMX95_CCM_NUM_CLK_SRC + 55)
+#define IMX95_CLK_BUSNETCMIX (IMX95_CCM_NUM_CLK_SRC + 56)
+#define IMX95_CLK_ENET (IMX95_CCM_NUM_CLK_SRC + 57)
+#define IMX95_CLK_ENETPHYTEST200M (IMX95_CCM_NUM_CLK_SRC + 58)
+#define IMX95_CLK_ENETPHYTEST500M (IMX95_CCM_NUM_CLK_SRC + 59)
+#define IMX95_CLK_ENETPHYTEST667M (IMX95_CCM_NUM_CLK_SRC + 60)
+#define IMX95_CLK_ENETREF (IMX95_CCM_NUM_CLK_SRC + 61)
+#define IMX95_CLK_ENETTIMER1 (IMX95_CCM_NUM_CLK_SRC + 62)
+#define IMX95_CLK_MQS2 (IMX95_CCM_NUM_CLK_SRC + 63)
+#define IMX95_CLK_SAI2 (IMX95_CCM_NUM_CLK_SRC + 64)
+#define IMX95_CLK_NOCAPB (IMX95_CCM_NUM_CLK_SRC + 65)
+#define IMX95_CLK_NOC (IMX95_CCM_NUM_CLK_SRC + 66)
+#define IMX95_CLK_NPUAPB (IMX95_CCM_NUM_CLK_SRC + 67)
+#define IMX95_CLK_NPU (IMX95_CCM_NUM_CLK_SRC + 68)
+#define IMX95_CLK_CCMCKO1 (IMX95_CCM_NUM_CLK_SRC + 69)
+#define IMX95_CLK_CCMCKO2 (IMX95_CCM_NUM_CLK_SRC + 70)
+#define IMX95_CLK_CCMCKO3 (IMX95_CCM_NUM_CLK_SRC + 71)
+#define IMX95_CLK_CCMCKO4 (IMX95_CCM_NUM_CLK_SRC + 72)
+#define IMX95_CLK_VPUAPB (IMX95_CCM_NUM_CLK_SRC + 73)
+#define IMX95_CLK_VPU (IMX95_CCM_NUM_CLK_SRC + 74)
+#define IMX95_CLK_VPUDSP (IMX95_CCM_NUM_CLK_SRC + 75)
+#define IMX95_CLK_VPUJPEG (IMX95_CCM_NUM_CLK_SRC + 76)
+#define IMX95_CLK_AUDIOXCVR (IMX95_CCM_NUM_CLK_SRC + 77)
+#define IMX95_CLK_BUSWAKEUP (IMX95_CCM_NUM_CLK_SRC + 78)
+#define IMX95_CLK_CAN2 (IMX95_CCM_NUM_CLK_SRC + 79)
+#define IMX95_CLK_CAN3 (IMX95_CCM_NUM_CLK_SRC + 80)
+#define IMX95_CLK_CAN4 (IMX95_CCM_NUM_CLK_SRC + 81)
+#define IMX95_CLK_CAN5 (IMX95_CCM_NUM_CLK_SRC + 82)
+#define IMX95_CLK_FLEXIO1 (IMX95_CCM_NUM_CLK_SRC + 83)
+#define IMX95_CLK_FLEXIO2 (IMX95_CCM_NUM_CLK_SRC + 84)
+#define IMX95_CLK_FLEXSPI1 (IMX95_CCM_NUM_CLK_SRC + 85)
+#define IMX95_CLK_I3C2 (IMX95_CCM_NUM_CLK_SRC + 86)
+#define IMX95_CLK_I3C2SLOW (IMX95_CCM_NUM_CLK_SRC + 87)
+#define IMX95_CLK_LPI2C3 (IMX95_CCM_NUM_CLK_SRC + 88)
+#define IMX95_CLK_LPI2C4 (IMX95_CCM_NUM_CLK_SRC + 89)
+#define IMX95_CLK_LPI2C5 (IMX95_CCM_NUM_CLK_SRC + 90)
+#define IMX95_CLK_LPI2C6 (IMX95_CCM_NUM_CLK_SRC + 91)
+#define IMX95_CLK_LPI2C7 (IMX95_CCM_NUM_CLK_SRC + 92)
+#define IMX95_CLK_LPI2C8 (IMX95_CCM_NUM_CLK_SRC + 93)
+#define IMX95_CLK_LPSPI3 (IMX95_CCM_NUM_CLK_SRC + 94)
+#define IMX95_CLK_LPSPI4 (IMX95_CCM_NUM_CLK_SRC + 95)
+#define IMX95_CLK_LPSPI5 (IMX95_CCM_NUM_CLK_SRC + 96)
+#define IMX95_CLK_LPSPI6 (IMX95_CCM_NUM_CLK_SRC + 97)
+#define IMX95_CLK_LPSPI7 (IMX95_CCM_NUM_CLK_SRC + 98)
+#define IMX95_CLK_LPSPI8 (IMX95_CCM_NUM_CLK_SRC + 99)
+#define IMX95_CLK_LPTMR2 (IMX95_CCM_NUM_CLK_SRC + 100)
+#define IMX95_CLK_LPUART3 (IMX95_CCM_NUM_CLK_SRC + 101)
+#define IMX95_CLK_LPUART4 (IMX95_CCM_NUM_CLK_SRC + 102)
+#define IMX95_CLK_LPUART5 (IMX95_CCM_NUM_CLK_SRC + 103)
+#define IMX95_CLK_LPUART6 (IMX95_CCM_NUM_CLK_SRC + 104)
+#define IMX95_CLK_LPUART7 (IMX95_CCM_NUM_CLK_SRC + 105)
+#define IMX95_CLK_LPUART8 (IMX95_CCM_NUM_CLK_SRC + 106)
+#define IMX95_CLK_SAI3 (IMX95_CCM_NUM_CLK_SRC + 107)
+#define IMX95_CLK_SAI4 (IMX95_CCM_NUM_CLK_SRC + 108)
+#define IMX95_CLK_SAI5 (IMX95_CCM_NUM_CLK_SRC + 109)
+#define IMX95_CLK_SPDIF (IMX95_CCM_NUM_CLK_SRC + 110)
+#define IMX95_CLK_SWOTRACE (IMX95_CCM_NUM_CLK_SRC + 111)
+#define IMX95_CLK_TPM4 (IMX95_CCM_NUM_CLK_SRC + 112)
+#define IMX95_CLK_TPM5 (IMX95_CCM_NUM_CLK_SRC + 113)
+#define IMX95_CLK_TPM6 (IMX95_CCM_NUM_CLK_SRC + 114)
+#define IMX95_CLK_TSTMR2 (IMX95_CCM_NUM_CLK_SRC + 115)
+#define IMX95_CLK_USBPHYBURUNIN (IMX95_CCM_NUM_CLK_SRC + 116)
+#define IMX95_CLK_USDHC1 (IMX95_CCM_NUM_CLK_SRC + 117)
+#define IMX95_CLK_USDHC2 (IMX95_CCM_NUM_CLK_SRC + 118)
+#define IMX95_CLK_USDHC3 (IMX95_CCM_NUM_CLK_SRC + 119)
+#define IMX95_CLK_V2XPK (IMX95_CCM_NUM_CLK_SRC + 120)
+#define IMX95_CLK_WAKEUPAXI (IMX95_CCM_NUM_CLK_SRC + 121)
+#define IMX95_CLK_XSPISLVROOT (IMX95_CCM_NUM_CLK_SRC + 122)
+#define IMX95_CLK_SEL_EXT (IMX95_CCM_NUM_CLK_SRC + 123 + 0)
+#define IMX95_CLK_SEL_A55C0 (IMX95_CCM_NUM_CLK_SRC + 123 + 1)
+#define IMX95_CLK_SEL_A55C1 (IMX95_CCM_NUM_CLK_SRC + 123 + 2)
+#define IMX95_CLK_SEL_A55C2 (IMX95_CCM_NUM_CLK_SRC + 123 + 3)
+#define IMX95_CLK_SEL_A55C3 (IMX95_CCM_NUM_CLK_SRC + 123 + 4)
+#define IMX95_CLK_SEL_A55C4 (IMX95_CCM_NUM_CLK_SRC + 123 + 5)
+#define IMX95_CLK_SEL_A55C5 (IMX95_CCM_NUM_CLK_SRC + 123 + 6)
+#define IMX95_CLK_SEL_A55P (IMX95_CCM_NUM_CLK_SRC + 123 + 7)
+#define IMX95_CLK_SEL_DRAM (IMX95_CCM_NUM_CLK_SRC + 123 + 8)
+#define IMX95_CLK_SEL_TEMPSENSE (IMX95_CCM_NUM_CLK_SRC + 123 + 9)
+
+#endif /* __CLOCK_IMX95_H */
diff --git a/arch/arm64/boot/dts/freescale/imx95-pinfunc.h b/arch/arm64/boot/dts/freescale/imx95-pinfunc.h
new file mode 100644
index 000000000000..9f614eea7c86
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx95-pinfunc.h
@@ -0,0 +1,865 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright 2024 NXP
+ */
+
+#ifndef __DTS_IMX95_PINFUNC_H
+#define __DTS_IMX95_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define IMX95_PAD_DAP_TDI__JTAG_MUX_TDI 0x0000 0x0204 0x0610 0x00 0x00
+#define IMX95_PAD_DAP_TDI__NETCMIX_TOP_MQS2_LEFT 0x0000 0x0204 0x0000 0x01 0x00
+#define IMX95_PAD_DAP_TDI__NETCMIX_TOP_NETC_TMR_1588_ALARM1 0x0000 0x0204 0x0000 0x02 0x00
+#define IMX95_PAD_DAP_TDI__CAN2_TX 0x0000 0x0204 0x0000 0x03 0x00
+#define IMX95_PAD_DAP_TDI__FLEXIO2_FLEXIO_BIT30 0x0000 0x0204 0x0000 0x04 0x00
+#define IMX95_PAD_DAP_TDI__GPIO3_IO_BIT28 0x0000 0x0204 0x0000 0x05 0x00
+#define IMX95_PAD_DAP_TDI__LPUART5_RX 0x0000 0x0204 0x0570 0x06 0x00
+
+#define IMX95_PAD_DAP_TMS_SWDIO__JTAG_MUX_TMS 0x0004 0x0208 0x0614 0x00 0x00
+#define IMX95_PAD_DAP_TMS_SWDIO__CAN4_TX 0x0004 0x0208 0x0000 0x02 0x00
+#define IMX95_PAD_DAP_TMS_SWDIO__FLEXIO2_FLEXIO_BIT31 0x0004 0x0208 0x0000 0x04 0x00
+#define IMX95_PAD_DAP_TMS_SWDIO__GPIO3_IO_BIT29 0x0004 0x0208 0x0000 0x05 0x00
+#define IMX95_PAD_DAP_TMS_SWDIO__LPUART5_RTS_B 0x0004 0x0208 0x0000 0x06 0x00
+
+#define IMX95_PAD_DAP_TCLK_SWCLK__JTAG_MUX_TCK 0x0008 0x020C 0x060C 0x00 0x00
+#define IMX95_PAD_DAP_TCLK_SWCLK__CAN4_RX 0x0008 0x020C 0x044C 0x02 0x00
+#define IMX95_PAD_DAP_TCLK_SWCLK__FLEXIO1_FLEXIO_BIT30 0x0008 0x020C 0x0460 0x04 0x00
+#define IMX95_PAD_DAP_TCLK_SWCLK__GPIO3_IO_BIT30 0x0008 0x020C 0x0000 0x05 0x00
+#define IMX95_PAD_DAP_TCLK_SWCLK__LPUART5_CTS_B 0x0008 0x020C 0x056C 0x06 0x00
+
+#define IMX95_PAD_DAP_TDO_TRACESWO__JTAG_MUX_TDO 0x000C 0x0210 0x0000 0x00 0x00
+#define IMX95_PAD_DAP_TDO_TRACESWO__NETCMIX_TOP_MQS2_RIGHT 0x000C 0x0210 0x0000 0x01 0x00
+#define IMX95_PAD_DAP_TDO_TRACESWO__NETCMIX_TOP_NETC_TMR_1588_ALARM 0x000C 0x0210 0x0000 0x02 0x00
+#define IMX95_PAD_DAP_TDO_TRACESWO__CAN2_RX 0x000C 0x0210 0x0444 0x03 0x00
+#define IMX95_PAD_DAP_TDO_TRACESWO__FLEXIO1_FLEXIO_BIT31 0x000C 0x0210 0x0464 0x04 0x00
+#define IMX95_PAD_DAP_TDO_TRACESWO__GPIO3_IO_BIT31 0x000C 0x0210 0x0000 0x05 0x00
+#define IMX95_PAD_DAP_TDO_TRACESWO__LPUART5_TX 0x000C 0x0210 0x0574 0x06 0x00
+
+#define IMX95_PAD_GPIO_IO00__GPIO2_IO_BIT0 0x0010 0x0214 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO00__LPI2C3_SDA 0x0010 0x0214 0x0504 0x11 0x00
+#define IMX95_PAD_GPIO_IO00__LPSPI6_PCS0 0x0010 0x0214 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO00__LPUART5_TX 0x0010 0x0214 0x0574 0x05 0x01
+#define IMX95_PAD_GPIO_IO00__LPI2C5_SDA 0x0010 0x0214 0x0514 0x16 0x00
+#define IMX95_PAD_GPIO_IO00__FLEXIO1_FLEXIO_BIT0 0x0010 0x0214 0x0468 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO01__GPIO2_IO_BIT1 0x0014 0x0218 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO01__LPI2C3_SCL 0x0014 0x0218 0x0500 0x11 0x00
+#define IMX95_PAD_GPIO_IO01__LPSPI6_SIN 0x0014 0x0218 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO01__LPUART5_RX 0x0014 0x0218 0x0570 0x05 0x01
+#define IMX95_PAD_GPIO_IO01__LPI2C5_SCL 0x0014 0x0218 0x0510 0x16 0x00
+#define IMX95_PAD_GPIO_IO01__FLEXIO1_FLEXIO_BIT1 0x0014 0x0218 0x046C 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO02__GPIO2_IO_BIT2 0x0018 0x021C 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO02__LPI2C4_SDA 0x0018 0x021C 0x050C 0x11 0x00
+#define IMX95_PAD_GPIO_IO02__LPSPI6_SOUT 0x0018 0x021C 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO02__LPUART5_CTS_B 0x0018 0x021C 0x056C 0x05 0x01
+#define IMX95_PAD_GPIO_IO02__LPI2C6_SDA 0x0018 0x021C 0x051C 0x16 0x00
+#define IMX95_PAD_GPIO_IO02__FLEXIO1_FLEXIO_BIT2 0x0018 0x021C 0x0470 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO03__GPIO2_IO_BIT3 0x001C 0x0220 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO03__LPI2C4_SCL 0x001C 0x0220 0x0508 0x11 0x00
+#define IMX95_PAD_GPIO_IO03__LPSPI6_SCK 0x001C 0x0220 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO03__LPUART5_RTS_B 0x001C 0x0220 0x0000 0x05 0x00
+#define IMX95_PAD_GPIO_IO03__LPI2C6_SCL 0x001C 0x0220 0x0518 0x16 0x00
+#define IMX95_PAD_GPIO_IO03__FLEXIO1_FLEXIO_BIT3 0x001C 0x0220 0x0474 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO04__GPIO2_IO_BIT4 0x0020 0x0224 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO04__TPM3_CH0 0x0020 0x0224 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO04__AONMIX_TOP_PDM_CLK 0x0020 0x0224 0x0000 0x02 0x00
+#define IMX95_PAD_GPIO_IO04__CAN4_TX 0x0020 0x0224 0x0000 0x03 0x00
+#define IMX95_PAD_GPIO_IO04__LPSPI7_PCS0 0x0020 0x0224 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO04__LPUART6_TX 0x0020 0x0224 0x0580 0x05 0x01
+#define IMX95_PAD_GPIO_IO04__LPI2C6_SDA 0x0020 0x0224 0x051C 0x16 0x01
+#define IMX95_PAD_GPIO_IO04__FLEXIO1_FLEXIO_BIT4 0x0020 0x0224 0x0478 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO05__GPIO2_IO_BIT5 0x0024 0x0228 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO05__TPM4_CH0 0x0024 0x0228 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO05__AONMIX_TOP_PDM_BIT_STREAM_BIT0 0x0024 0x0228 0x040C 0x02 0x01
+#define IMX95_PAD_GPIO_IO05__CAN4_RX 0x0024 0x0228 0x044C 0x03 0x01
+#define IMX95_PAD_GPIO_IO05__LPSPI7_SIN 0x0024 0x0228 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO05__LPUART6_RX 0x0024 0x0228 0x057C 0x05 0x01
+#define IMX95_PAD_GPIO_IO05__LPI2C6_SCL 0x0024 0x0228 0x0518 0x16 0x01
+#define IMX95_PAD_GPIO_IO05__FLEXIO1_FLEXIO_BIT5 0x0024 0x0228 0x047C 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO06__GPIO2_IO_BIT6 0x0028 0x022C 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO06__TPM5_CH0 0x0028 0x022C 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO06__AONMIX_TOP_PDM_BIT_STREAM_BIT1 0x0028 0x022C 0x0410 0x02 0x01
+#define IMX95_PAD_GPIO_IO06__LPSPI7_SOUT 0x0028 0x022C 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO06__LPUART6_CTS_B 0x0028 0x022C 0x0578 0x05 0x01
+#define IMX95_PAD_GPIO_IO06__LPI2C7_SDA 0x0028 0x022C 0x0524 0x16 0x00
+#define IMX95_PAD_GPIO_IO06__FLEXIO1_FLEXIO_BIT6 0x0028 0x022C 0x0480 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO07__GPIO2_IO_BIT7 0x002C 0x0230 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO07__LPSPI3_PCS1 0x002C 0x0230 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO07__LPSPI7_SCK 0x002C 0x0230 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO07__LPUART6_RTS_B 0x002C 0x0230 0x0000 0x05 0x00
+#define IMX95_PAD_GPIO_IO07__LPI2C7_SCL 0x002C 0x0230 0x0520 0x16 0x00
+#define IMX95_PAD_GPIO_IO07__FLEXIO1_FLEXIO_BIT7 0x002C 0x0230 0x0484 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO08__GPIO2_IO_BIT8 0x0030 0x0234 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO08__LPSPI3_PCS0 0x0030 0x0234 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO08__TPM6_CH0 0x0030 0x0234 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO08__LPUART7_TX 0x0030 0x0234 0x0588 0x05 0x01
+#define IMX95_PAD_GPIO_IO08__LPI2C7_SDA 0x0030 0x0234 0x0524 0x16 0x01
+#define IMX95_PAD_GPIO_IO08__FLEXIO1_FLEXIO_BIT8 0x0030 0x0234 0x0488 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO09__GPIO2_IO_BIT9 0x0034 0x0238 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO09__LPSPI3_SIN 0x0034 0x0238 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO09__TPM3_EXTCLK 0x0034 0x0238 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO09__LPUART7_RX 0x0034 0x0238 0x0584 0x05 0x01
+#define IMX95_PAD_GPIO_IO09__LPI2C7_SCL 0x0034 0x0238 0x0520 0x16 0x01
+#define IMX95_PAD_GPIO_IO09__FLEXIO1_FLEXIO_BIT9 0x0034 0x0238 0x048C 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO10__GPIO2_IO_BIT10 0x0038 0x023C 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO10__LPSPI3_SOUT 0x0038 0x023C 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO10__TPM4_EXTCLK 0x0038 0x023C 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO10__LPUART7_CTS_B 0x0038 0x023C 0x0000 0x05 0x00
+#define IMX95_PAD_GPIO_IO10__LPI2C8_SDA 0x0038 0x023C 0x052C 0x16 0x00
+#define IMX95_PAD_GPIO_IO10__FLEXIO1_FLEXIO_BIT10 0x0038 0x023C 0x0490 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO11__GPIO2_IO_BIT11 0x003C 0x0240 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO11__LPSPI3_SCK 0x003C 0x0240 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO11__TPM5_EXTCLK 0x003C 0x0240 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO11__LPUART7_RTS_B 0x003C 0x0240 0x0000 0x05 0x00
+#define IMX95_PAD_GPIO_IO11__LPI2C8_SCL 0x003C 0x0240 0x0528 0x16 0x00
+#define IMX95_PAD_GPIO_IO11__FLEXIO1_FLEXIO_BIT11 0x003C 0x0240 0x0494 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO12__GPIO2_IO_BIT12 0x0040 0x0244 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO12__TPM3_CH2 0x0040 0x0244 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO12__AONMIX_TOP_PDM_BIT_STREAM_BIT2 0x0040 0x0244 0x0414 0x02 0x00
+#define IMX95_PAD_GPIO_IO12__FLEXIO1_FLEXIO_BIT12 0x0040 0x0244 0x0498 0x03 0x00
+#define IMX95_PAD_GPIO_IO12__LPSPI8_PCS0 0x0040 0x0244 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO12__LPUART8_TX 0x0040 0x0244 0x0000 0x05 0x00
+#define IMX95_PAD_GPIO_IO12__LPI2C8_SDA 0x0040 0x0244 0x052C 0x16 0x01
+#define IMX95_PAD_GPIO_IO12__SAI3_RX_SYNC 0x0040 0x0244 0x0590 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO13__GPIO2_IO_BIT13 0x0044 0x0248 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO13__TPM4_CH2 0x0044 0x0248 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO13__AONMIX_TOP_PDM_BIT_STREAM_BIT3 0x0044 0x0248 0x0418 0x02 0x00
+#define IMX95_PAD_GPIO_IO13__LPSPI8_SIN 0x0044 0x0248 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO13__LPUART8_RX 0x0044 0x0248 0x0000 0x05 0x00
+#define IMX95_PAD_GPIO_IO13__LPI2C8_SCL 0x0044 0x0248 0x0528 0x16 0x01
+#define IMX95_PAD_GPIO_IO13__FLEXIO1_FLEXIO_BIT13 0x0044 0x0248 0x049C 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO14__GPIO2_IO_BIT14 0x0048 0x024C 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO14__LPUART3_TX 0x0048 0x024C 0x055C 0x01 0x01
+#define IMX95_PAD_GPIO_IO14__LPSPI8_SOUT 0x0048 0x024C 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO14__LPUART8_CTS_B 0x0048 0x024C 0x0000 0x05 0x00
+#define IMX95_PAD_GPIO_IO14__LPUART4_TX 0x0048 0x024C 0x0568 0x06 0x01
+#define IMX95_PAD_GPIO_IO14__FLEXIO1_FLEXIO_BIT14 0x0048 0x024C 0x04A0 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO15__GPIO2_IO_BIT15 0x004C 0x0250 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO15__LPUART3_RX 0x004C 0x0250 0x0558 0x01 0x01
+#define IMX95_PAD_GPIO_IO15__LPSPI8_SCK 0x004C 0x0250 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO15__LPUART8_RTS_B 0x004C 0x0250 0x0000 0x05 0x00
+#define IMX95_PAD_GPIO_IO15__LPUART4_RX 0x004C 0x0250 0x0564 0x06 0x01
+#define IMX95_PAD_GPIO_IO15__FLEXIO1_FLEXIO_BIT15 0x004C 0x0250 0x04A4 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO16__GPIO2_IO_BIT16 0x0050 0x0254 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO16__SAI3_TX_BCLK 0x0050 0x0254 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO16__AONMIX_TOP_PDM_BIT_STREAM_BIT2 0x0050 0x0254 0x0414 0x02 0x01
+#define IMX95_PAD_GPIO_IO16__LPUART3_CTS_B 0x0050 0x0254 0x0554 0x04 0x01
+#define IMX95_PAD_GPIO_IO16__LPSPI4_PCS2 0x0050 0x0254 0x0538 0x05 0x01
+#define IMX95_PAD_GPIO_IO16__LPUART4_CTS_B 0x0050 0x0254 0x0560 0x06 0x01
+#define IMX95_PAD_GPIO_IO16__FLEXIO1_FLEXIO_BIT16 0x0050 0x0254 0x04A8 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO17__GPIO2_IO_BIT17 0x0054 0x0258 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO17__SAI3_MCLK 0x0054 0x0258 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO17__LPUART3_RTS_B 0x0054 0x0258 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO17__LPSPI4_PCS1 0x0054 0x0258 0x0534 0x05 0x01
+#define IMX95_PAD_GPIO_IO17__LPUART4_RTS_B 0x0054 0x0258 0x0000 0x06 0x00
+#define IMX95_PAD_GPIO_IO17__FLEXIO1_FLEXIO_BIT17 0x0054 0x0258 0x04AC 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO18__GPIO2_IO_BIT18 0x0058 0x025C 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO18__SAI3_RX_BCLK 0x0058 0x025C 0x058C 0x01 0x00
+#define IMX95_PAD_GPIO_IO18__LPSPI5_PCS0 0x0058 0x025C 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO18__LPSPI4_PCS0 0x0058 0x025C 0x0530 0x05 0x01
+#define IMX95_PAD_GPIO_IO18__TPM5_CH2 0x0058 0x025C 0x0000 0x06 0x00
+#define IMX95_PAD_GPIO_IO18__FLEXIO1_FLEXIO_BIT18 0x0058 0x025C 0x04B0 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO19__GPIO2_IO_BIT19 0x005C 0x0260 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO19__SAI3_RX_SYNC 0x005C 0x0260 0x0590 0x01 0x01
+#define IMX95_PAD_GPIO_IO19__AONMIX_TOP_PDM_BIT_STREAM_BIT3 0x005C 0x0260 0x0418 0x02 0x01
+#define IMX95_PAD_GPIO_IO19__FLEXIO1_FLEXIO_BIT19 0x005C 0x0260 0x04B4 0x03 0x00
+#define IMX95_PAD_GPIO_IO19__LPSPI5_SIN 0x005C 0x0260 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO19__LPSPI4_SIN 0x005C 0x0260 0x0540 0x05 0x01
+#define IMX95_PAD_GPIO_IO19__TPM6_CH2 0x005C 0x0260 0x0000 0x06 0x00
+#define IMX95_PAD_GPIO_IO19__SAI3_TX_DATA_BIT0 0x005C 0x0260 0x0000 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO20__GPIO2_IO_BIT20 0x0060 0x0264 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO20__SAI3_RX_DATA_BIT0 0x0060 0x0264 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO20__AONMIX_TOP_PDM_BIT_STREAM_BIT0 0x0060 0x0264 0x040C 0x02 0x02
+#define IMX95_PAD_GPIO_IO20__LPSPI5_SOUT 0x0060 0x0264 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO20__LPSPI4_SOUT 0x0060 0x0264 0x0544 0x05 0x01
+#define IMX95_PAD_GPIO_IO20__TPM3_CH1 0x0060 0x0264 0x0000 0x06 0x00
+#define IMX95_PAD_GPIO_IO20__FLEXIO1_FLEXIO_BIT20 0x0060 0x0264 0x04B8 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO21__GPIO2_IO_BIT21 0x0064 0x0268 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO21__SAI3_TX_DATA_BIT0 0x0064 0x0268 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO21__AONMIX_TOP_PDM_CLK 0x0064 0x0268 0x0000 0x02 0x00
+#define IMX95_PAD_GPIO_IO21__FLEXIO1_FLEXIO_BIT21 0x0064 0x0268 0x04BC 0x03 0x00
+#define IMX95_PAD_GPIO_IO21__LPSPI5_SCK 0x0064 0x0268 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO21__LPSPI4_SCK 0x0064 0x0268 0x053C 0x05 0x01
+#define IMX95_PAD_GPIO_IO21__TPM4_CH1 0x0064 0x0268 0x0000 0x06 0x00
+#define IMX95_PAD_GPIO_IO21__SAI3_RX_BCLK 0x0064 0x0268 0x058C 0x07 0x01
+
+#define IMX95_PAD_GPIO_IO22__GPIO2_IO_BIT22 0x0068 0x026C 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO22__USDHC3_CLK 0x0068 0x026C 0x05C8 0x01 0x00
+#define IMX95_PAD_GPIO_IO22__SPDIF_IN 0x0068 0x026C 0x0454 0x02 0x02
+#define IMX95_PAD_GPIO_IO22__CAN5_TX 0x0068 0x026C 0x0000 0x03 0x00
+#define IMX95_PAD_GPIO_IO22__TPM5_CH1 0x0068 0x026C 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO22__TPM6_EXTCLK 0x0068 0x026C 0x0000 0x05 0x00
+#define IMX95_PAD_GPIO_IO22__LPI2C5_SDA 0x0068 0x026C 0x0514 0x16 0x01
+#define IMX95_PAD_GPIO_IO22__FLEXIO1_FLEXIO_BIT22 0x0068 0x026C 0x04C0 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO23__GPIO2_IO_BIT23 0x006C 0x0270 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO23__USDHC3_CMD 0x006C 0x0270 0x05CC 0x01 0x00
+#define IMX95_PAD_GPIO_IO23__SPDIF_OUT 0x006C 0x0270 0x0000 0x02 0x00
+#define IMX95_PAD_GPIO_IO23__CAN5_RX 0x006C 0x0270 0x0450 0x03 0x00
+#define IMX95_PAD_GPIO_IO23__TPM6_CH1 0x006C 0x0270 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO23__LPI2C5_SCL 0x006C 0x0270 0x0510 0x16 0x01
+#define IMX95_PAD_GPIO_IO23__FLEXIO1_FLEXIO_BIT23 0x006C 0x0270 0x04C4 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO24__GPIO2_IO_BIT24 0x0070 0x0274 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO24__USDHC3_DATA0 0x0070 0x0274 0x05D0 0x01 0x00
+#define IMX95_PAD_GPIO_IO24__TPM3_CH3 0x0070 0x0274 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO24__JTAG_MUX_TDO 0x0070 0x0274 0x0000 0x05 0x00
+#define IMX95_PAD_GPIO_IO24__LPSPI6_PCS1 0x0070 0x0274 0x0000 0x06 0x00
+#define IMX95_PAD_GPIO_IO24__FLEXIO1_FLEXIO_BIT24 0x0070 0x0274 0x04C8 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO25__GPIO2_IO_BIT25 0x0074 0x0278 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO25__USDHC3_DATA1 0x0074 0x0278 0x05D4 0x01 0x00
+#define IMX95_PAD_GPIO_IO25__CAN2_TX 0x0074 0x0278 0x0000 0x02 0x00
+#define IMX95_PAD_GPIO_IO25__TPM4_CH3 0x0074 0x0278 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO25__JTAG_MUX_TCK 0x0074 0x0278 0x060C 0x05 0x01
+#define IMX95_PAD_GPIO_IO25__LPSPI7_PCS1 0x0074 0x0278 0x0000 0x06 0x00
+#define IMX95_PAD_GPIO_IO25__FLEXIO1_FLEXIO_BIT25 0x0074 0x0278 0x04CC 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO26__GPIO2_IO_BIT26 0x0078 0x027C 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO26__USDHC3_DATA2 0x0078 0x027C 0x05D8 0x01 0x00
+#define IMX95_PAD_GPIO_IO26__AONMIX_TOP_PDM_BIT_STREAM_BIT1 0x0078 0x027C 0x0410 0x02 0x02
+#define IMX95_PAD_GPIO_IO26__FLEXIO1_FLEXIO_BIT26 0x0078 0x027C 0x0458 0x03 0x01
+#define IMX95_PAD_GPIO_IO26__TPM5_CH3 0x0078 0x027C 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO26__JTAG_MUX_TDI 0x0078 0x027C 0x0610 0x05 0x01
+#define IMX95_PAD_GPIO_IO26__LPSPI8_PCS1 0x0078 0x027C 0x0000 0x06 0x00
+#define IMX95_PAD_GPIO_IO26__SAI3_TX_SYNC 0x0078 0x027C 0x0000 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO27__GPIO2_IO_BIT27 0x007C 0x0280 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO27__USDHC3_DATA3 0x007C 0x0280 0x05DC 0x01 0x00
+#define IMX95_PAD_GPIO_IO27__CAN2_RX 0x007C 0x0280 0x0444 0x02 0x02
+#define IMX95_PAD_GPIO_IO27__TPM6_CH3 0x007C 0x0280 0x0000 0x04 0x00
+#define IMX95_PAD_GPIO_IO27__JTAG_MUX_TMS 0x007C 0x0280 0x0614 0x05 0x01
+#define IMX95_PAD_GPIO_IO27__LPSPI5_PCS1 0x007C 0x0280 0x0000 0x06 0x00
+#define IMX95_PAD_GPIO_IO27__FLEXIO1_FLEXIO_BIT27 0x007C 0x0280 0x045C 0x07 0x01
+
+#define IMX95_PAD_GPIO_IO28__GPIO2_IO_BIT28 0x0080 0x0284 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO28__LPI2C3_SDA 0x0080 0x0284 0x0504 0x11 0x01
+#define IMX95_PAD_GPIO_IO28__CAN3_TX 0x0080 0x0284 0x0000 0x02 0x00
+#define IMX95_PAD_GPIO_IO28__FLEXIO1_FLEXIO_BIT28 0x0080 0x0284 0x0000 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO29__GPIO2_IO_BIT29 0x0084 0x0288 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO29__LPI2C3_SCL 0x0084 0x0288 0x0500 0x11 0x01
+#define IMX95_PAD_GPIO_IO29__CAN3_RX 0x0084 0x0288 0x0448 0x02 0x01
+#define IMX95_PAD_GPIO_IO29__FLEXIO1_FLEXIO_BIT29 0x0084 0x0288 0x0000 0x07 0x00
+
+#define IMX95_PAD_GPIO_IO30__GPIO2_IO_BIT30 0x0088 0x028C 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO30__LPI2C4_SDA 0x0088 0x028C 0x050C 0x11 0x01
+#define IMX95_PAD_GPIO_IO30__CAN5_TX 0x0088 0x028C 0x0000 0x02 0x00
+#define IMX95_PAD_GPIO_IO30__FLEXIO1_FLEXIO_BIT30 0x0088 0x028C 0x0460 0x07 0x01
+
+#define IMX95_PAD_GPIO_IO31__GPIO2_IO_BIT31 0x008C 0x0290 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO31__LPI2C4_SCL 0x008C 0x0290 0x0508 0x11 0x01
+#define IMX95_PAD_GPIO_IO31__CAN5_RX 0x008C 0x0290 0x0450 0x02 0x01
+#define IMX95_PAD_GPIO_IO31__FLEXIO1_FLEXIO_BIT31 0x008C 0x0290 0x0464 0x07 0x01
+
+#define IMX95_PAD_GPIO_IO32__GPIO5_IO_BIT12 0x0090 0x0294 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO32__HSIOMIX_TOP_PCIE1_CLKREQ_B 0x0090 0x0294 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO32__LPUART6_TX 0x0090 0x0294 0x0580 0x02 0x00
+#define IMX95_PAD_GPIO_IO32__LPSPI4_PCS2 0x0090 0x0294 0x0538 0x04 0x00
+
+#define IMX95_PAD_GPIO_IO33__GPIO5_IO_BIT13 0x0094 0x0298 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO33__LPUART6_RX 0x0094 0x0298 0x057C 0x02 0x00
+#define IMX95_PAD_GPIO_IO33__LPSPI4_PCS1 0x0094 0x0298 0x0534 0x04 0x00
+
+#define IMX95_PAD_GPIO_IO34__GPIO5_IO_BIT14 0x0098 0x029C 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO34__LPUART6_CTS_B 0x0098 0x029C 0x0578 0x02 0x00
+#define IMX95_PAD_GPIO_IO34__LPSPI4_PCS0 0x0098 0x029C 0x0530 0x04 0x00
+
+#define IMX95_PAD_GPIO_IO35__GPIO5_IO_BIT15 0x009C 0x02A0 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO35__HSIOMIX_TOP_PCIE2_CLKREQ_B 0x009C 0x02A0 0x0000 0x01 0x00
+#define IMX95_PAD_GPIO_IO35__LPUART6_RTS_B 0x009C 0x02A0 0x0000 0x02 0x00
+#define IMX95_PAD_GPIO_IO35__LPSPI4_SIN 0x009C 0x02A0 0x0540 0x04 0x00
+
+#define IMX95_PAD_GPIO_IO36__LPSPI4_SOUT 0x00A0 0x02A4 0x0544 0x04 0x00
+#define IMX95_PAD_GPIO_IO36__GPIO5_IO_BIT16 0x00A0 0x02A4 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO36__LPUART7_TX 0x00A0 0x02A4 0x0588 0x02 0x00
+
+#define IMX95_PAD_GPIO_IO37__GPIO5_IO_BIT17 0x00A4 0x02A8 0x0000 0x00 0x00
+#define IMX95_PAD_GPIO_IO37__LPUART7_RX 0x00A4 0x02A8 0x0584 0x02 0x00
+#define IMX95_PAD_GPIO_IO37__LPSPI4_SCK 0x00A4 0x02A8 0x053C 0x04 0x00
+
+#define IMX95_PAD_CCM_CLKO1__CCMSRCGPCMIX_TOP_CLKO_1 0x00A8 0x02AC 0x0000 0x00 0x00
+#define IMX95_PAD_CCM_CLKO1__NETCMIX_TOP_NETC_TMR_1588_TRIG1 0x00A8 0x02AC 0x0434 0x01 0x00
+#define IMX95_PAD_CCM_CLKO1__FLEXIO1_FLEXIO_BIT26 0x00A8 0x02AC 0x0458 0x04 0x00
+#define IMX95_PAD_CCM_CLKO1__GPIO3_IO_BIT26 0x00A8 0x02AC 0x0000 0x05 0x00
+
+#define IMX95_PAD_CCM_CLKO2__GPIO3_IO_BIT27 0x00AC 0x02B0 0x0000 0x05 0x00
+#define IMX95_PAD_CCM_CLKO2__CCMSRCGPCMIX_TOP_CLKO_2 0x00AC 0x02B0 0x0000 0x00 0x00
+#define IMX95_PAD_CCM_CLKO2__NETCMIX_TOP_NETC_TMR_1588_PP1 0x00AC 0x02B0 0x0000 0x01 0x00
+#define IMX95_PAD_CCM_CLKO2__FLEXIO1_FLEXIO_BIT27 0x00AC 0x02B0 0x045C 0x04 0x00
+
+#define IMX95_PAD_CCM_CLKO3__CCMSRCGPCMIX_TOP_CLKO_3 0x00B0 0x02B4 0x0000 0x00 0x00
+#define IMX95_PAD_CCM_CLKO3__NETCMIX_TOP_NETC_TMR_1588_TRIG2 0x00B0 0x02B4 0x0438 0x01 0x00
+#define IMX95_PAD_CCM_CLKO3__CAN3_TX 0x00B0 0x02B4 0x0000 0x02 0x00
+#define IMX95_PAD_CCM_CLKO3__FLEXIO2_FLEXIO_BIT28 0x00B0 0x02B4 0x0000 0x04 0x00
+#define IMX95_PAD_CCM_CLKO3__GPIO4_IO_BIT28 0x00B0 0x02B4 0x0000 0x05 0x00
+
+#define IMX95_PAD_CCM_CLKO4__CCMSRCGPCMIX_TOP_CLKO_4 0x00B4 0x02B8 0x0000 0x00 0x00
+#define IMX95_PAD_CCM_CLKO4__NETCMIX_TOP_NETC_TMR_1588_PP2 0x00B4 0x02B8 0x0000 0x01 0x00
+#define IMX95_PAD_CCM_CLKO4__CAN3_RX 0x00B4 0x02B8 0x0448 0x02 0x00
+#define IMX95_PAD_CCM_CLKO4__FLEXIO2_FLEXIO_BIT29 0x00B4 0x02B8 0x0000 0x04 0x00
+#define IMX95_PAD_CCM_CLKO4__GPIO4_IO_BIT29 0x00B4 0x02B8 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_MDC__NETCMIX_TOP_NETC_MDC 0x00B8 0x02BC 0x0424 0x00 0x00
+#define IMX95_PAD_ENET1_MDC__LPUART3_DCD_B 0x00B8 0x02BC 0x0000 0x01 0x00
+#define IMX95_PAD_ENET1_MDC__I3C2_SCL 0x00B8 0x02BC 0x04F8 0x02 0x00
+#define IMX95_PAD_ENET1_MDC__HSIOMIX_TOP_USB1_OTG_ID 0x00B8 0x02BC 0x0000 0x03 0x00
+#define IMX95_PAD_ENET1_MDC__FLEXIO2_FLEXIO_BIT0 0x00B8 0x02BC 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_MDC__GPIO4_IO_BIT0 0x00B8 0x02BC 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_MDIO__NETCMIX_TOP_NETC_MDIO 0x00BC 0x02C0 0x0428 0x00 0x00
+#define IMX95_PAD_ENET1_MDIO__LPUART3_RIN_B 0x00BC 0x02C0 0x0000 0x01 0x00
+#define IMX95_PAD_ENET1_MDIO__I3C2_SDA 0x00BC 0x02C0 0x04FC 0x02 0x00
+#define IMX95_PAD_ENET1_MDIO__HSIOMIX_TOP_USB1_OTG_PWR 0x00BC 0x02C0 0x0000 0x03 0x00
+#define IMX95_PAD_ENET1_MDIO__FLEXIO2_FLEXIO_BIT1 0x00BC 0x02C0 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_MDIO__GPIO4_IO_BIT1 0x00BC 0x02C0 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_TD3__NETCMIX_TOP_ETH0_RGMII_TD3 0x00C0 0x02C4 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_TD3__CAN2_TX 0x00C0 0x02C4 0x0000 0x02 0x00
+#define IMX95_PAD_ENET1_TD3__HSIOMIX_TOP_USB2_OTG_ID 0x00C0 0x02C4 0x0000 0x03 0x00
+#define IMX95_PAD_ENET1_TD3__FLEXIO2_FLEXIO_BIT2 0x00C0 0x02C4 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_TD3__GPIO4_IO_BIT2 0x00C0 0x02C4 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_TD2__NETCMIX_TOP_ETH0_RGMII_TD2 0x00C4 0x02C8 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_TD2__NETCMIX_TOP_ETH0_RMII_REF50_CLK 0x00C4 0x02C8 0x0000 0x01 0x00
+#define IMX95_PAD_ENET1_TD2__CAN2_RX 0x00C4 0x02C8 0x0444 0x02 0x01
+#define IMX95_PAD_ENET1_TD2__HSIOMIX_TOP_USB2_OTG_OC 0x00C4 0x02C8 0x0000 0x03 0x00
+#define IMX95_PAD_ENET1_TD2__FLEXIO2_FLEXIO_BIT3 0x00C4 0x02C8 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_TD2__GPIO4_IO_BIT3 0x00C4 0x02C8 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_TD1__NETCMIX_TOP_ETH0_RGMII_TD1 0x00C8 0x02CC 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_TD1__LPUART3_RTS_B 0x00C8 0x02CC 0x0000 0x01 0x00
+#define IMX95_PAD_ENET1_TD1__I3C2_PUR 0x00C8 0x02CC 0x0000 0x02 0x00
+#define IMX95_PAD_ENET1_TD1__HSIOMIX_TOP_USB1_OTG_OC 0x00C8 0x02CC 0x0000 0x03 0x00
+#define IMX95_PAD_ENET1_TD1__FLEXIO2_FLEXIO_BIT4 0x00C8 0x02CC 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_TD1__GPIO4_IO_BIT4 0x00C8 0x02CC 0x0000 0x05 0x00
+#define IMX95_PAD_ENET1_TD1__I3C2_PUR_B 0x00C8 0x02CC 0x0000 0x06 0x00
+#define IMX95_PAD_ENET1_TD1__NETCMIX_TOP_ETH0_RMII_TXD1 0x00C8 0x02CC 0x0000 0x07 0x00
+
+#define IMX95_PAD_ENET1_TD0__NETCMIX_TOP_ETH0_RGMII_TD0 0x00CC 0x02D0 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_TD0__LPUART3_TX 0x00CC 0x02D0 0x055C 0x01 0x00
+#define IMX95_PAD_ENET1_TD0__NETCMIX_TOP_ETH0_RMII_TXD0 0x00CC 0x02D0 0x0000 0x02 0x00
+#define IMX95_PAD_ENET1_TD0__FLEXIO2_FLEXIO_BIT5 0x00CC 0x02D0 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_TD0__GPIO4_IO_BIT5 0x00CC 0x02D0 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_TX_CTL__NETCMIX_TOP_ETH0_RGMII_TX_CTL 0x00D0 0x02D4 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_TX_CTL__LPUART3_DTR_B 0x00D0 0x02D4 0x0000 0x01 0x00
+#define IMX95_PAD_ENET1_TX_CTL__NETCMIX_TOP_ETH0_RMII_TX_EN 0x00D0 0x02D4 0x0000 0x02 0x00
+#define IMX95_PAD_ENET1_TX_CTL__FLEXIO2_FLEXIO_BIT6 0x00D0 0x02D4 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_TX_CTL__GPIO4_IO_BIT6 0x00D0 0x02D4 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_TXC__NETCMIX_TOP_ETH0_RGMII_TX_CLK 0x00D4 0x02D8 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_TXC__CCMSRCGPCMIX_TOP_ENET_CLK_ROOT 0x00D4 0x02D8 0x0000 0x01 0x00
+#define IMX95_PAD_ENET1_TXC__FLEXIO2_FLEXIO_BIT7 0x00D4 0x02D8 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_TXC__GPIO4_IO_BIT7 0x00D4 0x02D8 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_RX_CTL__NETCMIX_TOP_ETH0_RGMII_RX_CTL 0x00D8 0x02DC 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_RX_CTL__LPUART3_DSR_B 0x00D8 0x02DC 0x0000 0x01 0x00
+#define IMX95_PAD_ENET1_RX_CTL__NETCMIX_TOP_ETH0_RMII_CRS_DV 0x00D8 0x02DC 0x0000 0x02 0x00
+#define IMX95_PAD_ENET1_RX_CTL__HSIOMIX_TOP_USB2_OTG_PWR 0x00D8 0x02DC 0x0000 0x03 0x00
+#define IMX95_PAD_ENET1_RX_CTL__FLEXIO2_FLEXIO_BIT8 0x00D8 0x02DC 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_RX_CTL__GPIO4_IO_BIT8 0x00D8 0x02DC 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_RXC__NETCMIX_TOP_ETH0_RGMII_RX_CLK 0x00DC 0x02E0 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_RXC__NETCMIX_TOP_ETH0_RMII_RX_ER 0x00DC 0x02E0 0x042C 0x01 0x00
+#define IMX95_PAD_ENET1_RXC__FLEXIO2_FLEXIO_BIT9 0x00DC 0x02E0 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_RXC__GPIO4_IO_BIT9 0x00DC 0x02E0 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_RD0__NETCMIX_TOP_ETH0_RGMII_RD0 0x00E0 0x02E4 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_RD0__LPUART3_RX 0x00E0 0x02E4 0x0558 0x01 0x00
+#define IMX95_PAD_ENET1_RD0__NETCMIX_TOP_ETH0_RMII_RXD0 0x00E0 0x02E4 0x0000 0x02 0x00
+#define IMX95_PAD_ENET1_RD0__FLEXIO2_FLEXIO_BIT10 0x00E0 0x02E4 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_RD0__GPIO4_IO_BIT10 0x00E0 0x02E4 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_RD1__NETCMIX_TOP_ETH0_RGMII_RD1 0x00E4 0x02E8 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_RD1__LPUART3_CTS_B 0x00E4 0x02E8 0x0554 0x01 0x00
+#define IMX95_PAD_ENET1_RD1__NETCMIX_TOP_ETH0_RMII_RXD1 0x00E4 0x02E8 0x0000 0x02 0x00
+#define IMX95_PAD_ENET1_RD1__LPTMR2_ALT1 0x00E4 0x02E8 0x0548 0x03 0x00
+#define IMX95_PAD_ENET1_RD1__FLEXIO2_FLEXIO_BIT11 0x00E4 0x02E8 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_RD1__GPIO4_IO_BIT11 0x00E4 0x02E8 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_RD2__NETCMIX_TOP_ETH0_RGMII_RD2 0x00E8 0x02EC 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_RD2__NETCMIX_TOP_ETH0_RMII_RX_ER 0x00E8 0x02EC 0x042C 0x02 0x01
+#define IMX95_PAD_ENET1_RD2__LPTMR2_ALT2 0x00E8 0x02EC 0x054C 0x03 0x00
+#define IMX95_PAD_ENET1_RD2__FLEXIO2_FLEXIO_BIT12 0x00E8 0x02EC 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_RD2__GPIO4_IO_BIT12 0x00E8 0x02EC 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET1_RD3__NETCMIX_TOP_ETH0_RGMII_RD3 0x00EC 0x02F0 0x0000 0x00 0x00
+#define IMX95_PAD_ENET1_RD3__LPTMR2_ALT3 0x00EC 0x02F0 0x0550 0x03 0x00
+#define IMX95_PAD_ENET1_RD3__FLEXIO2_FLEXIO_BIT13 0x00EC 0x02F0 0x0000 0x04 0x00
+#define IMX95_PAD_ENET1_RD3__GPIO4_IO_BIT13 0x00EC 0x02F0 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET2_MDC__NETCMIX_TOP_NETC_MDC 0x00F0 0x02F4 0x0424 0x00 0x01
+#define IMX95_PAD_ENET2_MDC__LPUART4_DCD_B 0x00F0 0x02F4 0x0000 0x01 0x00
+#define IMX95_PAD_ENET2_MDC__NETCMIX_TOP_SAI2_RX_SYNC 0x00F0 0x02F4 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_MDC__FLEXIO2_FLEXIO_BIT14 0x00F0 0x02F4 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_MDC__GPIO4_IO_BIT14 0x00F0 0x02F4 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET2_MDIO__NETCMIX_TOP_NETC_MDIO 0x00F4 0x02F8 0x0428 0x00 0x01
+#define IMX95_PAD_ENET2_MDIO__LPUART4_RIN_B 0x00F4 0x02F8 0x0000 0x01 0x00
+#define IMX95_PAD_ENET2_MDIO__NETCMIX_TOP_SAI2_RX_BCLK 0x00F4 0x02F8 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_MDIO__FLEXIO2_FLEXIO_BIT15 0x00F4 0x02F8 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_MDIO__GPIO4_IO_BIT15 0x00F4 0x02F8 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET2_TD3__NETCMIX_TOP_SAI2_RX_DATA_BIT0 0x00F8 0x02FC 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_TD3__FLEXIO2_FLEXIO_BIT16 0x00F8 0x02FC 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_TD3__GPIO4_IO_BIT16 0x00F8 0x02FC 0x0000 0x05 0x00
+#define IMX95_PAD_ENET2_TD3__NETCMIX_TOP_ETH1_RGMII_TD3 0x00F8 0x02FC 0x0000 0x00 0x00
+
+#define IMX95_PAD_ENET2_TD2__NETCMIX_TOP_ETH1_RGMII_TD2 0x00FC 0x0300 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_TD2__NETCMIX_TOP_ETH1_RMII_REF50_CLK 0x00FC 0x0300 0x0000 0x01 0x00
+#define IMX95_PAD_ENET2_TD2__NETCMIX_TOP_SAI2_RX_DATA_BIT1 0x00FC 0x0300 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_TD2__SAI4_TX_SYNC 0x00FC 0x0300 0x05A4 0x03 0x00
+#define IMX95_PAD_ENET2_TD2__FLEXIO2_FLEXIO_BIT17 0x00FC 0x0300 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_TD2__GPIO4_IO_BIT17 0x00FC 0x0300 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET2_TD1__NETCMIX_TOP_ETH1_RGMII_TD1 0x0100 0x0304 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_TD1__LPUART4_RTS_B 0x0100 0x0304 0x0000 0x01 0x00
+#define IMX95_PAD_ENET2_TD1__NETCMIX_TOP_SAI2_RX_DATA_BIT2 0x0100 0x0304 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_TD1__SAI4_TX_BCLK 0x0100 0x0304 0x05A0 0x03 0x00
+#define IMX95_PAD_ENET2_TD1__FLEXIO2_FLEXIO_BIT18 0x0100 0x0304 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_TD1__GPIO4_IO_BIT18 0x0100 0x0304 0x0000 0x05 0x00
+#define IMX95_PAD_ENET2_TD1__NETCMIX_TOP_ETH1_RMII_TXD1 0x0100 0x0304 0x0000 0x06 0x00
+
+#define IMX95_PAD_ENET2_TD0__NETCMIX_TOP_ETH1_RGMII_TD0 0x0104 0x0308 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_TD0__LPUART4_TX 0x0104 0x0308 0x0568 0x01 0x00
+#define IMX95_PAD_ENET2_TD0__NETCMIX_TOP_SAI2_RX_DATA_BIT3 0x0104 0x0308 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_TD0__SAI4_TX_DATA_BIT0 0x0104 0x0308 0x0000 0x03 0x00
+#define IMX95_PAD_ENET2_TD0__FLEXIO2_FLEXIO_BIT19 0x0104 0x0308 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_TD0__GPIO4_IO_BIT19 0x0104 0x0308 0x0000 0x05 0x00
+#define IMX95_PAD_ENET2_TD0__NETCMIX_TOP_ETH1_RMII_TXD0 0x0104 0x0308 0x0000 0x06 0x00
+
+#define IMX95_PAD_ENET2_TX_CTL__NETCMIX_TOP_ETH1_RGMII_TX_CTL 0x0108 0x030C 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_TX_CTL__LPUART4_DTR_B 0x0108 0x030C 0x0000 0x01 0x00
+#define IMX95_PAD_ENET2_TX_CTL__NETCMIX_TOP_SAI2_TX_SYNC 0x0108 0x030C 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_TX_CTL__NETCMIX_TOP_ETH1_RMII_TX_EN 0x0108 0x030C 0x0000 0x03 0x00
+#define IMX95_PAD_ENET2_TX_CTL__FLEXIO2_FLEXIO_BIT20 0x0108 0x030C 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_TX_CTL__GPIO4_IO_BIT20 0x0108 0x030C 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET2_TXC__NETCMIX_TOP_ETH1_RGMII_TX_CLK 0x010C 0x0310 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_TXC__CCMSRCGPCMIX_TOP_ENET_CLK_ROOT 0x010C 0x0310 0x0000 0x01 0x00
+#define IMX95_PAD_ENET2_TXC__NETCMIX_TOP_SAI2_TX_BCLK 0x010C 0x0310 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_TXC__FLEXIO2_FLEXIO_BIT21 0x010C 0x0310 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_TXC__GPIO4_IO_BIT21 0x010C 0x0310 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET2_RX_CTL__NETCMIX_TOP_ETH1_RGMII_RX_CTL 0x0110 0x0314 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_RX_CTL__LPUART4_DSR_B 0x0110 0x0314 0x0000 0x01 0x00
+#define IMX95_PAD_ENET2_RX_CTL__NETCMIX_TOP_SAI2_TX_DATA_BIT0 0x0110 0x0314 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_RX_CTL__FLEXIO2_FLEXIO_BIT22 0x0110 0x0314 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_RX_CTL__GPIO4_IO_BIT22 0x0110 0x0314 0x0000 0x05 0x00
+#define IMX95_PAD_ENET2_RX_CTL__NETCMIX_TOP_ETH1_RMII_CRS_DV 0x0110 0x0314 0x0000 0x06 0x00
+
+#define IMX95_PAD_ENET2_RXC__NETCMIX_TOP_ETH1_RGMII_RX_CLK 0x0114 0x0318 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_RXC__NETCMIX_TOP_ETH1_RMII_RX_ER 0x0114 0x0318 0x0430 0x01 0x00
+#define IMX95_PAD_ENET2_RXC__NETCMIX_TOP_SAI2_TX_DATA_BIT1 0x0114 0x0318 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_RXC__SAI4_RX_SYNC 0x0114 0x0318 0x059C 0x03 0x00
+#define IMX95_PAD_ENET2_RXC__FLEXIO2_FLEXIO_BIT23 0x0114 0x0318 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_RXC__GPIO4_IO_BIT23 0x0114 0x0318 0x0000 0x05 0x00
+
+#define IMX95_PAD_ENET2_RD0__NETCMIX_TOP_ETH1_RGMII_RD0 0x0118 0x031C 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_RD0__LPUART4_RX 0x0118 0x031C 0x0564 0x01 0x00
+#define IMX95_PAD_ENET2_RD0__NETCMIX_TOP_SAI2_TX_DATA_BIT2 0x0118 0x031C 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_RD0__SAI4_RX_BCLK 0x0118 0x031C 0x0594 0x03 0x00
+#define IMX95_PAD_ENET2_RD0__FLEXIO2_FLEXIO_BIT24 0x0118 0x031C 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_RD0__GPIO4_IO_BIT24 0x0118 0x031C 0x0000 0x05 0x00
+#define IMX95_PAD_ENET2_RD0__NETCMIX_TOP_ETH1_RMII_RXD0 0x0118 0x031C 0x0000 0x06 0x00
+
+#define IMX95_PAD_ENET2_RD1__NETCMIX_TOP_ETH1_RGMII_RD1 0x011C 0x0320 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_RD1__SPDIF_IN 0x011C 0x0320 0x0454 0x01 0x00
+#define IMX95_PAD_ENET2_RD1__NETCMIX_TOP_SAI2_TX_DATA_BIT3 0x011C 0x0320 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_RD1__SAI4_RX_DATA_BIT0 0x011C 0x0320 0x0598 0x03 0x00
+#define IMX95_PAD_ENET2_RD1__FLEXIO2_FLEXIO_BIT25 0x011C 0x0320 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_RD1__GPIO4_IO_BIT25 0x011C 0x0320 0x0000 0x05 0x00
+#define IMX95_PAD_ENET2_RD1__NETCMIX_TOP_ETH1_RMII_RXD1 0x011C 0x0320 0x0000 0x06 0x00
+
+#define IMX95_PAD_ENET2_RD2__NETCMIX_TOP_ETH1_RGMII_RD2 0x0120 0x0324 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_RD2__LPUART4_CTS_B 0x0120 0x0324 0x0560 0x01 0x00
+#define IMX95_PAD_ENET2_RD2__NETCMIX_TOP_SAI2_MCLK 0x0120 0x0324 0x0000 0x02 0x00
+#define IMX95_PAD_ENET2_RD2__NETCMIX_TOP_MQS2_RIGHT 0x0120 0x0324 0x0000 0x03 0x00
+#define IMX95_PAD_ENET2_RD2__FLEXIO2_FLEXIO_BIT26 0x0120 0x0324 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_RD2__GPIO4_IO_BIT26 0x0120 0x0324 0x0000 0x05 0x00
+#define IMX95_PAD_ENET2_RD2__NETCMIX_TOP_ETH1_RMII_RX_ER 0x0120 0x0324 0x0430 0x06 0x01
+
+#define IMX95_PAD_ENET2_RD3__NETCMIX_TOP_ETH1_RGMII_RD3 0x0124 0x0328 0x0000 0x00 0x00
+#define IMX95_PAD_ENET2_RD3__SPDIF_OUT 0x0124 0x0328 0x0000 0x01 0x00
+#define IMX95_PAD_ENET2_RD3__SPDIF_IN 0x0124 0x0328 0x0454 0x02 0x01
+#define IMX95_PAD_ENET2_RD3__NETCMIX_TOP_MQS2_LEFT 0x0124 0x0328 0x0000 0x03 0x00
+#define IMX95_PAD_ENET2_RD3__FLEXIO2_FLEXIO_BIT27 0x0124 0x0328 0x0000 0x04 0x00
+#define IMX95_PAD_ENET2_RD3__GPIO4_IO_BIT27 0x0124 0x0328 0x0000 0x05 0x00
+
+#define IMX95_PAD_SD1_CLK__FLEXIO1_FLEXIO_BIT8 0x0128 0x032C 0x0488 0x04 0x01
+#define IMX95_PAD_SD1_CLK__GPIO3_IO_BIT8 0x0128 0x032C 0x0000 0x05 0x00
+#define IMX95_PAD_SD1_CLK__USDHC1_CLK 0x0128 0x032C 0x0000 0x00 0x00
+
+#define IMX95_PAD_SD1_CMD__USDHC1_CMD 0x012C 0x0330 0x0000 0x00 0x00
+#define IMX95_PAD_SD1_CMD__FLEXIO1_FLEXIO_BIT9 0x012C 0x0330 0x048C 0x04 0x01
+#define IMX95_PAD_SD1_CMD__GPIO3_IO_BIT9 0x012C 0x0330 0x0000 0x05 0x00
+
+#define IMX95_PAD_SD1_DATA0__USDHC1_DATA0 0x0130 0x0334 0x0000 0x00 0x00
+#define IMX95_PAD_SD1_DATA0__FLEXIO1_FLEXIO_BIT10 0x0130 0x0334 0x0490 0x04 0x01
+#define IMX95_PAD_SD1_DATA0__GPIO3_IO_BIT10 0x0130 0x0334 0x0000 0x05 0x00
+
+#define IMX95_PAD_SD1_DATA1__USDHC1_DATA1 0x0134 0x0338 0x0000 0x00 0x00
+#define IMX95_PAD_SD1_DATA1__FLEXIO1_FLEXIO_BIT11 0x0134 0x0338 0x0494 0x04 0x01
+#define IMX95_PAD_SD1_DATA1__GPIO3_IO_BIT11 0x0134 0x0338 0x0000 0x05 0x00
+
+#define IMX95_PAD_SD1_DATA2__USDHC1_DATA2 0x0138 0x033C 0x0000 0x00 0x00
+#define IMX95_PAD_SD1_DATA2__FLEXIO1_FLEXIO_BIT12 0x0138 0x033C 0x0498 0x04 0x01
+#define IMX95_PAD_SD1_DATA2__GPIO3_IO_BIT12 0x0138 0x033C 0x0000 0x05 0x00
+#define IMX95_PAD_SD1_DATA2__CCMSRCGPCMIX_TOP_PMIC_READY 0x0138 0x033C 0x0000 0x06 0x00
+
+#define IMX95_PAD_SD1_DATA3__USDHC1_DATA3 0x013C 0x0340 0x0000 0x00 0x00
+#define IMX95_PAD_SD1_DATA3__FLEXSPI1_A_SS1_B 0x013C 0x0340 0x0000 0x01 0x00
+#define IMX95_PAD_SD1_DATA3__FLEXIO1_FLEXIO_BIT13 0x013C 0x0340 0x049C 0x04 0x01
+#define IMX95_PAD_SD1_DATA3__GPIO3_IO_BIT13 0x013C 0x0340 0x0000 0x05 0x00
+
+#define IMX95_PAD_SD1_DATA4__USDHC1_DATA4 0x0140 0x0344 0x0000 0x00 0x00
+#define IMX95_PAD_SD1_DATA4__FLEXSPI1_A_DATA_BIT4 0x0140 0x0344 0x04E4 0x01 0x00
+#define IMX95_PAD_SD1_DATA4__FLEXIO1_FLEXIO_BIT14 0x0140 0x0344 0x04A0 0x04 0x01
+#define IMX95_PAD_SD1_DATA4__GPIO3_IO_BIT14 0x0140 0x0344 0x0000 0x05 0x00
+#define IMX95_PAD_SD1_DATA4__XSPI_DATA_BIT4 0x0140 0x0344 0x05FC 0x06 0x00
+
+#define IMX95_PAD_SD1_DATA5__USDHC1_DATA5 0x0144 0x0348 0x0000 0x00 0x00
+#define IMX95_PAD_SD1_DATA5__FLEXSPI1_A_DATA_BIT5 0x0144 0x0348 0x04E8 0x01 0x00
+#define IMX95_PAD_SD1_DATA5__USDHC1_RESET_B 0x0144 0x0348 0x0000 0x02 0x00
+#define IMX95_PAD_SD1_DATA5__FLEXIO1_FLEXIO_BIT15 0x0144 0x0348 0x04A4 0x04 0x01
+#define IMX95_PAD_SD1_DATA5__GPIO3_IO_BIT15 0x0144 0x0348 0x0000 0x05 0x00
+#define IMX95_PAD_SD1_DATA5__XSPI_DATA_BIT5 0x0144 0x0348 0x0600 0x06 0x00
+
+#define IMX95_PAD_SD1_DATA6__USDHC1_DATA6 0x0148 0x034C 0x0000 0x00 0x00
+#define IMX95_PAD_SD1_DATA6__FLEXSPI1_A_DATA_BIT6 0x0148 0x034C 0x04EC 0x01 0x00
+#define IMX95_PAD_SD1_DATA6__USDHC1_CD_B 0x0148 0x034C 0x0000 0x02 0x00
+#define IMX95_PAD_SD1_DATA6__FLEXIO1_FLEXIO_BIT16 0x0148 0x034C 0x04A8 0x04 0x01
+#define IMX95_PAD_SD1_DATA6__GPIO3_IO_BIT16 0x0148 0x034C 0x0000 0x05 0x00
+#define IMX95_PAD_SD1_DATA6__XSPI_DATA_BIT6 0x0148 0x034C 0x0604 0x06 0x00
+
+#define IMX95_PAD_SD1_DATA7__USDHC1_DATA7 0x014C 0x0350 0x0000 0x00 0x00
+#define IMX95_PAD_SD1_DATA7__FLEXSPI1_A_DATA_BIT7 0x014C 0x0350 0x04F0 0x01 0x00
+#define IMX95_PAD_SD1_DATA7__USDHC1_WP 0x014C 0x0350 0x0000 0x02 0x00
+#define IMX95_PAD_SD1_DATA7__FLEXIO1_FLEXIO_BIT17 0x014C 0x0350 0x04AC 0x04 0x01
+#define IMX95_PAD_SD1_DATA7__GPIO3_IO_BIT17 0x014C 0x0350 0x0000 0x05 0x00
+#define IMX95_PAD_SD1_DATA7__XSPI_DATA_BIT7 0x014C 0x0350 0x0608 0x06 0x00
+
+#define IMX95_PAD_SD1_STROBE__USDHC1_STROBE 0x0150 0x0354 0x0000 0x00 0x00
+#define IMX95_PAD_SD1_STROBE__FLEXSPI1_A_DQS 0x0150 0x0354 0x04D0 0x01 0x00
+#define IMX95_PAD_SD1_STROBE__FLEXIO1_FLEXIO_BIT18 0x0150 0x0354 0x04B0 0x04 0x01
+#define IMX95_PAD_SD1_STROBE__GPIO3_IO_BIT18 0x0150 0x0354 0x0000 0x05 0x00
+#define IMX95_PAD_SD1_STROBE__XSPI_DQS 0x0150 0x0354 0x05E4 0x06 0x00
+
+#define IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT 0x0154 0x0358 0x0000 0x00 0x00
+#define IMX95_PAD_SD2_VSELECT__USDHC2_WP 0x0154 0x0358 0x0000 0x01 0x00
+#define IMX95_PAD_SD2_VSELECT__LPTMR2_ALT3 0x0154 0x0358 0x0550 0x02 0x01
+#define IMX95_PAD_SD2_VSELECT__FLEXIO1_FLEXIO_BIT19 0x0154 0x0358 0x04B4 0x04 0x01
+#define IMX95_PAD_SD2_VSELECT__GPIO3_IO_BIT19 0x0154 0x0358 0x0000 0x05 0x00
+#define IMX95_PAD_SD2_VSELECT__CCMSRCGPCMIX_TOP_EXT_CLK1 0x0154 0x0358 0x0420 0x06 0x01
+
+#define IMX95_PAD_SD3_CLK__USDHC3_CLK 0x0158 0x035C 0x05C8 0x00 0x01
+#define IMX95_PAD_SD3_CLK__FLEXSPI1_A_SCLK 0x0158 0x035C 0x04F4 0x01 0x00
+#define IMX95_PAD_SD3_CLK__SAI5_TX_DATA_BIT1 0x0158 0x035C 0x0000 0x02 0x00
+#define IMX95_PAD_SD3_CLK__SAI5_RX_DATA_BIT0 0x0158 0x035C 0x05AC 0x03 0x00
+#define IMX95_PAD_SD3_CLK__FLEXIO1_FLEXIO_BIT20 0x0158 0x035C 0x04B8 0x04 0x01
+#define IMX95_PAD_SD3_CLK__GPIO3_IO_BIT20 0x0158 0x035C 0x0000 0x05 0x00
+#define IMX95_PAD_SD3_CLK__XSPI_CLK 0x0158 0x035C 0x05E8 0x06 0x00
+
+#define IMX95_PAD_SD3_CMD__USDHC3_CMD 0x015C 0x0360 0x05CC 0x00 0x01
+#define IMX95_PAD_SD3_CMD__FLEXSPI1_A_SS0_B 0x015C 0x0360 0x0000 0x01 0x00
+#define IMX95_PAD_SD3_CMD__SAI5_TX_DATA_BIT2 0x015C 0x0360 0x0000 0x02 0x00
+#define IMX95_PAD_SD3_CMD__SAI5_RX_SYNC 0x015C 0x0360 0x05BC 0x03 0x00
+#define IMX95_PAD_SD3_CMD__FLEXIO1_FLEXIO_BIT21 0x015C 0x0360 0x04BC 0x04 0x01
+#define IMX95_PAD_SD3_CMD__GPIO3_IO_BIT21 0x015C 0x0360 0x0000 0x05 0x00
+#define IMX95_PAD_SD3_CMD__XSPI_CS 0x015C 0x0360 0x05E0 0x06 0x00
+
+#define IMX95_PAD_SD3_DATA0__USDHC3_DATA0 0x0160 0x0364 0x05D0 0x00 0x01
+#define IMX95_PAD_SD3_DATA0__FLEXSPI1_A_DATA_BIT0 0x0160 0x0364 0x04D4 0x01 0x00
+#define IMX95_PAD_SD3_DATA0__SAI5_TX_DATA_BIT3 0x0160 0x0364 0x0000 0x02 0x00
+#define IMX95_PAD_SD3_DATA0__SAI5_RX_BCLK 0x0160 0x0364 0x05A8 0x03 0x00
+#define IMX95_PAD_SD3_DATA0__FLEXIO1_FLEXIO_BIT22 0x0160 0x0364 0x04C0 0x04 0x01
+#define IMX95_PAD_SD3_DATA0__GPIO3_IO_BIT22 0x0160 0x0364 0x0000 0x05 0x00
+#define IMX95_PAD_SD3_DATA0__XSPI_DATA_BIT0 0x0160 0x0364 0x05EC 0x06 0x00
+
+#define IMX95_PAD_SD3_DATA1__USDHC3_DATA1 0x0164 0x0368 0x05D4 0x00 0x01
+#define IMX95_PAD_SD3_DATA1__FLEXSPI1_A_DATA_BIT1 0x0164 0x0368 0x04D8 0x01 0x00
+#define IMX95_PAD_SD3_DATA1__SAI5_RX_DATA_BIT1 0x0164 0x0368 0x05B0 0x02 0x00
+#define IMX95_PAD_SD3_DATA1__SAI5_TX_DATA_BIT0 0x0164 0x0368 0x0000 0x03 0x00
+#define IMX95_PAD_SD3_DATA1__FLEXIO1_FLEXIO_BIT23 0x0164 0x0368 0x04C4 0x04 0x01
+#define IMX95_PAD_SD3_DATA1__GPIO3_IO_BIT23 0x0164 0x0368 0x0000 0x05 0x00
+#define IMX95_PAD_SD3_DATA1__XSPI_DATA_BIT1 0x0164 0x0368 0x05F0 0x06 0x00
+
+#define IMX95_PAD_SD3_DATA2__USDHC3_DATA2 0x0168 0x036C 0x05D8 0x00 0x01
+#define IMX95_PAD_SD3_DATA2__FLEXSPI1_A_DATA_BIT2 0x0168 0x036C 0x04DC 0x01 0x00
+#define IMX95_PAD_SD3_DATA2__SAI5_RX_DATA_BIT2 0x0168 0x036C 0x05B4 0x02 0x00
+#define IMX95_PAD_SD3_DATA2__SAI5_TX_SYNC 0x0168 0x036C 0x05C4 0x03 0x00
+#define IMX95_PAD_SD3_DATA2__FLEXIO1_FLEXIO_BIT24 0x0168 0x036C 0x04C8 0x04 0x01
+#define IMX95_PAD_SD3_DATA2__GPIO3_IO_BIT24 0x0168 0x036C 0x0000 0x05 0x00
+#define IMX95_PAD_SD3_DATA2__XSPI_DATA_BIT2 0x0168 0x036C 0x05F4 0x06 0x00
+
+#define IMX95_PAD_SD3_DATA3__USDHC3_DATA3 0x016C 0x0370 0x05DC 0x00 0x01
+#define IMX95_PAD_SD3_DATA3__FLEXSPI1_A_DATA_BIT3 0x016C 0x0370 0x04E0 0x01 0x00
+#define IMX95_PAD_SD3_DATA3__SAI5_RX_DATA_BIT3 0x016C 0x0370 0x05B8 0x02 0x00
+#define IMX95_PAD_SD3_DATA3__SAI5_TX_BCLK 0x016C 0x0370 0x05C0 0x03 0x00
+#define IMX95_PAD_SD3_DATA3__FLEXIO1_FLEXIO_BIT25 0x016C 0x0370 0x04CC 0x04 0x01
+#define IMX95_PAD_SD3_DATA3__GPIO3_IO_BIT25 0x016C 0x0370 0x0000 0x05 0x00
+#define IMX95_PAD_SD3_DATA3__XSPI_DATA_BIT3 0x016C 0x0370 0x05F8 0x06 0x00
+
+#define IMX95_PAD_XSPI1_DATA0__FLEXSPI1_A_DATA_BIT0 0x0170 0x0374 0x04D4 0x00 0x01
+#define IMX95_PAD_XSPI1_DATA0__NETCMIX_TOP_SAI2_TX_DATA_BIT4 0x0170 0x0374 0x0000 0x01 0x00
+#define IMX95_PAD_XSPI1_DATA0__SAI4_TX_BCLK 0x0170 0x0374 0x05A0 0x02 0x01
+#define IMX95_PAD_XSPI1_DATA0__SAI4_RX_DATA_BIT1 0x0170 0x0374 0x0000 0x03 0x00
+#define IMX95_PAD_XSPI1_DATA0__XSPI_DATA_BIT0 0x0170 0x0374 0x05EC 0x04 0x01
+#define IMX95_PAD_XSPI1_DATA0__GPIO5_IO_BIT0 0x0170 0x0374 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_DATA1__FLEXSPI1_A_DATA_BIT1 0x0174 0x0378 0x04D8 0x00 0x01
+#define IMX95_PAD_XSPI1_DATA1__NETCMIX_TOP_SAI2_TX_DATA_BIT5 0x0174 0x0378 0x0000 0x01 0x00
+#define IMX95_PAD_XSPI1_DATA1__SAI4_TX_SYNC 0x0174 0x0378 0x05A4 0x02 0x01
+#define IMX95_PAD_XSPI1_DATA1__SAI4_TX_DATA_BIT1 0x0174 0x0378 0x0000 0x03 0x00
+#define IMX95_PAD_XSPI1_DATA1__XSPI_DATA_BIT1 0x0174 0x0378 0x05F0 0x04 0x01
+#define IMX95_PAD_XSPI1_DATA1__GPIO5_IO_BIT1 0x0174 0x0378 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_DATA2__FLEXSPI1_A_DATA_BIT2 0x0178 0x037C 0x04DC 0x00 0x01
+#define IMX95_PAD_XSPI1_DATA2__NETCMIX_TOP_SAI2_TX_DATA_BIT6 0x0178 0x037C 0x0000 0x01 0x00
+#define IMX95_PAD_XSPI1_DATA2__SAI4_TX_DATA_BIT0 0x0178 0x037C 0x0000 0x02 0x00
+#define IMX95_PAD_XSPI1_DATA2__XSPI_DATA_BIT2 0x0178 0x037C 0x05F4 0x04 0x01
+#define IMX95_PAD_XSPI1_DATA2__GPIO5_IO_BIT2 0x0178 0x037C 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_DATA3__FLEXSPI1_A_DATA_BIT3 0x017C 0x0380 0x04E0 0x00 0x01
+#define IMX95_PAD_XSPI1_DATA3__NETCMIX_TOP_SAI2_TX_DATA_BIT7 0x017C 0x0380 0x0000 0x01 0x00
+#define IMX95_PAD_XSPI1_DATA3__SAI4_RX_DATA_BIT0 0x017C 0x0380 0x0598 0x02 0x01
+#define IMX95_PAD_XSPI1_DATA3__XSPI_DATA_BIT3 0x017C 0x0380 0x05F8 0x04 0x01
+#define IMX95_PAD_XSPI1_DATA3__GPIO5_IO_BIT3 0x017C 0x0380 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_DATA4__FLEXSPI1_A_DATA_BIT4 0x0180 0x0384 0x04E4 0x00 0x01
+#define IMX95_PAD_XSPI1_DATA4__SAI5_TX_DATA_BIT0 0x0180 0x0384 0x0000 0x01 0x00
+#define IMX95_PAD_XSPI1_DATA4__SAI5_RX_DATA_BIT1 0x0180 0x0384 0x05B0 0x02 0x01
+#define IMX95_PAD_XSPI1_DATA4__XSPI_DATA_BIT4 0x0180 0x0384 0x05FC 0x04 0x01
+#define IMX95_PAD_XSPI1_DATA4__GPIO5_IO_BIT4 0x0180 0x0384 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_DATA5__FLEXSPI1_A_DATA_BIT5 0x0184 0x0388 0x04E8 0x00 0x01
+#define IMX95_PAD_XSPI1_DATA5__SAI5_TX_SYNC 0x0184 0x0388 0x05C4 0x01 0x01
+#define IMX95_PAD_XSPI1_DATA5__SAI5_RX_DATA_BIT2 0x0184 0x0388 0x05B4 0x02 0x01
+#define IMX95_PAD_XSPI1_DATA5__NETCMIX_TOP_SAI2_RX_DATA_BIT6 0x0184 0x0388 0x043C 0x03 0x00
+#define IMX95_PAD_XSPI1_DATA5__XSPI_DATA_BIT5 0x0184 0x0388 0x0600 0x04 0x01
+#define IMX95_PAD_XSPI1_DATA5__GPIO5_IO_BIT5 0x0184 0x0388 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_DATA6__FLEXSPI1_A_DATA_BIT6 0x0188 0x038C 0x04EC 0x00 0x01
+#define IMX95_PAD_XSPI1_DATA6__SAI5_TX_BCLK 0x0188 0x038C 0x05C0 0x01 0x01
+#define IMX95_PAD_XSPI1_DATA6__SAI5_RX_DATA_BIT3 0x0188 0x038C 0x05B8 0x02 0x01
+#define IMX95_PAD_XSPI1_DATA6__NETCMIX_TOP_SAI2_RX_DATA_BIT7 0x0188 0x038C 0x0440 0x03 0x00
+#define IMX95_PAD_XSPI1_DATA6__XSPI_DATA_BIT6 0x0188 0x038C 0x0604 0x04 0x01
+#define IMX95_PAD_XSPI1_DATA6__GPIO5_IO_BIT6 0x0188 0x038C 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_DATA7__FLEXSPI1_A_DATA_BIT7 0x018C 0x0390 0x04F0 0x00 0x01
+#define IMX95_PAD_XSPI1_DATA7__SAI5_RX_DATA_BIT0 0x018C 0x0390 0x05AC 0x01 0x01
+#define IMX95_PAD_XSPI1_DATA7__SAI5_TX_DATA_BIT1 0x018C 0x0390 0x0000 0x02 0x00
+#define IMX95_PAD_XSPI1_DATA7__XSPI_DATA_BIT7 0x018C 0x0390 0x0608 0x04 0x01
+#define IMX95_PAD_XSPI1_DATA7__GPIO5_IO_BIT7 0x018C 0x0390 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_DQS__FLEXSPI1_A_DQS 0x0190 0x0394 0x04D0 0x00 0x01
+#define IMX95_PAD_XSPI1_DQS__SAI5_RX_SYNC 0x0190 0x0394 0x05BC 0x01 0x01
+#define IMX95_PAD_XSPI1_DQS__SAI5_TX_DATA_BIT2 0x0190 0x0394 0x0000 0x02 0x00
+#define IMX95_PAD_XSPI1_DQS__NETCMIX_TOP_SAI2_RX_DATA_BIT6 0x0190 0x0394 0x043C 0x03 0x01
+#define IMX95_PAD_XSPI1_DQS__XSPI_DQS 0x0190 0x0394 0x05E4 0x04 0x01
+#define IMX95_PAD_XSPI1_DQS__GPIO5_IO_BIT8 0x0190 0x0394 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_SCLK__FLEXSPI1_A_SCLK 0x0194 0x0398 0x04F4 0x00 0x01
+#define IMX95_PAD_XSPI1_SCLK__NETCMIX_TOP_SAI2_RX_DATA_BIT4 0x0194 0x0398 0x0000 0x01 0x00
+#define IMX95_PAD_XSPI1_SCLK__SAI4_RX_SYNC 0x0194 0x0398 0x059C 0x02 0x01
+#define IMX95_PAD_XSPI1_SCLK__EARC_DC_HPD_IN 0x0194 0x0398 0x0000 0x03 0x00
+#define IMX95_PAD_XSPI1_SCLK__XSPI_CLK 0x0194 0x0398 0x05E8 0x04 0x01
+#define IMX95_PAD_XSPI1_SCLK__GPIO5_IO_BIT9 0x0194 0x0398 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_SS0_B__FLEXSPI1_A_SS0_B 0x0198 0x039C 0x0000 0x00 0x00
+#define IMX95_PAD_XSPI1_SS0_B__NETCMIX_TOP_SAI2_RX_DATA_BIT5 0x0198 0x039C 0x0000 0x01 0x00
+#define IMX95_PAD_XSPI1_SS0_B__SAI4_RX_BCLK 0x0198 0x039C 0x0594 0x02 0x01
+#define IMX95_PAD_XSPI1_SS0_B__EARC_CEC_OUT 0x0198 0x039C 0x0000 0x03 0x00
+#define IMX95_PAD_XSPI1_SS0_B__XSPI_CS 0x0198 0x039C 0x05E0 0x04 0x01
+#define IMX95_PAD_XSPI1_SS0_B__GPIO5_IO_BIT10 0x0198 0x039C 0x0000 0x05 0x00
+
+#define IMX95_PAD_XSPI1_SS1_B__FLEXSPI1_A_SS1_B 0x019C 0x03A0 0x0000 0x00 0x00
+#define IMX95_PAD_XSPI1_SS1_B__SAI5_RX_BCLK 0x019C 0x03A0 0x05A8 0x01 0x01
+#define IMX95_PAD_XSPI1_SS1_B__SAI5_TX_DATA_BIT3 0x019C 0x03A0 0x0000 0x02 0x00
+#define IMX95_PAD_XSPI1_SS1_B__NETCMIX_TOP_SAI2_RX_DATA_BIT7 0x019C 0x03A0 0x0440 0x03 0x01
+#define IMX95_PAD_XSPI1_SS1_B__GPIO5_IO_BIT11 0x019C 0x03A0 0x0000 0x05 0x00
+
+#define IMX95_PAD_SD2_CD_B__USDHC2_CD_B 0x01A0 0x03A4 0x0000 0x00 0x00
+#define IMX95_PAD_SD2_CD_B__NETCMIX_TOP_NETC_TMR_1588_TRIG1 0x01A0 0x03A4 0x0434 0x01 0x01
+#define IMX95_PAD_SD2_CD_B__I3C2_SCL 0x01A0 0x03A4 0x04F8 0x02 0x01
+#define IMX95_PAD_SD2_CD_B__FLEXIO1_FLEXIO_BIT0 0x01A0 0x03A4 0x0468 0x04 0x01
+#define IMX95_PAD_SD2_CD_B__GPIO3_IO_BIT0 0x01A0 0x03A4 0x0000 0x05 0x00
+
+#define IMX95_PAD_SD2_CLK__USDHC2_CLK 0x01A4 0x03A8 0x0000 0x00 0x00
+#define IMX95_PAD_SD2_CLK__NETCMIX_TOP_NETC_TMR_1588_PP1 0x01A4 0x03A8 0x0000 0x01 0x00
+#define IMX95_PAD_SD2_CLK__I3C2_SDA 0x01A4 0x03A8 0x04FC 0x02 0x01
+#define IMX95_PAD_SD2_CLK__FLEXIO1_FLEXIO_BIT1 0x01A4 0x03A8 0x046C 0x04 0x01
+#define IMX95_PAD_SD2_CLK__GPIO3_IO_BIT1 0x01A4 0x03A8 0x0000 0x05 0x00
+#define IMX95_PAD_SD2_CLK__CCMSRCGPCMIX_TOP_OBSERVE_0 0x01A4 0x03A8 0x0000 0x06 0x00
+
+#define IMX95_PAD_SD2_CMD__USDHC2_CMD 0x01A8 0x03AC 0x0000 0x00 0x00
+#define IMX95_PAD_SD2_CMD__NETCMIX_TOP_NETC_TMR_1588_TRIG2 0x01A8 0x03AC 0x0438 0x01 0x01
+#define IMX95_PAD_SD2_CMD__I3C2_PUR 0x01A8 0x03AC 0x0000 0x02 0x00
+#define IMX95_PAD_SD2_CMD__I3C2_PUR_B 0x01A8 0x03AC 0x0000 0x03 0x00
+#define IMX95_PAD_SD2_CMD__FLEXIO1_FLEXIO_BIT2 0x01A8 0x03AC 0x0470 0x04 0x01
+#define IMX95_PAD_SD2_CMD__GPIO3_IO_BIT2 0x01A8 0x03AC 0x0000 0x05 0x00
+#define IMX95_PAD_SD2_CMD__CCMSRCGPCMIX_TOP_OBSERVE_1 0x01A8 0x03AC 0x0000 0x06 0x00
+
+#define IMX95_PAD_SD2_DATA0__USDHC2_DATA0 0x01AC 0x03B0 0x0000 0x00 0x00
+#define IMX95_PAD_SD2_DATA0__NETCMIX_TOP_NETC_TMR_1588_PP2 0x01AC 0x03B0 0x0000 0x01 0x00
+#define IMX95_PAD_SD2_DATA0__CAN2_TX 0x01AC 0x03B0 0x0000 0x02 0x00
+#define IMX95_PAD_SD2_DATA0__FLEXIO1_FLEXIO_BIT3 0x01AC 0x03B0 0x0474 0x04 0x01
+#define IMX95_PAD_SD2_DATA0__GPIO3_IO_BIT3 0x01AC 0x03B0 0x0000 0x05 0x00
+#define IMX95_PAD_SD2_DATA0__CCMSRCGPCMIX_TOP_OBSERVE_2 0x01AC 0x03B0 0x0000 0x06 0x00
+
+#define IMX95_PAD_SD2_DATA1__USDHC2_DATA1 0x01B0 0x03B4 0x0000 0x00 0x00
+#define IMX95_PAD_SD2_DATA1__NETCMIX_TOP_NETC_TMR_1588_CLK 0x01B0 0x03B4 0x0000 0x01 0x00
+#define IMX95_PAD_SD2_DATA1__CAN2_RX 0x01B0 0x03B4 0x0444 0x02 0x03
+#define IMX95_PAD_SD2_DATA1__FLEXIO1_FLEXIO_BIT4 0x01B0 0x03B4 0x0478 0x04 0x01
+#define IMX95_PAD_SD2_DATA1__GPIO3_IO_BIT4 0x01B0 0x03B4 0x0000 0x05 0x00
+
+#define IMX95_PAD_SD2_DATA2__USDHC2_DATA2 0x01B4 0x03B8 0x0000 0x00 0x00
+#define IMX95_PAD_SD2_DATA2__NETCMIX_TOP_NETC_TMR_1588_PP3 0x01B4 0x03B8 0x0000 0x01 0x00
+#define IMX95_PAD_SD2_DATA2__NETCMIX_TOP_MQS2_RIGHT 0x01B4 0x03B8 0x0000 0x02 0x00
+#define IMX95_PAD_SD2_DATA2__FLEXIO1_FLEXIO_BIT5 0x01B4 0x03B8 0x047C 0x04 0x01
+#define IMX95_PAD_SD2_DATA2__GPIO3_IO_BIT5 0x01B4 0x03B8 0x0000 0x05 0x00
+
+#define IMX95_PAD_SD2_DATA3__USDHC2_DATA3 0x01B8 0x03BC 0x0000 0x00 0x00
+#define IMX95_PAD_SD2_DATA3__LPTMR2_ALT1 0x01B8 0x03BC 0x0548 0x01 0x01
+#define IMX95_PAD_SD2_DATA3__NETCMIX_TOP_MQS2_LEFT 0x01B8 0x03BC 0x0000 0x02 0x00
+#define IMX95_PAD_SD2_DATA3__NETCMIX_TOP_NETC_TMR_1588_ALARM1 0x01B8 0x03BC 0x0000 0x03 0x00
+#define IMX95_PAD_SD2_DATA3__FLEXIO1_FLEXIO_BIT6 0x01B8 0x03BC 0x0480 0x04 0x01
+#define IMX95_PAD_SD2_DATA3__GPIO3_IO_BIT6 0x01B8 0x03BC 0x0000 0x05 0x00
+
+#define IMX95_PAD_SD2_RESET_B__USDHC2_RESET_B 0x01BC 0x03C0 0x0000 0x00 0x00
+#define IMX95_PAD_SD2_RESET_B__LPTMR2_ALT2 0x01BC 0x03C0 0x054C 0x01 0x01
+#define IMX95_PAD_SD2_RESET_B__NETCMIX_TOP_NETC_TMR_1588_GCLK 0x01BC 0x03C0 0x0000 0x03 0x00
+#define IMX95_PAD_SD2_RESET_B__FLEXIO1_FLEXIO_BIT7 0x01BC 0x03C0 0x0484 0x04 0x01
+#define IMX95_PAD_SD2_RESET_B__GPIO3_IO_BIT7 0x01BC 0x03C0 0x0000 0x05 0x00
+
+#define IMX95_PAD_I2C1_SCL__AONMIX_TOP_LPI2C1_SCL 0x01C0 0x03C4 0x0000 0x00 0x00
+#define IMX95_PAD_I2C1_SCL__AONMIX_TOP_I3C1_SCL 0x01C0 0x03C4 0x0000 0x01 0x00
+#define IMX95_PAD_I2C1_SCL__AONMIX_TOP_LPUART1_DCD_B 0x01C0 0x03C4 0x0000 0x02 0x00
+#define IMX95_PAD_I2C1_SCL__AONMIX_TOP_TPM2_CH0 0x01C0 0x03C4 0x0000 0x03 0x00
+#define IMX95_PAD_I2C1_SCL__VPUMIX_TOP_UART_RX 0x01C0 0x03C4 0x0000 0x04 0x00
+#define IMX95_PAD_I2C1_SCL__AONMIX_TOP_GPIO1_IO_BIT0 0x01C0 0x03C4 0x0000 0x05 0x00
+
+#define IMX95_PAD_I2C1_SDA__AONMIX_TOP_LPI2C1_SDA 0x01C4 0x03C8 0x0000 0x00 0x00
+#define IMX95_PAD_I2C1_SDA__AONMIX_TOP_I3C1_SDA 0x01C4 0x03C8 0x0000 0x01 0x00
+#define IMX95_PAD_I2C1_SDA__AONMIX_TOP_LPUART1_RIN_B 0x01C4 0x03C8 0x0000 0x02 0x00
+#define IMX95_PAD_I2C1_SDA__AONMIX_TOP_TPM2_CH1 0x01C4 0x03C8 0x0000 0x03 0x00
+#define IMX95_PAD_I2C1_SDA__VPUMIX_TOP_UART_TX 0x01C4 0x03C8 0x0000 0x04 0x00
+#define IMX95_PAD_I2C1_SDA__AONMIX_TOP_GPIO1_IO_BIT1 0x01C4 0x03C8 0x0000 0x05 0x00
+
+#define IMX95_PAD_I2C2_SCL__AONMIX_TOP_LPI2C2_SCL 0x01C8 0x03CC 0x0000 0x00 0x00
+#define IMX95_PAD_I2C2_SCL__AONMIX_TOP_I3C1_PUR 0x01C8 0x03CC 0x0000 0x01 0x00
+#define IMX95_PAD_I2C2_SCL__AONMIX_TOP_LPUART2_DCD_B 0x01C8 0x03CC 0x0000 0x02 0x00
+#define IMX95_PAD_I2C2_SCL__AONMIX_TOP_TPM2_CH2 0x01C8 0x03CC 0x0000 0x03 0x00
+#define IMX95_PAD_I2C2_SCL__AONMIX_TOP_SAI1_RX_SYNC 0x01C8 0x03CC 0x0000 0x04 0x00
+#define IMX95_PAD_I2C2_SCL__AONMIX_TOP_GPIO1_IO_BIT2 0x01C8 0x03CC 0x0000 0x05 0x00
+#define IMX95_PAD_I2C2_SCL__AONMIX_TOP_I3C1_PUR_B 0x01C8 0x03CC 0x0000 0x06 0x00
+
+#define IMX95_PAD_I2C2_SDA__AONMIX_TOP_LPI2C2_SDA 0x01CC 0x03D0 0x0000 0x00 0x00
+#define IMX95_PAD_I2C2_SDA__AONMIX_TOP_LPUART2_RIN_B 0x01CC 0x03D0 0x0000 0x02 0x00
+#define IMX95_PAD_I2C2_SDA__AONMIX_TOP_TPM2_CH3 0x01CC 0x03D0 0x0000 0x03 0x00
+#define IMX95_PAD_I2C2_SDA__AONMIX_TOP_SAI1_RX_BCLK 0x01CC 0x03D0 0x0000 0x04 0x00
+#define IMX95_PAD_I2C2_SDA__AONMIX_TOP_GPIO1_IO_BIT3 0x01CC 0x03D0 0x0000 0x05 0x00
+
+#define IMX95_PAD_UART1_RXD__AONMIX_TOP_LPUART1_RX 0x01D0 0x03D4 0x0000 0x00 0x00
+#define IMX95_PAD_UART1_RXD__S400_UART_RX 0x01D0 0x03D4 0x0000 0x01 0x00
+#define IMX95_PAD_UART1_RXD__AONMIX_TOP_LPSPI2_SIN 0x01D0 0x03D4 0x0000 0x02 0x00
+#define IMX95_PAD_UART1_RXD__AONMIX_TOP_TPM1_CH0 0x01D0 0x03D4 0x0000 0x03 0x00
+#define IMX95_PAD_UART1_RXD__AONMIX_TOP_GPIO1_IO_BIT4 0x01D0 0x03D4 0x0000 0x05 0x00
+
+#define IMX95_PAD_UART1_TXD__AONMIX_TOP_LPUART1_TX 0x01D4 0x03D8 0x0000 0x00 0x00
+#define IMX95_PAD_UART1_TXD__S400_UART_TX 0x01D4 0x03D8 0x0000 0x01 0x00
+#define IMX95_PAD_UART1_TXD__AONMIX_TOP_LPSPI2_PCS0 0x01D4 0x03D8 0x0000 0x02 0x00
+#define IMX95_PAD_UART1_TXD__AONMIX_TOP_TPM1_CH1 0x01D4 0x03D8 0x0000 0x03 0x00
+#define IMX95_PAD_UART1_TXD__AONMIX_TOP_GPIO1_IO_BIT5 0x01D4 0x03D8 0x0000 0x05 0x00
+
+#define IMX95_PAD_UART2_RXD__AONMIX_TOP_LPUART2_RX 0x01D8 0x03DC 0x0000 0x00 0x00
+#define IMX95_PAD_UART2_RXD__AONMIX_TOP_LPUART1_CTS_B 0x01D8 0x03DC 0x0000 0x01 0x00
+#define IMX95_PAD_UART2_RXD__AONMIX_TOP_LPSPI2_SOUT 0x01D8 0x03DC 0x0000 0x02 0x00
+#define IMX95_PAD_UART2_RXD__AONMIX_TOP_TPM1_CH2 0x01D8 0x03DC 0x0000 0x03 0x00
+#define IMX95_PAD_UART2_RXD__AONMIX_TOP_SAI1_MCLK 0x01D8 0x03DC 0x041C 0x04 0x00
+#define IMX95_PAD_UART2_RXD__AONMIX_TOP_GPIO1_IO_BIT6 0x01D8 0x03DC 0x0000 0x05 0x00
+
+#define IMX95_PAD_UART2_TXD__AONMIX_TOP_LPUART2_TX 0x01DC 0x03E0 0x0000 0x00 0x00
+#define IMX95_PAD_UART2_TXD__AONMIX_TOP_LPUART1_RTS_B 0x01DC 0x03E0 0x0000 0x01 0x00
+#define IMX95_PAD_UART2_TXD__AONMIX_TOP_LPSPI2_SCK 0x01DC 0x03E0 0x0000 0x02 0x00
+#define IMX95_PAD_UART2_TXD__AONMIX_TOP_TPM1_CH3 0x01DC 0x03E0 0x0000 0x03 0x00
+#define IMX95_PAD_UART2_TXD__AONMIX_TOP_GPIO1_IO_BIT7 0x01DC 0x03E0 0x0000 0x05 0x00
+
+#define IMX95_PAD_PDM_CLK__AONMIX_TOP_PDM_CLK 0x01E0 0x03E4 0x0000 0x00 0x00
+#define IMX95_PAD_PDM_CLK__AONMIX_TOP_MQS1_LEFT 0x01E0 0x03E4 0x0000 0x01 0x00
+#define IMX95_PAD_PDM_CLK__AONMIX_TOP_LPTMR1_ALT1 0x01E0 0x03E4 0x0000 0x04 0x00
+#define IMX95_PAD_PDM_CLK__AONMIX_TOP_GPIO1_IO_BIT8 0x01E0 0x03E4 0x0000 0x05 0x00
+#define IMX95_PAD_PDM_CLK__AONMIX_TOP_CAN1_TX 0x01E0 0x03E4 0x0000 0x06 0x00
+
+#define IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_PDM_BIT_STREAM_BIT0 0x01E4 0x03E8 0x040C 0x00 0x00
+#define IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_MQS1_RIGHT 0x01E4 0x03E8 0x0000 0x01 0x00
+#define IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_LPSPI1_PCS1 0x01E4 0x03E8 0x0000 0x02 0x00
+#define IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_TPM1_EXTCLK 0x01E4 0x03E8 0x0000 0x03 0x00
+#define IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_LPTMR1_ALT2 0x01E4 0x03E8 0x0000 0x04 0x00
+#define IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_GPIO1_IO_BIT9 0x01E4 0x03E8 0x0000 0x05 0x00
+#define IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_CAN1_RX 0x01E4 0x03E8 0x0408 0x06 0x00
+
+#define IMX95_PAD_PDM_BIT_STREAM1__AONMIX_TOP_PDM_BIT_STREAM_BIT1 0x01E8 0x03EC 0x0410 0x00 0x00
+#define IMX95_PAD_PDM_BIT_STREAM1__NMI_GLUE_NMI 0x01E8 0x03EC 0x0000 0x01 0x00
+#define IMX95_PAD_PDM_BIT_STREAM1__AONMIX_TOP_LPSPI2_PCS1 0x01E8 0x03EC 0x0000 0x02 0x00
+#define IMX95_PAD_PDM_BIT_STREAM1__AONMIX_TOP_TPM2_EXTCLK 0x01E8 0x03EC 0x0000 0x03 0x00
+#define IMX95_PAD_PDM_BIT_STREAM1__AONMIX_TOP_LPTMR1_ALT3 0x01E8 0x03EC 0x0000 0x04 0x00
+#define IMX95_PAD_PDM_BIT_STREAM1__AONMIX_TOP_GPIO1_IO_BIT10 0x01E8 0x03EC 0x0000 0x05 0x00
+#define IMX95_PAD_PDM_BIT_STREAM1__CCMSRCGPCMIX_TOP_EXT_CLK1 0x01E8 0x03EC 0x0420 0x06 0x00
+
+#define IMX95_PAD_SAI1_TXFS__AONMIX_TOP_SAI1_TX_SYNC 0x01EC 0x03F0 0x0000 0x00 0x00
+#define IMX95_PAD_SAI1_TXFS__AONMIX_TOP_SAI1_TX_DATA_BIT1 0x01EC 0x03F0 0x0000 0x01 0x00
+#define IMX95_PAD_SAI1_TXFS__AONMIX_TOP_LPSPI1_PCS0 0x01EC 0x03F0 0x0000 0x02 0x00
+#define IMX95_PAD_SAI1_TXFS__AONMIX_TOP_LPUART2_DTR_B 0x01EC 0x03F0 0x0000 0x03 0x00
+#define IMX95_PAD_SAI1_TXFS__AONMIX_TOP_MQS1_LEFT 0x01EC 0x03F0 0x0000 0x04 0x00
+#define IMX95_PAD_SAI1_TXFS__AONMIX_TOP_GPIO1_IO_BIT11 0x01EC 0x03F0 0x0000 0x05 0x00
+
+#define IMX95_PAD_SAI1_TXC__AONMIX_TOP_SAI1_TX_BCLK 0x01F0 0x03F4 0x0000 0x00 0x00
+#define IMX95_PAD_SAI1_TXC__AONMIX_TOP_LPUART2_CTS_B 0x01F0 0x03F4 0x0000 0x01 0x00
+#define IMX95_PAD_SAI1_TXC__AONMIX_TOP_LPSPI1_SIN 0x01F0 0x03F4 0x0000 0x02 0x00
+#define IMX95_PAD_SAI1_TXC__AONMIX_TOP_LPUART1_DSR_B 0x01F0 0x03F4 0x0000 0x03 0x00
+#define IMX95_PAD_SAI1_TXC__AONMIX_TOP_CAN1_RX 0x01F0 0x03F4 0x0408 0x04 0x01
+#define IMX95_PAD_SAI1_TXC__AONMIX_TOP_GPIO1_IO_BIT12 0x01F0 0x03F4 0x0000 0x05 0x00
+
+#define IMX95_PAD_SAI1_TXD0__AONMIX_TOP_SAI1_TX_DATA_BIT0 0x01F4 0x03F8 0x0000 0x00 0x00
+#define IMX95_PAD_SAI1_TXD0__AONMIX_TOP_LPUART2_RTS_B 0x01F4 0x03F8 0x0000 0x01 0x00
+#define IMX95_PAD_SAI1_TXD0__AONMIX_TOP_LPSPI1_SCK 0x01F4 0x03F8 0x0000 0x02 0x00
+#define IMX95_PAD_SAI1_TXD0__AONMIX_TOP_LPUART1_DTR_B 0x01F4 0x03F8 0x0000 0x03 0x00
+#define IMX95_PAD_SAI1_TXD0__AONMIX_TOP_CAN1_TX 0x01F4 0x03F8 0x0000 0x04 0x00
+#define IMX95_PAD_SAI1_TXD0__AONMIX_TOP_GPIO1_IO_BIT13 0x01F4 0x03F8 0x0000 0x05 0x00
+
+#define IMX95_PAD_SAI1_RXD0__AONMIX_TOP_SAI1_RX_DATA_BIT0 0x01F8 0x03FC 0x0000 0x00 0x00
+#define IMX95_PAD_SAI1_RXD0__AONMIX_TOP_SAI1_MCLK 0x01F8 0x03FC 0x041C 0x01 0x01
+#define IMX95_PAD_SAI1_RXD0__AONMIX_TOP_LPSPI1_SOUT 0x01F8 0x03FC 0x0000 0x02 0x00
+#define IMX95_PAD_SAI1_RXD0__AONMIX_TOP_LPUART2_DSR_B 0x01F8 0x03FC 0x0000 0x03 0x00
+#define IMX95_PAD_SAI1_RXD0__AONMIX_TOP_MQS1_RIGHT 0x01F8 0x03FC 0x0000 0x04 0x00
+#define IMX95_PAD_SAI1_RXD0__AONMIX_TOP_GPIO1_IO_BIT14 0x01F8 0x03FC 0x0000 0x05 0x00
+
+#define IMX95_PAD_WDOG_ANY__AONMIX_TOP_WDOG_ANY 0x01FC 0x0400 0x0000 0x00 0x00
+#define IMX95_PAD_WDOG_ANY__AONMIX_TOP_FCCU_EOUT1 0x01FC 0x0400 0x0000 0x01 0x00
+#define IMX95_PAD_WDOG_ANY__AONMIX_TOP_GPIO1_IO_BIT15 0x01FC 0x0400 0x0000 0x05 0x00
+#endif /* __DTS_IMX95_PINFUNC_H */
diff --git a/arch/arm64/boot/dts/freescale/imx95-power.h b/arch/arm64/boot/dts/freescale/imx95-power.h
new file mode 100644
index 000000000000..0b7f0bc30e19
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx95-power.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright 2024 NXP
+ */
+
+#ifndef __IMX95_POWER_H__
+#define __IMX95_POWER_H__
+
+#define IMX95_PD_ANA 0
+#define IMX95_PD_AON 1
+#define IMX95_PD_BBSM 2
+#define IMX95_PD_CAMERA 3
+#define IMX95_PD_CCMSRCGPC 4
+#define IMX95_PD_A55C0 5
+#define IMX95_PD_A55C1 6
+#define IMX95_PD_A55C2 7
+#define IMX95_PD_A55C3 8
+#define IMX95_PD_A55C4 9
+#define IMX95_PD_A55C5 10
+#define IMX95_PD_A55P 11
+#define IMX95_PD_DDR 12
+#define IMX95_PD_DISPLAY 13
+#define IMX95_PD_GPU 14
+#define IMX95_PD_HSIO_TOP 15
+#define IMX95_PD_HSIO_WAON 16
+#define IMX95_PD_M7 17
+#define IMX95_PD_NETC 18
+#define IMX95_PD_NOC 19
+#define IMX95_PD_NPU 20
+#define IMX95_PD_VPU 21
+#define IMX95_PD_WAKEUP 22
+
+#define IMX95_PERF_ELE 0
+#define IMX95_PERF_M33 1
+#define IMX95_PERF_WAKEUP 2
+#define IMX95_PERF_M7 3
+#define IMX95_PERF_DRAM 4
+#define IMX95_PERF_HSIO 5
+#define IMX95_PERF_NPU 6
+#define IMX95_PERF_NOC 7
+#define IMX95_PERF_A55 8
+#define IMX95_PERF_GPU 9
+#define IMX95_PERF_VPU 10
+#define IMX95_PERF_CAM 11
+#define IMX95_PERF_DISP 12
+
+#endif
diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
new file mode 100644
index 000000000000..1bbf9a0468f6
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
@@ -0,0 +1,1192 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright 2024 NXP
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/thermal/thermal.h>
+
+#include "imx95-clock.h"
+#include "imx95-pinfunc.h"
+#include "imx95-power.h"
+
+/ {
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ A55_0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0>;
+ enable-method = "psci";
+ #cooling-cells = <2>;
+ power-domains = <&scmi_devpd IMX95_PERF_A55>;
+ power-domain-names = "perf";
+ i-cache-size = <32768>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache_l0>;
+ };
+
+ A55_1: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x100>;
+ enable-method = "psci";
+ #cooling-cells = <2>;
+ power-domains = <&scmi_devpd IMX95_PERF_A55>;
+ power-domain-names = "perf";
+ i-cache-size = <32768>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache_l1>;
+ };
+
+ A55_2: cpu@200 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x200>;
+ enable-method = "psci";
+ #cooling-cells = <2>;
+ power-domains = <&scmi_devpd IMX95_PERF_A55>;
+ power-domain-names = "perf";
+ i-cache-size = <32768>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache_l2>;
+ };
+
+ A55_3: cpu@300 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x300>;
+ enable-method = "psci";
+ #cooling-cells = <2>;
+ power-domains = <&scmi_devpd IMX95_PERF_A55>;
+ power-domain-names = "perf";
+ i-cache-size = <32768>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache_l3>;
+ };
+
+ A55_4: cpu@400 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x400>;
+ power-domains = <&scmi_devpd IMX95_PERF_A55>;
+ power-domain-names = "perf";
+ enable-method = "psci";
+ #cooling-cells = <2>;
+ i-cache-size = <32768>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache_l4>;
+ };
+
+ A55_5: cpu@500 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x500>;
+ power-domains = <&scmi_devpd IMX95_PERF_A55>;
+ power-domain-names = "perf";
+ enable-method = "psci";
+ #cooling-cells = <2>;
+ i-cache-size = <32768>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache_l5>;
+ };
+
+ l2_cache_l0: l2-cache-l0 {
+ compatible = "cache";
+ cache-size = <65536>;
+ cache-line-size = <64>;
+ cache-sets = <256>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l1: l2-cache-l1 {
+ compatible = "cache";
+ cache-size = <65536>;
+ cache-line-size = <64>;
+ cache-sets = <256>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l2: l2-cache-l2 {
+ compatible = "cache";
+ cache-size = <65536>;
+ cache-line-size = <64>;
+ cache-sets = <256>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l3: l2-cache-l3 {
+ compatible = "cache";
+ cache-size = <65536>;
+ cache-line-size = <64>;
+ cache-sets = <256>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l4: l2-cache-l4 {
+ compatible = "cache";
+ cache-size = <65536>;
+ cache-line-size = <64>;
+ cache-sets = <256>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l5: l2-cache-l5 {
+ compatible = "cache";
+ cache-size = <65536>;
+ cache-line-size = <64>;
+ cache-sets = <256>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l3_cache: l3-cache {
+ compatible = "cache";
+ cache-size = <524288>;
+ cache-line-size = <64>;
+ cache-sets = <1024>;
+ cache-level = <3>;
+ cache-unified;
+ };
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&A55_0>;
+ };
+
+ core1 {
+ cpu = <&A55_1>;
+ };
+
+ core2 {
+ cpu = <&A55_2>;
+ };
+
+ core3 {
+ cpu = <&A55_3>;
+ };
+
+ core4 {
+ cpu = <&A55_4>;
+ };
+
+ core5 {
+ cpu = <&A55_5>;
+ };
+ };
+ };
+ };
+
+ clk_ext1: clock-ext1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <133000000>;
+ clock-output-names = "clk_ext1";
+ };
+
+ sai1_mclk: clock-sai-mclk1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency= <0>;
+ clock-output-names = "sai1_mclk";
+ };
+
+ sai2_mclk: clock-sai-mclk2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency= <0>;
+ clock-output-names = "sai2_mclk";
+ };
+
+ sai3_mclk: clock-sai-mclk3 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency= <0>;
+ clock-output-names = "sai3_mclk";
+ };
+
+ sai4_mclk: clock-sai-mclk4 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency= <0>;
+ clock-output-names = "sai4_mclk";
+ };
+
+ sai5_mclk: clock-sai-mclk5 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency= <0>;
+ clock-output-names = "sai5_mclk";
+ };
+
+ osc_24m: clock-24m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "osc_24m";
+ };
+
+ sram1: sram@204c0000 {
+ compatible = "mmio-sram";
+ reg = <0x0 0x204c0000 0x0 0x18000>;
+ ranges = <0x0 0x0 0x204c0000 0x18000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ firmware {
+ scmi {
+ compatible = "arm,scmi";
+ mboxes = <&mu2 5 0>, <&mu2 3 0>, <&mu2 3 1>;
+ shmem = <&scmi_buf0>, <&scmi_buf1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ scmi_devpd: protocol@11 {
+ reg = <0x11>;
+ #power-domain-cells = <1>;
+ };
+
+ scmi_perf: protocol@13 {
+ reg = <0x13>;
+ #power-domain-cells = <1>;
+ };
+
+ scmi_clk: protocol@14 {
+ reg = <0x14>;
+ #clock-cells = <1>;
+ };
+
+ scmi_sensor: protocol@15 {
+ reg = <0x15>;
+ #thermal-sensor-cells = <1>;
+ };
+
+ scmi_iomuxc: protocol@19 {
+ reg = <0x19>;
+ };
+
+ };
+ };
+
+ pmu {
+ compatible = "arm,cortex-a55-pmu";
+ interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ thermal-zones {
+ a55-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <2000>;
+ thermal-sensors = <&scmi_sensor 1>;
+
+ trips {
+ cpu_alert0: trip0 {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_crit0: trip1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_alert0>;
+ 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 {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
+ clock-frequency = <24000000>;
+ arm,no-tick-in-suspend;
+ interrupt-parent = <&gic>;
+ };
+
+ gic: interrupt-controller@48000000 {
+ compatible = "arm,gic-v3";
+ reg = <0 0x48000000 0 0x10000>,
+ <0 0x48060000 0 0xc0000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ dma-noncoherent;
+ ranges;
+
+ its: msi-controller@48040000 {
+ compatible = "arm,gic-v3-its";
+ reg = <0 0x48040000 0 0x20000>;
+ msi-controller;
+ #msi-cells = <1>;
+ dma-noncoherent;
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ aips2: bus@42000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ reg = <0x0 0x42000000 0x0 0x800000>;
+ ranges = <0x42000000 0x0 0x42000000 0x8000000>,
+ <0x28000000 0x0 0x28000000 0x10000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mu7: mailbox@42430000 {
+ compatible = "fsl,imx95-mu";
+ reg = <0x42430000 0x10000>;
+ interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
+ wdog3: watchdog@42490000 {
+ compatible = "fsl,imx93-wdt";
+ reg = <0x42490000 0x10000>;
+ interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ timeout-sec = <40>;
+ status = "disabled";
+ };
+
+ tpm3: pwm@424e0000 {
+ compatible = "fsl,imx7ulp-pwm";
+ reg = <0x424e0000 0x1000>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ tpm4: pwm@424f0000 {
+ compatible = "fsl,imx7ulp-pwm";
+ reg = <0x424f0000 0x1000>;
+ clocks = <&scmi_clk IMX95_CLK_TPM4>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ tpm5: pwm@42500000 {
+ compatible = "fsl,imx7ulp-pwm";
+ reg = <0x42500000 0x1000>;
+ clocks = <&scmi_clk IMX95_CLK_TPM5>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ tpm6: pwm@42510000 {
+ compatible = "fsl,imx7ulp-pwm";
+ reg = <0x42510000 0x1000>;
+ clocks = <&scmi_clk IMX95_CLK_TPM6>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ lpi2c3: i2c@42530000 {
+ compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
+ reg = <0x42530000 0x10000>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPI2C3>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ lpi2c4: i2c@42540000 {
+ compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
+ reg = <0x42540000 0x10000>;
+ interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPI2C4>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ lpspi3: spi@42550000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
+ reg = <0x42550000 0x10000>;
+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPSPI3>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpspi4: spi@42560000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
+ reg = <0x42560000 0x10000>;
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPSPI4>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpuart3: serial@42570000 {
+ compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
+ "fsl,imx7ulp-lpuart";
+ reg = <0x42570000 0x1000>;
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPUART3>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart4: serial@42580000 {
+ compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
+ "fsl,imx7ulp-lpuart";
+ reg = <0x42580000 0x1000>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPUART4>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart5: serial@42590000 {
+ compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
+ "fsl,imx7ulp-lpuart";
+ reg = <0x42590000 0x1000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPUART5>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart6: serial@425a0000 {
+ compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
+ "fsl,imx7ulp-lpuart";
+ reg = <0x425a0000 0x1000>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPUART6>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart7: serial@42690000 {
+ compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
+ "fsl,imx7ulp-lpuart";
+ reg = <0x42690000 0x1000>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPUART7>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart8: serial@426a0000 {
+ compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
+ "fsl,imx7ulp-lpuart";
+ reg = <0x426a0000 0x1000>;
+ interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPUART8>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpi2c5: i2c@426b0000 {
+ compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
+ reg = <0x426b0000 0x10000>;
+ interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPI2C5>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ lpi2c6: i2c@426c0000 {
+ compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
+ reg = <0x426c0000 0x10000>;
+ interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPI2C6>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ lpi2c7: i2c@426d0000 {
+ compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
+ reg = <0x426d0000 0x10000>;
+ interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPI2C7>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ lpi2c8: i2c@426e0000 {
+ compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
+ reg = <0x426e0000 0x10000>;
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPI2C8>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ lpspi5: spi@426f0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
+ reg = <0x426f0000 0x10000>;
+ interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPSPI5>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpspi6: spi@42700000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
+ reg = <0x42700000 0x10000>;
+ interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPSPI6>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpspi7: spi@42710000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
+ reg = <0x42710000 0x10000>;
+ interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPSPI7>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpspi8: spi@42720000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
+ reg = <0x42720000 0x10000>;
+ interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPSPI8>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ mu8: mailbox@42730000 {
+ compatible = "fsl,imx95-mu";
+ reg = <0x42730000 0x10000>;
+ interrupts = <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+ };
+
+ aips3: bus@42800000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ reg = <0 0x42800000 0 0x800000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x42800000 0x0 0x42800000 0x800000>;
+
+ usdhc1: mmc@42850000 {
+ compatible = "fsl,imx95-usdhc", "fsl,imx8mm-usdhc";
+ reg = <0x42850000 0x10000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>,
+ <&scmi_clk IMX95_CLK_WAKEUPAXI>,
+ <&scmi_clk IMX95_CLK_USDHC1>;
+ clock-names = "ipg", "ahb", "per";
+ assigned-clocks = <&scmi_clk IMX95_CLK_USDHC1>;
+ assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1>;
+ assigned-clock-rates = <400000000>;
+ bus-width = <8>;
+ fsl,tuning-start-tap = <1>;
+ fsl,tuning-step= <2>;
+ status = "disabled";
+ };
+
+ usdhc2: mmc@42860000 {
+ compatible = "fsl,imx95-usdhc", "fsl,imx8mm-usdhc";
+ reg = <0x42860000 0x10000>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>,
+ <&scmi_clk IMX95_CLK_WAKEUPAXI>,
+ <&scmi_clk IMX95_CLK_USDHC2>;
+ clock-names = "ipg", "ahb", "per";
+ assigned-clocks = <&scmi_clk IMX95_CLK_USDHC2>;
+ assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1>;
+ assigned-clock-rates = <400000000>;
+ bus-width = <4>;
+ fsl,tuning-start-tap = <1>;
+ fsl,tuning-step= <2>;
+ status = "disabled";
+ };
+
+ usdhc3: mmc@428b0000 {
+ compatible = "fsl,imx95-usdhc", "fsl,imx8mm-usdhc";
+ reg = <0x428b0000 0x10000>;
+ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>,
+ <&scmi_clk IMX95_CLK_WAKEUPAXI>,
+ <&scmi_clk IMX95_CLK_USDHC3>;
+ clock-names = "ipg", "ahb", "per";
+ assigned-clocks = <&scmi_clk IMX95_CLK_USDHC3>;
+ assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1>;
+ assigned-clock-rates = <400000000>;
+ bus-width = <4>;
+ fsl,tuning-start-tap = <1>;
+ fsl,tuning-step= <2>;
+ status = "disabled";
+ };
+ };
+
+ gpio2: gpio@43810000 {
+ compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
+ reg = <0x0 0x43810000 0x0 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "gpio", "port";
+ gpio-ranges = <&scmi_iomuxc 0 4 32>;
+ };
+
+ gpio3: gpio@43820000 {
+ compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
+ reg = <0x0 0x43820000 0x0 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "gpio", "port";
+ gpio-ranges = <&scmi_iomuxc 0 104 8>, <&scmi_iomuxc 8 74 18>,
+ <&scmi_iomuxc 26 42 2>, <&scmi_iomuxc 28 0 4>;
+ };
+
+ gpio4: gpio@43840000 {
+ compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
+ reg = <0x0 0x43840000 0x0 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "gpio", "port";
+ gpio-ranges = <&scmi_iomuxc 0 46 28>, <&scmi_iomuxc 28 44 2>;
+ };
+
+ gpio5: gpio@43850000 {
+ compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
+ reg = <0x0 0x43850000 0x0 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>,
+ <&scmi_clk IMX95_CLK_BUSWAKEUP>;
+ clock-names = "gpio", "port";
+ gpio-ranges = <&scmi_iomuxc 0 92 12>, <&scmi_iomuxc 12 36 6>;
+ };
+
+ aips1: bus@44000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ reg = <0x0 0x44000000 0x0 0x800000>;
+ ranges = <0x44000000 0x0 0x44000000 0x800000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mu1: mailbox@44220000 {
+ compatible = "fsl,imx95-mu";
+ reg = <0x44220000 0x10000>;
+ interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_BUSAON>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
+ tpm1: pwm@44310000 {
+ compatible = "fsl,imx7ulp-pwm";
+ reg = <0x44310000 0x1000>;
+ clocks = <&scmi_clk IMX95_CLK_BUSAON>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ tpm2: pwm@44320000 {
+ compatible = "fsl,imx7ulp-pwm";
+ reg = <0x44320000 0x1000>;
+ clocks = <&scmi_clk IMX95_CLK_TPM2>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ lpi2c1: i2c@44340000 {
+ compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
+ reg = <0x44340000 0x10000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPI2C1>,
+ <&scmi_clk IMX95_CLK_BUSAON>;
+ clock-names = "per", "ipg";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ lpi2c2: i2c@44350000 {
+ compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
+ reg = <0x44350000 0x10000>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPI2C2>,
+ <&scmi_clk IMX95_CLK_BUSAON>;
+ clock-names = "per", "ipg";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ lpspi1: spi@44360000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
+ reg = <0x44360000 0x10000>;
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPSPI1>,
+ <&scmi_clk IMX95_CLK_BUSAON>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpspi2: spi@44370000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx95-spi", "fsl,imx7ulp-spi";
+ reg = <0x44370000 0x10000>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPSPI2>,
+ <&scmi_clk IMX95_CLK_BUSAON>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpuart1: serial@44380000 {
+ compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
+ "fsl,imx7ulp-lpuart";
+ reg = <0x44380000 0x1000>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPUART1>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart2: serial@44390000 {
+ compatible = "fsl,imx95-lpuart", "fsl,imx8ulp-lpuart",
+ "fsl,imx7ulp-lpuart";
+ reg = <0x44390000 0x1000>;
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_LPUART2>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ adc1: adc@44530000 {
+ compatible = "nxp,imx93-adc";
+ reg = <0x44530000 0x10000>;
+ interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_ADC>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ mu2: mailbox@445b0000 {
+ compatible = "fsl,imx95-mu";
+ reg = <0x445b0000 0x1000>;
+ ranges;
+ interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #mbox-cells = <2>;
+
+ sram0: sram@445b1000 {
+ compatible = "mmio-sram";
+ reg = <0x445b1000 0x400>;
+ ranges = <0x0 0x445b1000 0x400>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ scmi_buf0: scmi-sram-section@0 {
+ compatible = "arm,scmi-shmem";
+ reg = <0x0 0x80>;
+ };
+
+ scmi_buf1: scmi-sram-section@80 {
+ compatible = "arm,scmi-shmem";
+ reg = <0x80 0x80>;
+ };
+ };
+
+ };
+
+ mu3: mailbox@445d0000 {
+ compatible = "fsl,imx95-mu";
+ reg = <0x445d0000 0x10000>;
+ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_BUSAON>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
+ mu4: mailbox@445f0000 {
+ compatible = "fsl,imx95-mu";
+ reg = <0x445f0000 0x10000>;
+ interrupts = <GIC_SPI 230 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_BUSAON>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
+ mu6: mailbox@44630000 {
+ compatible = "fsl,imx95-mu";
+ reg = <0x44630000 0x10000>;
+ interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_BUSAON>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+ };
+
+ mailbox@47320000 {
+ compatible = "fsl,imx95-mu-v2x";
+ reg = <0x0 0x47320000 0x0 0x10000>;
+ interrupts = <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <2>;
+ };
+
+ mailbox@47350000 {
+ compatible = "fsl,imx95-mu-v2x";
+ reg = <0x0 0x47350000 0x0 0x10000>;
+ interrupts = <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <2>;
+ };
+
+ /* GPIO1 is under exclusive control of System Manager */
+ gpio1: gpio@47400000 {
+ compatible = "fsl,imx95-gpio", "fsl,imx8ulp-gpio";
+ reg = <0x0 0x47400000 0x0 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&scmi_clk IMX95_CLK_M33>,
+ <&scmi_clk IMX95_CLK_M33>;
+ clock-names = "gpio", "port";
+ gpio-ranges = <&scmi_iomuxc 0 112 16>;
+ status = "disabled";
+ };
+
+ elemu0: mailbox@47520000 {
+ compatible = "fsl,imx95-mu-ele";
+ reg = <0x0 0x47520000 0x0 0x10000>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
+ elemu1: mailbox@47530000 {
+ compatible = "fsl,imx95-mu-ele";
+ reg = <0x0 0x47530000 0x0 0x10000>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
+ elemu2: mailbox@47540000 {
+ compatible = "fsl,imx95-mu-ele";
+ reg = <0x0 0x47540000 0x0 0x10000>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
+ elemu3: mailbox@47550000 {
+ compatible = "fsl,imx95-mu-ele";
+ reg = <0x0 0x47550000 0x0 0x10000>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <2>;
+ };
+
+ elemu4: mailbox@47560000 {
+ compatible = "fsl,imx95-mu-ele";
+ reg = <0x0 0x47560000 0x0 0x10000>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
+ elemu5: mailbox@47570000 {
+ compatible = "fsl,imx95-mu-ele";
+ reg = <0x0 0x47570000 0x0 0x10000>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
+ aips4: bus@49000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ reg = <0x0 0x49000000 0x0 0x800000>;
+ ranges = <0x49000000 0x0 0x49000000 0x800000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ smmu: iommu@490d0000 {
+ compatible = "arm,smmu-v3";
+ reg = <0x490d0000 0x100000>;
+ interrupts = <GIC_SPI 325 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 334 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 326 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
+ #iommu-cells = <1>;
+ status = "disabled";
+ };
+ };
+
+ pcie0: pcie@4c300000 {
+ compatible = "fsl,imx95-pcie";
+ reg = <0 0x4c300000 0 0x10000>,
+ <0 0x60100000 0 0xfe00000>,
+ <0 0x4c360000 0 0x10000>,
+ <0 0x4c340000 0 0x2000>;
+ reg-names = "dbi", "config", "atu", "app";
+ ranges = <0x81000000 0x0 0x00000000 0x0 0x6ff00000 0 0x00100000>,
+ <0x82000000 0x0 0x10000000 0x9 0x10000000 0 0x10000000>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ linux,pci-domain = <0>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <1>;
+ num-viewport = <8>;
+ interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gic 0 0 GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gic 0 0 GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gic 0 0 GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_HSIO>,
+ <&scmi_clk IMX95_CLK_HSIOPLL>,
+ <&scmi_clk IMX95_CLK_HSIOPLL_VCO>,
+ <&scmi_clk IMX95_CLK_HSIOPCIEAUX>;
+ clock-names = "pcie", "pcie_bus", "pcie_phy", "pcie_aux";
+ assigned-clocks =<&scmi_clk IMX95_CLK_HSIOPLL_VCO>,
+ <&scmi_clk IMX95_CLK_HSIOPLL>,
+ <&scmi_clk IMX95_CLK_HSIOPCIEAUX>;
+ assigned-clock-rates = <3600000000>, <100000000>, <10000000>;
+ assigned-clock-parents = <0>, <0>,
+ <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>;
+ power-domains = <&scmi_devpd IMX95_PD_HSIO_TOP>;
+ fsl,max-link-speed = <3>;
+ status = "disabled";
+ };
+
+ pcie0_ep: pcie-ep@4c300000 {
+ compatible = "fsl,imx95-pcie-ep";
+ reg = <0 0x4c300000 0 0x10000>,
+ <0 0x4c360000 0 0x1000>,
+ <0 0x4c320000 0 0x1000>,
+ <0 0x4c340000 0 0x2000>,
+ <0 0x4c370000 0 0x10000>,
+ <0x9 0 1 0>;
+ reg-names = "dbi","atu", "dbi2", "app", "dma", "addr_space";
+ num-lanes = <1>;
+ interrupts = <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "dma";
+ clocks = <&scmi_clk IMX95_CLK_HSIO>,
+ <&scmi_clk IMX95_CLK_HSIOPLL>,
+ <&scmi_clk IMX95_CLK_HSIOPLL_VCO>,
+ <&scmi_clk IMX95_CLK_HSIOPCIEAUX>;
+ clock-names = "pcie", "pcie_bus", "pcie_phy", "pcie_aux";
+ assigned-clocks =<&scmi_clk IMX95_CLK_HSIOPLL_VCO>,
+ <&scmi_clk IMX95_CLK_HSIOPLL>,
+ <&scmi_clk IMX95_CLK_HSIOPCIEAUX>;
+ assigned-clock-rates = <3600000000>, <100000000>, <10000000>;
+ assigned-clock-parents = <0>, <0>,
+ <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>;
+ power-domains = <&scmi_devpd IMX95_PD_HSIO_TOP>;
+ status = "disabled";
+ };
+
+ pcie1: pcie@4c380000 {
+ compatible = "fsl,imx95-pcie";
+ reg = <0 0x4c380000 0 0x10000>,
+ <8 0x80100000 0 0xfe00000>,
+ <0 0x4c3e0000 0 0x10000>,
+ <0 0x4c3c0000 0 0x2000>;
+ reg-names = "dbi", "config", "atu", "app";
+ ranges = <0x81000000 0 0x00000000 0x8 0x8ff00000 0 0x00100000>,
+ <0x82000000 0 0x10000000 0xa 0x10000000 0 0x10000000>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ linux,pci-domain = <1>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <1>;
+ num-viewport = <8>;
+ interrupts = <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gic 0 0 GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gic 0 0 GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gic 0 0 GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk IMX95_CLK_HSIO>,
+ <&scmi_clk IMX95_CLK_HSIOPLL>,
+ <&scmi_clk IMX95_CLK_HSIOPLL_VCO>,
+ <&scmi_clk IMX95_CLK_HSIOPCIEAUX>;
+ clock-names = "pcie", "pcie_bus", "pcie_phy", "pcie_aux";
+ assigned-clocks =<&scmi_clk IMX95_CLK_HSIOPLL_VCO>,
+ <&scmi_clk IMX95_CLK_HSIOPLL>,
+ <&scmi_clk IMX95_CLK_HSIOPCIEAUX>;
+ assigned-clock-rates = <3600000000>, <100000000>, <10000000>;
+ assigned-clock-parents = <0>, <0>,
+ <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>;
+ power-domains = <&scmi_devpd IMX95_PD_HSIO_TOP>;
+ fsl,max-link-speed = <3>;
+ status = "disabled";
+ };
+
+ pcie1_ep: pcie-ep@4c380000 {
+ compatible = "fsl,imx95-pcie-ep";
+ reg = <0 0x4c380000 0 0x10000>,
+ <0 0x4c3e0000 0 0x1000>,
+ <0 0x4c3a0000 0 0x1000>,
+ <0 0x4c3c0000 0 0x2000>,
+ <0 0x4c3f0000 0 0x10000>,
+ <0xa 0 1 0>;
+ reg-names = "dbi", "atu", "dbi2", "app", "dma", "addr_space";
+ num-lanes = <1>;
+ interrupts = <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "dma";
+ clocks = <&scmi_clk IMX95_CLK_HSIO>,
+ <&scmi_clk IMX95_CLK_HSIOPLL>,
+ <&scmi_clk IMX95_CLK_HSIOPLL_VCO>,
+ <&scmi_clk IMX95_CLK_HSIOPCIEAUX>;
+ clock-names = "pcie", "pcie_bus", "pcie_phy", "pcie_aux";
+ assigned-clocks =<&scmi_clk IMX95_CLK_HSIOPLL_VCO>,
+ <&scmi_clk IMX95_CLK_HSIOPLL>,
+ <&scmi_clk IMX95_CLK_HSIOPCIEAUX>;
+ assigned-clock-rates = <3600000000>, <100000000>, <10000000>;
+ assigned-clock-parents = <0>, <0>,
+ <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>;
+ power-domains = <&scmi_devpd IMX95_PD_HSIO_TOP>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi
index dbd2fc3ba790..65f7b5a50eb5 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi
@@ -32,7 +32,7 @@ fman@1a00000 {
mdio@f1000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+ compatible = "fsl,fman-memac-mdio";
reg = <0xf1000 0x1000>;
pcsphy6: ethernet-phy@0 {
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi
index 6fc5d2560057..3f70482c98c3 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi
@@ -32,7 +32,7 @@ fman@1a00000 {
mdio@f3000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+ compatible = "fsl,fman-memac-mdio";
reg = <0xf3000 0x1000>;
pcsphy7: ethernet-phy@0 {
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi
index 4e02276fcf99..78841c1f3252 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi
@@ -31,7 +31,7 @@ fman@1a00000 {
mdio@e1000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+ compatible = "fsl,fman-memac-mdio";
reg = <0xe1000 0x1000>;
pcsphy0: ethernet-phy@0 {
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi
index 0312fa43fa77..1f43fa666222 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi
@@ -31,7 +31,7 @@ fman@1a00000 {
mdio@e3000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+ compatible = "fsl,fman-memac-mdio";
reg = <0xe3000 0x1000>;
pcsphy1: ethernet-phy@0 {
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi
index af2df07971dd..de0aa017701d 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi
@@ -31,7 +31,7 @@ fman@1a00000 {
mdio@e5000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+ compatible = "fsl,fman-memac-mdio";
reg = <0xe5000 0x1000>;
pcsphy2: ethernet-phy@0 {
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi
index 4ac98dc8b227..6904aa5d8e54 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi
@@ -31,7 +31,7 @@ fman@1a00000 {
mdio@e7000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+ compatible = "fsl,fman-memac-mdio";
reg = <0xe7000 0x1000>;
pcsphy3: ethernet-phy@0 {
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi
index bd932d8b0160..a3d29d470297 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi
@@ -31,7 +31,7 @@ fman@1a00000 {
mdio@e9000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+ compatible = "fsl,fman-memac-mdio";
reg = <0xe9000 0x1000>;
pcsphy4: ethernet-phy@0 {
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi
index 7de1c5203f3e..01b78c0463a7 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi
@@ -31,7 +31,7 @@ fman@1a00000 {
mdio@eb000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+ compatible = "fsl,fman-memac-mdio";
reg = <0xeb000 0x1000>;
pcsphy5: ethernet-phy@0 {
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
index ae1c2abaaf36..b0390b711fef 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
@@ -67,14 +67,14 @@ fman0: fman@1a00000 {
mdio0: mdio@fc000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+ compatible = "fsl,fman-memac-mdio";
reg = <0xfc000 0x1000>;
};
xmdio0: mdio@fd000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+ compatible = "fsl,fman-memac-mdio";
reg = <0xfd000 0x1000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/tqma8xx.dtsi b/arch/arm64/boot/dts/freescale/tqma8xx.dtsi
index d98469a7c47c..366912bf3d5e 100644
--- a/arch/arm64/boot/dts/freescale/tqma8xx.dtsi
+++ b/arch/arm64/boot/dts/freescale/tqma8xx.dtsi
@@ -61,12 +61,16 @@
flash0: flash@0 {
reg = <0>;
- #address-cells = <1>;
- #size-cells = <1>;
compatible = "jedec,spi-nor";
spi-max-frequency = <66000000>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index 7e137a884ae5..957a1b41f19b 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -1161,7 +1161,7 @@
};
usb3_otg_bc: usb3_otg_bc@ff200000 {
- compatible = "syscon", "simple-mfd";
+ compatible = "hisilicon,hi3660-usb3-otg-bc", "syscon", "simple-mfd";
reg = <0x0 0xff200000 0x0 0x1000>;
usb_phy: usb-phy {
diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts b/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts
index ad99aefeb185..b31cfa6b802d 100644
--- a/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts
+++ b/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts
@@ -106,8 +106,6 @@
&qspi {
status = "okay";
flash@0 {
- #address-cells = <1>;
- #size-cells = <1>;
compatible = "micron,mt25qu02g", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <100000000>;
diff --git a/arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts b/arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts
index 2d70a92c2090..7952c7f47cc2 100644
--- a/arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts
+++ b/arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts
@@ -83,8 +83,6 @@
&qspi {
status = "okay";
flash@0 {
- #address-cells = <1>;
- #size-cells = <1>;
compatible = "micron,mt25qu02g", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <100000000>;
diff --git a/arch/arm64/boot/dts/marvell/Makefile b/arch/arm64/boot/dts/marvell/Makefile
index 99b8cb3c49e1..ce751b5028e2 100644
--- a/arch/arm64/boot/dts/marvell/Makefile
+++ b/arch/arm64/boot/dts/marvell/Makefile
@@ -28,3 +28,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += cn9130-crb-A.dtb
dtb-$(CONFIG_ARCH_MVEBU) += cn9130-crb-B.dtb
dtb-$(CONFIG_ARCH_MVEBU) += ac5x-rd-carrier-cn9131.dtb
dtb-$(CONFIG_ARCH_MVEBU) += ac5-98dx35xx-rd.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += cn9130-cf-base.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += cn9130-cf-pro.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += cn9131-cf-solidwan.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += cn9132-clearfog.dtb
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts b/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts
index 63fbc8352161..56930f2ce481 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts
@@ -41,7 +41,7 @@
keys {
compatible = "gpio-keys";
- reset {
+ button-reset {
label = "reset";
linux,code = <KEY_RESTART>;
gpios = <&gpionb 14 GPIO_ACTIVE_LOW>;
@@ -57,17 +57,17 @@
leds {
compatible = "gpio-leds";
- vpn {
+ led-vpn {
label = "green:vpn";
gpios = <&gpionb 11 GPIO_ACTIVE_LOW>;
};
- wan {
+ led-wan {
label = "green:wan";
gpios = <&gpionb 12 GPIO_ACTIVE_LOW>;
};
- led_power: power {
+ led_power: led-power {
label = "green:power";
gpios = <&gpionb 13 GPIO_ACTIVE_LOW>;
default-state = "on";
diff --git a/arch/arm64/boot/dts/marvell/cn9130-cf-base.dts b/arch/arm64/boot/dts/marvell/cn9130-cf-base.dts
new file mode 100644
index 000000000000..788a5c302b17
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9130-cf-base.dts
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Josua Mayer <[email protected]>
+ *
+ * DTS for SolidRun CN9130 Clearfog Base.
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+#include "cn9130.dtsi"
+#include "cn9130-sr-som.dtsi"
+#include "cn9130-cf.dtsi"
+
+/ {
+ model = "SolidRun CN9130 Clearfog Base";
+ compatible = "solidrun,cn9130-clearfog-base",
+ "solidrun,cn9130-sr-som", "marvell,cn9130";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&rear_button_pins>;
+ pinctrl-names = "default";
+
+ button-0 {
+ /* The rear SW3 button */
+ label = "Rear Button";
+ gpios = <&cp0_gpio1 31 GPIO_ACTIVE_LOW>;
+ linux,can-disable;
+ linux,code = <BTN_0>;
+ };
+ };
+
+ rfkill-m2-gnss {
+ compatible = "rfkill-gpio";
+ label = "m.2 GNSS";
+ radio-type = "gps";
+ /* rfkill-gpio inverts internally */
+ shutdown-gpios = <&expander0 9 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* M.2 is B-keyed, so w-disable is for WWAN */
+ rfkill-m2-wwan {
+ compatible = "rfkill-gpio";
+ label = "m.2 WWAN";
+ radio-type = "wwan";
+ /* rfkill-gpio inverts internally */
+ shutdown-gpios = <&expander0 8 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+/* SRDS #3 - SGMII 1GE */
+&cp0_eth1 {
+ phy = <&phy1>;
+ phys = <&cp0_comphy3 1>;
+ phy-mode = "sgmii";
+ status = "okay";
+};
+
+&cp0_eth2_phy {
+ /*
+ * Configure LEDs default behaviour:
+ * - LED[0]: link/activity: On/blink (green)
+ * - LED[1]: link is 100/1000Mbps: On (yellow)
+ * - LED[2]: high impedance (floating)
+ */
+ marvell,reg-init = <3 16 0xf000 0x0a61>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WAN;
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_WAN;
+ default-state = "keep";
+ };
+ };
+};
+
+&cp0_gpio1 {
+ sim-select-hog {
+ gpio-hog;
+ gpios = <27 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "sim-select";
+ };
+};
+
+&cp0_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ /*
+ * Configure LEDs default behaviour:
+ * - LED[0]: link/activity: On/blink (green)
+ * - LED[1]: link is 100/1000Mbps: On (yellow)
+ * - LED[2]: high impedance (floating)
+ *
+ * Configure LEDs electrical polarity
+ * - on-state: low
+ * - off-state: high (not hi-z, to avoid residual glow)
+ */
+ marvell,reg-init = <3 16 0xf000 0x0a61>,
+ <3 17 0x003f 0x000a>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+ };
+};
+
+&cp0_pinctrl {
+ pinctrl-0 = <&sim_select_pins>;
+ pintrl-names = "default";
+
+ rear_button_pins: cp0-rear-button-pins {
+ marvell,pins = "mpp31";
+ marvell,function = "gpio";
+ };
+
+ sim_select_pins: cp0-sim-select-pins {
+ marvell,pins = "mpp27";
+ marvell,function = "gpio";
+ };
+};
+
+/*
+ * SRDS #4 - USB 3.0 host on M.2 connector
+ * USB-2.0 Host on Type-A connector
+ */
+&cp0_usb3_1 {
+ phys = <&cp0_comphy4 1>, <&cp0_utmi1>;
+ phy-names = "comphy", "utmi";
+ dr_mode = "host";
+ status = "okay";
+};
+
+&expander0 {
+ m2-full-card-power-off-hog {
+ gpio-hog;
+ gpios = <2 GPIO_ACTIVE_LOW>;
+ output-low;
+ line-name = "m2-full-card-power-off";
+ };
+
+ m2-reset-hog {
+ gpio-hog;
+ gpios = <10 GPIO_ACTIVE_LOW>;
+ output-low;
+ line-name = "m2-reset";
+ };
+};
diff --git a/arch/arm64/boot/dts/marvell/cn9130-cf-pro.dts b/arch/arm64/boot/dts/marvell/cn9130-cf-pro.dts
new file mode 100644
index 000000000000..a27fe0042867
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9130-cf-pro.dts
@@ -0,0 +1,375 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Josua Mayer <[email protected]>
+ *
+ * DTS for SolidRun CN9130 Clearfog Pro.
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+#include "cn9130.dtsi"
+#include "cn9130-sr-som.dtsi"
+#include "cn9130-cf.dtsi"
+
+/ {
+ model = "SolidRun CN9130 Clearfog Pro";
+ compatible = "solidrun,cn9130-clearfog-pro",
+ "solidrun,cn9130-sr-som", "marvell,cn9130";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&rear_button_pins>;
+ pinctrl-names = "default";
+
+ button-0 {
+ /* The rear SW3 button */
+ label = "Rear Button";
+ gpios = <&cp0_gpio2 0 GPIO_ACTIVE_LOW>;
+ linux,can-disable;
+ linux,code = <BTN_0>;
+ };
+ };
+};
+
+/* SRDS #3 - SGMII 1GE to L2 switch */
+&cp0_eth1 {
+ phys = <&cp0_comphy3 1>;
+ phy-mode = "sgmii";
+ status = "okay";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+};
+
+&cp0_eth2_phy {
+ /*
+ * Configure LEDs default behaviour similar to switch ports:
+ * - LED[0]: link/activity: On/blink (green)
+ * - LED[1]: link is 100/1000Mbps: On (red)
+ * - LED[2]: high impedance (floating)
+ *
+ * Switch port defaults:
+ * - LED0: link/activity: On/blink (green)
+ * - LED1: link is 1000Mbps: On (red)
+ *
+ * Identical configuration is impossible with hardware offload.
+ */
+ marvell,reg-init = <3 16 0xf000 0x0a61>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WAN;
+ label = "LED2";
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_WAN;
+ label = "LED1";
+ default-state = "keep";
+ };
+ };
+};
+
+&cp0_mdio {
+ ethernet-switch@4 {
+ compatible = "marvell,mv88e6085";
+ reg = <4>;
+ pinctrl-0 = <&dsa_clk_pins &dsa_pins>;
+ pinctrl-names = "default";
+ reset-gpios = <&cp0_gpio1 27 GPIO_ACTIVE_LOW>;
+ interrupt-parent = <&cp0_gpio1>;
+ interrupts = <29 IRQ_TYPE_EDGE_FALLING>;
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet-port@0 {
+ reg = <0>;
+ label = "lan5";
+ phy = <&switch0phy0>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ label = "LED12";
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_LAN;
+ label = "LED11";
+ default-state = "keep";
+ };
+ };
+ };
+
+ ethernet-port@1 {
+ reg = <1>;
+ label = "lan4";
+ phy = <&switch0phy1>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ label = "LED10";
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_LAN;
+ label = "LED9";
+ default-state = "keep";
+ };
+ };
+ };
+
+ ethernet-port@2 {
+ reg = <2>;
+ label = "lan3";
+ phy = <&switch0phy2>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ label = "LED8";
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_LAN;
+ label = "LED7";
+ default-state = "keep";
+ };
+ };
+ };
+
+ ethernet-port@3 {
+ reg = <3>;
+ label = "lan2";
+ phy = <&switch0phy3>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ label = "LED6";
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_LAN;
+ label = "LED5";
+ default-state = "keep";
+ };
+ };
+ };
+
+ ethernet-port@4 {
+ reg = <4>;
+ label = "lan1";
+ phy = <&switch0phy4>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ label = "LED4";
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_LAN;
+ label = "LED3";
+ default-state = "keep";
+ };
+ };
+ };
+
+ ethernet-port@5 {
+ reg = <5>;
+ label = "cpu";
+ ethernet = <&cp0_eth1>;
+ phy-mode = "sgmii";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+
+ ethernet-port@6 {
+ reg = <6>;
+ label = "lan6";
+ phy-mode = "rgmii";
+
+ /*
+ * Because of mdio address conflict the
+ * external phy is not readable.
+ * Force a fixed link instead.
+ */
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+ };
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ switch0phy0: ethernet-phy@0 {
+ reg = <0x0>;
+ };
+
+ switch0phy1: ethernet-phy@1 {
+ reg = <0x1>;
+ /*
+ * Indirectly configure default behaviour
+ * for port lan6 leds behind external phy.
+ * Internal PHYs are not using page 3,
+ * therefore writing to it is safe.
+ */
+ marvell,reg-init = <3 16 0xf000 0x0a61>;
+ };
+
+ switch0phy2: ethernet-phy@2 {
+ reg = <0x2>;
+ };
+
+ switch0phy3: ethernet-phy@3 {
+ reg = <0x3>;
+ };
+
+ switch0phy4: ethernet-phy@4 {
+ reg = <0x4>;
+ };
+ };
+
+ /*
+ * There is an external phy on the switch mdio bus.
+ * Because its mdio address collides with internal phys,
+ * it is not readable.
+ *
+ * mdio-external {
+ * compatible = "marvell,mv88e6xxx-mdio-external";
+ * #address-cells = <1>;
+ * #size-cells = <0>;
+ *
+ * ethernet-phy@1 {
+ * reg = <0x1>;
+ * };
+ * };
+ */
+ };
+};
+
+/* SRDS #4 - miniPCIe (CON2) */
+&cp0_pcie1 {
+ num-lanes = <1>;
+ phys = <&cp0_comphy4 1>;
+ /* dw-pcie inverts internally */
+ reset-gpios = <&expander0 2 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&cp0_pinctrl {
+ dsa_clk_pins: cp0-dsa-clk-pins {
+ marvell,pins = "mpp40";
+ marvell,function = "synce1";
+ };
+
+ dsa_pins: cp0-dsa-pins {
+ marvell,pins = "mpp27", "mpp29";
+ marvell,function = "gpio";
+ };
+
+ rear_button_pins: cp0-rear-button-pins {
+ marvell,pins = "mpp32";
+ marvell,function = "gpio";
+ };
+
+ cp0_spi1_cs1_pins: cp0-spi1-cs1-pins {
+ marvell,pins = "mpp12";
+ marvell,function = "spi1";
+ };
+};
+
+&cp0_spi1 {
+ /* add pin for chip-select 1 on mikrobus */
+ pinctrl-0 = <&cp0_spi1_pins &cp0_spi1_cs1_pins>;
+};
+
+/* USB-2.0 Host on Type-A connector */
+&cp0_usb3_1 {
+ phys = <&cp0_utmi1>;
+ phy-names = "utmi";
+ dr_mode = "host";
+ status = "okay";
+};
+
+&expander0 {
+ /* CON2 */
+ pcie1-0-clkreq-hog {
+ gpio-hog;
+ gpios = <4 GPIO_ACTIVE_LOW>;
+ input;
+ line-name = "pcie1.0-clkreq";
+ };
+
+ /* CON2 */
+ pcie1-0-w-disable-hog {
+ gpio-hog;
+ gpios = <7 GPIO_ACTIVE_LOW>;
+ output-low;
+ line-name = "pcie1.0-w-disable";
+ };
+};
diff --git a/arch/arm64/boot/dts/marvell/cn9130-cf.dtsi b/arch/arm64/boot/dts/marvell/cn9130-cf.dtsi
new file mode 100644
index 000000000000..ad0ab34b6602
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9130-cf.dtsi
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Josua Mayer <[email protected]>
+ *
+ * DTS for common base of SolidRun CN9130 Clearfog Base and Pro.
+ *
+ */
+
+/ {
+ aliases {
+ /* label nics same order as armada 388 clearfog */
+ ethernet0 = &cp0_eth2;
+ ethernet1 = &cp0_eth1;
+ ethernet2 = &cp0_eth0;
+ i2c1 = &cp0_i2c1;
+ mmc1 = &cp0_sdhci0;
+ };
+
+ reg_usb3_vbus0: regulator-usb3-vbus0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpios = <&expander0 6 GPIO_ACTIVE_LOW>;
+ };
+
+ sfp: sfp {
+ compatible = "sff,sfp";
+ i2c-bus = <&cp0_i2c1>;
+ los-gpios = <&expander0 12 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&expander0 15 GPIO_ACTIVE_LOW>;
+ tx-disable-gpios = <&expander0 14 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpios = <&expander0 13 GPIO_ACTIVE_HIGH>;
+ maximum-power-milliwatt = <2000>;
+ };
+};
+
+/* SRDS #2 - SFP+ 10GE */
+&cp0_eth0 {
+ managed = "in-band-status";
+ phys = <&cp0_comphy2 0>;
+ phy-mode = "10gbase-r";
+ sfp = <&sfp>;
+ status = "okay";
+};
+
+&cp0_i2c0 {
+ expander0: gpio-expander@20 {
+ compatible = "nxp,pca9555";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ pinctrl-0 = <&expander0_pins>;
+ pinctrl-names = "default";
+ interrupt-parent = <&cp0_gpio1>;
+ interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+
+ /* CON3 */
+ pcie2-0-clkreq-hog {
+ gpio-hog;
+ gpios = <0 GPIO_ACTIVE_LOW>;
+ input;
+ line-name = "pcie2.0-clkreq";
+ };
+
+ /* CON3 */
+ pcie2-0-w-disable-hog {
+ gpio-hog;
+ gpios = <3 GPIO_ACTIVE_LOW>;
+ output-low;
+ line-name = "pcie2.0-w-disable";
+ };
+
+ usb3-ilimit-hog {
+ gpio-hog;
+ gpios = <5 GPIO_ACTIVE_LOW>;
+ input;
+ line-name = "usb3-current-limit";
+ };
+
+ m2-devslp-hog {
+ gpio-hog;
+ gpios = <11 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "m.2 devslp";
+ };
+ };
+
+ /* The MCP3021 supports standard and fast modes */
+ adc@4c {
+ compatible = "microchip,mcp3021";
+ reg = <0x4c>;
+ };
+
+ carrier_eeprom: eeprom@52 {
+ compatible = "atmel,24c02";
+ reg = <0x52>;
+ pagesize = <8>;
+ };
+};
+
+&cp0_i2c1 {
+ /*
+ * Routed to SFP, M.2, mikrobus, and miniPCIe
+ * SFP limits this to 100kHz, and requires an AT24C01A/02/04 with
+ * address pins tied low, which takes addresses 0x50 and 0x51.
+ * Mikrobus doesn't specify beyond an I2C bus being present.
+ * PCIe uses ARP to assign addresses, or 0x63-0x64.
+ */
+ clock-frequency = <100000>;
+ pinctrl-0 = <&cp0_i2c1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+/* SRDS #5 - miniPCIe (CON3) */
+&cp0_pcie2 {
+ num-lanes = <1>;
+ phys = <&cp0_comphy5 2>;
+ /* dw-pcie inverts internally */
+ reset-gpios = <&expander0 1 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&cp0_pinctrl {
+ cp0_i2c1_pins: cp0-i2c1-pins {
+ marvell,pins = "mpp35", "mpp36";
+ marvell,function = "i2c1";
+ };
+
+ cp0_mmc0_pins: cp0-mmc0-pins {
+ marvell,pins = "mpp43", "mpp56", "mpp57", "mpp58",
+ "mpp59", "mpp60", "mpp61";
+ marvell,function = "sdio";
+ };
+
+ mikro_spi_pins: cp0-spi1-cs1-pins {
+ marvell,pins = "mpp12";
+ marvell,function = "spi1";
+ };
+
+ mikro_uart_pins: cp0-uart-pins {
+ marvell,pins = "mpp2", "mpp3";
+ marvell,function = "uart1";
+ };
+
+ expander0_pins: cp0-expander0-pins {
+ marvell,pins = "mpp4";
+ marvell,function = "gpio";
+ };
+};
+
+/* SRDS #0 - SATA on M.2 connector */
+&cp0_sata0 {
+ phys = <&cp0_comphy0 1>;
+ status = "okay";
+
+ /* only port 1 is available */
+ /delete-node/ sata-port@0;
+};
+
+/* microSD */
+&cp0_sdhci0 {
+ pinctrl-0 = <&cp0_mmc0_pins>;
+ pinctrl-names = "default";
+ bus-width = <4>;
+ no-1-8-v;
+ status = "okay";
+};
+
+&cp0_spi1 {
+ /* CS1 for mikrobus */
+ pinctrl-0 = <&cp0_spi1_pins &mikro_spi_pins>;
+};
+
+/*
+ * SRDS #1 - USB-3.0 Host on Type-A connector
+ * USB-2.0 Host on mPCI-e connector (CON3)
+ */
+&cp0_usb3_0 {
+ phys = <&cp0_comphy1 0>, <&cp0_utmi0>;
+ phy-names = "comphy", "utmi";
+ vbus-supply = <&reg_usb3_vbus0>;
+ dr_mode = "host";
+ status = "okay";
+};
+
+&cp0_utmi {
+ status = "okay";
+};
+
+/* mikrobus uart */
+&cp0_uart0 {
+ pinctrl-0 = <&mikro_uart_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/marvell/cn9130-sr-som.dtsi b/arch/arm64/boot/dts/marvell/cn9130-sr-som.dtsi
new file mode 100644
index 000000000000..4676e3488f54
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9130-sr-som.dtsi
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2024 Josua Mayer <[email protected]>
+ *
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "SolidRun CN9130 SoM";
+ compatible = "solidrun,cn9130-sr-som", "marvell,cn9130";
+
+ aliases {
+ ethernet0 = &cp0_eth0;
+ ethernet1 = &cp0_eth1;
+ ethernet2 = &cp0_eth2;
+ i2c0 = &cp0_i2c0;
+ mmc0 = &ap_sdhci0;
+ rtc0 = &cp0_rtc;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ v_1_8: regulator-1-8 {
+ compatible = "regulator-fixed";
+ regulator-name = "1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ /* requires assembly of R9307 */
+ vhv: regulator-vhv-1-8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vhv-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ pinctrl-0 = <&cp0_reg_vhv_pins>;
+ pinctrl-names = "default";
+ gpios = <&cp0_gpio2 9 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&ap_pinctrl {
+ ap_mmc0_pins: ap-mmc0-pins {
+ marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3", "mpp4", "mpp5",
+ "mpp6", "mpp7", "mpp8", "mpp9", "mpp10", "mpp12";
+ marvell,function = "sdio";
+ /*
+ * mpp12 is emmc reset, function should be sdio (hw_rst),
+ * but pinctrl-mvebu does not support this.
+ *
+ * From pinctrl-mvebu.h:
+ * "The name will be used to switch to this setting in DT description, e.g.
+ * marvell,function = "uart2". subname is only for debugging purposes."
+ */
+ };
+};
+
+&ap_sdhci0 {
+ bus-width = <8>;
+ pinctrl-0 = <&ap_mmc0_pins>;
+ pinctrl-names = "default";
+ vqmmc-supply = <&v_1_8>;
+ status = "okay";
+};
+
+&cp0_ethernet {
+ status = "okay";
+};
+
+/* for assembly with phy */
+&cp0_eth2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_eth2_pins>;
+ phy-mode = "rgmii-id";
+ phy = <&cp0_eth2_phy>;
+ status = "okay";
+};
+
+&cp0_i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_i2c0_pins>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ som_eeprom: eeprom@53 {
+ compatible = "atmel,24c02";
+ reg = <0x53>;
+ pagesize = <8>;
+ };
+};
+
+&cp0_mdio {
+ pinctrl-0 = <&cp0_mdio_pins>;
+ status = "okay";
+
+ /* assembly option */
+ cp0_eth2_phy: ethernet-phy@0 {
+ reg = <0>;
+ };
+};
+
+&cp0_spi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_spi1_pins>;
+ /* max speed limited by a mux */
+ spi-max-frequency = <1800000000>;
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ /* read command supports max. 50MHz */
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&cp0_syscon0 {
+ cp0_pinctrl: pinctrl {
+ compatible = "marvell,cp115-standalone-pinctrl";
+
+ cp0_eth2_pins: cp0-ge2-rgmii-pins {
+ marvell,pins = "mpp44", "mpp45", "mpp46", "mpp47",
+ "mpp48", "mpp49", "mpp50", "mpp51",
+ "mpp52", "mpp53", "mpp54", "mpp55";
+ /* docs call it "ge2", but cp110-pinctrl "ge1" */
+ marvell,function = "ge1";
+ };
+
+ cp0_i2c0_pins: cp0-i2c0-pins {
+ marvell,pins = "mpp37", "mpp38";
+ marvell,function = "i2c0";
+ };
+
+ cp0_mdio_pins: cp0-mdio-pins {
+ marvell,pins = "mpp40", "mpp41";
+ marvell,function = "ge";
+ };
+
+ cp0_spi1_pins: cp0-spi1-pins {
+ marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
+ marvell,function = "spi1";
+ };
+
+ cp0_reg_vhv_pins: cp0-reg-vhv-pins {
+ marvell,pins = "mpp41";
+ marvell,function = "gpio";
+ };
+ };
+};
+
+/* AP default console */
+&uart0 {
+ pinctrl-0 = <&uart0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/marvell/cn9131-cf-solidwan.dts b/arch/arm64/boot/dts/marvell/cn9131-cf-solidwan.dts
new file mode 100644
index 000000000000..b1ea7dcaed17
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9131-cf-solidwan.dts
@@ -0,0 +1,637 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Josua Mayer <[email protected]>
+ *
+ * DTS for SolidRun CN9130 Clearfog Base.
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+#include "cn9130.dtsi"
+#include "cn9130-sr-som.dtsi"
+
+/*
+ * Instantiate the external CP115
+ */
+
+#define CP11X_NAME cp1
+#define CP11X_BASE f4000000
+#define CP11X_PCIEx_MEM_BASE(iface) (0xe2000000 + (iface * 0x1000000))
+#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000
+#define CP11X_PCIE0_BASE f4600000
+#define CP11X_PCIE1_BASE f4620000
+#define CP11X_PCIE2_BASE f4640000
+
+#include "armada-cp115.dtsi"
+
+#undef CP11X_NAME
+#undef CP11X_BASE
+#undef CP11X_PCIEx_MEM_BASE
+#undef CP11X_PCIEx_MEM_SIZE
+#undef CP11X_PCIE0_BASE
+#undef CP11X_PCIE1_BASE
+#undef CP11X_PCIE2_BASE
+
+/ {
+ model = "SolidRun CN9131 SolidWAN";
+ compatible = "solidrun,cn9131-solidwan",
+ "solidrun,cn9130-sr-som", "marvell,cn9130";
+
+ aliases {
+ ethernet0 = &cp1_eth1;
+ ethernet1 = &cp1_eth2;
+ ethernet2 = &cp0_eth1;
+ ethernet3 = &cp0_eth2;
+ ethernet4 = &cp0_eth0;
+ ethernet5 = &cp1_eth0;
+ gpio0 = &ap_gpio;
+ gpio1 = &cp0_gpio1;
+ gpio2 = &cp0_gpio2;
+ gpio3 = &cp1_gpio1;
+ gpio4 = &cp1_gpio2;
+ gpio5 = &expander0;
+ i2c0 = &cp0_i2c0;
+ i2c1 = &cp0_i2c1;
+ i2c2 = &cp1_i2c1;
+ mmc0 = &ap_sdhci0;
+ mmc1 = &cp0_sdhci0;
+ rtc0 = &cp0_rtc;
+ rtc1 = &carrier_rtc;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_led_pins &cp1_led_pins>;
+
+ /* for sfp-1 (J42) */
+ led-sfp1-activity {
+ label = "sfp1:green";
+ gpios = <&cp0_gpio1 7 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* for sfp-1 (J42) */
+ led-sfp1-link {
+ label = "sfp1:yellow";
+ gpios = <&cp0_gpio1 4 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* (J28) */
+ led-sfp0-activity {
+ label = "sfp0:green";
+ gpios = <&cp1_gpio2 22 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* (J28) */
+ led-sfp0-link {
+ label = "sfp0:yellow";
+ gpios = <&cp1_gpio2 23 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ /* Type-A port on J53 */
+ reg_usb_a_vbus0: regulator-usb-a-vbus0 {
+ compatible = "regulator-fixed";
+ pinctrl-0 = <&cp0_reg_usb_a_vbus0_pins>;
+ pinctrl-names = "default";
+ regulator-name = "vbus0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpios = <&cp0_gpio1 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ reg_usb_a_vbus1: regulator-usb-a-vbus1 {
+ compatible = "regulator-fixed";
+ pinctrl-0 = <&cp0_reg_usb_a_vbus1_pins>;
+ pinctrl-names = "default";
+ regulator-name = "vbus1";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpios = <&cp0_gpio1 28 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ sfp0: sfp-0 {
+ compatible = "sff,sfp";
+ pinctrl-0 = <&cp0_sfp0_pins>;
+ pinctrl-names = "default";
+ i2c-bus = <&cp0_i2c1>;
+ los-gpios = <&cp0_gpio2 2 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&cp0_gpio2 0 GPIO_ACTIVE_LOW>;
+ tx-disable-gpios = <&cp0_gpio2 1 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpios = <&cp0_gpio1 31 GPIO_ACTIVE_HIGH>;
+ maximum-power-milliwatt = <2000>;
+ };
+
+ sfp1: sfp-1 {
+ compatible = "sff,sfp";
+ pinctrl-0 = <&cp1_sfp1_pins>;
+ pinctrl-names = "default";
+ i2c-bus = <&cp1_i2c1>;
+ los-gpios = <&cp1_gpio2 2 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&cp1_gpio2 18 GPIO_ACTIVE_LOW>;
+ tx-disable-gpios = <&cp1_gpio2 1 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpios = <&cp1_gpio2 17 GPIO_ACTIVE_HIGH>;
+ maximum-power-milliwatt = <2000>;
+ };
+};
+
+&cp0_ethernet {
+ status = "okay";
+};
+
+/* SRDS #2 - SFP+ 10GE */
+&cp0_eth0 {
+ managed = "in-band-status";
+ phy-mode = "10gbase-r";
+ phys = <&cp0_comphy2 0>;
+ sfp = <&sfp0>;
+ status = "okay";
+};
+
+/* SRDS #3 - SGMII 1GE */
+&cp0_eth1 {
+ managed = "in-band-status";
+ phy-mode = "sgmii";
+ /* Without mdio phy access rely on sgmii auto-negotiation. */
+ phys = <&cp0_comphy3 1>;
+ status = "okay";
+};
+
+/* SRDS #1 - SGMII */
+&cp0_eth2 {
+ /delete-property/ pinctrl-0;
+ /delete-property/ pinctrl-names;
+ managed = "in-band-status";
+ phy-mode = "sgmii";
+ phy = <&cp0_phy1>;
+ phys = <&cp0_comphy1 2>;
+};
+
+&cp0_gpio1 {
+ pcie0-0-w-disable-hog {
+ gpio-hog;
+ gpios = <6 GPIO_ACTIVE_LOW>;
+ output-low;
+ line-name = "pcie0.0-w-disable";
+ };
+
+ /* J34 */
+ m2-full-card-power-off-hog {
+ gpio-hog;
+ gpios = <8 GPIO_ACTIVE_LOW>;
+ output-low;
+ line-name = "m2-full-card-power-off";
+ };
+};
+
+&cp0_i2c0 {
+ /* assembly option */
+ fan-controller@18 {
+ compatible = "ti,amc6821";
+ reg = <0x18>;
+ };
+
+ expander0: gpio@41 {
+ compatible = "nxp,pca9536";
+ reg = <0x41>;
+
+ usb-a-vbus0-ilimit-hog {
+ gpio-hog;
+ gpios = <0 GPIO_ACTIVE_LOW>;
+ input;
+ line-name = "vbus0-ilimit";
+ };
+
+ /* duplicate connection, controlled by soc gpio */
+ usb-vbus0-enable-hog {
+ gpio-hog;
+ gpios = <1 GPIO_ACTIVE_HIGH>;
+ input;
+ line-name = "vbus0-enable";
+ };
+
+ usb-a-vbus1-ilimit-hog {
+ gpio-hog;
+ gpios = <2 GPIO_ACTIVE_LOW>;
+ input;
+ line-name = "vbus1-ilimit";
+ };
+
+ /* duplicate connection, controlled by soc gpio */
+ usb-vbus1-enable-hog {
+ gpio-hog;
+ gpios = <3 GPIO_ACTIVE_HIGH>;
+ input;
+ line-name = "vbus1-enable";
+ };
+ };
+
+ carrier_eeprom: eeprom@52 {
+ compatible = "atmel,24c02";
+ reg = <0x52>;
+ pagesize = <8>;
+ };
+
+ /* usb-hub@60 */
+
+ /* assembly option */
+ carrier_rtc: rtc@68 {
+ compatible = "st,m41t83";
+ reg = <0x68>;
+ pinctrl-0 = <&cp1_rtc_pins>;
+ pinctrl-names = "default";
+ interrupt-parent = <&cp1_gpio1>;
+ interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&cp1_gpio1 13 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&cp0_i2c1 {
+ /*
+ * Routed to SFP.
+ * Limit to 100kHz for compatibility with SFP modules,
+ * featuring AT24C01A/02/04 at addresses 0x50/0x51.
+ */
+ clock-frequency = <100000>;
+ pinctrl-0 = <&cp0_i2c1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&cp0_mdio {
+ /*
+ * SoM + Carrier each have a PHY at address 0.
+ * Remove the SoM phy node, and skip adding the carrier node.
+ * SGMII Auto-Negotation is enabled by bootloader for
+ * autonomous operation without mdio control.
+ */
+ /delete-node/ ethernet-phy@0;
+
+ /* U17016 */
+ cp0_phy1: ethernet-phy@1 {
+ reg = <1>;
+ /*
+ * Configure LEDs default behaviour:
+ * - LED[0]: link is 1000Mbps: On (yellow)
+ * - LED[1]: link/activity: On/blink (green)
+ * - LED[2]: high impedance (floating)
+ */
+ marvell,reg-init = <3 16 0xf000 0x0a17>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+ };
+};
+
+/* SRDS #0 - miniPCIe */
+&cp0_pcie0 {
+ num-lanes = <1>;
+ phys = <&cp0_comphy0 0>;
+ status = "okay";
+};
+
+/* SRDS #5 - M.2 B-Key (J34) */
+&cp0_pcie2 {
+ num-lanes = <1>;
+ phys = <&cp0_comphy5 2>;
+ status = "okay";
+};
+
+&cp0_pinctrl {
+ pinctrl-0 = <&cp0_m2_0_shutdown_pins &cp0_mpcie_rfkill_pins>;
+ pinctrl-names = "default";
+
+ cp0_i2c1_pins: cp0-i2c1-pins {
+ marvell,pins = "mpp35", "mpp36";
+ marvell,function = "i2c1";
+ };
+
+ cp0_led_pins: cp0-led-pins {
+ marvell,pins = "mpp4", "mpp7";
+ marvell,function = "gpio";
+ };
+
+ cp0_m2_0_shutdown_pins: cp0-m2-0-shutdown-pins {
+ marvell,pins = "mpp8";
+ marvell,function = "gpio";
+ };
+
+ cp0_mmc0_pins: cp0-mmc0-pins {
+ marvell,pins = "mpp43", "mpp56", "mpp57", "mpp58",
+ "mpp59", "mpp60", "mpp61";
+ marvell,function = "sdio";
+ };
+
+ cp0_mpcie_rfkill_pins: cp0-mpcie-rfkill-pins {
+ marvell,pins = "mpp6";
+ marvell,function = "gpio";
+ };
+
+ cp0_reg_usb_a_vbus0_pins: cp0-reg-usb-a-vbus0-pins {
+ marvell,pins = "mpp27";
+ marvell,function = "gpio";
+ };
+
+ cp0_reg_usb_a_vbus1_pins: cp0-reg-usb-a-vbus1-pins {
+ marvell,pins = "mpp28";
+ marvell,function = "gpio";
+ };
+
+ cp0_sfp0_pins: cp0-sfp0-pins {
+ marvell,pins = "mpp31", "mpp32", "mpp33", "mpp34";
+ marvell,function = "gpio";
+ };
+
+ cp0_spi1_cs1_pins: cp0-spi1-cs1-pins {
+ marvell,pins = "mpp12";
+ marvell,function = "spi1";
+ };
+};
+
+/* microSD */
+&cp0_sdhci0 {
+ pinctrl-0 = <&cp0_mmc0_pins>;
+ pinctrl-names = "default";
+ bus-width = <4>;
+ no-1-8-v;
+ status = "okay";
+};
+
+&cp0_spi1 {
+ /* add pin for chip-select 1 */
+ pinctrl-0 = <&cp0_spi1_pins &cp0_spi1_cs1_pins>;
+
+ flash@1 {
+ compatible = "jedec,spi-nor";
+ reg = <1>;
+ /* read command supports max. 50MHz */
+ spi-max-frequency = <50000000>;
+ };
+};
+
+/* USB-2.0 Host to USB-Hub */
+&cp0_usb3_0 {
+ phys = <&cp0_utmi0>;
+ phy-names = "utmi";
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* SRDS #4 - USB-3.0 Host to USB-Hub */
+&cp0_usb3_1 {
+ phys = <&cp0_comphy4 1>, <&cp0_utmi1>;
+ phy-names = "comphy", "utmi";
+ dr_mode = "host";
+ status = "okay";
+};
+
+&cp0_utmi {
+ status = "okay";
+};
+
+&cp0_utmi1 {
+ status = "disabled";
+};
+
+&cp1_ethernet {
+ status = "okay";
+};
+
+/* SRDS #4 - SFP+ 10GE */
+&cp1_eth0 {
+ managed = "in-band-status";
+ phy-mode = "10gbase-r";
+ phys = <&cp1_comphy4 0>;
+ sfp = <&sfp1>;
+ status = "okay";
+};
+
+/* SRDS #3 - SGMII 1GE */
+&cp1_eth1 {
+ managed = "in-band-status";
+ phy-mode = "sgmii";
+ phy = <&cp1_phy0>;
+ phys = <&cp0_comphy3 1>;
+ status = "okay";
+};
+
+/* SRDS #5 - SGMII 1GE */
+&cp1_eth2 {
+ managed = "in-band-status";
+ phy-mode = "sgmii";
+ phy = <&cp1_phy1>;
+ phys = <&cp0_comphy5 2>;
+ status = "okay";
+};
+
+&cp1_gpio1 {
+ status = "okay";
+
+ /* J30 */
+ m2-full-card-power-off-hog-0 {
+ gpio-hog;
+ gpios = <29 GPIO_ACTIVE_LOW>;
+ output-low;
+ line-name = "m2-full-card-power-off";
+ };
+
+ /* J44 */
+ m2-full-card-power-off-hog-1 {
+ gpio-hog;
+ gpios = <30 GPIO_ACTIVE_LOW>;
+ output-low;
+ line-name = "m2-full-card-power-off";
+ };
+};
+
+&cp1_gpio2 {
+ status = "okay";
+};
+
+&cp1_i2c1 {
+ /*
+ * Routed to SFP.
+ * Limit to 100kHz for compatibility with SFP modules,
+ * featuring AT24C01A/02/04 at addresses 0x50/0x51.
+ */
+ clock-frequency = <100000>;
+ pinctrl-0 = <&cp1_i2c1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&cp1_mdio {
+ pinctrl-0 = <&cp1_mdio_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ cp1_phy0: ethernet-phy@0 {
+ reg = <0>;
+ /*
+ * Configure LEDs default behaviour:
+ * - LED[0]: link is 1000Mbps: On (yellow)
+ * - LED[1]: link/activity: On/blink (green)
+ * - LED[2]: high impedance (floating)
+ */
+ marvell,reg-init = <3 16 0xf000 0x0a17>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+ };
+
+ cp1_phy1: ethernet-phy@1 {
+ reg = <1>;
+ /*
+ * Configure LEDs default behaviour:
+ * - LED[0]: link is 1000Mbps: On (yellow)
+ * - LED[1]: link/activity: On/blink (green)
+ * - LED[2]: high impedance (floating)
+ */
+ marvell,reg-init = <3 16 0xf000 0x0a17>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+ };
+};
+
+/* SRDS #0 - M.2 (J30) */
+&cp1_pcie0 {
+ num-lanes = <1>;
+ phys = <&cp1_comphy0 0>;
+ status = "okay";
+};
+
+&cp1_rtc {
+ status = "disabled";
+};
+
+/* SRDS #1 - SATA on M.2 (J44) */
+&cp1_sata0 {
+ phys = <&cp1_comphy1 0>;
+ status = "okay";
+
+ /* only port 0 is available */
+ /delete-node/ sata-port@1;
+};
+
+&cp1_syscon0 {
+ cp1_pinctrl: pinctrl {
+ compatible = "marvell,cp115-standalone-pinctrl";
+ pinctrl-0 = <&cp1_m2_1_shutdown_pins &cp1_m2_2_shutdown_pins>;
+ pinctrl-names = "default";
+
+ cp1_i2c1_pins: cp0-i2c1-pins {
+ marvell,pins = "mpp35", "mpp36";
+ marvell,function = "i2c1";
+ };
+
+ cp1_led_pins: cp1-led-pins {
+ marvell,pins = "mpp54", "mpp55";
+ marvell,function = "gpio";
+ };
+
+ cp1_m2_1_shutdown_pins: cp1-m2-1-shutdown-pins {
+ marvell,pins = "mpp29";
+ marvell,function = "gpio";
+ };
+
+ cp1_m2_2_shutdown_pins: cp1-m2-2-shutdown-pins {
+ marvell,pins = "mpp30";
+ marvell,function = "gpio";
+ };
+
+ cp1_mdio_pins: cp1-mdio-pins {
+ marvell,pins = "mpp37", "mpp38";
+ marvell,function = "ge";
+ };
+
+ cp1_rtc_pins: cp1-rtc-pins {
+ marvell,pins = "mpp12", "mpp13";
+ marvell,function = "gpio";
+ };
+
+ cp1_sfp1_pins: cp1-sfp1-pins {
+ marvell,pins = "mpp33", "mpp34", "mpp49", "mpp50";
+ marvell,function = "gpio";
+ };
+ };
+};
+
+/*
+ * SRDS #2 - USB-3.0 Host to M.2 (J44)
+ * USB-2.0 Host to M.2 (J30)
+ */
+&cp1_usb3_0 {
+ phys = <&cp1_comphy2 0>, <&cp1_utmi0>;
+ phy-names = "comphy", "utmi";
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* USB-2.0 Host to M.2 (J44) */
+&cp1_usb3_1 {
+ phys = <&cp1_utmi1>;
+ phy-names = "utmi";
+ dr_mode = "host";
+ status = "okay";
+};
+
+&cp1_utmi {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/marvell/cn9132-clearfog.dts b/arch/arm64/boot/dts/marvell/cn9132-clearfog.dts
new file mode 100644
index 000000000000..0f53745a6fa0
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9132-clearfog.dts
@@ -0,0 +1,673 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2024 Josua Mayer <[email protected]>
+ *
+ * DTS for SolidRun CN9132 Clearfog.
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+#include "cn9130.dtsi"
+#include "cn9132-sr-cex7.dtsi"
+
+/ {
+ model = "SolidRun CN9132 Clearfog";
+ compatible = "solidrun,cn9132-clearfog",
+ "solidrun,cn9132-sr-cex7", "marvell,cn9130";
+
+ aliases {
+ ethernet1 = &cp0_eth2;
+ ethernet2 = &cp0_eth0;
+ ethernet3 = &cp2_eth0;
+ ethernet4 = &cp1_eth0;
+ i2c7 = &carrier_mpcie_i2c;
+ i2c8 = &carrier_ptp_i2c;
+ mmc1 = &cp0_sdhci0;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_wake0_pins>;
+
+ button-0 {
+ label = "SW2";
+ gpios = <&cp1_gpio2 8 GPIO_ACTIVE_LOW>;
+ linux,can-disable;
+ linux,code = <BTN_2>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_batlow_pins &cp2_rsvd4_pins>;
+
+ /* LED11 */
+ led-io-0 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_DISK;
+ function-enumerator = <0>;
+ default-state = "off";
+ gpios = <&cp1_gpio1 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* LED12 */
+ led-io-1 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_DISK;
+ function-enumerator = <1>;
+ default-state = "off";
+ gpios = <&cp2_gpio1 4 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ /* CON4 W_DISABLE1/W_DISABLE2 */
+ rfkill-m2-wlan {
+ compatible = "rfkill-gpio";
+ label = "m.2 wlan (CON4)";
+ radio-type = "wlan";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_10g_phy_rst_01_pins>;
+ /* rfkill-gpio inverts internally */
+ shutdown-gpios = <&cp1_gpio2 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* CON5 W_DISABLE1/W_DISABLE2 */
+ rfkill-m2-wlan {
+ compatible = "rfkill-gpio";
+ label = "m.2 wlan (CON5)";
+ radio-type = "wlan";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_10g_phy_rst_23_pins>;
+ /* rfkill-gpio inverts internally */
+ shutdown-gpios = <&cp1_gpio2 10 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* J21 W_DISABLE1 */
+ rfkill-m2-wwan {
+ compatible = "rfkill-gpio";
+ label = "m.2 wwan (J21)";
+ radio-type = "wwan";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp2_rsvd3_pins>;
+ /* rfkill-gpio inverts internally */
+ shutdown-gpios = <&cp2_gpio1 3 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* J21 W_DISABLE1 */
+ rfkill-m2-gnss {
+ compatible = "rfkill-gpio";
+ label = "m.2 gnss (J21)";
+ radio-type = "gps";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp2_rsvd8_pins>;
+ /* rfkill-gpio inverts internally */
+ shutdown-gpios = <&cp2_gpio1 8 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* J14 W_DISABLE */
+ rfkill-mpcie-wlan {
+ compatible = "rfkill-gpio";
+ label = "mpcie wlan (J14)";
+ radio-type = "wlan";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp2_rsvd2_pins>;
+ /* rfkill-gpio inverts internally */
+ shutdown-gpios = <&cp2_gpio1 2 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp: sfp {
+ compatible = "sff,sfp";
+ i2c-bus = <&com_10g_sfp_i2c0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&com_10g_int0_pins>;
+ mod-def0-gpios = <&cp0_gpio1 24 GPIO_ACTIVE_LOW>;
+ maximum-power-milliwatt = <2000>;
+ };
+};
+
+&com_smbus {
+ /* This bus is also routed to STM32 BMC Microcontroller (U2) */
+
+ power-sensor@40 {
+ compatible = "ti,ina220";
+ reg = <0x40>;
+ #io-channel-cells = <1>;
+ label = "vdd_12v0";
+ shunt-resistor = <2000>;
+ };
+
+ adc@48 {
+ compatible = "ti,tla2021";
+ reg = <0x48>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* supplied by chaoskey hardware noise generator circuit */
+ channel@0 {
+ reg = <0>;
+ };
+ };
+};
+
+&cp0_eth_phy0 {
+ /*
+ * Configure LEDs default behaviour:
+ * - LED[0]: link is 1000Mbps: On (yellow): 0111
+ * - LED[1]: link/activity: On/Blink (green): 0001
+ * - LED[2]: Off (green): 1000
+ */
+ marvell,reg-init = <3 16 0xf000 0x0817>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ /* link */
+ reg = <0>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@1 {
+ /* act */
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@2 {
+ /* 1000 */
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+};
+
+/* SRDS #4 - 10GE */
+&cp0_eth0 {
+ phys = <&cp0_comphy4 0>;
+ phy-mode = "10gbase-r";
+ managed = "in-band-status";
+ sfp = <&sfp>;
+ status = "okay";
+};
+
+&cp0_eth2 {
+ phy-mode = "2500base-x";
+ phys = <&cp0_comphy5 2>;
+ status = "okay";
+
+ fixed-link {
+ speed = <2500>;
+ full-duplex;
+ pause;
+ };
+};
+
+&cp0_i2c1 {
+ /*
+ * Both COM and Carrier Board have a PCA9547 i2c mux at 0x77.
+ * Describe them as a single device merging each child bus.
+ */
+
+ i2c-mux@77 {
+ i2c@0 {
+ /* Routed to Full PCIe (J4) */
+ };
+
+ i2c@1 {
+ /* Routed to USB Hub (U29) */
+ };
+
+ i2c@2 {
+ /* Routed to M.2 (CON4) */
+ };
+
+ i2c@3 {
+ /* Routed to M.2 (CON5) */
+ };
+
+ i2c@4 {
+ /* Routed to M.2 (J21) */
+ };
+
+ carrier_mpcie_i2c: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+
+ /* Routed to mini-PCIe (J14) */
+ };
+
+ carrier_ptp_i2c: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+
+ /* Routed to various optional PTP related components */
+ };
+ };
+};
+
+&cp0_mdio {
+ ethernet-switch@4 {
+ compatible = "marvell,mv88e6085";
+ reg = <4>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sw_phy1: ethernet-phy@1 {
+ reg = <0x11>;
+ };
+
+ sw_phy2: ethernet-phy@2 {
+ reg = <0x12>;
+ };
+
+ sw_phy3: ethernet-phy@3 {
+ reg = <0x13>;
+ };
+
+ sw_phy4: ethernet-phy@4 {
+ reg = <0x14>;
+ };
+ };
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet-port@1 {
+ reg = <1>;
+ label = "lan1";
+ phy-handle = <&sw_phy1>;
+ phy-mode = "internal";
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+ };
+
+ ethernet-port@2 {
+ reg = <2>;
+ label = "lan2";
+ phy-handle = <&sw_phy2>;
+ phy-mode = "internal";
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+ };
+
+ ethernet-port@3 {
+ reg = <3>;
+ label = "lan3";
+ phy-handle = <&sw_phy3>;
+ phy-mode = "internal";
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+ };
+
+ ethernet-port@4 {
+ reg = <4>;
+ label = "lan4";
+ phy-handle = <&sw_phy4>;
+ phy-mode = "internal";
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+ };
+
+ ethernet-port@5 {
+ reg = <5>;
+ label = "cpu";
+ ethernet = <&cp0_eth2>;
+ phy-mode = "2500base-x";
+
+ fixed-link {
+ speed = <2500>;
+ full-duplex;
+ pause;
+ };
+ };
+ };
+ };
+};
+
+/* SRDS #0,#1,#2,#3 - PCIe */
+&cp0_pcie0 {
+ num-lanes = <4>;
+ phys = <&cp0_comphy0 0>, <&cp0_comphy1 0>, <&cp0_comphy2 0>, <&cp0_comphy3 0>;
+ status = "okay";
+};
+
+&cp0_pinctrl {
+ /*
+ * configure unused gpios exposed via pin headers:
+ * - J7-10: PWRBTN
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_pwrbtn_pins>;
+};
+
+/* microSD */
+&cp0_sdhci0 {
+ pinctrl-0 = <&cp0_mmc0_pins>, <&cp0_mmc0_cd_pins>;
+ pinctrl-names = "default";
+ bus-width = <4>;
+ no-1-8-v;
+ status = "okay";
+};
+
+&cp0_spi1 {
+ /* add CS1 */
+ pinctrl-0 = <&cp0_spi1_pins>, <&cp0_spi1_cs1_pins>;
+
+ flash@1 {
+ compatible = "jedec,spi-nor";
+ reg = <1>;
+ /* read command supports max. 50MHz */
+ spi-max-frequency = <50000000>;
+ };
+};
+
+/* J38 */
+&cp0_uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_uart2_pins>;
+ status = "okay";
+};
+
+&cp0_utmi {
+ /* M.2 "CON5" swaps D+/D- */
+ swap-dx-lanes = <1>;
+};
+
+&cp1_ethernet {
+ status = "okay";
+};
+
+/* SRDS #2 - 5GE */
+&cp1_eth0 {
+ phys = <&cp1_comphy2 0>;
+ phy-mode = "5gbase-r";
+ phy = <&cp1_eth_phy0>;
+ managed = "in-band-status";
+ status = "okay";
+};
+
+/* SRDS #0,#1 - PCIe */
+&cp1_pcie0 {
+ num-lanes = <2>;
+ phys = <&cp1_comphy0 0>, <&cp1_comphy1 0>;
+ status = "okay";
+};
+
+/* SRDS #4 - PCIe */
+&cp1_pcie1 {
+ num-lanes = <1>;
+ phys = <&cp1_comphy4 1>;
+ status = "okay";
+};
+
+/* SRDS #5 - PCIe */
+&cp1_pcie2 {
+ num-lanes = <1>;
+ phys = <&cp1_comphy5 2>;
+ status = "okay";
+};
+
+&cp1_pinctrl {
+ /*
+ * configure unused gpios exposed via pin headers:
+ * - J7-8: RSVD16
+ * - J7-10: THRM
+ * - J10-1: WAKE1
+ * - J10-2: SATA_ACT
+ * - J10-8: THERMTRIP
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_rsvd16_pins &cp1_sata_act_pins &cp1_thrm_irq_pins>,
+ <&cp1_thrm_trip_pins &cp1_wake1_pins>;
+};
+
+/* SRDS #3 - SATA */
+&cp1_sata0 {
+ status = "okay";
+
+ /* only port 1 is available */
+ /delete-node/ sata-port@0;
+
+ sata-port@1 {
+ phys = <&cp1_comphy3 1>;
+ };
+};
+
+&cp1_utmi {
+ /* M.2 "CON4" swaps D+/D- */
+ swap-dx-lanes = <0>;
+};
+
+&cp1_xmdio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_xmdio_pins>;
+ status = "okay";
+
+ cp1_eth_phy0: ethernet-phy@8 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <8>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&com_10g_int1_pins>;
+ interrupt-parent = <&cp1_gpio2>;
+ interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+ };
+};
+
+&cp2_ethernet {
+ status = "okay";
+};
+
+/* SRDS #2 - 5GE */
+&cp2_eth0 {
+ phys = <&cp2_comphy2 0>;
+ phy-mode = "5gbase-r";
+ phy = <&cp2_eth_phy0>;
+ managed = "in-band-status";
+ status = "okay";
+};
+
+&cp2_gpio1 {
+ pinctrl-names= "default";
+ pinctrl-0 = <&cp2_rsvd9_pins>;
+
+ /* J21 */
+ m2-wwan-reset-hog {
+ gpio-hog;
+ gpios = <9 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
+ output-low;
+ line-name = "m2-wwan-reset";
+ };
+};
+
+/* SRDS #0 - PCIe */
+&cp2_pcie0 {
+ num-lanes = <1>;
+ phys = <&cp2_comphy0 0>;
+ status = "okay";
+};
+
+/* SRDS #4 - PCIe */
+&cp2_pcie1 {
+ num-lanes = <1>;
+ phys = <&cp2_comphy4 1>;
+ status = "okay";
+};
+
+/* SRDS #5 - PCIe */
+&cp2_pcie2 {
+ num-lanes = <1>;
+ phys = <&cp2_comphy5 2>;
+ status = "okay";
+};
+
+&cp2_pinctrl {
+ /*
+ * configure unused gpios exposed via pin headers:
+ * - J7-1: RSVD10
+ * - J7-3: RSVD11
+ * - J7-5: RSVD56
+ * - J7-6: RSVD7
+ * - J7-7: RSVD27
+ * - J10-3: RSVD31
+ * - J10-5: RSVD5
+ * - J10-6: RSVD32
+ * - J10-7: RSVD0
+ * - J10-9: RSVD1
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp2_rsvd0_pins &cp2_rsvd1_pins &cp2_rsvd5_pins>,
+ <&cp2_rsvd7_pins &cp2_rsvd10_pins &cp2_rsvd11_pins>,
+ <&cp2_rsvd27_pins &cp2_rsvd31_pins &cp2_rsvd32_pins>,
+ <&cp2_rsvd56_pins>;
+};
+
+/* SRDS #3 - SATA */
+&cp2_sata0 {
+ status = "okay";
+
+ /* only port 1 is available */
+ /delete-node/ sata-port@0;
+
+ sata-port@1 {
+ phys = <&cp2_comphy3 1>;
+ };
+};
+
+&cp2_xmdio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp2_xmdio_pins>;
+ status = "okay";
+
+ cp2_eth_phy0: ethernet-phy@8 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <8>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&com_10g_int2_pins>;
+ interrupt-parent = <&cp2_gpio2>;
+ interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ default-state = "keep";
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/marvell/cn9132-sr-cex7.dtsi b/arch/arm64/boot/dts/marvell/cn9132-sr-cex7.dtsi
new file mode 100644
index 000000000000..afc041c1c448
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9132-sr-cex7.dtsi
@@ -0,0 +1,712 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2024 Josua Mayer <[email protected]>
+ *
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/*
+ * Instantiate the first external CP115
+ */
+
+#define CP11X_NAME cp1
+#define CP11X_BASE f4000000
+#define CP11X_PCIEx_MEM_BASE(iface) (0xe2000000 + (iface * 0x1000000))
+#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000
+#define CP11X_PCIE0_BASE f4600000
+#define CP11X_PCIE1_BASE f4620000
+#define CP11X_PCIE2_BASE f4640000
+
+#include "armada-cp115.dtsi"
+
+#undef CP11X_NAME
+#undef CP11X_BASE
+#undef CP11X_PCIEx_MEM_BASE
+#undef CP11X_PCIEx_MEM_SIZE
+#undef CP11X_PCIE0_BASE
+#undef CP11X_PCIE1_BASE
+#undef CP11X_PCIE2_BASE
+
+/*
+ * Instantiate the second external CP115
+ */
+
+#define CP11X_NAME cp2
+#define CP11X_BASE f6000000
+#define CP11X_PCIEx_MEM_BASE(iface) (0xe5000000 + (iface * 0x1000000))
+#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000
+#define CP11X_PCIE0_BASE f6600000
+#define CP11X_PCIE1_BASE f6620000
+#define CP11X_PCIE2_BASE f6640000
+
+#include "armada-cp115.dtsi"
+
+#undef CP11X_NAME
+#undef CP11X_BASE
+#undef CP11X_PCIEx_MEM_BASE
+#undef CP11X_PCIEx_MEM_SIZE
+#undef CP11X_PCIE0_BASE
+#undef CP11X_PCIE1_BASE
+#undef CP11X_PCIE2_BASE
+
+/ {
+ model = "SolidRun CN9132 COM Express Type 7 Module";
+ compatible = "solidrun,cn9132-sr-cex7", "marvell,cn9130";
+
+ aliases {
+ ethernet0 = &cp0_eth1;
+ gpio3 = &cp1_gpio1;
+ gpio4 = &cp1_gpio2;
+ gpio5 = &cp2_gpio1;
+ gpio6 = &cp2_gpio2;
+ i2c0 = &cp0_i2c0;
+ i2c1 = &cp0_i2c1;
+ i2c2 = &com_clkgen_i2c;
+ i2c3 = &com_10g_led_i2c;
+ i2c4 = &com_10g_sfp_i2c0;
+ i2c5 = &com_smbus;
+ i2c6 = &com_fanctrl_i2c;
+ mmc0 = &ap_sdhci0;
+ rtc0 = &cp0_rtc;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ fan: pwm-fan {
+ compatible = "pwm-fan";
+ cooling-levels = <0 51 102 153 204 255>;
+ #cooling-cells = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_fan_pwm_pins &cp0_fan_tacho_pins>;
+ pwms = <&cp0_gpio2 7 40000>;
+ interrupt-parent = <&cp0_gpio1>;
+ interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
+ };
+
+ v_1_8: regulator-1-8 {
+ compatible = "regulator-fixed";
+ regulator-name = "1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ap_vhv: regulator-ap-vhv-1-8 {
+ compatible = "regulator-fixed";
+ regulator-name = "ap-vhv-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ pinctrl-0 = <&cp0_reg_ap_vhv_pins>;
+ pinctrl-names = "default";
+ gpios = <&cp0_gpio2 21 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ cp_vhv: regulator-cp-vhv-1-8 {
+ compatible = "regulator-fixed";
+ regulator-name = "cp-vhv-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ pinctrl-0 = <&cp0_reg_cp_vhv_pins>;
+ pinctrl-names = "default";
+ gpios = <&cp0_gpio2 17 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&ap_pinctrl {
+ ap_mmc0_pins: ap-mmc0-pins {
+ marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3", "mpp4", "mpp5",
+ "mpp6", "mpp7", "mpp8", "mpp9", "mpp10", "mpp12";
+ marvell,function = "sdio";
+ /*
+ * mpp12 is emmc reset, function should be sdio (hw_rst),
+ * but pinctrl-mvebu does not support this.
+ *
+ * From pinctrl-mvebu.h:
+ * "The name will be used to switch to this setting in DT description, e.g.
+ * marvell,function = "uart2". subname is only for debugging purposes."
+ */
+ };
+};
+
+&ap_sdhci0 {
+ bus-width = <8>;
+ pinctrl-0 = <&ap_mmc0_pins>;
+ pinctrl-names = "default";
+ vqmmc-supply = <&v_1_8>;
+ status = "okay";
+};
+
+&ap_thermal_ic {
+ polling-delay = <1000>;
+
+ trips {
+ ap_active: trip-active {
+ temperature = <40000>;
+ hysteresis = <4000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&ap_active>;
+ cooling-device = <&fan THERMAL_NO_LIMIT 4>;
+ };
+
+ map1 {
+ trip = <&ap_crit>;
+ cooling-device = <&fan 4 5>;
+ };
+ };
+};
+
+&cp0_ethernet {
+ status = "okay";
+};
+
+&cp0_eth1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_eth1_pins>;
+ phy-mode = "rgmii-id";
+ phy = <&cp0_eth_phy0>;
+ status = "okay";
+};
+
+&cp0_gpio1 {
+ status = "okay";
+
+ /*
+ * Tacho signal used as interrupt source by pwm-fan driver.
+ * Hog IO as input to ensure mvebu-gpio irq driver`s
+ * irq_set_type can succeed.
+ */
+ pwm-tacho-irq-hog {
+ gpio-hog;
+ gpios = <26 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
+ input;
+ line-name = "fan-tacho";
+ };
+};
+
+&cp0_gpio2 {
+ status = "okay";
+};
+
+&cp0_i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_i2c0_pins>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ com_eeprom: eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ pagesize = <8>;
+ };
+
+ eeprom@53 {
+ compatible = "atmel,spd";
+ reg = <0x53>;
+ };
+};
+
+&cp0_i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_i2c1_pins>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9547";
+ reg = <0x77>;
+ i2c-mux-idle-disconnect;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ com_clkgen_i2c: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ /* clock-controller@6b */
+ };
+
+ com_10g_led_i2c: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ /* Routed to B2B Connector as I2C_10G_LED_SCL/SDA */
+ };
+
+ com_10g_sfp_i2c0: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ /* Routed to B2B Connector as I2C_SFP0_CP0_SCL/SDA */
+ };
+
+ com_smbus: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ /* Routed to B2B Connector as SBM_CLK/DAT */
+ };
+
+ com_fanctrl_i2c: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+
+ /* fan-controller@2f (assembly option) */
+ };
+ };
+};
+
+&cp0_mdio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_mdio_pins>;
+ status = "okay";
+
+ cp0_eth_phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+};
+
+&cp0_spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_spi1_pins>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ /* read command supports max. 50MHz */
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&cp0_syscon0 {
+ cp0_pinctrl: pinctrl {
+ compatible = "marvell,cp115-standalone-pinctrl";
+
+ com_10g_int0_pins: cp0-10g-int-pins {
+ marvell,pins = "mpp24";
+ marvell,function = "gpio";
+ };
+
+ cp0_eth1_pins: cp0-eth1-pins {
+ marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3",
+ "mpp4", "mpp5", "mpp6", "mpp7",
+ "mpp8", "mpp9", "mpp10", "mpp11";
+ /* docs call it "ge1", but cp110-pinctrl "ge0" */
+ marvell,function = "ge0";
+ };
+
+ cp0_fan_pwm_pins: cp0-fan-pwm-pins {
+ marvell,pins = "mpp39";
+ marvell,function = "gpio";
+ };
+
+ cp0_fan_tacho_pins: cp0-fan-tacho-pins {
+ marvell,pins = "mpp26";
+ marvell,function = "gpio";
+ };
+
+ cp0_i2c0_pins: cp0-i2c0-pins {
+ marvell,pins = "mpp37", "mpp38";
+ marvell,function = "i2c0";
+ };
+
+ cp0_i2c1_pins: cp0-i2c1-pins {
+ marvell,pins = "mpp35", "mpp36";
+ marvell,function = "i2c1";
+ };
+
+ cp0_mdio_pins: cp0-mdio-pins {
+ marvell,pins = "mpp40", "mpp41";
+ marvell,function = "ge";
+ };
+
+ cp0_mmc0_pins: cp0-mmc0-pins {
+ marvell,pins = "mpp56", "mpp57", "mpp58", "mpp59",
+ "mpp60", "mpp61";
+ marvell,function = "sdio";
+ };
+
+ cp0_mmc0_cd_pins: cp0-mmc0-cd-pins {
+ marvell,pins = "mpp55";
+ marvell,function = "sdio_cd";
+ };
+
+ cp0_pwrbtn_pins: cp0-pwrbtn-pins {
+ marvell,pins = "mpp31";
+ marvell,function = "gpio";
+ };
+
+ cp0_reg_ap_vhv_pins: cp0-reg-ap-vhv-pins {
+ marvell,pins = "mpp53";
+ marvell,function = "gpio";
+ };
+
+ cp0_reg_cp_vhv_pins: cp0-reg-cp-vhv-pins {
+ marvell,pins = "mpp49";
+ marvell,function = "gpio";
+ };
+
+ cp0_spi1_pins: cp0-spi1-pins {
+ marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
+ marvell,function = "spi1";
+ };
+
+ cp0_spi1_cs1_pins: cp0-spi1-cs1-pins {
+ marvell,pins = "mpp12";
+ marvell,function = "spi1";
+ };
+
+ cp0_uart2_pins: cp0-uart2-pins {
+ marvell,pins = "mpp50", "mpp51";
+ marvell,function = "uart2";
+ };
+ };
+};
+
+&cp0_thermal_ic {
+ polling-delay = <1000>;
+
+ trips {
+ cp0_active: trip-active {
+ temperature = <40000>;
+ hysteresis = <4000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&cp0_active>;
+ cooling-device = <&fan THERMAL_NO_LIMIT 4>;
+ };
+
+ map1 {
+ trip = <&cp0_crit>;
+ cooling-device = <&fan 4 5>;
+ };
+ };
+};
+
+/* USB-2.0 Host */
+&cp0_usb3_0 {
+ phys = <&cp0_utmi0>;
+ phy-names = "utmi";
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* USB-2.0 Host */
+&cp0_usb3_1 {
+ phys = <&cp0_utmi1>;
+ phy-names = "utmi";
+ dr_mode = "host";
+ status = "okay";
+};
+
+&cp0_utmi {
+ status = "okay";
+};
+
+&cp1_gpio1 {
+ status = "okay";
+};
+
+&cp1_gpio2 {
+ status = "okay";
+};
+
+&cp1_rtc {
+ status = "disabled";
+};
+
+&cp1_spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_spi1_pins>;
+ status = "okay";
+
+ tpm@0 {
+ reg = <0>;
+ compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+ spi-max-frequency = <10000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_tpm_irq_pins>;
+ interrupt-parent = <&cp1_gpio1>;
+ interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&cp1_syscon0 {
+ cp1_pinctrl: pinctrl {
+ compatible = "marvell,cp115-standalone-pinctrl";
+
+ com_10g_int1_pins: cp1-10g-int-pins {
+ marvell,pins = "mpp50";
+ marvell,function = "gpio";
+ };
+
+ cp1_10g_phy_rst_01_pins: cp1-10g-phy-rst-01-pins {
+ marvell,pins = "mpp43";
+ marvell,function = "gpio";
+ };
+
+ cp1_10g_phy_rst_23_pins: cp1-10g-phy-rst-23-pins {
+ marvell,pins = "mpp42";
+ marvell,function = "gpio";
+ };
+
+ cp1_batlow_pins: cp1-batlow-pins {
+ marvell,pins = "mpp11";
+ marvell,function = "gpio";
+ };
+
+ cp1_rsvd16_pins: cp1-rsvd16-pins {
+ marvell,pins = "mpp29";
+ marvell,function = "gpio";
+ };
+
+ cp1_sata_act_pins: cp1-sata-act-pins {
+ marvell,pins = "mpp39";
+ marvell,function = "gpio";
+ };
+
+ cp1_spi1_pins: cp1-spi1-pins {
+ marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
+ marvell,function = "spi1";
+ };
+
+ cp1_thrm_irq_pins: cp1-thrm-irq-pins {
+ marvell,pins = "mpp34";
+ marvell,function = "gpio";
+ };
+
+ cp1_thrm_trip_pins: cp1-thrm-trip-pins {
+ marvell,pins = "mpp33";
+ marvell,function = "gpio";
+ };
+
+ cp1_tpm_irq_pins: cp1-tpm-irq-pins {
+ marvell,pins = "mpp17";
+ marvell,function = "gpio";
+ };
+
+ cp1_wake0_pins: cp1-wake0-pins {
+ marvell,pins = "mpp40";
+ marvell,function = "gpio";
+ };
+
+ cp1_wake1_pins: cp1-wake1-pins {
+ marvell,pins = "mpp51";
+ marvell,function = "gpio";
+ };
+
+ cp1_xmdio_pins: cp1-xmdio-pins {
+ marvell,pins = "mpp37", "mpp38";
+ marvell,function = "xg";
+ };
+ };
+};
+
+&cp1_thermal_ic {
+ polling-delay = <1000>;
+
+ trips {
+ cp1_active: trip-active {
+ temperature = <40000>;
+ hysteresis = <4000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&cp1_active>;
+ cooling-device = <&fan THERMAL_NO_LIMIT 4>;
+ };
+
+ map1 {
+ trip = <&cp1_crit>;
+ cooling-device = <&fan 4 5>;
+ };
+ };
+};
+
+/* USB-2.0 Host */
+&cp1_usb3_0 {
+ phys = <&cp1_utmi0>;
+ phy-names = "utmi";
+ dr_mode = "host";
+ status = "okay";
+};
+
+&cp1_utmi {
+ status = "okay";
+};
+
+&cp2_ethernet {
+ status = "okay";
+};
+
+&cp2_gpio1 {
+ status = "okay";
+};
+
+&cp2_gpio2 {
+ status = "okay";
+};
+
+&cp2_rtc {
+ status = "disabled";
+};
+
+&cp2_syscon0 {
+ cp2_pinctrl: pinctrl {
+ compatible = "marvell,cp115-standalone-pinctrl";
+
+ com_10g_int2_pins: cp2-10g-int-pins {
+ marvell,pins = "mpp50";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd0_pins: cp2-rsvd0-pins {
+ marvell,pins = "mpp0";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd1_pins: cp2-rsvd1-pins {
+ marvell,pins = "mpp1";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd2_pins: cp2-rsvd2-pins {
+ marvell,pins = "mpp2";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd3_pins: cp2-rsvd3-pins {
+ marvell,pins = "mpp3";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd4_pins: cp2-rsvd4-pins {
+ marvell,pins = "mpp4";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd5_pins: cp2-rsvd5-pins {
+ marvell,pins = "mpp54";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd7_pins: cp2-rsvd7-pins {
+ marvell,pins = "mpp7";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd8_pins: cp2-rsvd8-pins {
+ marvell,pins = "mpp8";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd9_pins: cp2-rsvd9-pins {
+ marvell,pins = "mpp9";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd10_pins: cp2-rsvd10-pins {
+ marvell,pins = "mpp10";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd11_pins: cp2-rsvd11-pins {
+ marvell,pins = "mpp11";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd27_pins: cp2-rsvd27-pins {
+ marvell,pins = "mpp11";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd31_pins: cp2-rsvd31-pins {
+ marvell,pins = "mpp31";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd32_pins: cp2-rsvd32-pins {
+ marvell,pins = "mpp32";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd55_pins: cp2-rsvd55-pins {
+ marvell,pins = "mpp55";
+ marvell,function = "gpio";
+ };
+
+ cp2_rsvd56_pins: cp2-rsvd56-pins {
+ marvell,pins = "mpp56";
+ marvell,function = "gpio";
+ };
+
+ cp2_xmdio_pins: cp2-xmdio-pins {
+ marvell,pins = "mpp37", "mpp38";
+ marvell,function = "xg";
+ };
+ };
+};
+
+&cp2_thermal_ic {
+ polling-delay = <1000>;
+
+ trips {
+ cp2_active: trip-active {
+ temperature = <40000>;
+ hysteresis = <4000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&cp2_active>;
+ cooling-device = <&fan THERMAL_NO_LIMIT 4>;
+ };
+
+ map1 {
+ trip = <&cp2_crit>;
+ cooling-device = <&fan 4 5>;
+ };
+ };
+};
+
+/* USB-2.0/3.0 Host */
+&cp2_usb3_0 {
+ phys = <&cp2_utmi0>, <&cp2_comphy1 0>;
+ phy-names = "utmi", "comphy";
+ dr_mode = "host";
+ status = "okay";
+};
+
+&cp2_utmi {
+ status = "okay";
+};
+
+/* AP default console */
+&uart0 {
+ pinctrl-0 = <&uart0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index 37b4ca3a87c9..8fd7b2bb7a15 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -8,9 +8,12 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-cudy-wr3000-v1.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-openwrt-one.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-xiaomi-ax3000t.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-acelink-ew-7886cax.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-mini.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-emmc.dtbo
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo
@@ -62,6 +65,8 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327681.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327683.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262144.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262148.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589824.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589825.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-hayato-r1.dtb
@@ -69,6 +74,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-hayato-r5-sku2.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-spherion-r0.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-spherion-r4.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-evb.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-dojo-r1.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r1.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r2.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r3.dtb
@@ -76,5 +82,11 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-demo.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8365-evk.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-genio-1200-evk.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8390-genio-700-evk.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-kontron-3-5-sbc-i1200.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-radxa-nio-12l.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8516-pumpkin.dtb
+
+# Device tree overlays support
+DTC_FLAGS_mt7986a-bananapi-bpi-r3 := -@
+DTC_FLAGS_mt7986a-bananapi-bpi-r3-mini := -@
diff --git a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
index 234e3b23d7a8..c84c47c1352f 100644
--- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
@@ -137,7 +137,7 @@
<MT2712_PIN_74_GBE_TXD0__FUNC_GBE_TXD0>,
<MT2712_PIN_75_GBE_TXC__FUNC_GBE_TXC>,
<MT2712_PIN_76_GBE_TXEN__FUNC_GBE_TXEN>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
};
rx_pins {
pinmux = <MT2712_PIN_78_GBE_RXD3__FUNC_GBE_RXD3>,
@@ -151,7 +151,7 @@
mdio_pins {
pinmux = <MT2712_PIN_85_GBE_MDC__FUNC_GBE_MDC>,
<MT2712_PIN_86_GBE_MDIO__FUNC_GBE_MDIO>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
input-enable;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts b/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts
index 7364c7278276..91de920c2245 100644
--- a/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts
+++ b/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts
@@ -288,25 +288,25 @@
<PINMUX_GPIO161__FUNC_MSDC0_DAT7>,
<PINMUX_GPIO162__FUNC_MSDC0_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
pins-clk {
pinmux = <PINMUX_GPIO163__FUNC_MSDC0_CLK>;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
pins-rst {
pinmux = <PINMUX_GPIO165__FUNC_MSDC0_RSTB>;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
};
pins-ds {
pinmux = <PINMUX_GPIO164__FUNC_MSDC0_DSL>;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
index 224bb289660c..d12eac9b3eeb 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
@@ -149,9 +149,9 @@
#address-cells = <1>;
#size-cells = <0>;
- switch@0 {
+ switch@1f {
compatible = "mediatek,mt7531";
- reg = <0>;
+ reg = <0x1f>;
interrupt-controller;
#interrupt-cells = <1>;
interrupts-extended = <&pio 53 IRQ_TYPE_LEVEL_HIGH>;
@@ -329,8 +329,8 @@
/* eMMC is shared pin with parallel NAND */
emmc_pins_default: emmc-pins-default {
mux {
- function = "emmc", "emmc_rst";
- groups = "emmc";
+ function = "emmc";
+ groups = "emmc", "emmc_rst";
};
/* "NDL0","NDL1","NDL2","NDL3","NDL4","NDL5","NDL6","NDL7",
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
index 41629769bdc8..8c3e2e2578bc 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
@@ -268,8 +268,8 @@
/* eMMC is shared pin with parallel NAND */
emmc_pins_default: emmc-pins-default {
mux {
- function = "emmc", "emmc_rst";
- groups = "emmc";
+ function = "emmc";
+ groups = "emmc", "emmc_rst";
};
/* "NDL0","NDL1","NDL2","NDL3","NDL4","NDL5","NDL6","NDL7",
diff --git a/arch/arm64/boot/dts/mediatek/mt7981b-cudy-wr3000-v1.dts b/arch/arm64/boot/dts/mediatek/mt7981b-cudy-wr3000-v1.dts
new file mode 100644
index 000000000000..54101cc08a25
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7981b-cudy-wr3000-v1.dts
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+#include "mt7981b.dtsi"
+
+/ {
+ compatible = "cudy,wr3000-v1", "mediatek,mt7981b";
+ model = "Cudy WR3000 V1";
+
+ memory@40000000 {
+ reg = <0 0x40000000 0 0x10000000>;
+ device_type = "memory";
+ };
+
+ keys {
+ compatible = "gpio-keys";
+
+ key-wps {
+ label = "WPS";
+ gpios = <&pio 0 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_WPS_BUTTON>;
+ };
+
+ key-reset {
+ label = "RESET";
+ gpios = <&pio 1 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_RESTART>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_WAN;
+ gpios = <&pio 5 GPIO_ACTIVE_LOW>;
+ };
+
+ led-1 {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_WLAN_2GHZ;
+ gpios = <&pio 6 GPIO_ACTIVE_LOW>;
+ };
+
+ led-2 {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_WLAN_5GHZ;
+ gpios = <&pio 7 GPIO_ACTIVE_LOW>;
+ };
+
+ led-3 {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_LAN;
+ gpios = <&pio 9 GPIO_ACTIVE_LOW>;
+ };
+
+ led-4 {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_STATUS;
+ gpios = <&pio 10 GPIO_ACTIVE_LOW>;
+ };
+
+ led-5 {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_WAN_ONLINE;
+ gpios = <&pio 11 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7981b-openwrt-one.dts b/arch/arm64/boot/dts/mediatek/mt7981b-openwrt-one.dts
new file mode 100644
index 000000000000..4f6cbb491287
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7981b-openwrt-one.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+
+/dts-v1/;
+
+#include "mt7981b.dtsi"
+
+/ {
+ compatible = "openwrt,one", "mediatek,mt7981b";
+ model = "OpenWrt One";
+
+ memory@40000000 {
+ reg = <0 0x40000000 0 0x40000000>;
+ device_type = "memory";
+ };
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
index 4feff3d1c5f4..64aeeb24efac 100644
--- a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi
@@ -2,6 +2,7 @@
#include <dt-bindings/clock/mediatek,mt7981-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/mt7986-resets.h>
/ {
compatible = "mediatek,mt7981b";
@@ -62,12 +63,19 @@
#clock-cells = <1>;
};
- clock-controller@1001b000 {
+ topckgen: clock-controller@1001b000 {
compatible = "mediatek,mt7981-topckgen", "syscon";
reg = <0 0x1001b000 0 0x1000>;
#clock-cells = <1>;
};
+ watchdog: watchdog@1001c000 {
+ compatible = "mediatek,mt7986-wdt";
+ reg = <0 0x1001c000 0 0x1000>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ #reset-cells = <1>;
+ };
+
clock-controller@1001e000 {
compatible = "mediatek,mt7981-apmixedsys";
reg = <0 0x1001e000 0 0x1000>;
@@ -78,20 +86,80 @@
compatible = "mediatek,mt7981-pwm";
reg = <0 0x10048000 0 0x1000>;
clocks = <&infracfg CLK_INFRA_PWM_STA>,
- <&infracfg CLK_INFRA_PWM_HCK>,
- <&infracfg CLK_INFRA_PWM1_CK>,
- <&infracfg CLK_INFRA_PWM2_CK>,
- <&infracfg CLK_INFRA_PWM3_CK>;
+ <&infracfg CLK_INFRA_PWM_HCK>,
+ <&infracfg CLK_INFRA_PWM1_CK>,
+ <&infracfg CLK_INFRA_PWM2_CK>,
+ <&infracfg CLK_INFRA_PWM3_CK>;
clock-names = "top", "main", "pwm1", "pwm2", "pwm3";
#pwm-cells = <2>;
};
+ i2c@11007000 {
+ compatible = "mediatek,mt7981-i2c";
+ reg = <0 0x11007000 0 0x1000>,
+ <0 0x10217080 0 0x80>;
+ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_I2C0_CK>,
+ <&infracfg CLK_INFRA_AP_DMA_CK>,
+ <&infracfg CLK_INFRA_I2C_MCK_CK>,
+ <&infracfg CLK_INFRA_I2C_PCK_CK>;
+ clock-names = "main", "dma", "arb", "pmic";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ pio: pinctrl@11d00000 {
+ compatible = "mediatek,mt7981-pinctrl";
+ reg = <0 0x11d00000 0 0x1000>,
+ <0 0x11c00000 0 0x1000>,
+ <0 0x11c10000 0 0x1000>,
+ <0 0x11d20000 0 0x1000>,
+ <0 0x11e00000 0 0x1000>,
+ <0 0x11e20000 0 0x1000>,
+ <0 0x11f00000 0 0x1000>,
+ <0 0x11f10000 0 0x1000>,
+ <0 0x1000b000 0 0x1000>;
+ reg-names = "gpio", "iocfg_rt", "iocfg_rm", "iocfg_rb", "iocfg_lb",
+ "iocfg_bl", "iocfg_tm", "iocfg_tl", "eint";
+ interrupt-controller;
+ interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ gpio-ranges = <&pio 0 0 56>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ efuse@11f20000 {
+ compatible = "mediatek,mt7981-efuse", "mediatek,efuse";
+ reg = <0 0x11f20000 0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
clock-controller@15000000 {
compatible = "mediatek,mt7981-ethsys", "syscon";
reg = <0 0x15000000 0 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
+
+ wifi@18000000 {
+ compatible = "mediatek,mt7981-wmac";
+ reg = <0 0x18000000 0 0x1000000>,
+ <0 0x10003000 0 0x1000>,
+ <0 0x11d10000 0 0x1000>;
+ interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&topckgen CLK_TOP_NETSYS_MCU_SEL>,
+ <&topckgen CLK_TOP_AP2CNN_HOST_SEL>;
+ clock-names = "mcu", "ap2conn";
+ resets = <&watchdog MT7986_TOPRGU_CONSYS_SW_RST>;
+ reset-names = "consys";
+ };
};
timer {
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso
index 779dc6782bb1..047a8388811e 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso
+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso
@@ -9,21 +9,17 @@
/ {
compatible = "bananapi,bpi-r3", "mediatek,mt7986a";
-
- fragment@0 {
- target-path = "/soc/mmc@11230000";
- __overlay__ {
- bus-width = <8>;
- max-frequency = <200000000>;
- cap-mmc-highspeed;
- mmc-hs200-1_8v;
- mmc-hs400-1_8v;
- hs400-ds-delay = <0x14014>;
- non-removable;
- no-sd;
- no-sdio;
- status = "okay";
- };
- };
};
+&{/soc/mmc@11230000} {
+ bus-width = <8>;
+ max-frequency = <200000000>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ hs400-ds-delay = <0x14014>;
+ non-removable;
+ no-sd;
+ no-sdio;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-mini.dts b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-mini.dts
new file mode 100644
index 000000000000..e2a2fea7adf0
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-mini.dts
@@ -0,0 +1,493 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Authors: Frank Wunderlich <[email protected]>
+ * Eric Woudstra <[email protected]>
+ * Tianling Shen <[email protected]>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#include "mt7986a.dtsi"
+
+/ {
+ model = "Bananapi BPI-R3 Mini";
+ chassis-type = "embedded";
+ compatible = "bananapi,bpi-r3mini", "mediatek,mt7986a";
+
+ aliases {
+ serial0 = &uart0;
+ ethernet0 = &gmac0;
+ ethernet1 = &gmac1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ dcin: regulator-12v {
+ compatible = "regulator-fixed";
+ regulator-name = "12vd";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ fan: pwm-fan {
+ compatible = "pwm-fan";
+ #cooling-cells = <2>;
+ /*
+ * The signal is inverted on this board and the PWM driver
+ * does not support polarity inversion.
+ */
+ /* cooling level (0, 1, 2) */
+ cooling-levels = <255 96 0>;
+ pwms = <&pwm 0 10000>;
+ };
+
+ reg_1p8v: regulator-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "1.8vd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ vin-supply = <&dcin>;
+ };
+
+ reg_3p3v: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3vd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ vin-supply = <&dcin>;
+ };
+
+ usb_vbus: regulator-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpios = <&pio 20 GPIO_ACTIVE_LOW>;
+ regulator-boot-on;
+ };
+
+ en8811_a: regulator-phy1 {
+ compatible = "regulator-fixed";
+ regulator-name = "phy1";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pio 16 GPIO_ACTIVE_LOW>;
+ regulator-always-on;
+ };
+
+ en8811_b: regulator-phy2 {
+ compatible = "regulator-fixed";
+ regulator-name = "phy2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pio 17 GPIO_ACTIVE_LOW>;
+ regulator-always-on;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ green_led: led-0 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_POWER;
+ gpios = <&pio 19 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ reset-key {
+ label = "reset";
+ linux,code = <KEY_RESTART>;
+ gpios = <&pio 7 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+};
+
+&cpu_thermal {
+ cooling-maps {
+ map0 {
+ /* active: set fan to cooling level 2 */
+ cooling-device = <&fan 2 2>;
+ trip = <&cpu_trip_active_high>;
+ };
+
+ map1 {
+ /* active: set fan to cooling level 1 */
+ cooling-device = <&fan 1 1>;
+ trip = <&cpu_trip_active_med>;
+ };
+
+ map2 {
+ /* active: set fan to cooling level 0 */
+ cooling-device = <&fan 0 0>;
+ trip = <&cpu_trip_active_low>;
+ };
+ };
+};
+
+&crypto {
+ status = "okay";
+};
+
+&eth {
+ status = "okay";
+
+ gmac0: mac@0 {
+ compatible = "mediatek,eth-mac";
+ reg = <0>;
+ phy-mode = "2500base-x";
+ phy-handle = <&phy0>;
+ };
+
+ gmac1: mac@1 {
+ compatible = "mediatek,eth-mac";
+ reg = <1>;
+ phy-mode = "2500base-x";
+ phy-handle = <&phy1>;
+ };
+
+ mdio: mdio-bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+};
+
+&mmc0 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_pins_default>;
+ pinctrl-1 = <&mmc0_pins_uhs>;
+ vmmc-supply = <&reg_3p3v>;
+ vqmmc-supply = <&reg_1p8v>;
+};
+
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_pins>;
+ status = "okay";
+
+ /* MAC Address EEPROM */
+ eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+
+ address-width = <8>;
+ pagesize = <8>;
+ size = <256>;
+ };
+};
+
+&mdio {
+ phy0: ethernet-phy@14 {
+ reg = <14>;
+ interrupts-extended = <&pio 48 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&pio 49 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <20000>;
+ phy-mode = "2500base-x";
+ full-duplex;
+ pause;
+ airoha,pnswap-rx;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 { /* en8811_a_gpio5 */
+ reg = <0>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_LAN;
+ function-enumerator = <1>;
+ default-state = "keep";
+ };
+ led@1 { /* en8811_a_gpio4 */
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ function-enumerator = <2>;
+ default-state = "keep";
+ };
+ };
+ };
+
+ phy1: ethernet-phy@15 {
+ reg = <15>;
+ interrupts-extended = <&pio 46 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&pio 47 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <20000>;
+ phy-mode = "2500base-x";
+ full-duplex;
+ pause;
+ airoha,pnswap-rx;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 { /* en8811_b_gpio5 */
+ reg = <0>;
+ color = <LED_COLOR_ID_YELLOW>;
+ function = LED_FUNCTION_WAN;
+ function-enumerator = <1>;
+ default-state = "keep";
+ };
+ led@1 { /* en8811_b_gpio4 */
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WAN;
+ function-enumerator = <2>;
+ default-state = "keep";
+ };
+ };
+ };
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_pins>;
+ status = "okay";
+};
+
+&pcie_phy {
+ status = "okay";
+};
+
+&pio {
+ i2c_pins: i2c-pins {
+ mux {
+ function = "i2c";
+ groups = "i2c";
+ };
+ };
+
+ mmc0_pins_default: mmc0-pins {
+ mux {
+ function = "emmc";
+ groups = "emmc_51";
+ };
+ conf-cmd-dat {
+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2",
+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5",
+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD";
+ input-enable;
+ drive-strength = <4>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>; /* pull-up 10K */
+ };
+ conf-clk {
+ pins = "EMMC_CK";
+ drive-strength = <6>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>; /* pull-down 50K */
+ };
+ conf-ds {
+ pins = "EMMC_DSL";
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>; /* pull-down 50K */
+ };
+ conf-rst {
+ pins = "EMMC_RSTB";
+ drive-strength = <4>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>; /* pull-up 10K */
+ };
+ };
+
+ mmc0_pins_uhs: mmc0-uhs-pins {
+ mux {
+ function = "emmc";
+ groups = "emmc_51";
+ };
+ conf-cmd-dat {
+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2",
+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5",
+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD";
+ input-enable;
+ drive-strength = <4>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>; /* pull-up 10K */
+ };
+ conf-clk {
+ pins = "EMMC_CK";
+ drive-strength = <6>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>; /* pull-down 50K */
+ };
+ conf-ds {
+ pins = "EMMC_DSL";
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>; /* pull-down 50K */
+ };
+ conf-rst {
+ pins = "EMMC_RSTB";
+ drive-strength = <4>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>; /* pull-up 10K */
+ };
+ };
+
+ pcie_pins: pcie-pins {
+ mux {
+ function = "pcie";
+ groups = "pcie_clk", "pcie_wake", "pcie_pereset";
+ };
+ };
+
+ pwm_pins: pwm-pins {
+ mux {
+ function = "pwm";
+ groups = "pwm0";
+ };
+ };
+
+ spi_flash_pins: spi-flash-pins {
+ mux {
+ function = "spi";
+ groups = "spi0", "spi0_wp_hold";
+ };
+ };
+
+ usb_ngff_pins: usb-ngff-pins {
+ ngff-gnss-off-conf {
+ pins = "GPIO_6";
+ drive-strength = <8>;
+ mediatek,pull-up-adv = <1>;
+ };
+ ngff-pe-rst-conf {
+ pins = "GPIO_7";
+ drive-strength = <8>;
+ mediatek,pull-up-adv = <1>;
+ };
+ ngff-wwan-off-conf {
+ pins = "GPIO_8";
+ drive-strength = <8>;
+ mediatek,pull-up-adv = <1>;
+ };
+ ngff-pwr-off-conf {
+ pins = "GPIO_9";
+ drive-strength = <8>;
+ mediatek,pull-up-adv = <1>;
+ };
+ ngff-rst-conf {
+ pins = "GPIO_10";
+ drive-strength = <8>;
+ mediatek,pull-up-adv = <1>;
+ };
+ ngff-coex-conf {
+ pins = "SPI1_CS";
+ drive-strength = <8>;
+ mediatek,pull-up-adv = <1>;
+ };
+ };
+
+ wf_2g_5g_pins: wf-2g-5g-pins {
+ mux {
+ function = "wifi";
+ groups = "wf_2g", "wf_5g";
+ };
+ conf {
+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4",
+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6",
+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10",
+ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1",
+ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0",
+ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8",
+ "WF1_TOP_CLK", "WF1_TOP_DATA";
+ drive-strength = <4>;
+ };
+ };
+
+ wf_dbdc_pins: wf-dbdc-pins {
+ mux {
+ function = "wifi";
+ groups = "wf_dbdc";
+ };
+ conf {
+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4",
+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6",
+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10",
+ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1",
+ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0",
+ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8",
+ "WF1_TOP_CLK", "WF1_TOP_DATA";
+ drive-strength = <4>;
+ };
+ };
+
+ wf_led_pins: wf-led-pins {
+ mux {
+ function = "led";
+ groups = "wifi_led";
+ };
+ };
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_pins>;
+ status = "okay";
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_flash_pins>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "spi-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0>;
+
+ spi-max-frequency = <20000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ };
+};
+
+&ssusb {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_ngff_pins>;
+ vusb33-supply = <&reg_3p3v>;
+ vbus-supply = <&usb_vbus>;
+ status = "okay";
+};
+
+&trng {
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&usb_phy {
+ status = "okay";
+};
+
+&watchdog {
+ status = "okay";
+};
+
+&wifi {
+ status = "okay";
+ pinctrl-names = "default", "dbdc";
+ pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>;
+ pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>;
+
+ led {
+ led-active-low;
+ };
+};
+
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso
index 7b97c5c91bd0..24398f8a7da4 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso
+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso
@@ -9,46 +9,44 @@
/ {
compatible = "bananapi,bpi-r3", "mediatek,mt7986a";
+};
+
+&{/soc/spi@1100a000} {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ spi_nand: flash@0 {
+ compatible = "spi-nand";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+ spi-tx-buswidth = <4>;
+ spi-rx-buswidth = <4>;
- fragment@0 {
- target-path = "/soc/spi@1100a000";
- __overlay__ {
+ partitions {
+ compatible = "fixed-partitions";
#address-cells = <1>;
- #size-cells = <0>;
- spi_nand: flash@0 {
- compatible = "spi-nand";
- reg = <0>;
- spi-max-frequency = <10000000>;
- spi-tx-buswidth = <4>;
- spi-rx-buswidth = <4>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "bl2";
- reg = <0x0 0x100000>;
- read-only;
- };
-
- partition@100000 {
- label = "reserved";
- reg = <0x100000 0x280000>;
- };
-
- partition@380000 {
- label = "fip";
- reg = <0x380000 0x200000>;
- read-only;
- };
-
- partition@580000 {
- label = "ubi";
- reg = <0x580000 0x7a80000>;
- };
- };
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "bl2";
+ reg = <0x0 0x100000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "reserved";
+ reg = <0x100000 0x280000>;
+ };
+
+ partition@380000 {
+ label = "fip";
+ reg = <0x380000 0x200000>;
+ read-only;
+ };
+
+ partition@580000 {
+ label = "ubi";
+ reg = <0x580000 0x7a80000>;
};
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso
index e48881be4ed6..6a0d529b54ac 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso
+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso
@@ -9,54 +9,52 @@
/ {
compatible = "bananapi,bpi-r3", "mediatek,mt7986a";
+};
+
+&{/soc/spi@1100a000} {
+ #address-cells = <1>;
+ #size-cells = <0>;
- fragment@0 {
- target-path = "/soc/spi@1100a000";
- __overlay__ {
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+
+ partitions {
+ compatible = "fixed-partitions";
#address-cells = <1>;
- #size-cells = <0>;
- flash@0 {
- compatible = "jedec,spi-nor";
- reg = <0>;
- spi-max-frequency = <10000000>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "bl2";
- reg = <0x0 0x40000>;
- read-only;
- };
-
- partition@40000 {
- label = "u-boot-env";
- reg = <0x40000 0x40000>;
- };
-
- partition@80000 {
- label = "reserved2";
- reg = <0x80000 0x80000>;
- };
-
- partition@100000 {
- label = "fip";
- reg = <0x100000 0x80000>;
- read-only;
- };
-
- partition@180000 {
- label = "recovery";
- reg = <0x180000 0xa80000>;
- };
-
- partition@c00000 {
- label = "fit";
- reg = <0xc00000 0x1400000>;
- };
- };
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "bl2";
+ reg = <0x0 0x40000>;
+ read-only;
+ };
+
+ partition@40000 {
+ label = "u-boot-env";
+ reg = <0x40000 0x40000>;
+ };
+
+ partition@80000 {
+ label = "reserved2";
+ reg = <0x80000 0x80000>;
+ };
+
+ partition@100000 {
+ label = "fip";
+ reg = <0x100000 0x80000>;
+ read-only;
+ };
+
+ partition@180000 {
+ label = "recovery";
+ reg = <0x180000 0xa80000>;
+ };
+
+ partition@c00000 {
+ label = "fit";
+ reg = <0xc00000 0x1400000>;
};
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso
index f623bce075ce..d9e01967acc4 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso
+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso
@@ -9,15 +9,11 @@
/ {
compatible = "bananapi,bpi-r3", "mediatek,mt7986a";
-
- fragment@0 {
- target-path = "/soc/mmc@11230000";
- __overlay__ {
- bus-width = <4>;
- max-frequency = <52000000>;
- cap-sd-highspeed;
- status = "okay";
- };
- };
};
+&{/soc/mmc@11230000} {
+ bus-width = <4>;
+ max-frequency = <52000000>;
+ cap-sd-highspeed;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
index bba97de4fb44..aa728331e876 100644
--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
+#include <dt-bindings/clock/mediatek,mt7988-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy.h>
/ {
compatible = "mediatek,mt7988a";
@@ -78,7 +80,7 @@
#interrupt-cells = <3>;
};
- clock-controller@10001000 {
+ infracfg: clock-controller@10001000 {
compatible = "mediatek,mt7988-infracfg", "syscon";
reg = <0 0x10001000 0 0x1000>;
#clock-cells = <1>;
@@ -103,6 +105,92 @@
#clock-cells = <1>;
};
+ pwm@10048000 {
+ compatible = "mediatek,mt7988-pwm";
+ reg = <0 0x10048000 0 0x1000>;
+ clocks = <&infracfg CLK_INFRA_66M_PWM_BCK>,
+ <&infracfg CLK_INFRA_66M_PWM_HCK>,
+ <&infracfg CLK_INFRA_66M_PWM_CK1>,
+ <&infracfg CLK_INFRA_66M_PWM_CK2>,
+ <&infracfg CLK_INFRA_66M_PWM_CK3>,
+ <&infracfg CLK_INFRA_66M_PWM_CK4>,
+ <&infracfg CLK_INFRA_66M_PWM_CK5>,
+ <&infracfg CLK_INFRA_66M_PWM_CK6>,
+ <&infracfg CLK_INFRA_66M_PWM_CK7>,
+ <&infracfg CLK_INFRA_66M_PWM_CK8>;
+ clock-names = "top", "main", "pwm1", "pwm2", "pwm3",
+ "pwm4", "pwm5", "pwm6", "pwm7", "pwm8";
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
+ i2c@11003000 {
+ compatible = "mediatek,mt7981-i2c";
+ reg = <0 0x11003000 0 0x1000>,
+ <0 0x10217080 0 0x80>;
+ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_I2C_BCK>,
+ <&infracfg CLK_INFRA_66M_AP_DMA_BCK>;
+ clock-names = "main", "dma";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c@11004000 {
+ compatible = "mediatek,mt7981-i2c";
+ reg = <0 0x11004000 0 0x1000>,
+ <0 0x10217100 0 0x80>;
+ interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_I2C_BCK>,
+ <&infracfg CLK_INFRA_66M_AP_DMA_BCK>;
+ clock-names = "main", "dma";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c@11005000 {
+ compatible = "mediatek,mt7981-i2c";
+ reg = <0 0x11005000 0 0x1000>,
+ <0 0x10217180 0 0x80>;
+ interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_I2C_BCK>,
+ <&infracfg CLK_INFRA_66M_AP_DMA_BCK>;
+ clock-names = "main", "dma";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ usb@11190000 {
+ compatible = "mediatek,mt7988-xhci", "mediatek,mtk-xhci";
+ reg = <0 0x11190000 0 0x2e00>,
+ <0 0x11193e00 0 0x0100>;
+ reg-names = "mac", "ippc";
+ interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_USB_SYS>,
+ <&infracfg CLK_INFRA_USB_REF>,
+ <&infracfg CLK_INFRA_66M_USB_HCK>,
+ <&infracfg CLK_INFRA_133M_USB_HCK>,
+ <&infracfg CLK_INFRA_USB_XHCI>;
+ clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck", "xhci_ck";
+ };
+
+ usb@11200000 {
+ compatible = "mediatek,mt7988-xhci", "mediatek,mtk-xhci";
+ reg = <0 0x11200000 0 0x2e00>,
+ <0 0x11203e00 0 0x0100>;
+ reg-names = "mac", "ippc";
+ interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_USB_SYS_CK_P1>,
+ <&infracfg CLK_INFRA_USB_CK_P1>,
+ <&infracfg CLK_INFRA_66M_USB_HCK_CK_P1>,
+ <&infracfg CLK_INFRA_133M_USB_HCK_CK_P1>,
+ <&infracfg CLK_INFRA_USB_XHCI_CK_P1>;
+ clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck", "xhci_ck";
+ };
+
clock-controller@11f40000 {
compatible = "mediatek,mt7988-xfi-pll";
reg = <0 0x11f40000 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 90cbbc18a483..8d1cbc92bce3 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
@@ -27,6 +27,15 @@
hid-descr-addr = <0x0020>;
interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>;
};
+
+ /* Lenovo Ideapad C330 uses G2Touch touchscreen as a 2nd source touchscreen */
+ touchscreen@40 {
+ compatible = "hid-over-i2c";
+ reg = <0x40>;
+ hid-descr-addr = <0x0001>;
+ interrupt-parent = <&pio>;
+ interrupts = <88 IRQ_TYPE_LEVEL_LOW>;
+ };
};
&i2c4 {
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
index 6d962d437e02..b4d85147b77b 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
@@ -1134,12 +1134,6 @@
rtc: mt6397rtc {
compatible = "mediatek,mt6397-rtc";
};
-
- syscfg_pctl_pmic: syscon@c000 {
- compatible = "mediatek,mt6397-pctl-pmic-syscfg",
- "syscon";
- reg = <0 0x0000c000 0 0x0108>;
- };
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
index 3fab21f59d18..bb4671c18e3b 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
@@ -213,14 +213,14 @@
<MT8173_PIN_76_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
<MT8173_PIN_78_MSDC1_CMD__FUNC_MSDC1_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_4mA>;
+ drive-strength = <4>;
bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
};
pins_clk {
pinmux = <MT8173_PIN_77_MSDC1_CLK__FUNC_MSDC1_CLK>;
bias-pull-down;
- drive-strength = <MTK_DRIVE_4mA>;
+ drive-strength = <4>;
};
pins_insert {
@@ -241,13 +241,13 @@
<MT8173_PIN_64_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
<MT8173_PIN_66_MSDC0_CMD__FUNC_MSDC0_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_2mA>;
+ drive-strength = <2>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
pins_clk {
pinmux = <MT8173_PIN_65_MSDC0_CLK__FUNC_MSDC0_CLK>;
- drive-strength = <MTK_DRIVE_2mA>;
+ drive-strength = <2>;
bias-pull-down = <MTK_PUPD_SET_R1R0_01>;
};
@@ -265,13 +265,13 @@
<MT8173_PIN_76_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
<MT8173_PIN_78_MSDC1_CMD__FUNC_MSDC1_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_4mA>;
+ drive-strength = <4>;
bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
};
pins_clk {
pinmux = <MT8173_PIN_77_MSDC1_CLK__FUNC_MSDC1_CLK>;
- drive-strength = <MTK_DRIVE_4mA>;
+ drive-strength = <4>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
index 681deddffc2a..f04baea5d6cb 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
@@ -160,7 +160,6 @@
pinmux = <PINMUX_GPIO82__FUNC_SDA0>,
<PINMUX_GPIO83__FUNC_SCL0>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -169,7 +168,6 @@
pinmux = <PINMUX_GPIO81__FUNC_SDA1>,
<PINMUX_GPIO84__FUNC_SCL1>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -178,7 +176,6 @@
pinmux = <PINMUX_GPIO103__FUNC_SCL2>,
<PINMUX_GPIO104__FUNC_SDA2>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -187,7 +184,6 @@
pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
<PINMUX_GPIO51__FUNC_SDA3>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -196,7 +192,6 @@
pinmux = <PINMUX_GPIO105__FUNC_SCL4>,
<PINMUX_GPIO106__FUNC_SDA4>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -205,7 +200,6 @@
pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
<PINMUX_GPIO49__FUNC_SDA5>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-audio-da7219.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-audio-da7219.dtsi
index 8b57706ac814..586eee79c73c 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-audio-da7219.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-audio-da7219.dtsi
@@ -27,7 +27,7 @@
dlg,btn-cfg = <50>;
dlg,mic-det-thr = <500>;
dlg,jack-ins-deb = <20>;
- dlg,jack-det-rate = "32ms_64ms";
+ dlg,jack-det-rate = "32_64";
dlg,jack-rem-deb = <1>;
dlg,a-d-btn-thr = <0xa>;
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 072133fb0f01..f34964afe39b 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts
@@ -9,6 +9,7 @@
/ {
model = "Google cozmo board";
+ chassis-type = "laptop";
compatible = "google,cozmo", "mediatek,mt8183";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku1.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku1.dts
index b595622e7bee..72852b760038 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku1.dts
@@ -9,6 +9,7 @@
/ {
model = "Google fennel sku1 board";
+ chassis-type = "convertible";
compatible = "google,fennel-sku1", "google,fennel", "mediatek,mt8183";
pwmleds {
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku6.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku6.dts
index 5a1c39318a6c..757d0afd14fb 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku6.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku6.dts
@@ -9,6 +9,7 @@
/ {
model = "Google fennel sku6 board";
+ chassis-type = "convertible";
compatible = "google,fennel-sku6", "google,fennel", "mediatek,mt8183";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku7.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku7.dts
index 3ea4fdb40118..6641b087e7c5 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku7.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku7.dts
@@ -9,6 +9,7 @@
/ {
model = "Google fennel sku7 board";
+ chassis-type = "convertible";
compatible = "google,fennel-sku7", "google,fennel", "mediatek,mt8183";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14-sku2.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14-sku2.dts
index 3fc5a6181d7e..877256eab262 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14-sku2.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14-sku2.dts
@@ -9,6 +9,7 @@
/ {
model = "Google fennel14 sku2 board";
+ chassis-type = "laptop";
compatible = "google,fennel-sku2", "google,fennel", "mediatek,mt8183";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14.dts
index 23ad0b91e977..b981dd31a430 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14.dts
@@ -9,6 +9,7 @@
/ {
model = "Google fennel14 sku0 board";
+ chassis-type = "laptop";
compatible = "google,fennel-sku0", "google,fennel", "mediatek,mt8183";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kappa.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kappa.dts
index e5bd9191e426..f3ac9c074226 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kappa.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kappa.dts
@@ -9,6 +9,7 @@
/ {
model = "Google kappa board";
+ chassis-type = "laptop";
compatible = "google,kappa", "mediatek,mt8183";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kenzo.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kenzo.dts
index 8fa89db03e63..e8241587949b 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kenzo.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kenzo.dts
@@ -9,5 +9,6 @@
/ {
model = "Google kenzo sku17 board";
+ chassis-type = "laptop";
compatible = "google,juniper-sku17", "google,juniper", "mediatek,mt8183";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-makomo-sku0.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-makomo-sku0.dts
index 4eb2a0d571af..ddb993521bbf 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-makomo-sku0.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-makomo-sku0.dts
@@ -19,6 +19,6 @@
&mmc1_pins_uhs {
pins-clk {
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-makomo-sku1.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-makomo-sku1.dts
index 6a733361e8ae..10c4f920a7d8 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-makomo-sku1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-makomo-sku1.dts
@@ -19,6 +19,6 @@
&mmc1_pins_uhs {
pins-clk {
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-pico6.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-pico6.dts
index 6a7ae616512d..cce326aec1aa 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-pico6.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-pico6.dts
@@ -17,7 +17,7 @@
pinctrl-names = "default";
pinctrl-0 = <&bt_pins_wakeup>;
- wobt {
+ event-wobt {
label = "Wake on BT";
gpios = <&pio 42 GPIO_ACTIVE_HIGH>;
linux,code = <KEY_WAKEUP>;
@@ -47,10 +47,8 @@
};
};
-&wifi_wakeup {
- wowlan {
- gpios = <&pio 113 GPIO_ACTIVE_LOW>;
- };
+&wifi_wakeup_event {
+ gpios = <&pio 113 GPIO_ACTIVE_LOW>;
};
&wifi_pwrseq {
@@ -68,16 +66,16 @@
&mmc1_pins_default {
pins-cmd-dat {
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
};
pins-clk {
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
};
};
&mmc1_pins_uhs {
pins-clk {
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku0.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku0.dts
index 89208b843b27..928b205a616a 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku0.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku0.dts
@@ -9,6 +9,7 @@
/ {
model = "Google willow board sku0";
+ chassis-type = "laptop";
compatible = "google,willow-sku0", "google,willow", "mediatek,mt8183";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku1.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku1.dts
index c7b20441d053..71307a8052d6 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku1.dts
@@ -9,5 +9,6 @@
/ {
model = "Google willow board sku1";
+ chassis-type = "laptop";
compatible = "google,willow-sku1", "google,willow", "mediatek,mt8183";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
index 7592e3b86037..fa4ab4d2899f 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
@@ -155,21 +155,24 @@
vdd18-supply = <&pp1800_mipibrdg>;
vdd33-supply = <&vddio_mipibrdg>;
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
- anx7625_in: endpoint {
- remote-endpoint = <&dsi_out>;
+ port@0 {
+ reg = <0>;
+
+ anx7625_in: endpoint {
+ remote-endpoint = <&dsi_out>;
+ };
};
- };
- port@1 {
- reg = <1>;
+ port@1 {
+ reg = <1>;
- anx7625_out: endpoint {
- remote-endpoint = <&panel_in>;
+ anx7625_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dts
index 7739358008ee..5a416143b4a0 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dts
@@ -12,6 +12,7 @@
/ {
model = "MediaTek kodama sku32 board";
+ chassis-type = "tablet";
compatible = "google,kodama-sku32", "google,kodama", "mediatek,mt8183";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
index 100191c6453b..6345e969efae 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
@@ -152,7 +152,7 @@
pinctrl-names = "default";
pinctrl-0 = <&wifi_pins_wakeup>;
- button-wowlan {
+ wifi_wakeup_event: event-wowlan {
label = "Wake on WiFi";
gpios = <&pio 113 GPIO_ACTIVE_HIGH>;
linux,code = <KEY_WAKEUP>;
@@ -488,7 +488,7 @@
<PINMUX_GPIO172__FUNC_TDM_DATA1_2ND>,
<PINMUX_GPIO173__FUNC_TDM_DATA2_2ND>,
<PINMUX_GPIO10__FUNC_TDM_DATA3>; /*8ch-i2s to it6505*/
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
};
};
@@ -502,7 +502,7 @@
<PINMUX_GPIO10__FUNC_GPIO10>;
input-enable;
bias-pull-down;
- drive-strength = <MTK_DRIVE_2mA>;
+ drive-strength = <2>;
};
};
@@ -533,7 +533,6 @@
pinmux = <PINMUX_GPIO82__FUNC_SDA0>,
<PINMUX_GPIO83__FUNC_SCL0>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -542,7 +541,6 @@
pinmux = <PINMUX_GPIO81__FUNC_SDA1>,
<PINMUX_GPIO84__FUNC_SCL1>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -551,7 +549,6 @@
pinmux = <PINMUX_GPIO103__FUNC_SCL2>,
<PINMUX_GPIO104__FUNC_SDA2>;
bias-disable;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -560,7 +557,6 @@
pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
<PINMUX_GPIO51__FUNC_SDA3>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -569,7 +565,6 @@
pinmux = <PINMUX_GPIO105__FUNC_SCL4>,
<PINMUX_GPIO106__FUNC_SDA4>;
bias-disable;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -578,7 +573,6 @@
pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
<PINMUX_GPIO49__FUNC_SDA5>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -679,14 +673,14 @@
<PINMUX_GPIO34__FUNC_MSDC1_DAT1>,
<PINMUX_GPIO33__FUNC_MSDC1_DAT2>,
<PINMUX_GPIO30__FUNC_MSDC1_DAT3>;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
input-enable;
mediatek,pull-up-adv = <10>;
};
pins-clk {
pinmux = <PINMUX_GPIO29__FUNC_MSDC1_CLK>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
mediatek,pull-down-adv = <10>;
input-enable;
};
@@ -803,7 +797,6 @@
};
pins-rts {
pinmux = <PINMUX_GPIO47__FUNC_URTS1>;
- output-enable;
};
pins-cts {
pinmux = <PINMUX_GPIO46__FUNC_UCTS1>;
@@ -822,7 +815,6 @@
};
pins-rts {
pinmux = <PINMUX_GPIO47__FUNC_URTS1>;
- output-enable;
};
pins-cts {
pinmux = <PINMUX_GPIO46__FUNC_UCTS1>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts b/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts
index 333c516af490..1aa668c3ccf9 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts
@@ -197,7 +197,6 @@
pinmux = <PINMUX_GPIO82__FUNC_SDA0>,
<PINMUX_GPIO83__FUNC_SCL0>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -206,7 +205,6 @@
pinmux = <PINMUX_GPIO81__FUNC_SDA1>,
<PINMUX_GPIO84__FUNC_SCL1>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -215,7 +213,6 @@
pinmux = <PINMUX_GPIO103__FUNC_SCL2>,
<PINMUX_GPIO104__FUNC_SDA2>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -224,7 +221,6 @@
pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
<PINMUX_GPIO51__FUNC_SDA3>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -233,7 +229,6 @@
pinmux = <PINMUX_GPIO105__FUNC_SCL4>,
<PINMUX_GPIO106__FUNC_SDA4>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -242,7 +237,6 @@
pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
<PINMUX_GPIO49__FUNC_SDA5>;
mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <00>;
};
};
@@ -356,14 +350,14 @@
<PINMUX_GPIO34__FUNC_MSDC1_DAT1>,
<PINMUX_GPIO33__FUNC_MSDC1_DAT2>,
<PINMUX_GPIO30__FUNC_MSDC1_DAT3>;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
input-enable;
mediatek,pull-up-adv = <10>;
};
pins_clk {
pinmux = <PINMUX_GPIO29__FUNC_MSDC1_CLK>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
mediatek,pull-down-adv = <10>;
input-enable;
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 774ae5d9143f..fbf145639b8c 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -1183,7 +1183,7 @@
status = "disabled";
};
- thermal: thermal@1100b000 {
+ thermal: thermal-sensor@1100b000 {
#thermal-sensor-cells = <1>;
compatible = "mediatek,mt8183-thermal";
reg = <0 0x1100b000 0 0xc00>;
@@ -2090,61 +2090,129 @@
};
};
- /* The tzts1 ~ tzts6 don't need to polling */
- /* The tzts1 ~ tzts6 don't need to thermal throttle */
-
- tzts1: tzts1 {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ tzts1: soc-thermal {
+ polling-delay = <1000>;
+ polling-delay-passive = <250>;
thermal-sensors = <&thermal 1>;
sustainable-power = <5000>;
- trips {};
- cooling-maps {};
+ trips {
+ soc_alert: trip-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ soc_crit: trip-crit {
+ temperature = <100000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
};
- tzts2: tzts2 {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ tzts2: gpu-thermal {
+ polling-delay = <1000>;
+ polling-delay-passive = <250>;
thermal-sensors = <&thermal 2>;
sustainable-power = <5000>;
- trips {};
- cooling-maps {};
+
+ trips {
+ gpu_alert: trip-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ gpu_crit: trip-crit {
+ temperature = <100000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
};
- tzts3: tzts3 {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ tzts3: md1-thermal {
+ polling-delay = <1000>;
+ polling-delay-passive = <250>;
thermal-sensors = <&thermal 3>;
sustainable-power = <5000>;
- trips {};
- cooling-maps {};
+
+ trips {
+ md1_alert: trip-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ md1_crit: trip-crit {
+ temperature = <100000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
};
- tzts4: tzts4 {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ tzts4: cpu-little-thermal {
+ polling-delay = <1000>;
+ polling-delay-passive = <250>;
thermal-sensors = <&thermal 4>;
sustainable-power = <5000>;
- trips {};
- cooling-maps {};
+
+ trips {
+ cpul_alert: trip-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpul_crit: trip-crit {
+ temperature = <100000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
};
- tzts5: tzts5 {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ tzts5: cpu-big-thermal {
+ polling-delay = <1000>;
+ polling-delay-passive = <250>;
thermal-sensors = <&thermal 5>;
sustainable-power = <5000>;
- trips {};
- cooling-maps {};
+
+ trips {
+ cpub_alert: trip-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpub_crit: trip-crit {
+ temperature = <100000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
};
- tztsABB: tztsABB {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ tztsABB: tsabb-thermal {
+ polling-delay = <1000>;
+ polling-delay-passive = <250>;
thermal-sensors = <&thermal 6>;
sustainable-power = <5000>;
- trips {};
- cooling-maps {};
+
+ trips {
+ tsabb_alert: trip-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ tsabb_crit: trip-crit {
+ temperature = <100000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
};
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589824.dts b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589824.dts
new file mode 100644
index 000000000000..d16834eec87a
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589824.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2022 Google LLC
+ */
+
+/dts-v1/;
+#include "mt8186-corsola-voltorb.dtsi"
+
+/ {
+ model = "Google Voltorb sku589824 board";
+ compatible = "google,voltorb-sku589824", "google,voltorb",
+ "mediatek,mt8186";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589825.dts b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589825.dts
new file mode 100644
index 000000000000..45e57f7706cc
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb-sku589825.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2022 Google LLC
+ */
+
+/dts-v1/;
+#include "mt8186-corsola-voltorb.dtsi"
+
+/ {
+ model = "Google Voltorb sku589825 board";
+ compatible = "google,voltorb-sku589825", "google,voltorb",
+ "mediatek,mt8186";
+};
+
+&i2c1 {
+ touchscreen@10 {
+ compatible = "elan,ekth6915";
+ reg = <0x10>;
+ interrupts-extended = <&pio 12 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&touchscreen_pins>;
+ reset-gpios = <&pio 60 GPIO_ACTIVE_LOW>;
+ vcc33-supply = <&pp3300_s3>;
+ };
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtsi b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtsi
new file mode 100644
index 000000000000..52ec58128d56
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtsi
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2022 Google LLC
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/spmi/spmi.h>
+
+#include "mt8186-corsola-steelix.dtsi"
+
+/ {
+ chassis-type = "laptop";
+
+ max98360a: max98360a {
+ compatible = "maxim,max98360a";
+ sdmode-gpios = <&pio 150 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ };
+};
+
+&cpu6 {
+ proc-supply = <&mt6319_buck1>;
+};
+
+&cpu7 {
+ proc-supply = <&mt6319_buck1>;
+};
+
+&gpio_keys {
+ status = "disabled";
+};
+
+&keyboard_controller {
+ linux,keymap = <
+ MATRIX_KEY(0x00, 0x02, KEY_BACK)
+ MATRIX_KEY(0x03, 0x02, KEY_REFRESH)
+ MATRIX_KEY(0x02, 0x02, KEY_ZOOM)
+ MATRIX_KEY(0x01, 0x02, KEY_SCALE)
+ MATRIX_KEY(0x03, 0x04, KEY_SYSRQ)
+ MATRIX_KEY(0x02, 0x04, KEY_BRIGHTNESSDOWN)
+ MATRIX_KEY(0x01, 0x04, KEY_BRIGHTNESSUP)
+ MATRIX_KEY(0x02, 0x09, KEY_MUTE)
+ MATRIX_KEY(0x01, 0x09, KEY_VOLUMEDOWN)
+ MATRIX_KEY(0x00, 0x04, KEY_VOLUMEUP)
+ CROS_STD_MAIN_KEYMAP
+ >;
+};
+
+&mt6366_vproc11_reg {
+ status = "disabled";
+};
+
+&cluster1_opp_14 {
+ opp-hz = /bits/ 64 <2050000000>;
+ opp-microvolt = <1118750>;
+};
+
+&cluster1_opp_15 {
+ 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>;
+ };
+ };
+};
+
+&spmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spmi_pins>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ status = "okay";
+
+ pmic@6 {
+ compatible = "mediatek,mt6319-regulator", "mediatek,mt6315-regulator";
+ reg = <0x6 SPMI_USID>;
+
+ regulators {
+ mt6319_buck1: vbuck1 {
+ regulator-name = "ppvar_dvdd_proc_bc_mt6319";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1193750>;
+ regulator-enable-ramp-delay = <256>;
+ regulator-allowed-modes = <0 1 2>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&touchscreen {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
index 1807e9d6cb0e..afdab5724eaa 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
@@ -42,7 +42,7 @@
default-brightness-level = <576>;
};
- bt-sco-codec {
+ bt-sco {
compatible = "linux,bt-sco";
#sound-dai-cells = <0>;
};
@@ -223,12 +223,44 @@
mediatek,adsp = <&adsp>;
mediatek,platform = <&afe>;
- playback-codecs {
- sound-dai = <&it6505dptx>, <&rt1019p>;
+ audio-routing =
+ "Headphone", "HPOL",
+ "Headphone", "HPOR",
+ "IN1P", "Headset Mic",
+ "Speakers", "Speaker",
+ "HDMI1", "TX";
+
+ hs-playback-dai-link {
+ link-name = "I2S0";
+ dai-format = "i2s";
+ mediatek,clk-provider = "cpu";
+ codec {
+ sound-dai = <&rt5682s 0>;
+ };
+ };
+
+ hs-capture-dai-link {
+ link-name = "I2S1";
+ dai-format = "i2s";
+ mediatek,clk-provider = "cpu";
+ codec {
+ sound-dai = <&rt5682s 0>;
+ };
};
- headset-codec {
- sound-dai = <&rt5682s 0>;
+ spk-share-dai-link {
+ link-name = "I2S2";
+ mediatek,clk-provider = "cpu";
+ };
+
+ spk-hdmi-playback-dai-link {
+ link-name = "I2S3";
+ dai-format = "i2s";
+ mediatek,clk-provider = "cpu";
+ /* RT1019P and IT6505 connected to the same I2S line */
+ codec {
+ sound-dai = <&it6505dptx>, <&rt1019p>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8188.dtsi b/arch/arm64/boot/dts/mediatek/mt8188.dtsi
index b4315c9214dc..29d012d28edb 100644
--- a/arch/arm64/boot/dts/mediatek/mt8188.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8188.dtsi
@@ -8,6 +8,7 @@
#include <dt-bindings/clock/mediatek,mt8188-clk.h>
#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/phy/phy.h>
#include <dt-bindings/pinctrl/mediatek,mt8188-pinfunc.h>
#include <dt-bindings/power/mediatek,mt8188-power.h>
@@ -293,6 +294,112 @@
clock-output-names = "clk32k";
};
+ gpu_opp_table: opp-table-gpu {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-390000000 {
+ opp-hz = /bits/ 64 <390000000>;
+ opp-microvolt = <575000>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-431000000 {
+ opp-hz = /bits/ 64 <431000000>;
+ opp-microvolt = <587500>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-473000000 {
+ opp-hz = /bits/ 64 <473000000>;
+ opp-microvolt = <600000>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-515000000 {
+ opp-hz = /bits/ 64 <515000000>;
+ opp-microvolt = <612500>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-556000000 {
+ opp-hz = /bits/ 64 <556000000>;
+ opp-microvolt = <625000>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-598000000 {
+ opp-hz = /bits/ 64 <598000000>;
+ opp-microvolt = <637500>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-640000000 {
+ opp-hz = /bits/ 64 <640000000>;
+ opp-microvolt = <650000>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-670000000 {
+ opp-hz = /bits/ 64 <670000000>;
+ opp-microvolt = <662500>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-700000000 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <675000>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-730000000 {
+ opp-hz = /bits/ 64 <730000000>;
+ opp-microvolt = <687500>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-760000000 {
+ opp-hz = /bits/ 64 <760000000>;
+ opp-microvolt = <700000>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-790000000 {
+ opp-hz = /bits/ 64 <790000000>;
+ opp-microvolt = <712500>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-835000000 {
+ opp-hz = /bits/ 64 <835000000>;
+ opp-microvolt = <731250>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-880000000 {
+ opp-hz = /bits/ 64 <880000000>;
+ opp-microvolt = <750000>;
+ opp-supported-hw = <0xff>;
+ };
+ opp-915000000 {
+ opp-hz = /bits/ 64 <915000000>;
+ opp-microvolt = <775000>;
+ opp-supported-hw = <0x8f>;
+ };
+ opp-915000000-5 {
+ opp-hz = /bits/ 64 <915000000>;
+ opp-microvolt = <762500>;
+ opp-supported-hw = <0x30>;
+ };
+ opp-915000000-6 {
+ opp-hz = /bits/ 64 <915000000>;
+ opp-microvolt = <750000>;
+ opp-supported-hw = <0x70>;
+ };
+ opp-950000000 {
+ opp-hz = /bits/ 64 <950000000>;
+ opp-microvolt = <800000>;
+ opp-supported-hw = <0x8f>;
+ };
+ opp-950000000-5 {
+ opp-hz = /bits/ 64 <950000000>;
+ opp-microvolt = <775000>;
+ opp-supported-hw = <0x30>;
+ };
+ opp-950000000-6 {
+ opp-hz = /bits/ 64 <950000000>;
+ opp-microvolt = <750000>;
+ opp-supported-hw = <0x70>;
+ };
+ };
+
pmu-a55 {
compatible = "arm,cortex-a55-pmu";
interrupt-parent = <&gic>;
@@ -383,6 +490,329 @@
#interrupt-cells = <2>;
};
+ scpsys: syscon@10006000 {
+ compatible = "mediatek,mt8188-scpsys", "syscon", "simple-mfd";
+ reg = <0 0x10006000 0 0x1000>;
+
+ /* System Power Manager */
+ spm: power-controller {
+ compatible = "mediatek,mt8188-power-controller";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ /* power domain of the SoC */
+ mfg0: power-domain@MT8188_POWER_DOMAIN_MFG0 {
+ reg = <MT8188_POWER_DOMAIN_MFG0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ power-domain@MT8188_POWER_DOMAIN_MFG1 {
+ reg = <MT8188_POWER_DOMAIN_MFG1>;
+ clocks = <&topckgen CLK_APMIXED_MFGPLL>,
+ <&topckgen CLK_TOP_MFG_CORE_TMP>;
+ clock-names = "mfg", "alt";
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ power-domain@MT8188_POWER_DOMAIN_MFG2 {
+ reg = <MT8188_POWER_DOMAIN_MFG2>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_MFG3 {
+ reg = <MT8188_POWER_DOMAIN_MFG3>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_MFG4 {
+ reg = <MT8188_POWER_DOMAIN_MFG4>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_VPPSYS0 {
+ reg = <MT8188_POWER_DOMAIN_VPPSYS0>;
+ clocks = <&topckgen CLK_TOP_VPP>,
+ <&topckgen CLK_TOP_CAM>,
+ <&topckgen CLK_TOP_CCU>,
+ <&topckgen CLK_TOP_IMG>,
+ <&topckgen CLK_TOP_VENC>,
+ <&topckgen CLK_TOP_VDEC>,
+ <&topckgen CLK_TOP_WPE_VPP>,
+ <&topckgen CLK_TOP_CFGREG_CLOCK_EN_VPP0>,
+ <&topckgen CLK_TOP_CFGREG_F26M_VPP0>,
+ <&vppsys0 CLK_VPP0_SMI_COMMON_MMSRAM>,
+ <&vppsys0 CLK_VPP0_GALS_VDO0_LARB0_MMSRAM>,
+ <&vppsys0 CLK_VPP0_GALS_VDO0_LARB1_MMSRAM>,
+ <&vppsys0 CLK_VPP0_GALS_VENCSYS_MMSRAM>,
+ <&vppsys0 CLK_VPP0_GALS_VENCSYS_CORE1_MMSRAM>,
+ <&vppsys0 CLK_VPP0_GALS_INFRA_MMSRAM>,
+ <&vppsys0 CLK_VPP0_GALS_CAMSYS_MMSRAM>,
+ <&vppsys0 CLK_VPP0_GALS_VPP1_LARB5_MMSRAM>,
+ <&vppsys0 CLK_VPP0_GALS_VPP1_LARB6_MMSRAM>,
+ <&vppsys0 CLK_VPP0_SMI_REORDER_MMSRAM>,
+ <&vppsys0 CLK_VPP0_SMI_IOMMU>,
+ <&vppsys0 CLK_VPP0_GALS_IMGSYS_CAMSYS>,
+ <&vppsys0 CLK_VPP0_GALS_EMI0_EMI1>,
+ <&vppsys0 CLK_VPP0_SMI_SUB_COMMON_REORDER>,
+ <&vppsys0 CLK_VPP0_SMI_RSI>,
+ <&vppsys0 CLK_VPP0_SMI_COMMON_LARB4>,
+ <&vppsys0 CLK_VPP0_GALS_VDEC_VDEC_CORE1>,
+ <&vppsys0 CLK_VPP0_GALS_VPP1_WPESYS>,
+ <&vppsys0 CLK_VPP0_GALS_VDO0_VDO1_VENCSYS_CORE1>;
+ clock-names = "top", "cam", "ccu", "img", "venc",
+ "vdec", "wpe", "cfgck", "cfgxo",
+ "ss-sram-cmn", "ss-sram-v0l0", "ss-sram-v0l1",
+ "ss-sram-ve0", "ss-sram-ve1", "ss-sram-ifa",
+ "ss-sram-cam", "ss-sram-v1l5", "ss-sram-v1l6",
+ "ss-sram-rdr", "ss-iommu", "ss-imgcam",
+ "ss-emi", "ss-subcmn-rdr", "ss-rsi",
+ "ss-cmn-l4", "ss-vdec1", "ss-wpe",
+ "ss-cvdo-ve1";
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ power-domain@MT8188_POWER_DOMAIN_VDOSYS0 {
+ reg = <MT8188_POWER_DOMAIN_VDOSYS0>;
+ clocks = <&topckgen CLK_TOP_CFGREG_CLOCK_EN_VDO0>,
+ <&topckgen CLK_TOP_CFGREG_F26M_VDO0>,
+ <&vdosys0 CLK_VDO0_SMI_GALS>,
+ <&vdosys0 CLK_VDO0_SMI_COMMON>,
+ <&vdosys0 CLK_VDO0_SMI_EMI>,
+ <&vdosys0 CLK_VDO0_SMI_IOMMU>,
+ <&vdosys0 CLK_VDO0_SMI_LARB>,
+ <&vdosys0 CLK_VDO0_SMI_RSI>,
+ <&vdosys0 CLK_VDO0_APB_BUS>;
+ clock-names = "cfgck", "cfgxo", "ss-gals",
+ "ss-cmn", "ss-emi", "ss-iommu",
+ "ss-larb", "ss-rsi", "ss-bus";
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ power-domain@MT8188_POWER_DOMAIN_VPPSYS1 {
+ reg = <MT8188_POWER_DOMAIN_VPPSYS1>;
+ clocks = <&topckgen CLK_TOP_CFGREG_CLOCK_EN_VPP1>,
+ <&topckgen CLK_TOP_CFGREG_F26M_VPP1>,
+ <&vppsys1 CLK_VPP1_GALS5>,
+ <&vppsys1 CLK_VPP1_GALS6>,
+ <&vppsys1 CLK_VPP1_LARB5>,
+ <&vppsys1 CLK_VPP1_LARB6>;
+ clock-names = "cfgck", "cfgxo",
+ "ss-vpp1-g5", "ss-vpp1-g6",
+ "ss-vpp1-l5", "ss-vpp1-l6";
+ mediatek,infracfg = <&infracfg_ao>;
+ #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";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+
+ cam_vcore: power-domain@MT8188_POWER_DOMAIN_CAM_VCORE {
+ reg = <MT8188_POWER_DOMAIN_CAM_VCORE>;
+ clocks = <&topckgen CLK_TOP_CAM>,
+ <&topckgen CLK_TOP_CCU>,
+ <&topckgen CLK_TOP_CCU_AHB>,
+ <&topckgen CLK_TOP_CFGREG_CLOCK_ISP_AXI_GALS>;
+ clock-names = "cam", "ccu", "bus", "cfgck";
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ power-domain@MT8188_POWER_DOMAIN_CAM_MAIN {
+ reg = <MT8188_POWER_DOMAIN_CAM_MAIN>;
+ clocks = <&camsys CLK_CAM_MAIN_LARB13>,
+ <&camsys CLK_CAM_MAIN_LARB14>,
+ <&camsys CLK_CAM_MAIN_CAM2MM0_GALS>,
+ <&camsys CLK_CAM_MAIN_CAM2MM1_GALS>,
+ <&camsys CLK_CAM_MAIN_CAM2SYS_GALS>;
+ clock-names= "ss-cam-l13", "ss-cam-l14",
+ "ss-cam-mm0", "ss-cam-mm1",
+ "ss-camsys";
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ power-domain@MT8188_POWER_DOMAIN_CAM_SUBB {
+ reg = <MT8188_POWER_DOMAIN_CAM_SUBB>;
+ clocks = <&camsys CLK_CAM_MAIN_CAM_SUBB>,
+ <&camsys_rawb CLK_CAM_RAWB_LARBX>,
+ <&camsys_yuvb CLK_CAM_YUVB_LARBX>;
+ clock-names = "ss-camb-sub",
+ "ss-camb-raw",
+ "ss-camb-yuv";
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_CAM_SUBA {
+ reg =<MT8188_POWER_DOMAIN_CAM_SUBA>;
+ clocks = <&camsys CLK_CAM_MAIN_CAM_SUBA>,
+ <&camsys_rawa CLK_CAM_RAWA_LARBX>,
+ <&camsys_yuva CLK_CAM_YUVA_LARBX>;
+ clock-names = "ss-cama-sub",
+ "ss-cama-raw",
+ "ss-cama-yuv";
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_VDOSYS1 {
+ reg = <MT8188_POWER_DOMAIN_VDOSYS1>;
+ clocks = <&topckgen CLK_TOP_CFGREG_CLOCK_EN_VDO1>,
+ <&topckgen CLK_TOP_CFGREG_F26M_VDO1>,
+ <&vdosys1 CLK_VDO1_SMI_LARB2>,
+ <&vdosys1 CLK_VDO1_SMI_LARB3>,
+ <&vdosys1 CLK_VDO1_GALS>;
+ clock-names = "cfgck", "cfgxo", "ss-larb2",
+ "ss-larb3", "ss-gals";
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ power-domain@MT8188_POWER_DOMAIN_HDMI_TX {
+ reg = <MT8188_POWER_DOMAIN_HDMI_TX>;
+ clocks = <&topckgen CLK_TOP_HDMI_APB>,
+ <&topckgen CLK_TOP_HDCP_24M>;
+ clock-names = "bus", "hdcp";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_DP_TX {
+ reg = <MT8188_POWER_DOMAIN_DP_TX>;
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_EDP_TX {
+ reg = <MT8188_POWER_DOMAIN_EDP_TX>;
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_VENC {
+ reg = <MT8188_POWER_DOMAIN_VENC>;
+ clocks = <&vencsys CLK_VENC1_LARB>,
+ <&vencsys CLK_VENC1_VENC>,
+ <&vencsys CLK_VENC1_GALS>,
+ <&vencsys CLK_VENC1_GALS_SRAM>;
+ clock-names = "ss-ve1-larb", "ss-ve1-core",
+ "ss-ve1-gals", "ss-ve1-sram";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_WPE {
+ reg = <MT8188_POWER_DOMAIN_WPE>;
+ clocks = <&wpesys CLK_WPE_TOP_SMI_LARB7>,
+ <&wpesys CLK_WPE_TOP_SMI_LARB7_PCLK_EN>;
+ clock-names = "ss-wpe-l7", "ss-wpe-l7pce";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_PEXTP_MAC_P0 {
+ reg = <MT8188_POWER_DOMAIN_PEXTP_MAC_P0>;
+ mediatek,infracfg = <&infracfg_ao>;
+ clocks = <&pericfg_ao CLK_PERI_AO_PCIE_P0_FMEM>;
+ clock-names = "ss-pextp-fmem";
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_CSIRX_TOP {
+ reg = <MT8188_POWER_DOMAIN_CSIRX_TOP>;
+ clocks = <&topckgen CLK_TOP_SENINF>,
+ <&topckgen CLK_TOP_SENINF1>;
+ clock-names = "seninf0", "seninf1";
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_PEXTP_PHY_TOP {
+ reg = <MT8188_POWER_DOMAIN_PEXTP_PHY_TOP>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_ADSP_AO {
+ reg = <MT8188_POWER_DOMAIN_ADSP_AO>;
+ clocks = <&topckgen CLK_TOP_AUDIO_LOCAL_BUS>,
+ <&topckgen CLK_TOP_ADSP>;
+ clock-names = "bus", "main";
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ power-domain@MT8188_POWER_DOMAIN_ADSP_INFRA {
+ reg = <MT8188_POWER_DOMAIN_ADSP_INFRA>;
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ power-domain@MT8188_POWER_DOMAIN_AUDIO_ASRC {
+ reg = <MT8188_POWER_DOMAIN_AUDIO_ASRC>;
+ clocks = <&topckgen CLK_TOP_ASM_H>;
+ clock-names = "asm";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_AUDIO {
+ reg = <MT8188_POWER_DOMAIN_AUDIO>;
+ clocks = <&topckgen CLK_TOP_A1SYS_HP>,
+ <&topckgen CLK_TOP_AUD_INTBUS>,
+ <&adsp_audio26m CLK_AUDIODSP_AUDIO26M>;
+ clock-names = "a1sys", "intbus", "adspck";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_ADSP {
+ reg = <MT8188_POWER_DOMAIN_ADSP>;
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+
+ power-domain@MT8188_POWER_DOMAIN_ETHER {
+ reg = <MT8188_POWER_DOMAIN_ETHER>;
+ clocks = <&pericfg_ao CLK_PERI_AO_ETHERNET_MAC>;
+ clock-names = "ethermac";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+
watchdog: watchdog@10007000 {
compatible = "mediatek,mt8188-wdt";
reg = <0 0x10007000 0 0x100>;
@@ -413,6 +843,22 @@
clock-names = "spi", "wrap";
};
+ gce0: mailbox@10320000 {
+ compatible = "mediatek,mt8188-gce";
+ reg = <0 0x10320000 0 0x4000>;
+ interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH 0>;
+ #mbox-cells = <2>;
+ clocks = <&infracfg_ao CLK_INFRA_AO_GCE>;
+ };
+
+ gce1: mailbox@10330000 {
+ compatible = "mediatek,mt8188-gce";
+ reg = <0 0x10330000 0 0x4000>;
+ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH 0>;
+ #mbox-cells = <2>;
+ clocks = <&infracfg_ao CLK_INFRA_AO_GCE2>;
+ };
+
scp: scp@10500000 {
compatible = "mediatek,mt8188-scp";
reg = <0 0x10500000 0 0x100000>,
@@ -827,6 +1273,23 @@
#clock-cells = <1>;
};
+ gpu: gpu@13000000 {
+ compatible = "mediatek,mt8188-mali", "arm,mali-valhall-jm";
+ reg = <0 0x13000000 0 0x4000>;
+
+ clocks = <&mfgcfg CLK_MFGCFG_BG3D>;
+ interrupts = <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "job", "mmu", "gpu";
+ operating-points-v2 = <&gpu_opp_table>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_MFG2>,
+ <&spm MT8188_POWER_DOMAIN_MFG3>,
+ <&spm MT8188_POWER_DOMAIN_MFG4>;
+ power-domain-names = "core0", "core1", "core2";
+ status = "disabled";
+ };
+
mfgcfg: clock-controller@13fbf000 {
compatible = "mediatek,mt8188-mfgcfg";
reg = <0 0x13fbf000 0 0x1000>;
@@ -952,5 +1415,22 @@
reg = <0 0x1a000000 0 0x1000>;
#clock-cells = <1>;
};
+
+ vdosys0: syscon@1c01d000 {
+ compatible = "mediatek,mt8188-vdosys0", "syscon";
+ reg = <0 0x1c01d000 0 0x1000>;
+ #clock-cells = <1>;
+ mboxes = <&gce0 0 CMDQ_THR_PRIO_4>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0xd000 0x1000>;
+ };
+
+ vdosys1: syscon@1c100000 {
+ compatible = "mediatek,mt8188-vdosys1", "syscon";
+ reg = <0 0x1c100000 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ mboxes = <&gce0 1 CMDQ_THR_PRIO_4>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0 0x1000>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts
index fd2cb8765a15..ac2673e56fb8 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts
@@ -7,6 +7,7 @@
/ {
model = "Google Hayato rev1";
+ chassis-type = "convertible";
compatible = "google,hayato-rev1", "google,hayato", "mediatek,mt8192";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r5-sku2.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r5-sku2.dts
index 3127ee5f6172..cd86ad9ba28a 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r5-sku2.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r5-sku2.dts
@@ -7,6 +7,7 @@
/ {
model = "Google Hayato rev5";
+ chassis-type = "convertible";
compatible = "google,hayato-rev5-sku2", "google,hayato-sku2",
"google,hayato", "mediatek,mt8192";
};
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 bc88866ab2f5..29aa87e93888 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
@@ -8,6 +8,7 @@
/ {
model = "Google Spherion (rev0 - 3)";
+ chassis-type = "laptop";
compatible = "google,spherion-rev3", "google,spherion-rev2",
"google,spherion-rev1", "google,spherion-rev0",
"google,spherion", "mediatek,mt8192";
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r4.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r4.dts
index 0039158c9e60..5e9e598bab90 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r4.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r4.dts
@@ -8,6 +8,7 @@
/ {
model = "Google Spherion (rev4)";
+ chassis-type = "laptop";
compatible = "google,spherion-rev4", "google,spherion",
"mediatek,mt8192";
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
index 7a704246678f..08d71ddf3668 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
@@ -147,6 +147,7 @@
regulator-boot-on;
gpio = <&pio 127 GPIO_ACTIVE_HIGH>;
vin-supply = <&pp3300_g>;
+ off-on-delay-us = <500000>;
};
/* separately switched 3.3V power rail */
diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
index 84cbdf6e9eb0..47dea10dd3b8 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
@@ -2234,7 +2234,7 @@
};
};
- gpu0-thermal {
+ gpu-thermal {
polling-delay = <1000>;
polling-delay-passive = <250>;
thermal-sensors = <&lvts_ap MT8192_AP_GPU0>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry-dojo-r1.dts b/arch/arm64/boot/dts/mediatek/mt8195-cherry-dojo-r1.dts
new file mode 100644
index 000000000000..88123842c818
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry-dojo-r1.dts
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2022 MediaTek Inc.
+ */
+/dts-v1/;
+#include "mt8195-cherry.dtsi"
+
+/ {
+ model = "HP Dojo (sku 1, 3, 5, 7) board";
+ chassis-type = "convertible";
+ compatible = "google,dojo-sku7", "google,dojo-sku5",
+ "google,dojo-sku3", "google,dojo-sku1",
+ "google,dojo", "mediatek,mt8195";
+};
+
+&audio_codec {
+ compatible = "realtek,rt5682s";
+ realtek,amic-delay-ms = <250>;
+};
+
+&i2c2 {
+ spk_r_amp: amplifier@38 {
+ compatible = "maxim,max98390";
+ reg = <0x38>;
+ reset-gpios = <&pio 100 GPIO_ACTIVE_LOW>;
+ sound-name-prefix = "Right";
+ #sound-dai-cells = <0>;
+ };
+
+ spk_l_amp: amplifier@39 {
+ compatible = "maxim,max98390";
+ reg = <0x39>;
+ sound-name-prefix = "Left";
+ #sound-dai-cells = <0>;
+ };
+};
+
+&i2c4 {
+ touchscreen@15 {
+ compatible = "hid-over-i2c";
+ reg = <0x15>;
+ hid-descr-addr = <0x0001>;
+ interrupts-extended = <&pio 92 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&touchscreen_pins>;
+ post-power-on-delay-ms = <10>;
+ vdd-supply = <&pp3300_s3>;
+ };
+};
+
+&keyboard_controller {
+ linux,keymap = <
+ CROS_STD_MAIN_KEYMAP
+
+ MATRIX_KEY(0x00, 0x02, KEY_BACK)
+ MATRIX_KEY(0x03, 0x02, KEY_REFRESH)
+ MATRIX_KEY(0x02, 0x02, KEY_ZOOM)
+ MATRIX_KEY(0x01, 0x02, KEY_SCALE)
+ MATRIX_KEY(0x03, 0x04, KEY_SYSRQ)
+ MATRIX_KEY(0x02, 0x04, KEY_BRIGHTNESSDOWN)
+ MATRIX_KEY(0x01, 0x04, KEY_BRIGHTNESSUP)
+ MATRIX_KEY(0x02, 0x09, KEY_KBDILLUMTOGGLE)
+ MATRIX_KEY(0x01, 0x09, KEY_PLAYPAUSE)
+ MATRIX_KEY(0x00, 0x04, KEY_MICMUTE)
+ MATRIX_KEY(0x00, 0x01, KEY_MUTE)
+ MATRIX_KEY(0x01, 0x05, KEY_VOLUMEDOWN)
+ MATRIX_KEY(0x03, 0x05, KEY_VOLUMEUP)
+ >;
+};
+
+&pcie0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_pins_default>;
+ status = "okay";
+};
+
+&pciephy {
+ status = "okay";
+};
+
+&pio_default {
+ pins-low-power-hdmi-disable {
+ pinmux = <PINMUX_GPIO31__FUNC_GPIO31>,
+ <PINMUX_GPIO32__FUNC_GPIO32>,
+ <PINMUX_GPIO33__FUNC_GPIO33>,
+ <PINMUX_GPIO34__FUNC_GPIO34>,
+ <PINMUX_GPIO35__FUNC_GPIO35>;
+ input-enable;
+ bias-pull-down;
+ };
+};
+
+&sound {
+ compatible = "mediatek,mt8195_mt6359_max98390_rt5682";
+ model = "m8195_m98390_5682s";
+
+ audio-routing =
+ "Headphone", "HPOL",
+ "Headphone", "HPOR",
+ "IN1P", "Headset Mic",
+ "Right Spk", "Right BE_OUT",
+ "Left Spk", "Left BE_OUT";
+
+ spk-playback-dai-link {
+ codec {
+ sound-dai = <&spk_r_amp>, <&spk_l_amp>;
+ };
+ };
+};
+
+&spk_amplifier {
+ /* Disable RT1019P, not present on Dojo */
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
index 4a11918da370..fe5400e17b0f 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
@@ -240,6 +240,7 @@
spk_amplifier: rt1019p {
compatible = "realtek,rt1019p";
label = "rt1019p";
+ #sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&rt1019p_pins_default>;
sdb-gpios = <&pio 100 GPIO_ACTIVE_HIGH>;
@@ -366,6 +367,7 @@
&dp_tx {
status = "okay";
+ #sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&dptx_pin>;
@@ -436,6 +438,7 @@
/* Realtek RT5682i or RT5682s, sharing the same configuration */
reg = <0x1a>;
interrupts-extended = <&pio 89 IRQ_TYPE_EDGE_BOTH>;
+ #sound-dai-cells = <0>;
realtek,jd-src = <1>;
AVDD-supply = <&mt6359_vio18_ldo_reg>;
@@ -1162,6 +1165,48 @@
"AFE_SOF_DL2", "AFE_SOF_DL3", "AFE_SOF_UL4", "AFE_SOF_UL5";
pinctrl-names = "default";
pinctrl-0 = <&aud_pins_default>;
+
+ audio-routing =
+ "Headphone", "HPOL",
+ "Headphone", "HPOR",
+ "IN1P", "Headset Mic",
+ "Ext Spk", "Speaker";
+
+ mm-dai-link {
+ link-name = "ETDM1_IN_BE";
+ mediatek,clk-provider = "cpu";
+ };
+
+ hs-playback-dai-link {
+ link-name = "ETDM1_OUT_BE";
+ mediatek,clk-provider = "cpu";
+ codec {
+ sound-dai = <&audio_codec>;
+ };
+ };
+
+ hs-capture-dai-link {
+ link-name = "ETDM2_IN_BE";
+ mediatek,clk-provider = "cpu";
+ codec {
+ sound-dai = <&audio_codec>;
+ };
+ };
+
+ spk-playback-dai-link {
+ link-name = "ETDM2_OUT_BE";
+ mediatek,clk-provider = "cpu";
+ codec {
+ sound-dai = <&spk_amplifier>;
+ };
+ };
+
+ displayport-dai-link {
+ link-name = "DPTX_BE";
+ codec {
+ sound-dai = <&dp_tx>;
+ };
+ };
};
&spi0 {
@@ -1389,6 +1434,11 @@
MATRIX_KEY(0x02, 0x09, 0) /* T8 */
MATRIX_KEY(0x01, 0x09, 0) /* T9 */
MATRIX_KEY(0x00, 0x04, 0) /* T10 */
+
+ /* T11 to T13 are present only on Dojo */
+ MATRIX_KEY(0x00, 0x01, 0) /* T11 */
+ MATRIX_KEY(0x01, 0x05, 0) /* T12 */
+ MATRIX_KEY(0x03, 0x05, 0) /* T13 */
>;
linux,keymap = <
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-demo.dts b/arch/arm64/boot/dts/mediatek/mt8195-demo.dts
index b82f7176b4a1..31d424b8fc7c 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195-demo.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8195-demo.dts
@@ -305,14 +305,14 @@
<PINMUX_GPIO78__FUNC_GBE_TXD2>,
<PINMUX_GPIO79__FUNC_GBE_TXD1>,
<PINMUX_GPIO80__FUNC_GBE_TXD0>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
};
pins-cc {
pinmux = <PINMUX_GPIO85__FUNC_GBE_TXC>,
<PINMUX_GPIO88__FUNC_GBE_TXEN>,
<PINMUX_GPIO87__FUNC_GBE_RXDV>,
<PINMUX_GPIO86__FUNC_GBE_RXC>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
};
pins-rxd {
pinmux = <PINMUX_GPIO81__FUNC_GBE_RXD3>,
@@ -377,7 +377,7 @@
mmc0_default_pins: mmc0-default-pins {
pins-clk {
pinmux = <PINMUX_GPIO122__FUNC_MSDC0_CLK>;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
@@ -392,13 +392,13 @@
<PINMUX_GPIO116__FUNC_MSDC0_DAT7>,
<PINMUX_GPIO121__FUNC_MSDC0_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
pins-rst {
pinmux = <PINMUX_GPIO120__FUNC_MSDC0_RSTB>;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
};
@@ -406,7 +406,7 @@
mmc0_uhs_pins: mmc0-uhs-pins {
pins-clk {
pinmux = <PINMUX_GPIO122__FUNC_MSDC0_CLK>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
@@ -421,19 +421,19 @@
<PINMUX_GPIO116__FUNC_MSDC0_DAT7>,
<PINMUX_GPIO121__FUNC_MSDC0_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
pins-ds {
pinmux = <PINMUX_GPIO127__FUNC_MSDC0_DSL>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
pins-rst {
pinmux = <PINMUX_GPIO120__FUNC_MSDC0_RSTB>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
};
@@ -441,7 +441,7 @@
mmc1_default_pins: mmc1-default-pins {
pins-clk {
pinmux = <PINMUX_GPIO111__FUNC_MSDC1_CLK>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
@@ -452,7 +452,7 @@
<PINMUX_GPIO114__FUNC_MSDC1_DAT2>,
<PINMUX_GPIO115__FUNC_MSDC1_DAT3>;
input-enable;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
@@ -465,7 +465,7 @@
mmc1_uhs_pins: mmc1-uhs-pins {
pins-clk {
pinmux = <PINMUX_GPIO111__FUNC_MSDC1_CLK>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
@@ -476,7 +476,7 @@
<PINMUX_GPIO114__FUNC_MSDC1_DAT2>,
<PINMUX_GPIO115__FUNC_MSDC1_DAT3>;
input-enable;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-evb.dts b/arch/arm64/boot/dts/mediatek/mt8195-evb.dts
index 341b6e074139..83456d649ff7 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8195-evb.dts
@@ -74,7 +74,6 @@
pinmux = <PINMUX_GPIO8__FUNC_SDA0>,
<PINMUX_GPIO9__FUNC_SCL0>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
- mediatek,drive-strength-adv = <0>;
drive-strength = <6>;
};
};
@@ -84,7 +83,6 @@
pinmux = <PINMUX_GPIO10__FUNC_SDA1>,
<PINMUX_GPIO11__FUNC_SCL1>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
- mediatek,drive-strength-adv = <0>;
drive-strength = <6>;
};
};
@@ -94,7 +92,7 @@
pinmux = <PINMUX_GPIO16__FUNC_SDA4>,
<PINMUX_GPIO17__FUNC_SCL4>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
- mediatek,drive-strength-adv = <7>;
+ drive-strength-microamp = <1000>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
index 5d8b68f86ce4..2ee45752583c 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
@@ -3880,7 +3880,7 @@
};
};
- gpu0-thermal {
+ gpu-thermal {
polling-delay = <1000>;
polling-delay-passive = <250>;
thermal-sensors = <&lvts_ap MT8195_AP_GPU0>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
index 50cbaefa1a99..4211a992dd9d 100644
--- a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
@@ -308,7 +308,7 @@
mmc1_uhs_pins: mmc1-uhs-pins {
clk-pins {
pinmux = <MT8365_PIN_88_MSDC1_CLK__FUNC_MSDC1_CLK>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
@@ -319,7 +319,7 @@
<MT8365_PIN_92_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
<MT8365_PIN_87_MSDC1_CMD__FUNC_MSDC1_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8365.dtsi b/arch/arm64/boot/dts/mediatek/mt8365.dtsi
index 24581f7410aa..eb449bfa8803 100644
--- a/arch/arm64/boot/dts/mediatek/mt8365.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8365.dtsi
@@ -300,9 +300,8 @@
};
scpsys: syscon@10006000 {
- compatible = "mediatek,mt8365-syscfg", "syscon", "simple-mfd";
+ compatible = "mediatek,mt8365-scpsys", "syscon", "simple-mfd";
reg = <0 0x10006000 0 0x1000>;
- #power-domain-cells = <1>;
/* System Power Manager */
spm: power-controller {
diff --git a/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts b/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts
new file mode 100644
index 000000000000..1474bef7e754
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts
@@ -0,0 +1,880 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ * Author: Chris Chen <[email protected]>
+ * Pablo Sun <[email protected]>
+ * Macpaul Lin <[email protected]>
+ */
+/dts-v1/;
+
+#include "mt8188.dtsi"
+#include "mt6359.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/mediatek,mt8188-pinfunc.h>
+#include <dt-bindings/regulator/mediatek,mt6360-regulator.h>
+#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/usb/pd.h>
+
+/ {
+ model = "MediaTek Genio-700 EVK";
+ compatible = "mediatek,mt8390-evk", "mediatek,mt8390",
+ "mediatek,mt8188";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:921600n8";
+ };
+
+ firmware {
+ optee {
+ compatible = "linaro,optee-tz";
+ method = "smc";
+ };
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0x2 0x00000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /*
+ * 12 MiB reserved for OP-TEE (BL32)
+ * +-----------------------+ 0x43e0_0000
+ * | SHMEM 2MiB |
+ * +-----------------------+ 0x43c0_0000
+ * | | TA_RAM 8MiB |
+ * + TZDRAM +--------------+ 0x4340_0000
+ * | | TEE_RAM 2MiB |
+ * +-----------------------+ 0x4320_0000
+ */
+ optee_reserved: optee@43200000 {
+ no-map;
+ reg = <0 0x43200000 0 0x00c00000>;
+ };
+
+ scp_mem: memory@50000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x50000000 0 0x2900000>;
+ no-map;
+ };
+
+ /* 2 MiB reserved for ARM Trusted Firmware (BL31) */
+ bl31_secmon_reserved: memory@54600000 {
+ no-map;
+ reg = <0 0x54600000 0x0 0x200000>;
+ };
+
+ apu_mem: memory@55000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x55000000 0 0x1400000>; /* 20 MB */
+ };
+
+ vpu_mem: memory@57000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x57000000 0 0x1400000>; /* 20 MB */
+ };
+ };
+
+ common_fixed_5v: regulator-0 {
+ compatible = "regulator-fixed";
+ regulator-name = "5v_en";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&pio 10 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ edp_panel_fixed_3v3: regulator-1 {
+ compatible = "regulator-fixed";
+ regulator-name = "edp_panel_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>;
+ };
+
+ gpio_fixed_3v3: regulator-2 {
+ compatible = "regulator-fixed";
+ regulator-name = "gpio_3v3_en";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pio 9 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ sdio_fixed_1v8: regulator-3 {
+ compatible = "regulator-fixed";
+ regulator-name = "sdio_io";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ sdio_fixed_3v3: regulator-4 {
+ compatible = "regulator-fixed";
+ regulator-name = "sdio_card";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pio 74 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ touch0_fixed_3v3: regulator-5 {
+ compatible = "regulator-fixed";
+ regulator-name = "touch_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pio 119 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ usb_hub_fixed_3v3: regulator-6 {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_hub_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;
+ };
+
+ 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 {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_p0_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&pio 84 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ usb_p1_vbus: regulator-9 {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_p1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&pio 87 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ usb_p2_vbus: regulator-10 {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_p2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ };
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ touchscreen@5d {
+ compatible = "goodix,gt9271";
+ reg = <0x5d>;
+ interrupt-parent = <&pio>;
+ interrupts-extended = <&pio 6 IRQ_TYPE_EDGE_RISING>;
+ irq-gpios = <&pio 6 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>;
+ AVDD28-supply = <&touch0_fixed_3v3>;
+ VDDIO-supply = <&mt6359_vio18_ldo_reg>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&touch_pins>;
+ };
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ clock-frequency = <400000>;
+ status = "okay";
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins>;
+ clock-frequency = <400000>;
+ status = "okay";
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c3_pins>;
+ clock-frequency = <400000>;
+ status = "okay";
+};
+
+&i2c4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c4_pins>;
+ pinctrl-1 = <&rt1715_int_pins>;
+ clock-frequency = <1000000>;
+ status = "okay";
+};
+
+&i2c5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c5_pins>;
+ clock-frequency = <400000>;
+ status = "okay";
+};
+
+&i2c6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c6_pins>;
+ clock-frequency = <400000>;
+ status = "okay";
+};
+
+&mmc0 {
+ status = "okay";
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_default_pins>;
+ pinctrl-1 = <&mmc0_uhs_pins>;
+ bus-width = <8>;
+ max-frequency = <200000000>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ supports-cqe;
+ cap-mmc-hw-reset;
+ no-sdio;
+ no-sd;
+ hs400-ds-delay = <0x1481b>;
+ vmmc-supply = <&mt6359_vemc_1_ldo_reg>;
+ vqmmc-supply = <&mt6359_vufs_ldo_reg>;
+ non-removable;
+};
+
+&mmc1 {
+ status = "okay";
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_default_pins>;
+ pinctrl-1 = <&mmc1_uhs_pins>;
+ bus-width = <4>;
+ max-frequency = <200000000>;
+ cap-sd-highspeed;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ no-mmc;
+ no-sdio;
+ cd-gpios = <&pio 2 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&mt6359_vpa_buck_reg>;
+ vqmmc-supply = <&mt6359_vsim1_ldo_reg>;
+};
+
+&mt6359_vbbck_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359_vcn18_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359_vcn33_2_bt_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359_vcore_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vgpu11_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vpa_buck_reg {
+ regulator-max-microvolt = <3100000>;
+};
+
+&mt6359_vpu_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vrf12_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359_vsim1_ldo_reg {
+ regulator-enable-ramp-delay = <480>;
+};
+
+&mt6359_vufs_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359codec {
+ mediatek,mic-type-0 = <1>; /* ACC */
+ mediatek,mic-type-1 = <3>; /* DCC */
+};
+
+&pio {
+ audio_default_pins: audio-default-pins {
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO101__FUNC_O_AUD_CLK_MOSI>,
+ <PINMUX_GPIO102__FUNC_O_AUD_SYNC_MOSI>,
+ <PINMUX_GPIO103__FUNC_O_AUD_DAT_MOSI0>,
+ <PINMUX_GPIO104__FUNC_O_AUD_DAT_MOSI1>,
+ <PINMUX_GPIO105__FUNC_I0_AUD_DAT_MISO0>,
+ <PINMUX_GPIO106__FUNC_I0_AUD_DAT_MISO1>,
+ <PINMUX_GPIO107__FUNC_B0_I2SIN_MCK>,
+ <PINMUX_GPIO108__FUNC_B0_I2SIN_BCK>,
+ <PINMUX_GPIO109__FUNC_B0_I2SIN_WS>,
+ <PINMUX_GPIO110__FUNC_I0_I2SIN_D0>,
+ <PINMUX_GPIO114__FUNC_O_I2SO2_MCK>,
+ <PINMUX_GPIO115__FUNC_B0_I2SO2_BCK>,
+ <PINMUX_GPIO116__FUNC_B0_I2SO2_WS>,
+ <PINMUX_GPIO117__FUNC_O_I2SO2_D0>,
+ <PINMUX_GPIO118__FUNC_O_I2SO2_D1>,
+ <PINMUX_GPIO121__FUNC_B0_PCM_CLK>,
+ <PINMUX_GPIO122__FUNC_B0_PCM_SYNC>,
+ <PINMUX_GPIO124__FUNC_I0_PCM_DI>,
+ <PINMUX_GPIO125__FUNC_O_DMIC1_CLK>,
+ <PINMUX_GPIO126__FUNC_I0_DMIC1_DAT>,
+ <PINMUX_GPIO128__FUNC_O_DMIC2_CLK>,
+ <PINMUX_GPIO129__FUNC_I0_DMIC2_DAT>;
+ };
+ };
+
+ dptx_pins: dptx-pins {
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO46__FUNC_I0_DP_TX_HPD>;
+ bias-pull-up;
+ };
+ };
+
+ edp_panel_3v3_en_pins: edp-panel-3v3-en-pins {
+ pins1 {
+ pinmux = <PINMUX_GPIO15__FUNC_B_GPIO15>;
+ output-high;
+ };
+ };
+
+ eth_default_pins: eth-default-pins {
+ pins-cc {
+ pinmux = <PINMUX_GPIO139__FUNC_B0_GBE_TXC>,
+ <PINMUX_GPIO140__FUNC_I0_GBE_RXC>,
+ <PINMUX_GPIO141__FUNC_I0_GBE_RXDV>,
+ <PINMUX_GPIO142__FUNC_O_GBE_TXEN>;
+ drive-strength = <8>;
+ };
+
+ pins-mdio {
+ pinmux = <PINMUX_GPIO143__FUNC_O_GBE_MDC>,
+ <PINMUX_GPIO144__FUNC_B1_GBE_MDIO>;
+ drive-strength = <8>;
+ input-enable;
+ };
+
+ pins-power {
+ pinmux = <PINMUX_GPIO145__FUNC_B_GPIO145>,
+ <PINMUX_GPIO146__FUNC_B_GPIO146>;
+ output-high;
+ };
+
+ pins-rxd {
+ pinmux = <PINMUX_GPIO135__FUNC_I0_GBE_RXD3>,
+ <PINMUX_GPIO136__FUNC_I0_GBE_RXD2>,
+ <PINMUX_GPIO137__FUNC_I0_GBE_RXD1>,
+ <PINMUX_GPIO138__FUNC_I0_GBE_RXD0>;
+ drive-strength = <8>;
+ };
+
+ pins-txd {
+ pinmux = <PINMUX_GPIO131__FUNC_O_GBE_TXD3>,
+ <PINMUX_GPIO132__FUNC_O_GBE_TXD2>,
+ <PINMUX_GPIO133__FUNC_O_GBE_TXD1>,
+ <PINMUX_GPIO134__FUNC_O_GBE_TXD0>;
+ drive-strength = <8>;
+ };
+ };
+
+ eth_sleep_pins: eth-sleep-pins {
+ pins-cc {
+ pinmux = <PINMUX_GPIO139__FUNC_B_GPIO139>,
+ <PINMUX_GPIO140__FUNC_B_GPIO140>,
+ <PINMUX_GPIO141__FUNC_B_GPIO141>,
+ <PINMUX_GPIO142__FUNC_B_GPIO142>;
+ };
+
+ pins-mdio {
+ pinmux = <PINMUX_GPIO143__FUNC_B_GPIO143>,
+ <PINMUX_GPIO144__FUNC_B_GPIO144>;
+ input-disable;
+ bias-disable;
+ };
+
+ pins-rxd {
+ pinmux = <PINMUX_GPIO135__FUNC_B_GPIO135>,
+ <PINMUX_GPIO136__FUNC_B_GPIO136>,
+ <PINMUX_GPIO137__FUNC_B_GPIO137>,
+ <PINMUX_GPIO138__FUNC_B_GPIO138>;
+ };
+
+ pins-txd {
+ pinmux = <PINMUX_GPIO131__FUNC_B_GPIO131>,
+ <PINMUX_GPIO132__FUNC_B_GPIO132>,
+ <PINMUX_GPIO133__FUNC_B_GPIO133>,
+ <PINMUX_GPIO134__FUNC_B_GPIO134>;
+ };
+ };
+
+ i2c0_pins: i2c0-pins {
+ pins {
+ pinmux = <PINMUX_GPIO56__FUNC_B1_SDA0>,
+ <PINMUX_GPIO55__FUNC_B1_SCL0>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_011>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c1_pins: i2c1-pins {
+ pins {
+ pinmux = <PINMUX_GPIO58__FUNC_B1_SDA1>,
+ <PINMUX_GPIO57__FUNC_B1_SCL1>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_011>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c2_pins: i2c2-pins {
+ pins {
+ pinmux = <PINMUX_GPIO60__FUNC_B1_SDA2>,
+ <PINMUX_GPIO59__FUNC_B1_SCL2>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_011>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c3_pins: i2c3-pins {
+ pins {
+ pinmux = <PINMUX_GPIO62__FUNC_B1_SDA3>,
+ <PINMUX_GPIO61__FUNC_B1_SCL3>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_011>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c4_pins: i2c4-pins {
+ pins {
+ pinmux = <PINMUX_GPIO64__FUNC_B1_SDA4>,
+ <PINMUX_GPIO63__FUNC_B1_SCL4>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_011>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c5_pins: i2c5-pins {
+ pins {
+ pinmux = <PINMUX_GPIO66__FUNC_B1_SDA5>,
+ <PINMUX_GPIO65__FUNC_B1_SCL5>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_011>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c6_pins: i2c6-pins {
+ pins {
+ pinmux = <PINMUX_GPIO68__FUNC_B1_SDA6>,
+ <PINMUX_GPIO67__FUNC_B1_SCL6>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_011>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ gpio_key_pins: gpio-key-pins {
+ pins {
+ pinmux = <PINMUX_GPIO42__FUNC_B1_KPCOL0>,
+ <PINMUX_GPIO43__FUNC_B1_KPCOL1>,
+ <PINMUX_GPIO44__FUNC_B1_KPROW0>;
+ };
+ };
+
+ mmc0_default_pins: mmc0-default-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO157__FUNC_B1_MSDC0_CLK>;
+ drive-strength = <6>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO161__FUNC_B1_MSDC0_DAT0>,
+ <PINMUX_GPIO160__FUNC_B1_MSDC0_DAT1>,
+ <PINMUX_GPIO159__FUNC_B1_MSDC0_DAT2>,
+ <PINMUX_GPIO158__FUNC_B1_MSDC0_DAT3>,
+ <PINMUX_GPIO154__FUNC_B1_MSDC0_DAT4>,
+ <PINMUX_GPIO153__FUNC_B1_MSDC0_DAT5>,
+ <PINMUX_GPIO152__FUNC_B1_MSDC0_DAT6>,
+ <PINMUX_GPIO151__FUNC_B1_MSDC0_DAT7>,
+ <PINMUX_GPIO156__FUNC_B1_MSDC0_CMD>;
+ input-enable;
+ drive-strength = <6>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-rst {
+ pinmux = <PINMUX_GPIO155__FUNC_O_MSDC0_RSTB>;
+ drive-strength = <6>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc0_uhs_pins: mmc0-uhs-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO157__FUNC_B1_MSDC0_CLK>;
+ drive-strength = <8>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO161__FUNC_B1_MSDC0_DAT0>,
+ <PINMUX_GPIO160__FUNC_B1_MSDC0_DAT1>,
+ <PINMUX_GPIO159__FUNC_B1_MSDC0_DAT2>,
+ <PINMUX_GPIO158__FUNC_B1_MSDC0_DAT3>,
+ <PINMUX_GPIO154__FUNC_B1_MSDC0_DAT4>,
+ <PINMUX_GPIO153__FUNC_B1_MSDC0_DAT5>,
+ <PINMUX_GPIO152__FUNC_B1_MSDC0_DAT6>,
+ <PINMUX_GPIO151__FUNC_B1_MSDC0_DAT7>,
+ <PINMUX_GPIO156__FUNC_B1_MSDC0_CMD>;
+ input-enable;
+ drive-strength = <8>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-ds {
+ pinmux = <PINMUX_GPIO162__FUNC_B0_MSDC0_DSL>;
+ drive-strength = <8>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-rst {
+ pinmux = <PINMUX_GPIO155__FUNC_O_MSDC0_RSTB>;
+ drive-strength = <8>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc1_default_pins: mmc1-default-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO164__FUNC_B1_MSDC1_CLK>;
+ drive-strength = <6>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO163__FUNC_B1_MSDC1_CMD>,
+ <PINMUX_GPIO165__FUNC_B1_MSDC1_DAT0>,
+ <PINMUX_GPIO166__FUNC_B1_MSDC1_DAT1>,
+ <PINMUX_GPIO167__FUNC_B1_MSDC1_DAT2>,
+ <PINMUX_GPIO168__FUNC_B1_MSDC1_DAT3>;
+ input-enable;
+ drive-strength = <6>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-insert {
+ pinmux = <PINMUX_GPIO2__FUNC_B_GPIO2>;
+ bias-pull-up;
+ };
+ };
+
+ mmc1_uhs_pins: mmc1-uhs-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO164__FUNC_B1_MSDC1_CLK>;
+ drive-strength = <6>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO163__FUNC_B1_MSDC1_CMD>,
+ <PINMUX_GPIO165__FUNC_B1_MSDC1_DAT0>,
+ <PINMUX_GPIO166__FUNC_B1_MSDC1_DAT1>,
+ <PINMUX_GPIO167__FUNC_B1_MSDC1_DAT2>,
+ <PINMUX_GPIO168__FUNC_B1_MSDC1_DAT3>;
+ input-enable;
+ drive-strength = <6>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc2_default_pins: mmc2-default-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO170__FUNC_B1_MSDC2_CLK>;
+ drive-strength = <4>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO169__FUNC_B1_MSDC2_CMD>,
+ <PINMUX_GPIO171__FUNC_B1_MSDC2_DAT0>,
+ <PINMUX_GPIO172__FUNC_B1_MSDC2_DAT1>,
+ <PINMUX_GPIO173__FUNC_B1_MSDC2_DAT2>,
+ <PINMUX_GPIO174__FUNC_B1_MSDC2_DAT3>;
+ input-enable;
+ drive-strength = <6>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-pcm {
+ pinmux = <PINMUX_GPIO123__FUNC_O_PCM_DO>;
+ };
+ };
+
+ mmc2_uhs_pins: mmc2-uhs-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO170__FUNC_B1_MSDC2_CLK>;
+ drive-strength = <4>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO169__FUNC_B1_MSDC2_CMD>,
+ <PINMUX_GPIO171__FUNC_B1_MSDC2_DAT0>,
+ <PINMUX_GPIO172__FUNC_B1_MSDC2_DAT1>,
+ <PINMUX_GPIO173__FUNC_B1_MSDC2_DAT2>,
+ <PINMUX_GPIO174__FUNC_B1_MSDC2_DAT3>;
+ input-enable;
+ drive-strength = <6>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc2_eint_pins: mmc2-eint-pins {
+ pins-dat1 {
+ pinmux = <PINMUX_GPIO172__FUNC_B_GPIO172>;
+ input-enable;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc2_dat1_pins: mmc2-dat1-pins {
+ pins-dat1 {
+ pinmux = <PINMUX_GPIO172__FUNC_B1_MSDC2_DAT1>;
+ input-enable;
+ drive-strength = <6>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ panel_default_pins: panel-default-pins {
+ pins-dcdc {
+ pinmux = <PINMUX_GPIO45__FUNC_B_GPIO45>;
+ output-low;
+ };
+
+ pins-en {
+ pinmux = <PINMUX_GPIO111__FUNC_B_GPIO111>;
+ output-low;
+ };
+
+ pins-rst {
+ pinmux = <PINMUX_GPIO25__FUNC_B_GPIO25>;
+ output-high;
+ };
+ };
+
+ rt1715_int_pins: rt1715-int-pins {
+ pins_cmd0_dat {
+ pinmux = <PINMUX_GPIO12__FUNC_B_GPIO12>;
+ bias-pull-up;
+ input-enable;
+ };
+ };
+
+ spi0_pins: spi0-pins {
+ pins-spi {
+ pinmux = <PINMUX_GPIO69__FUNC_O_SPIM0_CSB>,
+ <PINMUX_GPIO70__FUNC_O_SPIM0_CLK>,
+ <PINMUX_GPIO71__FUNC_B0_SPIM0_MOSI>,
+ <PINMUX_GPIO72__FUNC_B0_SPIM0_MISO>;
+ bias-disable;
+ };
+ };
+
+ spi1_pins: spi1-pins {
+ pins-spi {
+ pinmux = <PINMUX_GPIO75__FUNC_O_SPIM1_CSB>,
+ <PINMUX_GPIO76__FUNC_O_SPIM1_CLK>,
+ <PINMUX_GPIO77__FUNC_B0_SPIM1_MOSI>,
+ <PINMUX_GPIO78__FUNC_B0_SPIM1_MISO>;
+ bias-disable;
+ };
+ };
+
+ spi2_pins: spi2-pins {
+ pins-spi {
+ pinmux = <PINMUX_GPIO79__FUNC_O_SPIM2_CSB>,
+ <PINMUX_GPIO80__FUNC_O_SPIM2_CLK>,
+ <PINMUX_GPIO81__FUNC_B0_SPIM2_MOSI>,
+ <PINMUX_GPIO82__FUNC_B0_SPIM2_MISO>;
+ bias-disable;
+ };
+ };
+
+ touch_pins: touch-pins {
+ pins-irq {
+ pinmux = <PINMUX_GPIO6__FUNC_B_GPIO6>;
+ input-enable;
+ bias-disable;
+ };
+
+ pins-reset {
+ pinmux = <PINMUX_GPIO5__FUNC_B_GPIO5>;
+ output-high;
+ };
+ };
+
+ uart0_pins: uart0-pins {
+ pins {
+ pinmux = <PINMUX_GPIO31__FUNC_O_UTXD0>,
+ <PINMUX_GPIO32__FUNC_I1_URXD0>;
+ bias-pull-up;
+ };
+ };
+
+ uart1_pins: uart1-pins {
+ pins {
+ pinmux = <PINMUX_GPIO33__FUNC_O_UTXD1>,
+ <PINMUX_GPIO34__FUNC_I1_URXD1>;
+ bias-pull-up;
+ };
+ };
+
+ uart2_pins: uart2-pins {
+ pins {
+ pinmux = <PINMUX_GPIO35__FUNC_O_UTXD2>,
+ <PINMUX_GPIO36__FUNC_I1_URXD2>;
+ bias-pull-up;
+ };
+ };
+
+ usb_default_pins: usb-default-pins {
+ pins-iddig {
+ pinmux = <PINMUX_GPIO83__FUNC_B_GPIO83>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins-valid {
+ pinmux = <PINMUX_GPIO85__FUNC_I0_VBUSVALID>;
+ input-enable;
+ };
+
+ pins-vbus {
+ pinmux = <PINMUX_GPIO84__FUNC_O_USB_DRVVBUS>;
+ output-high;
+ };
+
+ };
+
+ usb1_default_pins: usb1-default-pins {
+ pins-valid {
+ pinmux = <PINMUX_GPIO88__FUNC_I0_VBUSVALID_1P>;
+ input-enable;
+ };
+
+ pins-usb-hub-3v3-en {
+ pinmux = <PINMUX_GPIO112__FUNC_B_GPIO112>;
+ output-high;
+ };
+ };
+
+ wifi_pwrseq_pins: wifi-pwrseq-pins {
+ pins-wifi-enable {
+ pinmux = <PINMUX_GPIO127__FUNC_B_GPIO127>;
+ output-low;
+ };
+ };
+};
+
+&pmic {
+ interrupt-parent = <&pio>;
+ interrupts = <222 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&scp {
+ memory-region = <&scp_mem>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-0 = <&uart1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2_pins>;
+ pinctrl-names = "default";
+ 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";
+};
+
+&u3phy1 {
+ status = "okay";
+};
+
+&u3phy2 {
+ status = "okay";
+};
+
+&xhci0 {
+ status = "okay";
+ vusb33-supply = <&mt6359_vusb_ldo_reg>;
+};
+
+&xhci1 {
+ status = "okay";
+ vusb33-supply = <&mt6359_vusb_ldo_reg>;
+ vbus-supply = <&usb_hub_reset_1v8>;
+};
+
+&xhci2 {
+ status = "okay";
+ vusb33-supply = <&mt6359_vusb_ldo_reg>;
+};
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 1558649f633c..a06610fff8ad 100644
--- a/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts
@@ -475,7 +475,7 @@
<PINMUX_GPIO86__FUNC_GBE_RXC>,
<PINMUX_GPIO87__FUNC_GBE_RXDV>,
<PINMUX_GPIO88__FUNC_GBE_TXEN>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
};
pins-mdio {
@@ -502,7 +502,7 @@
<PINMUX_GPIO78__FUNC_GBE_TXD2>,
<PINMUX_GPIO79__FUNC_GBE_TXD1>,
<PINMUX_GPIO80__FUNC_GBE_TXD0>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
};
};
@@ -567,7 +567,7 @@
pinmux = <PINMUX_GPIO12__FUNC_SDA2>,
<PINMUX_GPIO13__FUNC_SCL2>;
bias-pull-up = <MTK_PULL_SET_RSEL_111>;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
};
};
@@ -582,7 +582,7 @@
mmc0_default_pins: mmc0-default-pins {
pins-clk {
pinmux = <PINMUX_GPIO122__FUNC_MSDC0_CLK>;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
@@ -597,13 +597,13 @@
<PINMUX_GPIO116__FUNC_MSDC0_DAT7>,
<PINMUX_GPIO121__FUNC_MSDC0_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
pins-rst {
pinmux = <PINMUX_GPIO120__FUNC_MSDC0_RSTB>;
- drive-strength = <MTK_DRIVE_6mA>;
+ drive-strength = <6>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
};
@@ -611,7 +611,7 @@
mmc0_uhs_pins: mmc0-uhs-pins {
pins-clk {
pinmux = <PINMUX_GPIO122__FUNC_MSDC0_CLK>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
@@ -626,19 +626,19 @@
<PINMUX_GPIO116__FUNC_MSDC0_DAT7>,
<PINMUX_GPIO121__FUNC_MSDC0_CMD>;
input-enable;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
pins-ds {
pinmux = <PINMUX_GPIO127__FUNC_MSDC0_DSL>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
pins-rst {
pinmux = <PINMUX_GPIO120__FUNC_MSDC0_RSTB>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
};
@@ -646,7 +646,7 @@
mmc1_default_pins: mmc1-default-pins {
pins-clk {
pinmux = <PINMUX_GPIO111__FUNC_MSDC1_CLK>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
@@ -657,7 +657,7 @@
<PINMUX_GPIO114__FUNC_MSDC1_DAT2>,
<PINMUX_GPIO115__FUNC_MSDC1_DAT3>;
input-enable;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
};
@@ -665,7 +665,7 @@
mmc1_uhs_pins: mmc1-uhs-pins {
pins-clk {
pinmux = <PINMUX_GPIO111__FUNC_MSDC1_CLK>;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
};
@@ -676,7 +676,7 @@
<PINMUX_GPIO114__FUNC_MSDC1_DAT2>,
<PINMUX_GPIO115__FUNC_MSDC1_DAT3>;
input-enable;
- drive-strength = <MTK_DRIVE_8mA>;
+ drive-strength = <8>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
};
};
@@ -854,6 +854,10 @@
&u3phy1 {
status = "okay";
+
+ u3port1: usb-phy@700 {
+ mediatek,force-mode;
+ };
};
&u3phy2 {
@@ -900,6 +904,8 @@
};
&xhci1 {
+ phys = <&u2port1 PHY_TYPE_USB2>,
+ <&u3port1 PHY_TYPE_USB3>;
vusb33-supply = <&mt6359_vusb_ldo_reg>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8395-kontron-3-5-sbc-i1200.dts b/arch/arm64/boot/dts/mediatek/mt8395-kontron-3-5-sbc-i1200.dts
new file mode 100644
index 000000000000..e4b2af9489a8
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8395-kontron-3-5-sbc-i1200.dts
@@ -0,0 +1,1127 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2024 Kontron Europe GmbH
+ *
+ * Author: Michael Walle <[email protected]>
+ */
+/dts-v1/;
+
+#include "mt8195.dtsi"
+#include "mt6359.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/mt8195-pinfunc.h>
+#include <dt-bindings/regulator/mediatek,mt6360-regulator.h>
+#include <dt-bindings/spmi/spmi.h>
+
+/ {
+ model = "Kontron 3.5\"-SBC-i1200";
+ compatible = "kontron,3-5-sbc-i1200", "mediatek,mt8395", "mediatek,mt8195";
+
+ aliases {
+ mmc0 = &mmc0;
+ mmc1 = &mmc1;
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ serial4 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ firmware {
+ optee {
+ compatible = "linaro,optee-tz";
+ method = "smc";
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_keys_pins>;
+
+ key-0 {
+ gpios = <&pio 106 GPIO_ACTIVE_LOW>;
+ label = "volume_up";
+ linux,code = <KEY_VOLUMEUP>;
+ wakeup-source;
+ debounce-interval = <15>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pins>;
+
+ led-0 {
+ gpios = <&pio 107 GPIO_ACTIVE_HIGH>;
+ default-state = "keep";
+ function = LED_FUNCTION_POWER;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0x0 0x80000000>;
+ };
+
+ vsys: regulator-vsys {
+ compatible = "regulator-fixed";
+ regulator-name = "vsys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /*
+ * 12 MiB reserved for OP-TEE (BL32)
+ * +-----------------------+ 0x43e0_0000
+ * | SHMEM 2MiB |
+ * +-----------------------+ 0x43c0_0000
+ * | | TA_RAM 8MiB |
+ * + TZDRAM +--------------+ 0x4340_0000
+ * | | TEE_RAM 2MiB |
+ * +-----------------------+ 0x4320_0000
+ */
+ optee_reserved: optee@43200000 {
+ no-map;
+ reg = <0 0x43200000 0 0x00c00000>;
+ };
+
+ scp_mem: memory@50000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x50000000 0 0x2900000>;
+ no-map;
+ };
+
+ vpu_mem: memory@53000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x53000000 0 0x1400000>; /* 20 MB */
+ };
+
+ /* 2 MiB reserved for ARM Trusted Firmware (BL31) */
+ bl31_secmon_mem: memory@54600000 {
+ no-map;
+ reg = <0 0x54600000 0x0 0x200000>;
+ };
+
+ snd_dma_mem: memory@60000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x60000000 0 0x1100000>;
+ no-map;
+ };
+
+ apu_mem: memory@62000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x62000000 0 0x1400000>; /* 20 MB */
+ };
+ };
+
+ thermal_sensor0: thermal-sensor-0 {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&auxadc 0>;
+ io-channel-names = "sensor-channel";
+ temperature-lookup-table = <(-25000) 1474
+ (-20000) 1374
+ (-15000) 1260
+ (-10000) 1134
+ (-5000) 1004
+ 0 874
+ 5000 750
+ 10000 635
+ 15000 532
+ 20000 443
+ 25000 367
+ 30000 303
+ 35000 250
+ 40000 206
+ 45000 170
+ 50000 141
+ 55000 117
+ 60000 97
+ 65000 81
+ 70000 68
+ 75000 57
+ 80000 48
+ 85000 41
+ 90000 35
+ 95000 30
+ 100000 25
+ 105000 22
+ 110000 19
+ 115000 16
+ 120000 14
+ 125000 12
+ 130000 10
+ 135000 9
+ 140000 8
+ 145000 7
+ 150000 6>;
+ };
+
+ thermal_sensor1: thermal-sensor-1 {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&auxadc 1>;
+ io-channel-names = "sensor-channel";
+ temperature-lookup-table = <(-25000) 1474
+ (-20000) 1374
+ (-15000) 1260
+ (-10000) 1134
+ (-5000) 1004
+ 0 874
+ 5000 750
+ 10000 635
+ 15000 532
+ 20000 443
+ 25000 367
+ 30000 303
+ 35000 250
+ 40000 206
+ 45000 170
+ 50000 141
+ 55000 117
+ 60000 97
+ 65000 81
+ 70000 68
+ 75000 57
+ 80000 48
+ 85000 41
+ 90000 35
+ 95000 30
+ 100000 25
+ 105000 22
+ 110000 19
+ 115000 16
+ 120000 14
+ 125000 12
+ 130000 10
+ 135000 9
+ 140000 8
+ 145000 7
+ 150000 6>;
+ };
+
+ thermal_sensor2: thermal-sensor-2 {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&auxadc 2>;
+ io-channel-names = "sensor-channel";
+ temperature-lookup-table = <(-25000) 1474
+ (-20000) 1374
+ (-15000) 1260
+ (-10000) 1134
+ (-5000) 1004
+ 0 874
+ 5000 750
+ 10000 635
+ 15000 532
+ 20000 443
+ 25000 367
+ 30000 303
+ 35000 250
+ 40000 206
+ 45000 170
+ 50000 141
+ 55000 117
+ 60000 97
+ 65000 81
+ 70000 68
+ 75000 57
+ 80000 48
+ 85000 41
+ 90000 35
+ 95000 30
+ 100000 25
+ 105000 22
+ 110000 19
+ 115000 16
+ 120000 14
+ 125000 12
+ 130000 10
+ 135000 9
+ 140000 8
+ 145000 7
+ 150000 6>;
+ };
+};
+
+&auxadc {
+ status = "okay";
+};
+
+&eth {
+ phy-mode ="rgmii-id";
+ phy-handle = <&ethernet_phy0>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&eth_default_pins>;
+ pinctrl-1 = <&eth_sleep_pins>;
+ status = "okay";
+
+ mdio {
+ ethernet_phy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <0x1>;
+ interrupts-extended = <&pio 94 IRQ_TYPE_LEVEL_LOW>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <80000>;
+ reset-gpios = <&pio 93 GPIO_ACTIVE_HIGH>;
+ };
+ };
+};
+
+&gpu {
+ status = "okay";
+ mali-supply = <&mt6315_7_vbuck1>;
+};
+
+/* CSI1/CSI2 connector */
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ clock-frequency = <100000>;
+ status = "okay";
+};
+
+/* CSI3 connector */
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ clock-frequency = <100000>;
+ status = "okay";
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ /* LVDS bridge @f */
+};
+
+/* Touch panel connector */
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c3_pins>;
+ clock-frequency = <100000>;
+ status = "okay";
+};
+
+/* B2B connector */
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-0 = <&i2c4_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&i2c6 {
+ clock-frequency = <400000>;
+ pinctrl-0 = <&i2c6_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ mt6360: pmic@34 {
+ compatible = "mediatek,mt6360";
+ reg = <0x34>;
+ interrupt-controller;
+ interrupts-extended = <&pio 101 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-names = "IRQB";
+ #interrupt-cells = <1>;
+
+ regulator {
+ compatible = "mediatek,mt6360-regulator";
+ LDO_VIN1-supply = <&vsys>;
+ LDO_VIN2-supply = <&vsys>;
+ LDO_VIN3-supply = <&vsys>;
+
+ mt6360_buck1: BUCK1 {
+ regulator-name = "emi_vdd2";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP
+ MT6360_OPMODE_ULP>;
+ regulator-always-on;
+ };
+
+ mt6360_buck2: BUCK2 {
+ regulator-name = "emi_vddq";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP
+ MT6360_OPMODE_ULP>;
+ regulator-always-on;
+ };
+
+ mt6360_ldo1: LDO1 {
+ regulator-name = "mt6360_ldo1"; /* Test point */
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+
+ mt6360_ldo2: LDO2 {
+ regulator-name = "panel1_p1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+
+ mt6360_ldo3: LDO3 {
+ regulator-name = "vmc_pmu";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+
+ mt6360_ldo5: LDO5 {
+ regulator-name = "vmch_pmu";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+
+ mt6360_ldo6: LDO6 {
+ regulator-name = "mt6360_ldo6"; /* Test point */
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+
+ mt6360_ldo7: LDO7 {
+ regulator-name = "emi_vmddr_en";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&mmc0 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_default_pins>;
+ pinctrl-1 = <&mmc0_uhs_pins>;
+ bus-width = <8>;
+ max-frequency = <200000000>;
+ hs400-ds-delay = <0x14c11>;
+ cap-mmc-highspeed;
+ cap-mmc-hw-reset;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ no-sdio;
+ no-sd;
+ non-removable;
+ vmmc-supply = <&mt6359_vemc_1_ldo_reg>;
+ vqmmc-supply = <&mt6359_vufs_ldo_reg>;
+ status = "okay";
+};
+
+&mmc1 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_default_pins>, <&mmc1_detect_pins>;
+ pinctrl-1 = <&mmc1_default_pins>;
+ cd-gpios = <&pio 129 GPIO_ACTIVE_LOW>;
+ bus-width = <4>;
+ max-frequency = <200000000>;
+ cap-sd-highspeed;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ no-mmc;
+ vmmc-supply = <&mt6360_ldo5>;
+ vqmmc-supply = <&mt6360_ldo3>;
+ status = "okay";
+};
+
+&mt6359_vbbck_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359_vcore_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vgpu11_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vproc1_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vproc2_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vpu_buck_reg {
+ regulator-always-on;
+};
+
+&mt6359_vrf12_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359_vsram_md_ldo_reg {
+ regulator-always-on;
+};
+
+&mt6359_vsram_others_ldo_reg {
+ regulator-always-on;
+};
+
+&nor_flash {
+ pinctrl-names = "default";
+ pinctrl-0 = <&nor_pins_default>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <52000000>;
+ spi-rx-bus-width = <2>;
+ spi-tx-bus-width = <2>;
+ };
+};
+
+&pcie0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_pins_default>;
+ status = "okay";
+};
+
+&pcie1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_pins_default>;
+ status = "okay";
+};
+
+&pciephy {
+ status = "okay";
+};
+
+&pio {
+ eth_default_pins: eth-default-pins {
+ pins-txd {
+ pinmux = <PINMUX_GPIO77__FUNC_GBE_TXD3>,
+ <PINMUX_GPIO78__FUNC_GBE_TXD2>,
+ <PINMUX_GPIO79__FUNC_GBE_TXD1>,
+ <PINMUX_GPIO80__FUNC_GBE_TXD0>;
+ drive-strength = <8>;
+ };
+
+ pins-rxd {
+ pinmux = <PINMUX_GPIO81__FUNC_GBE_RXD3>,
+ <PINMUX_GPIO82__FUNC_GBE_RXD2>,
+ <PINMUX_GPIO83__FUNC_GBE_RXD1>,
+ <PINMUX_GPIO84__FUNC_GBE_RXD0>;
+ };
+
+ pins-cc {
+ pinmux = <PINMUX_GPIO85__FUNC_GBE_TXC>,
+ <PINMUX_GPIO86__FUNC_GBE_RXC>,
+ <PINMUX_GPIO87__FUNC_GBE_RXDV>,
+ <PINMUX_GPIO88__FUNC_GBE_TXEN>;
+ drive-strength = <8>;
+ };
+
+ pins-mdio {
+ pinmux = <PINMUX_GPIO89__FUNC_GBE_MDC>,
+ <PINMUX_GPIO90__FUNC_GBE_MDIO>;
+ input-enable;
+ };
+
+ pins-power {
+ pinmux = <PINMUX_GPIO91__FUNC_GPIO91>,
+ <PINMUX_GPIO92__FUNC_GPIO92>;
+ output-high;
+ };
+
+ pins-reset {
+ pinmux = <PINMUX_GPIO93__FUNC_GPIO93>;
+ output-high;
+ };
+
+ pins-interrupt {
+ pinmux = <PINMUX_GPIO94__FUNC_GPIO94>;
+ input-enable;
+ };
+ };
+
+ eth_sleep_pins: eth-sleep-pins {
+ pins-txd {
+ pinmux = <PINMUX_GPIO77__FUNC_GPIO77>,
+ <PINMUX_GPIO78__FUNC_GPIO78>,
+ <PINMUX_GPIO79__FUNC_GPIO79>,
+ <PINMUX_GPIO80__FUNC_GPIO80>;
+ };
+
+ pins-cc {
+ pinmux = <PINMUX_GPIO85__FUNC_GPIO85>,
+ <PINMUX_GPIO88__FUNC_GPIO88>,
+ <PINMUX_GPIO87__FUNC_GPIO87>,
+ <PINMUX_GPIO86__FUNC_GPIO86>;
+ };
+
+ pins-rxd {
+ pinmux = <PINMUX_GPIO81__FUNC_GPIO81>,
+ <PINMUX_GPIO82__FUNC_GPIO82>,
+ <PINMUX_GPIO83__FUNC_GPIO83>,
+ <PINMUX_GPIO84__FUNC_GPIO84>;
+ };
+
+ pins-mdio {
+ pinmux = <PINMUX_GPIO89__FUNC_GPIO89>,
+ <PINMUX_GPIO90__FUNC_GPIO90>;
+ input-disable;
+ bias-disable;
+ };
+ };
+
+ gpio_keys_pins: gpio-keys-pins {
+ pins {
+ pinmux = <PINMUX_GPIO106__FUNC_GPIO106>;
+ input-enable;
+ };
+ };
+
+ i2c0_pins: i2c0-pins {
+ pins {
+ pinmux = <PINMUX_GPIO8__FUNC_SDA0>,
+ <PINMUX_GPIO9__FUNC_SCL0>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c1_pins: i2c1-pins {
+ pins {
+ pinmux = <PINMUX_GPIO10__FUNC_SDA1>,
+ <PINMUX_GPIO11__FUNC_SCL1>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c2_pins: i2c2-default-pins {
+ pins-bus {
+ pinmux = <PINMUX_GPIO12__FUNC_SDA2>,
+ <PINMUX_GPIO13__FUNC_SCL2>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c3_pins: i2c3-pins {
+ pins {
+ pinmux = <PINMUX_GPIO14__FUNC_SDA3>,
+ <PINMUX_GPIO15__FUNC_SCL3>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c4_pins: i2c4-pins {
+ pins {
+ pinmux = <PINMUX_GPIO16__FUNC_SDA4>,
+ <PINMUX_GPIO17__FUNC_SCL4>;
+ bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ i2c6_pins: i2c6-pins {
+ pins {
+ pinmux = <PINMUX_GPIO25__FUNC_SDA6>,
+ <PINMUX_GPIO26__FUNC_SCL6>;
+ bias-pull-up;
+ drive-strength-microamp = <1000>;
+ };
+ };
+
+ mmc0_default_pins: mmc0-default-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO122__FUNC_MSDC0_CLK>;
+ drive-strength = <6>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO126__FUNC_MSDC0_DAT0>,
+ <PINMUX_GPIO125__FUNC_MSDC0_DAT1>,
+ <PINMUX_GPIO124__FUNC_MSDC0_DAT2>,
+ <PINMUX_GPIO123__FUNC_MSDC0_DAT3>,
+ <PINMUX_GPIO119__FUNC_MSDC0_DAT4>,
+ <PINMUX_GPIO118__FUNC_MSDC0_DAT5>,
+ <PINMUX_GPIO117__FUNC_MSDC0_DAT6>,
+ <PINMUX_GPIO116__FUNC_MSDC0_DAT7>,
+ <PINMUX_GPIO121__FUNC_MSDC0_CMD>;
+ input-enable;
+ drive-strength = <6>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-rst {
+ pinmux = <PINMUX_GPIO120__FUNC_MSDC0_RSTB>;
+ drive-strength = <6>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc0_uhs_pins: mmc0-uhs-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO122__FUNC_MSDC0_CLK>;
+ drive-strength = <8>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO126__FUNC_MSDC0_DAT0>,
+ <PINMUX_GPIO125__FUNC_MSDC0_DAT1>,
+ <PINMUX_GPIO124__FUNC_MSDC0_DAT2>,
+ <PINMUX_GPIO123__FUNC_MSDC0_DAT3>,
+ <PINMUX_GPIO119__FUNC_MSDC0_DAT4>,
+ <PINMUX_GPIO118__FUNC_MSDC0_DAT5>,
+ <PINMUX_GPIO117__FUNC_MSDC0_DAT6>,
+ <PINMUX_GPIO116__FUNC_MSDC0_DAT7>,
+ <PINMUX_GPIO121__FUNC_MSDC0_CMD>;
+ input-enable;
+ drive-strength = <8>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-ds {
+ pinmux = <PINMUX_GPIO127__FUNC_MSDC0_DSL>;
+ drive-strength = <8>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-rst {
+ pinmux = <PINMUX_GPIO120__FUNC_MSDC0_RSTB>;
+ drive-strength = <8>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc1_default_pins: mmc1-default-pins {
+ pins-clk {
+ pinmux = <PINMUX_GPIO111__FUNC_MSDC1_CLK>;
+ drive-strength = <8>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO110__FUNC_MSDC1_CMD>,
+ <PINMUX_GPIO112__FUNC_MSDC1_DAT0>,
+ <PINMUX_GPIO113__FUNC_MSDC1_DAT1>,
+ <PINMUX_GPIO114__FUNC_MSDC1_DAT2>,
+ <PINMUX_GPIO115__FUNC_MSDC1_DAT3>;
+ input-enable;
+ drive-strength = <8>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ mmc1_detect_pins: mmc1-detect-pins {
+ pins-insert {
+ pinmux = <PINMUX_GPIO129__FUNC_GPIO129>;
+ bias-pull-up;
+ };
+ };
+
+ nor_pins_default: nor-default-pins {
+ pins-ck-io {
+ pinmux = <PINMUX_GPIO142__FUNC_SPINOR_IO0>,
+ <PINMUX_GPIO141__FUNC_SPINOR_CK>,
+ <PINMUX_GPIO143__FUNC_SPINOR_IO1>;
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ pins-cs {
+ pinmux = <PINMUX_GPIO140__FUNC_SPINOR_CS>;
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+
+ pcie0_pins_default: pcie0-default-pins {
+ pins-bus {
+ pinmux = <PINMUX_GPIO19__FUNC_WAKEN>,
+ <PINMUX_GPIO20__FUNC_PERSTN>,
+ <PINMUX_GPIO21__FUNC_CLKREQN>;
+ bias-pull-up;
+ };
+ };
+
+ pcie1_pins_default: pcie1-default-pins {
+ pins-bus {
+ pinmux = <PINMUX_GPIO0__FUNC_PERSTN_1>,
+ <PINMUX_GPIO1__FUNC_CLKREQN_1>,
+ <PINMUX_GPIO2__FUNC_WAKEN_1>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ led_pins: led-pins {
+ pins-power-en {
+ pinmux = <PINMUX_GPIO107__FUNC_GPIO107>;
+ output-high;
+ };
+ };
+
+ spi0_pins: spi0-default-pins {
+ pins-cs-mosi-clk {
+ pinmux = <PINMUX_GPIO132__FUNC_SPIM0_CSB>,
+ <PINMUX_GPIO134__FUNC_SPIM0_MO>,
+ <PINMUX_GPIO133__FUNC_SPIM0_CLK>;
+ bias-disable;
+ };
+
+ pins-miso {
+ pinmux = <PINMUX_GPIO135__FUNC_SPIM0_MI>;
+ bias-pull-down;
+ };
+ };
+
+ spi1_pins: spi1-default-pins {
+ pins-cs-mosi-clk {
+ pinmux = <PINMUX_GPIO136__FUNC_SPIM1_CSB>,
+ <PINMUX_GPIO138__FUNC_SPIM1_MO>,
+ <PINMUX_GPIO137__FUNC_SPIM1_CLK>;
+ bias-disable;
+ };
+
+ pins-miso {
+ pinmux = <PINMUX_GPIO139__FUNC_SPIM1_MI>;
+ bias-pull-down;
+ };
+ };
+
+ uart0_pins: uart0-pins {
+ pins-rx {
+ pinmux = <PINMUX_GPIO99__FUNC_URXD0>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins-tx {
+ pinmux = <PINMUX_GPIO98__FUNC_UTXD0>;
+ };
+ };
+
+ uart1_pins: uart1-pins {
+ pins-rx {
+ pinmux = <PINMUX_GPIO103__FUNC_URXD1>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins-tx {
+ pinmux = <PINMUX_GPIO102__FUNC_UTXD1>;
+ };
+
+ pins-rts {
+ pinmux = <PINMUX_GPIO100__FUNC_URTS1>;
+ };
+
+ pins-cts {
+ pinmux = <PINMUX_GPIO101__FUNC_UCTS1>;
+ input-enable;
+ };
+ };
+
+ uart2_pins: uart2-pins {
+ pins-rx {
+ pinmux = <PINMUX_GPIO68__FUNC_URXD2>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins-tx {
+ pinmux = <PINMUX_GPIO67__FUNC_UTXD2>;
+ };
+
+ pins-rts {
+ pinmux = <PINMUX_GPIO66__FUNC_URTS2>;
+ };
+
+ pins-cts {
+ pinmux = <PINMUX_GPIO65__FUNC_UCTS2>;
+ input-enable;
+ };
+ };
+
+ uart3_pins: uart3-pins {
+ pins-rx {
+ pinmux = <PINMUX_GPIO5__FUNC_URXD3>;
+ input-enable;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-tx {
+ pinmux = <PINMUX_GPIO4__FUNC_UTXD3>;
+ };
+ };
+
+ uart4_pins: uart4-pins {
+ pins-rx {
+ pinmux = <PINMUX_GPIO7__FUNC_URXD4>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins-tx {
+ pinmux = <PINMUX_GPIO6__FUNC_UTXD4>;
+ };
+ };
+};
+
+&pmic {
+ interrupts-extended = <&pio 222 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&scp {
+ memory-region = <&scp_mem>;
+ firmware-name = "mediatek/mt8195/scp.img";
+ status = "okay";
+};
+
+&spmi {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ mt6315@6 {
+ compatible = "mediatek,mt6315-regulator";
+ reg = <0x6 SPMI_USID>;
+
+ regulators {
+ mt6315_6_vbuck1: vbuck1 {
+ regulator-name = "Vbcpu";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1193750>;
+ regulator-enable-ramp-delay = <256>;
+ regulator-ramp-delay = <6250>;
+ regulator-allowed-modes = <0 1 2>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ mt6315@7 {
+ compatible = "mediatek,mt6315-regulator";
+ reg = <0x7 SPMI_USID>;
+
+ regulators {
+ mt6315_7_vbuck1: vbuck1 {
+ regulator-name = "Vgpu";
+ regulator-min-microvolt = <625000>;
+ regulator-max-microvolt = <1193750>;
+ regulator-enable-ramp-delay = <256>;
+ regulator-ramp-delay = <6250>;
+ regulator-allowed-modes = <0 1 2>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+/* USB3.2 front port */
+&ssusb0 {
+ dr_mode = "host";
+ vusb33-supply = <&mt6359_vusb_ldo_reg>;
+ status = "okay";
+};
+
+/* USB2.0 M.2 Key-E */
+&ssusb2 {
+ vusb33-supply = <&mt6359_vusb_ldo_reg>;
+ status = "okay";
+};
+
+/* USB2.0 to on-board usb hub */
+&ssusb3 {
+ vusb33-supply = <&mt6359_vusb_ldo_reg>;
+ status = "okay";
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+ mediatek,pad-select = <0>;
+ status = "okay";
+
+ tpm: tpm@0 {
+ compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+ reg = <0>;
+ spi-max-frequency = <18500000>;
+ };
+};
+
+/* B2B connector */
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
+ mediatek,pad-select = <0>;
+ status = "okay";
+};
+
+&thermal_zones {
+ cpu-thermal {
+ polling-delay = <1000>; /* milliseconds */
+ polling-delay-passive = <0>; /* milliseconds */
+ thermal-sensors = <&thermal_sensor0>;
+
+ trips {
+ trip-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-crit {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ pcb-top-thermal {
+ polling-delay = <1000>; /* milliseconds */
+ polling-delay-passive = <0>; /* milliseconds */
+ thermal-sensors = <&thermal_sensor1>;
+
+ trips {
+ trip-alert {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-crit {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ pcb-bottom-thermal {
+ polling-delay = <1000>; /* milliseconds */
+ polling-delay-passive = <0>; /* milliseconds */
+ thermal-sensors = <&thermal_sensor2>;
+
+ trips {
+ trip-alert {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-crit {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_pins>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_pins>;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart4_pins>;
+ status = "okay";
+};
+
+/* USB3 */
+&u3phy0 {
+ status = "okay";
+};
+
+/* PCIe1/USB2 */
+&u3phy1 {
+ status = "okay";
+};
+
+/* USB2 */
+&u3phy2 {
+ status = "okay";
+};
+
+/* USB2 */
+&u3phy3 {
+ status = "okay";
+};
+
+/* USB3.2 front port */
+&xhci0 {
+ status = "okay";
+};
+
+/* USB2.0 M.2 Key-B */
+&xhci1 {
+ vusb33-supply = <&mt6359_vusb_ldo_reg>;
+ mediatek,u3p-dis-msk = <0x01>;
+ status = "okay";
+};
+
+/* USB2.0 M.2 Key-E */
+&xhci2 {
+ status = "okay";
+};
+
+/* USB2.0 to on-board usb hub */
+&xhci3 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
index e5d9b671a405..4b5f6cf16f70 100644
--- a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts
@@ -140,6 +140,38 @@
};
};
+&cpu0 {
+ cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu1 {
+ cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu2 {
+ cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu3 {
+ cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu4 {
+ cpu-supply = <&mt6315_6_vbuck1>;
+};
+
+&cpu5 {
+ cpu-supply = <&mt6315_6_vbuck1>;
+};
+
+&cpu6 {
+ cpu-supply = <&mt6315_6_vbuck1>;
+};
+
+&cpu7 {
+ cpu-supply = <&mt6315_6_vbuck1>;
+};
+
&eth {
phy-mode = "rgmii-rxid";
phy-handle = <&rgmii_phy>;
@@ -343,6 +375,14 @@
};
};
+&mfg0 {
+ domain-supply = <&mt6315_7_vbuck1>;
+};
+
+&mfg1 {
+ domain-supply = <&mt6359_vsram_others_ldo_reg>;
+};
+
/* MMC0 Controller: eMMC (HS400). Power lines are shared with UFS! */
&mmc0 {
pinctrl-names = "default", "state_uhs";
@@ -434,6 +474,8 @@
};
&pio {
+ mediatek,rsel-resistance-in-si-unit;
+
eth_default_pins: eth-default-pins {
pins-cc {
pinmux = <PINMUX_GPIO85__FUNC_GBE_TXC>,
@@ -509,7 +551,7 @@
pins-bus {
pinmux = <PINMUX_GPIO12__FUNC_SDA2>,
<PINMUX_GPIO13__FUNC_SCL2>;
- bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ bias-pull-up = <1000>;
drive-strength = <6>;
drive-strength-microamp = <1000>;
};
@@ -519,7 +561,7 @@
pins-bus {
pinmux = <PINMUX_GPIO16__FUNC_SDA4>,
<PINMUX_GPIO17__FUNC_SCL4>;
- bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ bias-pull-up = <1000>;
drive-strength-microamp = <1000>;
};
};
@@ -528,7 +570,7 @@
pins {
pinmux = <PINMUX_GPIO25__FUNC_SDA6>,
<PINMUX_GPIO26__FUNC_SCL6>;
- bias-pull-up = <MTK_PULL_SET_RSEL_111>;
+ bias-disable;
};
};
@@ -683,6 +725,26 @@
};
};
+ usb3_port0_pins: usb3p0-default-pins {
+ pins-vbus {
+ pinmux = <PINMUX_GPIO63__FUNC_VBUSVALID>;
+ input-enable;
+ };
+ };
+
+ usb2_port0_pins: usb2p0-default-pins {
+ pins-iddig {
+ pinmux = <PINMUX_GPIO130__FUNC_IDDIG_1P>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins-vbus {
+ pinmux = <PINMUX_GPIO131__FUNC_USB_DRVVBUS_1P>;
+ output-low;
+ };
+ };
+
wifi_vreg_pins: wifi-vreg-pins {
pins-wifi-pmu-en {
pinmux = <PINMUX_GPIO65__FUNC_GPIO65>;
@@ -707,6 +769,10 @@
status = "okay";
};
+&pciephy {
+ status = "okay";
+};
+
&pmic {
interrupts-extended = <&pio 222 IRQ_TYPE_LEVEL_HIGH>;
};
@@ -774,6 +840,18 @@
};
};
+&u3phy0 {
+ status = "okay";
+};
+
+&u3phy1 {
+ status = "okay";
+};
+
+&u3phy2 {
+ status = "okay";
+};
+
&uart0 {
/* Exposed at 40 pin connector */
pinctrl-0 = <&uart0_pins>;
@@ -789,6 +867,8 @@
};
&ssusb0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb3_port0_pins>;
role-switch-default-mode = "host";
usb-role-switch;
vusb33-supply = <&mt6359_vusb_ldo_reg>;
@@ -802,6 +882,8 @@
};
&ssusb2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2_port0_pins>;
vusb33-supply = <&mt6359_vusb_ldo_reg>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi
index 2c5574734c9e..e60acc74e822 100644
--- a/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi
@@ -13,6 +13,20 @@
priority = <200>;
};
+ i2c0_imux: i2c-mux-0 {
+ compatible = "i2c-mux-pinctrl";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-parent = <&i2c0>;
+ };
+
+ i2c0_emux: i2c-mux-1 {
+ compatible = "i2c-mux-gpio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-parent = <&i2c0>;
+ };
+
leds {
compatible = "gpio-leds";
led-0 {
@@ -248,6 +262,186 @@
default-state = "off";
};
};
+
+ sfp_eth12: sfp-eth12 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp1>;
+ tx-disable-gpios = <&sgpio_out2 11 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 11 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 11 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 12 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth13: sfp-eth13 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp2>;
+ tx-disable-gpios = <&sgpio_out2 12 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 12 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 12 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 13 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth14: sfp-eth14 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp3>;
+ tx-disable-gpios = <&sgpio_out2 13 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 13 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 13 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 14 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth15: sfp-eth15 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp4>;
+ tx-disable-gpios = <&sgpio_out2 14 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 14 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 14 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 15 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth48: sfp-eth48 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp5>;
+ tx-disable-gpios = <&sgpio_out2 15 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 15 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 15 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 16 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth49: sfp-eth49 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp6>;
+ tx-disable-gpios = <&sgpio_out2 16 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 16 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 16 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 17 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth50: sfp-eth50 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp7>;
+ tx-disable-gpios = <&sgpio_out2 17 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 17 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 17 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 18 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth51: sfp-eth51 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp8>;
+ tx-disable-gpios = <&sgpio_out2 18 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 18 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 18 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 19 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth52: sfp-eth52 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp9>;
+ tx-disable-gpios = <&sgpio_out2 19 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 19 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 19 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 20 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth53: sfp-eth53 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp10>;
+ tx-disable-gpios = <&sgpio_out2 20 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 20 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 20 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 21 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth54: sfp-eth54 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp11>;
+ tx-disable-gpios = <&sgpio_out2 21 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 21 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 21 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 22 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth55: sfp-eth55 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp12>;
+ tx-disable-gpios = <&sgpio_out2 22 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 22 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 22 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 23 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth56: sfp-eth56 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp13>;
+ tx-disable-gpios = <&sgpio_out2 23 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 23 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 23 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 24 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth57: sfp-eth57 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp14>;
+ tx-disable-gpios = <&sgpio_out2 24 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 24 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 24 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 25 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth58: sfp-eth58 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp15>;
+ tx-disable-gpios = <&sgpio_out2 25 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 25 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 25 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 26 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth59: sfp-eth59 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp16>;
+ tx-disable-gpios = <&sgpio_out2 26 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 26 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 26 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 27 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth60: sfp-eth60 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp17>;
+ tx-disable-gpios = <&sgpio_out2 27 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 27 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 27 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 28 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth61: sfp-eth61 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp18>;
+ tx-disable-gpios = <&sgpio_out2 28 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 28 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 28 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 29 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth62: sfp-eth62 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp19>;
+ tx-disable-gpios = <&sgpio_out2 29 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 29 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 29 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 30 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth63: sfp-eth63 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp20>;
+ tx-disable-gpios = <&sgpio_out2 30 1 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sgpio_in2 30 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 30 2 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 31 0 GPIO_ACTIVE_HIGH>;
+ };
};
&sgpio0 {
@@ -385,21 +579,6 @@
};
};
-&axi {
- i2c0_imux: i2c-mux-0 {
- compatible = "i2c-mux-pinctrl";
- #address-cells = <1>;
- #size-cells = <0>;
- i2c-parent = <&i2c0>;
- };
- i2c0_emux: i2c-mux-1 {
- compatible = "i2c-mux-gpio";
- #address-cells = <1>;
- #size-cells = <0>;
- i2c-parent = <&i2c0>;
- };
-};
-
&i2c0_imux {
pinctrl-names =
"i2c_sfp1", "i2c_sfp2", "i2c_sfp3", "i2c_sfp4",
@@ -535,169 +714,6 @@
};
};
-&axi {
- sfp_eth12: sfp-eth12 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp1>;
- tx-disable-gpios = <&sgpio_out2 11 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 11 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 11 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 12 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth13: sfp-eth13 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp2>;
- tx-disable-gpios = <&sgpio_out2 12 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 12 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 12 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 13 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth14: sfp-eth14 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp3>;
- tx-disable-gpios = <&sgpio_out2 13 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 13 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 13 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 14 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth15: sfp-eth15 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp4>;
- tx-disable-gpios = <&sgpio_out2 14 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 14 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 14 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 15 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth48: sfp-eth48 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp5>;
- tx-disable-gpios = <&sgpio_out2 15 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 15 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 15 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 16 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth49: sfp-eth49 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp6>;
- tx-disable-gpios = <&sgpio_out2 16 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 16 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 16 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 17 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth50: sfp-eth50 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp7>;
- tx-disable-gpios = <&sgpio_out2 17 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 17 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 17 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 18 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth51: sfp-eth51 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp8>;
- tx-disable-gpios = <&sgpio_out2 18 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 18 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 18 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 19 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth52: sfp-eth52 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp9>;
- tx-disable-gpios = <&sgpio_out2 19 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 19 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 19 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 20 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth53: sfp-eth53 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp10>;
- tx-disable-gpios = <&sgpio_out2 20 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 20 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 20 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 21 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth54: sfp-eth54 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp11>;
- tx-disable-gpios = <&sgpio_out2 21 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 21 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 21 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 22 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth55: sfp-eth55 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp12>;
- tx-disable-gpios = <&sgpio_out2 22 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 22 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 22 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 23 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth56: sfp-eth56 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp13>;
- tx-disable-gpios = <&sgpio_out2 23 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 23 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 23 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 24 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth57: sfp-eth57 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp14>;
- tx-disable-gpios = <&sgpio_out2 24 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 24 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 24 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 25 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth58: sfp-eth58 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp15>;
- tx-disable-gpios = <&sgpio_out2 25 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 25 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 25 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 26 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth59: sfp-eth59 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp16>;
- tx-disable-gpios = <&sgpio_out2 26 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 26 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 26 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 27 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth60: sfp-eth60 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp17>;
- tx-disable-gpios = <&sgpio_out2 27 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 27 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 27 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 28 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth61: sfp-eth61 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp18>;
- tx-disable-gpios = <&sgpio_out2 28 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 28 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 28 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 29 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth62: sfp-eth62 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp19>;
- tx-disable-gpios = <&sgpio_out2 29 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 29 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 29 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 30 0 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth63: sfp-eth63 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp20>;
- tx-disable-gpios = <&sgpio_out2 30 1 GPIO_ACTIVE_LOW>;
- los-gpios = <&sgpio_in2 30 1 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 30 2 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 31 0 GPIO_ACTIVE_HIGH>;
- };
-};
-
&switch {
ethernet-ports {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi
index af2f1831f07f..196868898f49 100644
--- a/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi
@@ -13,6 +13,13 @@
priority = <200>;
};
+ i2c0_imux: i2c-mux {
+ compatible = "i2c-mux-pinctrl";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-parent = <&i2c0>;
+ };
+
leds {
compatible = "gpio-leds";
led-0 {
@@ -56,6 +63,46 @@
default-state = "off";
};
};
+
+ sfp_eth60: sfp-eth60 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp1>;
+ tx-disable-gpios = <&sgpio_out2 28 0 GPIO_ACTIVE_LOW>;
+ rate-select0-gpios = <&sgpio_out2 28 1 GPIO_ACTIVE_HIGH>;
+ los-gpios = <&sgpio_in2 28 0 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 28 1 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 28 2 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth61: sfp-eth61 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp2>;
+ tx-disable-gpios = <&sgpio_out2 29 0 GPIO_ACTIVE_LOW>;
+ rate-select0-gpios = <&sgpio_out2 29 1 GPIO_ACTIVE_HIGH>;
+ los-gpios = <&sgpio_in2 29 0 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 29 1 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 29 2 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth62: sfp-eth62 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp3>;
+ tx-disable-gpios = <&sgpio_out2 30 0 GPIO_ACTIVE_LOW>;
+ rate-select0-gpios = <&sgpio_out2 30 1 GPIO_ACTIVE_HIGH>;
+ los-gpios = <&sgpio_in2 30 0 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 30 1 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 30 2 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp_eth63: sfp-eth63 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp4>;
+ tx-disable-gpios = <&sgpio_out2 31 0 GPIO_ACTIVE_LOW>;
+ rate-select0-gpios = <&sgpio_out2 31 1 GPIO_ACTIVE_HIGH>;
+ los-gpios = <&sgpio_in2 31 0 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sgpio_in2 31 1 GPIO_ACTIVE_LOW>;
+ tx-fault-gpios = <&sgpio_in2 31 2 GPIO_ACTIVE_HIGH>;
+ };
};
&gpio {
@@ -119,15 +166,6 @@
microchip,sgpio-port-ranges = <0 0>, <16 18>, <28 31>;
};
-&axi {
- i2c0_imux: i2c-mux {
- compatible = "i2c-mux-pinctrl";
- #address-cells = <1>;
- #size-cells = <0>;
- i2c-parent = <&i2c0>;
- };
-};
-
&i2c0_imux {
pinctrl-names =
"i2c_sfp1", "i2c_sfp2", "i2c_sfp3", "i2c_sfp4",
@@ -159,45 +197,6 @@
};
};
-&axi {
- sfp_eth60: sfp-eth60 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp1>;
- tx-disable-gpios = <&sgpio_out2 28 0 GPIO_ACTIVE_LOW>;
- rate-select0-gpios = <&sgpio_out2 28 1 GPIO_ACTIVE_HIGH>;
- los-gpios = <&sgpio_in2 28 0 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 28 1 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 28 2 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth61: sfp-eth61 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp2>;
- tx-disable-gpios = <&sgpio_out2 29 0 GPIO_ACTIVE_LOW>;
- rate-select0-gpios = <&sgpio_out2 29 1 GPIO_ACTIVE_HIGH>;
- los-gpios = <&sgpio_in2 29 0 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 29 1 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 29 2 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth62: sfp-eth62 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp3>;
- tx-disable-gpios = <&sgpio_out2 30 0 GPIO_ACTIVE_LOW>;
- rate-select0-gpios = <&sgpio_out2 30 1 GPIO_ACTIVE_HIGH>;
- los-gpios = <&sgpio_in2 30 0 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 30 1 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 30 2 GPIO_ACTIVE_HIGH>;
- };
- sfp_eth63: sfp-eth63 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c_sfp4>;
- tx-disable-gpios = <&sgpio_out2 31 0 GPIO_ACTIVE_LOW>;
- rate-select0-gpios = <&sgpio_out2 31 1 GPIO_ACTIVE_HIGH>;
- los-gpios = <&sgpio_in2 31 0 GPIO_ACTIVE_HIGH>;
- mod-def0-gpios = <&sgpio_in2 31 1 GPIO_ACTIVE_LOW>;
- tx-fault-gpios = <&sgpio_in2 31 2 GPIO_ACTIVE_HIGH>;
- };
-};
-
&mdio0 {
status = "okay";
phy0: ethernet-phy@0 {
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts
index 1607ee14216f..82a59e33c46c 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts
@@ -1,11 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
-#include <dt-bindings/input/linux-event-codes.h>
-#include <dt-bindings/input/gpio-keys.h>
-
-#include "tegra234-p3767.dtsi"
-#include "tegra234-p3768-0000.dtsi"
+#include "tegra234-p3768-0000+p3767.dtsi"
/ {
compatible = "nvidia,p3768-0000+p3767-0000", "nvidia,p3767-0000", "nvidia,tegra234";
@@ -29,83 +25,12 @@
status = "okay";
};
- pwm@32a0000 {
- assigned-clocks = <&bpmp TEGRA234_CLK_PWM3>;
- assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
- status = "okay";
- };
-
hda@3510000 {
nvidia,model = "NVIDIA Jetson Orin NX HDA";
};
-
- padctl@3520000 {
- status = "okay";
- };
- };
-
- gpio-keys {
- compatible = "gpio-keys";
-
- 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>;
- };
- };
-
- pwm-fan {
- cooling-levels = <0 88 187 255>;
- };
-
- 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_aon TEGRA234_AON_GPIO(AA, 5) GPIO_ACTIVE_HIGH>;
- enable-active-high;
};
sound {
label = "NVIDIA Jetson Orin NX APE";
};
-
- 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>;
- };
-
- map-active-2 {
- cooling-device = <&fan 2 3>;
- trip = <&tj_trip_active2>;
- };
- };
- };
- };
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0005.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0005.dts
index dc2d4bef1e83..9f5e07012b87 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0005.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0005.dts
@@ -1,11 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
-#include <dt-bindings/input/linux-event-codes.h>
-#include <dt-bindings/input/gpio-keys.h>
-
-#include "tegra234-p3767.dtsi"
-#include "tegra234-p3768-0000.dtsi"
+#include "tegra234-p3768-0000+p3767.dtsi"
/ {
compatible = "nvidia,p3768-0000+p3767-0005", "nvidia,p3767-0005", "nvidia,tegra234";
@@ -17,32 +13,7 @@
};
};
- pwm-fan {
- cooling-levels = <0 88 187 255>;
- };
-
sound {
label = "NVIDIA Jetson Orin Nano APE";
};
-
- 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>;
- };
-
- map-active-2 {
- cooling-device = <&fan 2 3>;
- trip = <&tj_trip_active2>;
- };
- };
- };
- };
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi
index 5d0298b6c30d..6d64a24fa251 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi
@@ -1,7 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/input/gpio-keys.h>
+
+#include "tegra234-p3767.dtsi"
+
/ {
- compatible = "nvidia,p3768-0000";
aliases {
serial0 = &tcu;
@@ -210,6 +214,7 @@
compatible = "pwm-fan";
pwms = <&pwm3 0 45334>;
#cooling-cells = <2>;
+ cooling-levels = <0 88 187 255>;
};
vdd_1v8_sys: regulator-vdd-1v8-sys {
@@ -241,4 +246,25 @@
serial {
status = "okay";
};
+
+ 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>;
+ };
+
+ map-active-2 {
+ cooling-device = <&fan 2 3>;
+ trip = <&tj_trip_active2>;
+ };
+ };
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index f63abb43e9fe..0e5c810304fb 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -5,11 +5,13 @@ apq8016-sbc-usb-host-dtbs := apq8016-sbc.dtb apq8016-sbc-usb-host.dtbo
dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-usb-host.dtb
dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-d3-camera-mezzanine.dtb
+dtb-$(CONFIG_ARCH_QCOM) += apq8016-schneider-hmibsc.dtb
dtb-$(CONFIG_ARCH_QCOM) += apq8039-t2.dtb
dtb-$(CONFIG_ARCH_QCOM) += apq8094-sony-xperia-kitakami-karin_windy.dtb
dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb
dtb-$(CONFIG_ARCH_QCOM) += apq8096-ifc6640.dtb
dtb-$(CONFIG_ARCH_QCOM) += ipq5018-rdp432-c2.dtb
+dtb-$(CONFIG_ARCH_QCOM) += ipq5018-tplink-archer-ax55-v1.dtb
dtb-$(CONFIG_ARCH_QCOM) += ipq5332-rdp441.dtb
dtb-$(CONFIG_ARCH_QCOM) += ipq5332-rdp442.dtb
dtb-$(CONFIG_ARCH_QCOM) += ipq5332-rdp468.dtb
@@ -29,8 +31,13 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-alcatel-idol347.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-asus-z00l.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-gplus-fl8005a.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-huawei-g7.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8916-lg-c50.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8916-lg-m216.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-longcheer-l8150.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-longcheer-l8910.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8916-motorola-harpia.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8916-motorola-osprey.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8916-motorola-surnia.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-a3u-eur.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-a5u-eur.dtb
@@ -93,9 +100,11 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-poplar.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-xiaomi-sagit.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcm6490-fairphone-fp5.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcm6490-idp.dtb
+dtb-$(CONFIG_ARCH_QCOM) += qcm6490-shift-otter.dtb
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) += qdu1000-idp.dtb
dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1.dtb
dtb-$(CONFIG_ARCH_QCOM) += qrb4210-rb2.dtb
@@ -106,6 +115,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sa8155p-adp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sa8295p-adp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sa8540p-ride.dtb
dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-acer-aspire1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-idp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1.dtb
@@ -175,6 +185,7 @@ 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) += sda660-inforce-ifc6560.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sdm450-lenovo-tbx605f.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm450-motorola-ali.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-ganges-kirin.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-discovery.dtb
@@ -241,8 +252,16 @@ dtb-$(CONFIG_ARCH_QCOM) += sm8450-sony-xperia-nagara-pdx224.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8550-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8550-qrd.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm8550-samsung-q5q.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8550-sony-xperia-yodo-pdx234.dtb
+
+sm8650-hdk-display-card-dtbs := sm8650-hdk.dtb sm8650-hdk-display-card.dtbo
+
+dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8650-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8650-qrd.dtb
+dtb-$(CONFIG_ARCH_QCOM) += x1e80100-asus-vivobook-s15.dtb
dtb-$(CONFIG_ARCH_QCOM) += x1e80100-crd.dtb
+dtb-$(CONFIG_ARCH_QCOM) += x1e80100-lenovo-yoga-slim7x.dtb
dtb-$(CONFIG_ARCH_QCOM) += x1e80100-qcp.dtb
diff --git a/arch/arm64/boot/dts/qcom/apq8016-schneider-hmibsc.dts b/arch/arm64/boot/dts/qcom/apq8016-schneider-hmibsc.dts
new file mode 100644
index 000000000000..75c6137e5a11
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8016-schneider-hmibsc.dts
@@ -0,0 +1,491 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024, Linaro Ltd.
+ */
+
+/dts-v1/;
+
+#include "msm8916-pm8916.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
+#include <dt-bindings/sound/apq8016-lpass.h>
+
+/ {
+ model = "Schneider Electric HMIBSC Board";
+ compatible = "schneider,apq8016-hmibsc", "qcom,apq8016";
+
+ aliases {
+ i2c1 = &blsp_i2c6;
+ i2c3 = &blsp_i2c4;
+ i2c4 = &blsp_i2c3;
+ mmc0 = &sdhc_1; /* eMMC */
+ mmc1 = &sdhc_2; /* SD card */
+ serial0 = &blsp_uart1;
+ serial1 = &blsp_uart2;
+ spi0 = &blsp_spi5;
+ usid0 = &pm8916_0;
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ hdmi-out {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con: endpoint {
+ remote-endpoint = <&adv7533_out>;
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ autorepeat;
+ pinctrl-0 = <&msm_key_volp_n_default>;
+ pinctrl-names = "default";
+
+ button {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&tlmm 107 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-0 = <&pm8916_mpps_leds>;
+ pinctrl-names = "default";
+
+ led-1 {
+ function = LED_FUNCTION_WLAN;
+ color = <LED_COLOR_ID_YELLOW>;
+ gpios = <&pm8916_mpps 2 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "phy0tx";
+ default-state = "off";
+ };
+
+ led-2 {
+ function = LED_FUNCTION_BLUETOOTH;
+ color = <LED_COLOR_ID_BLUE>;
+ gpios = <&pm8916_mpps 3 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "bluetooth-power";
+ default-state = "off";
+ };
+ };
+
+ memory@80000000 {
+ reg = <0 0x80000000 0 0x40000000>;
+ };
+
+ reserved-memory {
+ ramoops@bff00000 {
+ compatible = "ramoops";
+ reg = <0x0 0xbff00000 0x0 0x100000>;
+ record-size = <0x20000>;
+ console-size = <0x20000>;
+ ftrace-size = <0x20000>;
+ ecc-size = <16>;
+ };
+ };
+
+ usb-hub {
+ compatible = "smsc,usb3503";
+ reset-gpios = <&pm8916_gpios 1 GPIO_ACTIVE_LOW>;
+ initial-mode = <1>;
+ };
+
+ usb_id: usb-id {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&usb_id_default>;
+ pinctrl-names = "default";
+ };
+};
+
+&blsp_i2c3 {
+ status = "okay";
+
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
+};
+
+&blsp_i2c4 {
+ status = "okay";
+
+ adv_bridge: bridge@39 {
+ compatible = "adi,adv7533";
+ reg = <0x39>;
+ interrupts-extended = <&tlmm 31 IRQ_TYPE_EDGE_FALLING>;
+
+ adi,dsi-lanes = <4>;
+ clocks = <&rpmcc RPM_SMD_BB_CLK2>;
+ clock-names = "cec";
+ pd-gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>;
+
+ avdd-supply = <&pm8916_l6>;
+ a2vdd-supply = <&pm8916_l6>;
+ dvdd-supply = <&pm8916_l6>;
+ pvdd-supply = <&pm8916_l6>;
+ v1p2-supply = <&pm8916_l6>;
+ v3p3-supply = <&pm8916_l17>;
+
+ pinctrl-0 = <&adv7533_int_active &adv7533_switch_active>;
+ pinctrl-1 = <&adv7533_int_suspend &adv7533_switch_suspend>;
+ pinctrl-names = "default","sleep";
+ #sound-dai-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ adv7533_in: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ adv7533_out: endpoint {
+ remote-endpoint = <&hdmi_con>;
+ };
+ };
+ };
+ };
+};
+
+&blsp_i2c6 {
+ status = "okay";
+
+ rtc@30 {
+ compatible = "sii,s35390a";
+ reg = <0x30>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c256";
+ reg = <0x50>;
+ };
+};
+
+&blsp_spi5 {
+ cs-gpios = <&tlmm 18 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ tpm@0 {
+ compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+ reg = <0>;
+ spi-max-frequency = <500000>;
+ };
+};
+
+&blsp_uart1 {
+ label = "UART0";
+ status = "okay";
+};
+
+&blsp_uart2 {
+ label = "UART1";
+ status = "okay";
+};
+
+&lpass {
+ status = "okay";
+};
+
+&mdss {
+ status = "okay";
+};
+
+&mdss_dsi0_out {
+ data-lanes = <0 1 2 3>;
+ remote-endpoint = <&adv7533_in>;
+};
+
+&pm8916_codec {
+ qcom,mbhc-vthreshold-low = <75 150 237 450 500>;
+ qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
+ status = "okay";
+};
+
+&pm8916_gpios {
+ gpio-line-names =
+ "USB_HUB_RESET_N_PM",
+ "USB_SW_SEL_PM",
+ "NC",
+ "NC";
+
+ usb_hub_reset_pm: usb-hub-reset-pm-state {
+ pins = "gpio1";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ input-disable;
+ output-high;
+ };
+
+ usb_hub_reset_pm_device: usb-hub-reset-pm-device-state {
+ pins = "gpio1";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ input-disable;
+ output-low;
+ };
+
+ usb_sw_sel_pm: usb-sw-sel-pm-state {
+ pins = "gpio2";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ power-source = <PM8916_GPIO_VPH>;
+ input-disable;
+ output-high;
+ };
+
+ usb_sw_sel_pm_device: usb-sw-sel-pm-device-state {
+ pins = "gpio2";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ power-source = <PM8916_GPIO_VPH>;
+ input-disable;
+ output-low;
+ };
+};
+
+&pm8916_mpps {
+ gpio-line-names =
+ "NC",
+ "WLAN_LED_CTRL",
+ "BT_LED_CTRL",
+ "NC";
+
+ pm8916_mpps_leds: pm8916-mpps-state {
+ pins = "mpp2", "mpp3";
+ function = "digital";
+ output-low;
+ };
+};
+
+&pm8916_resin {
+ linux,code = <KEY_POWER>;
+ status = "okay";
+};
+
+&pm8916_rpm_regulators {
+ pm8916_l17: l17 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&sdhc_1 {
+ status = "okay";
+};
+
+&sdhc_2 {
+ pinctrl-0 = <&sdc2_default &sdc2_cd_default>;
+ pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>;
+ pinctrl-names = "default", "sleep";
+ cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&sound {
+ pinctrl-0 = <&cdc_pdm_default &sec_mi2s_default>;
+ pinctrl-1 = <&cdc_pdm_sleep &sec_mi2s_sleep>;
+ pinctrl-names = "default", "sleep";
+ model = "HMIBSC";
+ audio-routing =
+ "AMIC2", "MIC BIAS Internal2",
+ "AMIC3", "MIC BIAS External1";
+ status = "okay";
+
+ quaternary-dai-link {
+ link-name = "ADV7533";
+ cpu {
+ sound-dai = <&lpass MI2S_QUATERNARY>;
+ };
+ codec {
+ sound-dai = <&adv_bridge 0>;
+ };
+ };
+
+ primary-dai-link {
+ link-name = "WCD";
+ cpu {
+ sound-dai = <&lpass MI2S_PRIMARY>;
+ };
+ codec {
+ sound-dai = <&lpass_codec 0>, <&pm8916_codec 0>;
+ };
+ };
+
+ tertiary-dai-link {
+ link-name = "WCD-Capture";
+ cpu {
+ sound-dai = <&lpass MI2S_TERTIARY>;
+ };
+ codec {
+ sound-dai = <&lpass_codec 1>, <&pm8916_codec 1>;
+ };
+ };
+};
+
+&tlmm {
+ pinctrl-0 = <&uart1_mux0_rs232_high &uart1_mux1_rs232_low>;
+ pinctrl-names = "default";
+
+ adv7533_int_active: adv533-int-active-state {
+ pins = "gpio31";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ adv7533_int_suspend: adv7533-int-suspend-state {
+ pins = "gpio31";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ adv7533_switch_active: adv7533-switch-active-state {
+ pins = "gpio32";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ adv7533_switch_suspend: adv7533-switch-suspend-state {
+ pins = "gpio32";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ msm_key_volp_n_default: msm-key-volp-n-default-state {
+ pins = "gpio107";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ sdc2_cd_default: sdc2-cd-default-state {
+ pins = "gpio38";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ /*
+ * UART1 being the debug console supports various modes of
+ * operation (RS-232/485/422) controlled via GPIOs configured
+ * mux as follows:
+ *
+ * gpio100 gpio99 UART mode
+ * 0 0 loopback
+ * 0 1 RS-232
+ * 1 0 RS-485
+ * 1 1 RS-422
+ *
+ * The default mode configured here is RS-232 mode.
+ */
+ uart1_mux0_rs232_high: uart1-mux0-rs232-state {
+ bootph-all;
+ pins = "gpio99";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-high;
+ };
+
+ uart1_mux1_rs232_low: uart1-mux1-rs232-state {
+ bootph-all;
+ pins = "gpio100";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+
+ usb_id_default: usb-id-default-state {
+ pins = "gpio110";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+};
+
+&usb {
+ extcon = <&usb_id>, <&usb_id>;
+ pinctrl-0 = <&usb_sw_sel_pm &usb_hub_reset_pm>;
+ pinctrl-1 = <&usb_sw_sel_pm_device &usb_hub_reset_pm_device>;
+ pinctrl-names = "default", "device";
+ status = "okay";
+};
+
+&usb_hs_phy {
+ extcon = <&usb_id>;
+};
+
+&wcnss {
+ firmware-name = "qcom/apq8016/wcnss.mbn";
+ status = "okay";
+};
+
+&wcnss_ctrl {
+ firmware-name = "qcom/apq8016/WCNSS_qcom_wlan_nv_sbc.bin";
+};
+
+&wcnss_iris {
+ compatible = "qcom,wcn3620";
+};
+
+&wcnss_mem {
+ status = "okay";
+};
+
+/* PINCTRL - additions to nodes defined in msm8916.dtsi */
+
+/*
+ * 2mA drive strength is not enough when connecting multiple
+ * I2C devices with different pull up resistors.
+ */
+&blsp_i2c4_default {
+ drive-strength = <16>;
+};
+
+&blsp_i2c6_default {
+ drive-strength = <16>;
+};
+
+&blsp_uart1_default {
+ bootph-all;
+};
+
+/* Enable CoreSight */
+&cti0 { status = "okay"; };
+&cti1 { status = "okay"; };
+&cti12 { status = "okay"; };
+&cti13 { status = "okay"; };
+&cti14 { status = "okay"; };
+&cti15 { status = "okay"; };
+&debug0 { status = "okay"; };
+&debug1 { status = "okay"; };
+&debug2 { status = "okay"; };
+&debug3 { status = "okay"; };
+&etf { status = "okay"; };
+&etm0 { status = "okay"; };
+&etm1 { status = "okay"; };
+&etm2 { status = "okay"; };
+&etm3 { status = "okay"; };
+&etr { status = "okay"; };
+&funnel0 { status = "okay"; };
+&funnel1 { status = "okay"; };
+&replicator { status = "okay"; };
+&stm { status = "okay"; };
+&tpiu { status = "okay"; };
diff --git a/arch/arm64/boot/dts/qcom/ipq5018-tplink-archer-ax55-v1.dts b/arch/arm64/boot/dts/qcom/ipq5018-tplink-archer-ax55-v1.dts
new file mode 100644
index 000000000000..5bb021cb29cd
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/ipq5018-tplink-archer-ax55-v1.dts
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+#include "ipq5018.dtsi"
+
+/ {
+ model = "TP-Link Archer AX55 v1";
+ compatible = "tplink,archer-ax55-v1", "qcom,ipq5018";
+
+ aliases {
+ serial0 = &blsp1_uart1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-0 = <&led_pins>;
+ pinctrl-names = "default";
+
+ led-0 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-1 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WAN_ONLINE;
+ gpios = <&tlmm 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-2 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WLAN_2GHZ;
+ gpios = <&tlmm 13 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-3 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_POWER;
+ gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-4 {
+ color = <LED_COLOR_ID_ORANGE>;
+ function = LED_FUNCTION_WAN;
+ gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-5 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_USB;
+ gpios = <&tlmm 38 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-6 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WLAN_5GHZ;
+ gpios = <&tlmm 39 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ buttons {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&button_pins>;
+ pinctrl-names = "default";
+
+ button-reset {
+ debounce-interval = <60>;
+ gpios = <&tlmm 25 GPIO_ACTIVE_LOW>;
+ label = "reset";
+ linux,code = <KEY_RESTART>;
+ };
+
+ button-wps {
+ debounce-interval = <60>;
+ gpios = <&tlmm 31 GPIO_ACTIVE_LOW>;
+ label = "wps";
+ linux,code = <KEY_WPS_BUTTON>;
+ };
+ };
+};
+
+&blsp1_uart1 {
+ pinctrl-0 = <&uart_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&sleep_clk {
+ clock-frequency = <32000>;
+};
+
+&tlmm {
+ button_pins: button-pins-state {
+ pins = "gpio25", "gpio31";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ led_pins: led-pins-state {
+ pins = "gpio10", "gpio11", "gpio13", "gpio18", "gpio22",
+ "gpio38", "gpio39";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ uart_pins: uart-pins-state {
+ pins = "gpio20", "gpio21";
+ function = "blsp0_uart0";
+ drive-strength = <8>;
+ bias-disable;
+ };
+};
+
+&xo_board_clk {
+ clock-frequency = <24000000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
index 32b178b639f0..7e6e2c121979 100644
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -179,7 +179,6 @@
<0>;
#clock-cells = <1>;
#reset-cells = <1>;
- #power-domain-cells = <1>;
};
tcsr_mutex: hwlock@1905000 {
diff --git a/arch/arm64/boot/dts/qcom/ipq5332.dtsi b/arch/arm64/boot/dts/qcom/ipq5332.dtsi
index 770d9c2fb456..573656587c0d 100644
--- a/arch/arm64/boot/dts/qcom/ipq5332.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5332.dtsi
@@ -208,7 +208,6 @@
reg = <0x01800000 0x80000>;
#clock-cells = <1>;
#reset-cells = <1>;
- #power-domain-cells = <1>;
clocks = <&xo_board>,
<&sleep_clk>,
<0>,
diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
index 17ab6c475958..e1e45da7f787 100644
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -396,7 +396,7 @@
};
};
- gcc: gcc@1800000 {
+ gcc: clock-controller@1800000 {
compatible = "qcom,gcc-ipq6018";
reg = <0x0 0x01800000 0x0 0x80000>;
clocks = <&xo>, <&sleep_clk>;
@@ -457,6 +457,25 @@
};
};
+ sdhc: mmc@7804000 {
+ compatible = "qcom,ipq6018-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0x0 0x07804000 0x0 0x1000>,
+ <0x0 0x07805000 0x0 0x1000>;
+ reg-names = "hc", "cqhci";
+
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC1_AHB_CLK>,
+ <&gcc GCC_SDCC1_APPS_CLK>,
+ <&xo>;
+ clock-names = "iface", "core", "xo";
+ resets = <&gcc GCC_SDCC1_BCR>;
+ max-frequency = <192000000>;
+ status = "disabled";
+ };
+
blsp_dma: dma-controller@7884000 {
compatible = "qcom,bam-v1.7.0";
reg = <0x0 0x07884000 0x0 0x2b000>;
@@ -685,6 +704,7 @@
clocks = <&xo>;
clock-names = "ref";
tx-fifo-resize;
+ snps,parkmode-disable-ss-quirk;
snps,is-utmi-l1-suspend;
snps,hird-threshold = /bits/ 8 <0x0>;
snps,dis_u2_susphy_quirk;
@@ -923,7 +943,6 @@
thermal-zones {
nss-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 4>;
trips {
@@ -937,7 +956,6 @@
nss-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 5>;
trips {
@@ -951,7 +969,6 @@
wcss-phya0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 7>;
trips {
@@ -979,7 +996,6 @@
cpu-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 13>;
trips {
@@ -1009,7 +1025,6 @@
lpass-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 14>;
trips {
@@ -1023,7 +1038,6 @@
ddrss-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 15>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
index 5d42de829e75..284a4553070f 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -363,7 +363,7 @@
};
};
- gcc: gcc@1800000 {
+ gcc: clock-controller@1800000 {
compatible = "qcom,gcc-ipq8074";
reg = <0x01800000 0x80000>;
clocks = <&xo>,
@@ -666,6 +666,7 @@
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
phys = <&qusb_phy_0>, <&ssphy_0>;
phy-names = "usb2-phy", "usb3-phy";
+ snps,parkmode-disable-ss-quirk;
snps,is-utmi-l1-suspend;
snps,hird-threshold = /bits/ 8 <0x0>;
snps,dis_u2_susphy_quirk;
@@ -715,6 +716,7 @@
interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
phys = <&qusb_phy_1>, <&ssphy_1>;
phy-names = "usb2-phy", "usb3-phy";
+ snps,parkmode-disable-ss-quirk;
snps,is-utmi-l1-suspend;
snps,hird-threshold = /bits/ 8 <0x0>;
snps,dis_u2_susphy_quirk;
@@ -982,7 +984,6 @@
thermal-zones {
nss-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 4>;
@@ -997,7 +998,6 @@
nss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 5>;
@@ -1012,7 +1012,6 @@
nss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 6>;
@@ -1027,7 +1026,6 @@
wcss-phya0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 7>;
@@ -1042,7 +1040,6 @@
wcss-phya1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 8>;
@@ -1057,7 +1054,6 @@
cpu0_thermal: cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 9>;
@@ -1072,7 +1068,6 @@
cpu1_thermal: cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 10>;
@@ -1087,7 +1082,6 @@
cpu2_thermal: cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 11>;
@@ -1102,7 +1096,6 @@
cpu3_thermal: cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 12>;
@@ -1117,7 +1110,6 @@
cluster_thermal: cluster-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 13>;
@@ -1132,7 +1124,6 @@
wcss-phyb0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 14>;
@@ -1147,7 +1138,6 @@
wcss-phyb1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 15>;
diff --git a/arch/arm64/boot/dts/qcom/ipq9574.dtsi b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
index 7f2e5cbf3bbb..48dfafea46a7 100644
--- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
@@ -8,6 +8,7 @@
#include <dt-bindings/clock/qcom,apss-ipq.h>
#include <dt-bindings/clock/qcom,ipq9574-gcc.h>
+#include <dt-bindings/interconnect/qcom,ipq9574.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/qcom,ipq9574-gcc.h>
#include <dt-bindings/thermal/thermal.h>
@@ -232,6 +233,16 @@
clock-names = "core";
};
+ mdio: mdio@90000 {
+ compatible = "qcom,ipq9574-mdio", "qcom,ipq4019-mdio";
+ reg = <0x00090000 0x64>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&gcc GCC_MDIO_AHB_CLK>;
+ clock-names = "gcc_mdio_ahb_clk";
+ status = "disabled";
+ };
+
qfprom: efuse@a4000 {
compatible = "qcom,ipq9574-qfprom", "qcom,qfprom";
reg = <0x000a4000 0x5a1>;
@@ -305,7 +316,7 @@
<0>;
#clock-cells = <1>;
#reset-cells = <1>;
- #power-domain-cells = <1>;
+ #interconnect-cells = <1>;
};
tcsr_mutex: hwlock@1905000 {
@@ -749,8 +760,6 @@
thermal-zones {
nss-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 3>;
trips {
@@ -763,8 +772,6 @@
};
ubi-0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 4>;
trips {
@@ -777,8 +784,6 @@
};
ubi-1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 5>;
trips {
@@ -791,8 +796,6 @@
};
ubi-2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 6>;
trips {
@@ -805,8 +808,6 @@
};
ubi-3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 7>;
trips {
@@ -819,8 +820,6 @@
};
cpuss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 8>;
trips {
@@ -833,8 +832,6 @@
};
cpuss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 9>;
trips {
@@ -847,8 +844,6 @@
};
cpu0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 10>;
trips {
@@ -877,8 +872,6 @@
};
cpu1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 11>;
trips {
@@ -907,8 +900,6 @@
};
cpu2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 12>;
trips {
@@ -937,8 +928,6 @@
};
cpu3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 13>;
trips {
@@ -967,8 +956,6 @@
};
wcss-phyb-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 14>;
trips {
@@ -981,8 +968,6 @@
};
top-glue-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens 15>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/msm8216-samsung-fortuna3g.dts b/arch/arm64/boot/dts/qcom/msm8216-samsung-fortuna3g.dts
index 366914be7d53..fba68bf8bf79 100644
--- a/arch/arm64/boot/dts/qcom/msm8216-samsung-fortuna3g.dts
+++ b/arch/arm64/boot/dts/qcom/msm8216-samsung-fortuna3g.dts
@@ -9,3 +9,17 @@
compatible = "samsung,fortuna3g", "qcom,msm8916";
chassis-type = "handset";
};
+
+&battery {
+ charge-term-current-microamp = <200000>;
+ constant-charge-current-max-microamp = <1000000>;
+ constant-charge-voltage-max-microvolt = <4350000>;
+};
+
+&st_accel {
+ status = "okay";
+};
+
+&st_magn {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts b/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts
index b32c7a97394d..b4ce14a79370 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts
@@ -3,6 +3,7 @@
/dts-v1/;
#include "msm8916-pm8916.dtsi"
+#include "msm8916-modem-qdsp6.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
@@ -135,6 +136,17 @@
status = "okay";
};
+&mpss_mem {
+ reg = <0x0 0x86800000 0x0 0x4500000>;
+};
+
+&pm8916_codec {
+ qcom,micbias-lvl = <2800>;
+ qcom,mbhc-vthreshold-low = <150 237 450 500 590>;
+ qcom,mbhc-vthreshold-high = <150 237 450 500 590>;
+ qcom,hphl-jack-type-normally-open;
+};
+
&pm8916_resin {
linux,code = <KEY_VOLUMEDOWN>;
status = "okay";
@@ -170,6 +182,20 @@
status = "okay";
};
+&sound {
+ model = "acer-a1-724";
+ audio-routing =
+ "DMIC1", "MIC BIAS External1",
+ "DMIC1", "Digital Mic1",
+ "AMIC2", "MIC BIAS Internal2",
+ "DMIC2", "MIC BIAS External1",
+ "DMIC2", "Digital Mic2";
+
+ pinctrl-0 = <&cdc_pdm_default &sec_mi2s_default &pri_mi2s_mclk_default &cdc_dmic_default>;
+ pinctrl-1 = <&cdc_pdm_sleep &sec_mi2s_sleep &pri_mi2s_mclk_sleep &cdc_dmic_sleep>;
+ pinctrl-names = "default", "sleep";
+};
+
&usb {
extcon = <&usb_id>, <&usb_id>;
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts b/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts
index b748d140b52e..f7be7e371820 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts
@@ -3,6 +3,7 @@
/dts-v1/;
#include "msm8916-pm8916.dtsi"
+#include "msm8916-modem-qdsp6.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
@@ -23,6 +24,28 @@
stdout-path = "serial0";
};
+ battery: battery {
+ compatible = "simple-battery";
+ device-chemistry = "lithium-ion-polymer";
+ voltage-min-design-microvolt = <3700000>;
+ voltage-max-design-microvolt = <4200000>;
+ energy-full-design-microwatt-hours = <13690000>;
+ charge-full-design-microamp-hours = <3700000>;
+
+ ocv-capacity-celsius = <25>;
+ ocv-capacity-table-0 =
+ <4186000 100>, <4126000 95>, <4078000 90>,
+ <4036000 85>, <3997000 80>, <3962000 75>,
+ <3932000 70>, <3904000 65>, <3874000 60>,
+ <3839000 55>, <3809000 50>, <3792000 45>,
+ <3780000 40>, <3772000 35>, <3764000 30>,
+ <3752000 25>, <3731000 20>, <3704000 16>,
+ <3677000 13>, <3670000 11>, <3668000 10>,
+ <3666000 9>, <3662000 8>, <3658000 7>, <3648000 6>,
+ <3624000 5>, <3580000 4>, <3518000 3>, <3434000 2>,
+ <3310000 1>, <3000000 0>;
+ };
+
flash-led-controller {
/* Actually qcom,leds-gpio-flash */
compatible = "sgmicro,sgm3140";
@@ -111,6 +134,22 @@
status = "okay";
};
+&mpss_mem {
+ reg = <0x0 0x86800000 0x0 0x5000000>;
+};
+
+&pm8916_bms {
+ monitored-battery = <&battery>;
+ status = "okay";
+};
+
+&pm8916_codec {
+ qcom,micbias-lvl = <2800>;
+ qcom,mbhc-vthreshold-low = <150 180 237 450 500>;
+ qcom,mbhc-vthreshold-high = <150 180 237 450 500>;
+ qcom,hphl-jack-type-normally-open;
+};
+
&pm8916_resin {
linux,code = <KEY_VOLUMEDOWN>;
status = "okay";
@@ -141,6 +180,14 @@
status = "okay";
};
+&sound {
+ model = "msm8916-1mic";
+ audio-routing =
+ "AMIC1", "MIC BIAS External1",
+ "AMIC2", "MIC BIAS Internal2",
+ "AMIC3", "MIC BIAS External1";
+};
+
&usb {
extcon = <&usb_id>, <&usb_id>;
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-lg-c50.dts b/arch/arm64/boot/dts/qcom/msm8916-lg-c50.dts
new file mode 100644
index 000000000000..a823a1c40208
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-lg-c50.dts
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include "msm8916-pm8916.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "LG Leon LTE";
+ compatible = "lg,c50", "qcom,msm8916";
+ chassis-type = "handset";
+
+ aliases {
+ mmc0 = &sdhc_1; /* eMMC */
+ mmc1 = &sdhc_2; /* SD card */
+ serial0 = &blsp_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&gpio_keys_default>;
+ pinctrl-names = "default";
+
+ label = "GPIO Buttons";
+
+ volume-up-button {
+ label = "Volume Up";
+ gpios = <&tlmm 108 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down-button {
+ label = "Volume Down";
+ gpios = <&tlmm 107 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+
+ reg_sd_vmmc: regulator-sdcard-vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "sdcard-vmmc";
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+
+ gpio = <&tlmm 60 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ startup-delay-us = <5000>;
+
+ pinctrl-0 = <&sd_vmmc_en_default>;
+ pinctrl-names = "default";
+ };
+};
+
+&blsp_uart2 {
+ status = "okay";
+};
+
+&pm8916_usbin {
+ status = "okay";
+};
+
+&pm8916_vib {
+ status = "okay";
+};
+
+&sdhc_1 {
+ status = "okay";
+};
+
+&sdhc_2 {
+ vmmc-supply = <&reg_sd_vmmc>;
+
+ pinctrl-0 = <&sdc2_default &sdc2_cd_default>;
+ pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>;
+ pinctrl-names = "default", "sleep";
+
+ cd-gpios = <&tlmm 38 GPIO_ACTIVE_HIGH>;
+
+ status = "okay";
+};
+
+&usb {
+ dr_mode = "peripheral";
+ extcon = <&pm8916_usbin>;
+ status = "okay";
+};
+
+&usb_hs_phy {
+ extcon = <&pm8916_usbin>;
+};
+
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
+&wcnss {
+ status = "okay";
+};
+
+&wcnss_iris {
+ compatible = "qcom,wcn3620";
+};
+
+&wcnss_mem {
+ status = "okay";
+};
+
+&tlmm {
+ gpio_keys_default: gpio-keys-default-state {
+ pins = "gpio107", "gpio108";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ sd_vmmc_en_default: sd-vmmc-en-default-state {
+ pins = "gpio60";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ sdc2_cd_default: sdc2-cd-default-state {
+ pins = "gpio38";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-lg-m216.dts b/arch/arm64/boot/dts/qcom/msm8916-lg-m216.dts
new file mode 100644
index 000000000000..07345e694f6f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-lg-m216.dts
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include "msm8916-pm8916.dtsi"
+#include "msm8916-modem-qdsp6.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "LG K10 (K420n)";
+ compatible = "lg,m216", "qcom,msm8916";
+ chassis-type = "handset";
+
+ aliases {
+ mmc0 = &sdhc_1; /* eMMC */
+ mmc1 = &sdhc_2; /* SD card */
+ serial0 = &blsp_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ battery: battery {
+ compatible = "simple-battery";
+ voltage-min-design-microvolt = <3300000>;
+ voltage-max-design-microvolt = <4350000>;
+ energy-full-design-microwatt-hours = <8800000>;
+ charge-full-design-microamp-hours = <2300000>;
+
+ ocv-capacity-celsius = <25>;
+ ocv-capacity-table-0 = <4342000 100>, <4266000 95>, <4206000 90>,
+ <4148000 85>, <4094000 80>, <4046000 75>, <3994000 70>,
+ <3956000 65>, <3916000 60>, <3866000 55>, <3831000 50>,
+ <3808000 45>, <3789000 40>, <3776000 35>, <3769000 30>,
+ <3760000 25>, <3740000 20>, <3712000 16>, <3684000 13>,
+ <3676000 11>, <3674000 10>, <3672000 9>, <3669000 8>,
+ <3665000 7>, <3660000 6>, <3643000 5>, <3602000 4>,
+ <3542000 3>, <3458000 2>, <3326000 1>, <3000000 0>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&gpio_keys_default>;
+ pinctrl-names = "default";
+
+ label = "GPIO Buttons";
+
+ volume-up-button {
+ label = "Volume Up";
+ gpios = <&tlmm 107 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down-button {
+ label = "Volume Down";
+ gpios = <&tlmm 108 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+};
+
+&blsp_i2c2 {
+ status = "okay";
+
+ accelerometer@11 {
+ compatible = "bosch,bmc150_accel";
+ reg = <0x11>;
+
+ interrupts-extended = <&tlmm 115 IRQ_TYPE_EDGE_RISING>;
+
+ mount-matrix = "0", "1", "0",
+ "-1", "0", "0",
+ "0", "0", "1";
+
+ vdd-supply = <&pm8916_l17>;
+ vddio-supply = <&pm8916_l6>;
+
+ pinctrl-0 = <&accel_int_default>;
+ pinctrl-names = "default";
+ };
+
+ magnetometer@13 {
+ compatible = "bosch,bmc150_magn";
+ reg = <0x13>;
+
+ interrupts-extended = <&tlmm 69 IRQ_TYPE_EDGE_RISING>;
+
+ vdd-supply = <&pm8916_l17>;
+ vddio-supply = <&pm8916_l6>;
+
+ pinctrl-0 = <&magn_int_default>;
+ pinctrl-names = "default";
+ };
+};
+
+&blsp_i2c5 {
+ status = "okay";
+
+ touchscreen@34 {
+ compatible = "melfas,mip4_ts";
+ reg = <0x34>;
+
+ interrupts-extended = <&tlmm 13 IRQ_TYPE_EDGE_FALLING>;
+ ce-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&touchscreen_default>;
+ pinctrl-names = "default";
+ };
+};
+
+&blsp_uart2 {
+ status = "okay";
+};
+
+&mpss_mem {
+ reg = <0x0 0x86800000 0x0 0x4a00000>;
+};
+
+&pm8916_bms {
+ monitored-battery = <&battery>;
+ power-supplies = <&pm8916_charger>;
+
+ status = "okay";
+};
+
+&pm8916_charger {
+ qcom,fast-charge-safe-current = <700000>;
+ qcom,fast-charge-safe-voltage = <4300000>;
+
+ monitored-battery = <&battery>;
+ status = "okay";
+};
+
+&pm8916_codec {
+ qcom,micbias1-ext-cap;
+ qcom,micbias-lvl = <2800>;
+ qcom,mbhc-vthreshold-low = <75 100 120 180 500>;
+ qcom,mbhc-vthreshold-high = <75 100 120 180 500>;
+ qcom,hphl-jack-type-normally-open;
+};
+
+&pm8916_rpm_regulators {
+ pm8916_l17: l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+};
+
+&pm8916_vib {
+ status = "okay";
+};
+
+&sdhc_1 {
+ status = "okay";
+};
+
+&sdhc_2 {
+ pinctrl-0 = <&sdc2_default &sdc2_cd_default>;
+ pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>;
+ pinctrl-names = "default", "sleep";
+
+ cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
+
+ status = "okay";
+};
+
+&sound {
+ audio-routing =
+ "AMIC1", "MIC BIAS External1",
+ "AMIC2", "MIC BIAS Internal2",
+ "AMIC3", "MIC BIAS External1";
+};
+
+&usb {
+ dr_mode = "peripheral";
+ extcon = <&pm8916_charger>;
+ status = "okay";
+};
+
+&usb_hs_phy {
+ extcon = <&pm8916_charger>;
+};
+
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
+&wcnss {
+ status = "okay";
+};
+
+&wcnss_iris {
+ compatible = "qcom,wcn3620";
+};
+
+&wcnss_mem {
+ status = "okay";
+};
+
+&tlmm {
+ accel_int_default: accel-int-default-state {
+ pins = "gpio115";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ gpio_keys_default: gpio-keys-default-state {
+ pins = "gpio107", "gpio108";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ magn_int_default: magn-int-default-state {
+ pins = "gpio69";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ sdc2_cd_default: sdc2-cd-default-state {
+ pins = "gpio38";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ touchscreen_default: touchscreen-default-state {
+ touchscreen-pins {
+ pins = "gpio13";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ ce-pins {
+ pins = "gpio12";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-motorola-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-motorola-common.dtsi
new file mode 100644
index 000000000000..6a27d0ecd2ad
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-motorola-common.dtsi
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include "msm8916-pm8916.dtsi"
+#include "msm8916-modem-qdsp6.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ aliases {
+ mmc0 = &sdhc_1; /* eMMC */
+ mmc1 = &sdhc_2; /* SD card */
+ serial0 = &blsp_uart1;
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&gpio_keys_default>;
+ pinctrl-names = "default";
+
+ label = "GPIO Buttons";
+
+ volume-up-button {
+ label = "Volume Up";
+ gpios = <&tlmm 107 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <15>;
+ };
+ };
+
+ usb_id: usb-id {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpios = <&tlmm 91 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&usb_id_default>;
+ pinctrl-1 = <&usb_id_sleep>;
+ pinctrl-names = "default", "sleep";
+ };
+};
+
+&blsp_i2c2 {
+ status = "okay";
+
+ touchscreen: touchscreen@20 {
+ compatible = "syna,rmi4-i2c";
+ reg = <0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vio-supply = <&pm8916_l6>;
+
+ syna,startup-delay-ms = <100>;
+
+ rmi4-f01@1 {
+ reg = <1>;
+ syna,nosleep-mode = <1>; /* Allow sleeping */
+ };
+
+ rmi4-f11@11 {
+ reg = <11>;
+ syna,sensor-type = <1>; /* Touchscreen */
+ };
+ };
+};
+
+&blsp_uart1 {
+ status = "okay";
+};
+
+&mpss_mem {
+ reg = <0x0 0x86800000 0x0 0x5500000>;
+};
+
+&pm8916_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&pm8916_rpm_regulators {
+ pm8916_l16: l16 {
+ regulator-min-microvolt = <3100000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&pm8916_vib {
+ status = "okay";
+};
+
+&sdhc_1 {
+ status = "okay";
+};
+
+&sdhc_2 {
+ status = "okay";
+};
+
+&usb {
+ extcon = <&usb_id>, <&usb_id>;
+ status = "okay";
+};
+
+&usb_hs_phy {
+ extcon = <&usb_id>;
+};
+
+&venus {
+ status = "okay";
+};
+
+&venus_mem {
+ status = "okay";
+};
+
+&wcnss {
+ status = "okay";
+};
+
+&wcnss_iris {
+ compatible = "qcom,wcn3620";
+};
+
+&wcnss_mem {
+ status = "okay";
+};
+
+/* CTS/RTX are not used */
+&blsp_uart1_default {
+ pins = "gpio0", "gpio1";
+};
+&blsp_uart1_sleep {
+ pins = "gpio0", "gpio1";
+};
+
+&tlmm {
+ gpio_keys_default: gpio-keys-default-state {
+ pins = "gpio107";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ usb_id_default: usb-id-default-state {
+ pins = "gpio91";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ usb_id_sleep: usb-id-sleep-state {
+ pins = "gpio91";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-motorola-harpia.dts b/arch/arm64/boot/dts/qcom/msm8916-motorola-harpia.dts
new file mode 100644
index 000000000000..8380451ebbf6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-motorola-harpia.dts
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include "msm8916-motorola-common.dtsi"
+
+/ {
+ model = "Motorola Moto G4 Play";
+ compatible = "motorola,harpia", "qcom,msm8916";
+ chassis-type = "handset";
+};
+
+&blsp_i2c1 {
+ status = "okay";
+
+ battery@36 {
+ compatible = "maxim,max17050";
+ reg = <0x36>;
+
+ interrupts-extended = <&tlmm 62 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&battery_alert_default>;
+ pinctrl-names = "default";
+
+ maxim,rsns-microohm = <10000>;
+ maxim,over-heat-temp = <600>;
+ maxim,cold-temp = <(-200)>;
+ maxim,dead-volt = <3200>;
+ maxim,over-volt = <4500>;
+ };
+
+ /* charger@6b */
+};
+
+&blsp_i2c4 {
+ status = "okay";
+
+ accelerometer@19 {
+ compatible = "bosch,bma253";
+ reg = <0x19>;
+
+ interrupts-extended = <&tlmm 115 IRQ_TYPE_EDGE_RISING>,
+ <&tlmm 119 IRQ_TYPE_EDGE_RISING>;
+
+ vdd-supply = <&pm8916_l17>;
+ vddio-supply = <&pm8916_l6>;
+
+ mount-matrix = "1", "0", "0",
+ "0", "-1", "0",
+ "0", "0", "1";
+
+ pinctrl-0 = <&accel_int_default>;
+ pinctrl-names = "default";
+ };
+
+ /* proximity@49 */
+};
+
+&pm8916_codec {
+ qcom,micbias-lvl = <2800>;
+ qcom,mbhc-vthreshold-low = <75 150 237 450 500>;
+ qcom,mbhc-vthreshold-high = <75 150 237 450 500>;
+ qcom,micbias1-ext-cap;
+};
+
+&pm8916_rpm_regulators {
+ pm8916_l17: l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+};
+
+&sdhc_2 {
+ pinctrl-0 = <&sdc2_default &sdc2_cd_default>;
+ pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>;
+ pinctrl-names = "default", "sleep";
+
+ cd-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>;
+};
+
+&sound {
+ audio-routing =
+ "AMIC1", "MIC BIAS External1",
+ "AMIC2", "MIC BIAS Internal2",
+ "AMIC3", "MIC BIAS External1";
+
+ pinctrl-0 = <&cdc_pdm_default &headset_switch_supply_en
+ &headset_switch_in>;
+ pinctrl-1 = <&cdc_pdm_sleep &headset_switch_supply_en
+ &headset_switch_in>;
+ pinctrl-names = "default", "sleep";
+};
+
+&touchscreen {
+ interrupts-extended = <&tlmm 13 IRQ_TYPE_EDGE_FALLING>;
+
+ vdd-supply = <&pm8916_l16>;
+
+ pinctrl-0 = <&ts_int_default>;
+ pinctrl-names = "default";
+};
+
+&tlmm {
+ accel_int_default: accel-int-default-state {
+ pins = "gpio115", "gpio119";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ battery_alert_default: battery-alert-default-state {
+ pins = "gpio62";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ headset_switch_in: headset-switch-in-state {
+ pins = "gpio112";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+
+ headset_switch_supply_en: headset-switch-supply-en-state {
+ pins = "gpio111";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ sdc2_cd_default: sdc2-cd-default-state {
+ pins = "gpio118";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ ts_int_default: ts-int-default-state {
+ pins = "gpio13";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-motorola-osprey.dts b/arch/arm64/boot/dts/qcom/msm8916-motorola-osprey.dts
new file mode 100644
index 000000000000..ec5589fc69bd
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-motorola-osprey.dts
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include "msm8916-motorola-common.dtsi"
+
+/ {
+ model = "Motorola Moto G 2015";
+ compatible = "motorola,osprey", "qcom,msm8916";
+ chassis-type = "handset";
+
+ reg_touch_vdda: regulator-touch-vdda {
+ compatible = "regulator-fixed";
+ regulator-name = "touch_vdda";
+ gpio = <&tlmm 114 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-0 = <&touch_vdda_default>;
+ pinctrl-names = "default";
+ startup-delay-us = <300>;
+ vin-supply = <&pm8916_l16>;
+ };
+};
+
+&blsp_i2c1 {
+ status = "okay";
+
+ battery@36 {
+ compatible = "maxim,max17050";
+ reg = <0x36>;
+
+ interrupts-extended = <&tlmm 49 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&battery_alert_default>;
+ pinctrl-names = "default";
+
+ maxim,rsns-microohm = <10000>;
+ maxim,over-heat-temp = <600>;
+ maxim,cold-temp = <(-200)>;
+ maxim,dead-volt = <3200>;
+ maxim,over-volt = <4500>;
+
+ };
+};
+
+&blsp_i2c6 {
+ /* magnetometer@c */
+};
+
+&pm8916_codec {
+ qcom,micbias1-ext-cap;
+ qcom,micbias2-ext-cap;
+};
+
+&sdhc_2 {
+ pinctrl-0 = <&sdc2_default &sdc2_cd_default>;
+ pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>;
+ pinctrl-names = "default", "sleep";
+
+ cd-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>;
+};
+
+&sound {
+ audio-routing =
+ "AMIC1", "MIC BIAS External1",
+ "AMIC3", "MIC BIAS External1";
+};
+
+&touchscreen {
+ interrupts-extended = <&tlmm 21 IRQ_TYPE_EDGE_FALLING>;
+
+ vdd-supply = <&reg_touch_vdda>;
+
+ pinctrl-0 = <&ts_int_default>;
+ pinctrl-names = "default";
+};
+
+&tlmm {
+ battery_alert_default: battery-alert-default-state {
+ pins = "gpio49";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ sdc2_cd_default: sdc2-cd-default-state {
+ pins = "gpio25";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ ts_int_default: ts-int-default-state {
+ pins = "gpio21";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ touch_vdda_default: touch-vdda-default-state {
+ pins = "gpio114";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-motorola-surnia.dts b/arch/arm64/boot/dts/qcom/msm8916-motorola-surnia.dts
new file mode 100644
index 000000000000..eecf78ba45bb
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-motorola-surnia.dts
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include "msm8916-motorola-common.dtsi"
+
+/ {
+ model = "Motorola Moto E 2015 LTE";
+ compatible = "motorola,surnia", "qcom,msm8916";
+ chassis-type = "handset";
+};
+
+&blsp_i2c4 {
+ status = "okay";
+
+ battery@36 {
+ compatible = "maxim,max17050";
+ reg = <0x36>;
+
+ interrupts-extended = <&tlmm 12 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&battery_alert_default>;
+ pinctrl-names = "default";
+
+ maxim,rsns-microohm = <10000>;
+ maxim,over-heat-temp = <600>;
+ maxim,cold-temp = <(-200)>;
+ maxim,dead-volt = <3200>;
+ maxim,over-volt = <4500>;
+
+ };
+};
+
+&pm8916_codec {
+ qcom,micbias1-ext-cap;
+ qcom,micbias2-ext-cap;
+};
+
+&sdhc_2 {
+ pinctrl-0 = <&sdc2_default &sdc2_cd_default>;
+ pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>;
+ pinctrl-names = "default", "sleep";
+
+ cd-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>;
+};
+
+&sound {
+ audio-routing =
+ "AMIC1", "MIC BIAS External1",
+ "AMIC3", "MIC BIAS External1";
+};
+
+&touchscreen {
+ interrupts-extended = <&tlmm 21 IRQ_TYPE_EDGE_FALLING>;
+
+ vdd-supply = <&pm8916_l16>;
+
+ pinctrl-0 = <&ts_int_default>;
+ pinctrl-names = "default";
+};
+
+&tlmm {
+ battery_alert_default: battery-alert-default-state {
+ pins = "gpio12";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ sdc2_cd_default: sdc2-cd-default-state {
+ pins = "gpio25";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ ts_int_default: ts-int-default-state {
+ pins = "gpio21";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
index 4bbbee80b5e4..e6355e5e2177 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
@@ -28,6 +28,12 @@
};
};
+ battery: battery {
+ compatible = "simple-battery";
+ precharge-current-microamp = <450000>;
+ precharge-upper-limit-microvolt = <3500000>;
+ };
+
clk_pwm: pwm {
compatible = "clk-pwm";
#pwm-cells = <2>;
@@ -245,7 +251,7 @@
&blsp_i2c4 {
status = "okay";
- battery@35 {
+ fuel-gauge@35 {
compatible = "richtek,rt5033-battery";
reg = <0x35>;
interrupt-parent = <&tlmm>;
@@ -253,6 +259,44 @@
pinctrl-names = "default";
pinctrl-0 = <&fg_alert_default>;
+
+ power-supplies = <&charger>;
+ };
+};
+
+&blsp_i2c6 {
+ status = "okay";
+
+ pmic@34 {
+ compatible = "richtek,rt5033";
+ reg = <0x34>;
+
+ interrupts-extended = <&tlmm 62 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&pmic_int_default>;
+ pinctrl-names = "default";
+
+ regulators {
+ rt5033_reg_safe_ldo: SAFE_LDO {
+ regulator-min-microvolt = <4900000>;
+ regulator-max-microvolt = <4900000>;
+ regulator-always-on;
+ };
+
+ /*
+ * Needed for camera, but not used yet.
+ * Define empty nodes to allow disabling the unused
+ * regulators.
+ */
+ LDO {};
+ BUCK {};
+ };
+
+ charger: charger {
+ compatible = "richtek,rt5033-charger";
+ monitored-battery = <&battery>;
+ richtek,usb-connector = <&usb_con>;
+ };
};
};
@@ -476,6 +520,13 @@
bias-disable;
};
+ pmic_int_default: pmic-int-default-state {
+ pins = "gpio62";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
sdc2_cd_default: sdc2-cd-default-state {
pins = "gpio38";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
index 3b934f5eba47..906d31f1ea21 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
@@ -55,6 +55,12 @@
"0", "0", "1";
};
+&battery {
+ charge-term-current-microamp = <150000>;
+ constant-charge-current-max-microamp = <1000000>;
+ constant-charge-voltage-max-microvolt = <4350000>;
+};
+
&blsp_i2c5 {
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
index 391befa22bb4..fe39be7a742b 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
@@ -29,6 +29,12 @@
"0", "0", "1";
};
+&battery {
+ charge-term-current-microamp = <200000>;
+ constant-charge-current-max-microamp = <1500000>;
+ constant-charge-voltage-max-microvolt = <4350000>;
+};
+
&blsp_i2c5 {
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-e5.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-e5.dts
index fad2535255f7..800cb1038da0 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-e5.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-e5.dts
@@ -23,6 +23,12 @@
chassis-type = "handset";
};
+&battery {
+ charge-term-current-microamp = <200000>;
+ constant-charge-current-max-microamp = <1500000>;
+ constant-charge-voltage-max-microvolt = <4350000>;
+};
+
&blsp_i2c5 {
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-e7.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-e7.dts
index b412b61ca258..ec1debd2e245 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-e7.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-e7.dts
@@ -23,6 +23,13 @@
chassis-type = "handset";
};
+&battery {
+ charge-term-current-microamp = <200000>;
+ constant-charge-current-max-microamp = <1500000>;
+ constant-charge-voltage-max-microvolt = <4350000>;
+};
+
+
&pm8916_l17 {
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-fortuna-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-fortuna-common.dtsi
index 5e933fb8b363..81b3e0760154 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-fortuna-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-fortuna-common.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
/ {
aliases {
@@ -26,6 +27,12 @@
};
};
+ battery: battery {
+ compatible = "simple-battery";
+ precharge-current-microamp = <450000>;
+ precharge-upper-limit-microvolt = <3500000>;
+ };
+
clk_pwm_backlight: backlight {
compatible = "pwm-backlight";
pwms = <&clk_pwm 0 100000>;
@@ -78,6 +85,35 @@
max-microvolt = <3300000>;
};
+ i2c_nfc: i2c-nfc {
+ compatible = "i2c-gpio";
+ sda-gpios = <&tlmm 0 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&tlmm 1 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+
+ pinctrl-0 = <&nfc_i2c_default>;
+ pinctrl-names = "default";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ s3fwrn5_nfc: nfc@27 {
+ compatible = "samsung,s3fwrn5-i2c";
+ reg = <0x27>;
+
+ interrupts-extended = <&tlmm 21 IRQ_TYPE_EDGE_RISING>;
+
+ en-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>;
+ wake-gpios = <&tlmm 49 GPIO_ACTIVE_HIGH>;
+
+ clocks = <&rpmcc RPM_SMD_BB_CLK2_PIN>;
+
+ pinctrl-0 = <&nfc_default>, <&nfc_clk_req>;
+ pinctrl-names = "default";
+
+ status = "disabled";
+ };
+ };
+
reg_motor_vdd: regulator-motor-vdd {
compatible = "regulator-fixed";
regulator-name = "motor_vdd";
@@ -114,6 +150,82 @@
interrupts-extended = <&tlmm 12 IRQ_TYPE_EDGE_FALLING>;
pinctrl-0 = <&muic_int_default>;
pinctrl-names = "default";
+
+ usb_con: connector {
+ compatible = "usb-b-connector";
+ label = "micro-USB";
+ type = "micro";
+ };
+ };
+};
+
+&blsp_i2c2 {
+ /* Available sensors vary depending on model variant */
+ status = "okay";
+
+ bosch_accel: accelerometer@10 {
+ compatible = "bosch,bmc150_accel";
+ reg = <0x10>;
+ interrupts-extended = <&tlmm 115 IRQ_TYPE_EDGE_RISING>;
+
+ vdd-supply = <&pm8916_l5>;
+ vddio-supply = <&pm8916_l5>;
+
+ pinctrl-0 = <&accel_int_default>;
+ pinctrl-names = "default";
+
+ mount-matrix = "0", "-1", "0",
+ "-1", "0", "0",
+ "0", "0", "1";
+
+ status = "disabled";
+ };
+
+ bosch_magn: magnetometer@12 {
+ compatible = "bosch,bmc150_magn";
+ reg = <0x12>;
+
+ vdd-supply = <&pm8916_l5>;
+ vddio-supply = <&pm8916_l5>;
+
+ mount-matrix = "0", "-1", "0",
+ "-1", "0", "0",
+ "0", "0", "1";
+
+ status = "disabled";
+ };
+
+ st_accel: accelerometer@1d {
+ compatible = "st,lsm303c-accel";
+ reg = <0x1d>;
+ interrupts-extended = <&tlmm 115 IRQ_TYPE_LEVEL_HIGH>;
+
+ vdd-supply = <&pm8916_l17>;
+ vddio-supply = <&pm8916_l5>;
+
+ pinctrl-0 = <&accel_int_default>;
+ pinctrl-names = "default";
+
+ st,drdy-int-pin = <1>;
+ mount-matrix = "0", "-1", "0",
+ "1", "0", "0",
+ "0", "0", "-1";
+
+ status = "disabled";
+ };
+
+ st_magn: magnetometer@1e {
+ compatible = "st,lsm303c-magn";
+ reg = <0x1e>;
+
+ vdd-supply = <&pm8916_l17>;
+ vddio-supply = <&pm8916_l5>;
+
+ mount-matrix = "0", "-1", "0",
+ "1", "0", "0",
+ "0", "0", "-1";
+
+ status = "disabled";
};
};
@@ -128,6 +240,8 @@
pinctrl-0 = <&fg_alert_default>;
pinctrl-names = "default";
+
+ power-supplies = <&charger>;
};
};
@@ -151,6 +265,42 @@
};
};
+&blsp_i2c6 {
+ status = "okay";
+
+ pmic@34 {
+ compatible = "richtek,rt5033";
+ reg = <0x34>;
+
+ interrupts-extended = <&tlmm 62 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&pmic_int_default>;
+ pinctrl-names = "default";
+
+ regulators {
+ rt5033_reg_safe_ldo: SAFE_LDO {
+ regulator-min-microvolt = <4900000>;
+ regulator-max-microvolt = <4900000>;
+ regulator-always-on;
+ };
+
+ /*
+ * Needed for camera, but not used yet.
+ * Define empty nodes to allow disabling the unused
+ * regulators.
+ */
+ LDO {};
+ BUCK {};
+ };
+
+ charger: charger {
+ compatible = "richtek,rt5033-charger";
+ monitored-battery = <&battery>;
+ richtek,usb-connector = <&usb_con>;
+ };
+ };
+};
+
&blsp_uart2 {
status = "okay";
};
@@ -223,6 +373,13 @@
};
&tlmm {
+ accel_int_default: accel-int-default-state {
+ pins = "gpio115";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
backlight_en_default: backlight-en-default-state {
pins = "gpio98";
function = "gpio";
@@ -263,6 +420,36 @@
bias-disable;
};
+ nfc_default: nfc-default-state {
+ irq-pins {
+ pins = "gpio21";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ nfc-pins {
+ pins = "gpio20", "gpio49";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ nfc_i2c_default: nfc-i2c-default-state {
+ pins = "gpio0", "gpio1";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ pmic_int_default: pmic-int-default-state {
+ pins = "gpio62";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
sdc2_cd_default: sdc2-cd-default-state {
pins = "gpio38";
function = "gpio";
@@ -284,3 +471,13 @@
bias-disable;
};
};
+
+&pm8916_gpios {
+ nfc_clk_req: nfc-clk-req-state {
+ pins = "gpio2";
+ function = "func1";
+ power-source = <PM8916_GPIO_L2>;
+ bias-disable;
+ input-enable;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-gprimeltecan.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-gprimeltecan.dts
index 9d65fa58ba92..677e4e286ac0 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-gprimeltecan.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-gprimeltecan.dts
@@ -21,6 +21,76 @@
};
};
+&battery {
+ charge-term-current-microamp = <200000>;
+ constant-charge-current-max-microamp = <1000000>;
+ constant-charge-voltage-max-microvolt = <4350000>;
+};
+
+&bosch_accel {
+ status = "okay";
+};
+
+&bosch_magn {
+ status = "okay";
+};
+
+&blsp_i2c6 {
+ /* pmic@34 is on i2c_nfc instead */
+ /delete-node/ pmic@34;
+
+ nfc@27 {
+ compatible = "samsung,s3fwrn5-i2c";
+ reg = <0x27>;
+
+ interrupts-extended = <&tlmm 21 IRQ_TYPE_EDGE_RISING>;
+
+ en-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>;
+ wake-gpios = <&tlmm 49 GPIO_ACTIVE_HIGH>;
+
+ clocks = <&rpmcc RPM_SMD_BB_CLK2_PIN>;
+
+ pinctrl-0 = <&nfc_default>, <&nfc_clk_req>;
+ pinctrl-names = "default";
+ };
+};
+
+&i2c_nfc {
+ /* nfc@27 is on &blsp_i2c6 */
+
+ pmic@34 {
+ compatible = "richtek,rt5033";
+ reg = <0x34>;
+
+ interrupts-extended = <&tlmm 62 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&pmic_int_default>;
+ pinctrl-names = "default";
+
+ regulators {
+ rt5033_reg_safe_ldo: SAFE_LDO {
+ regulator-min-microvolt = <4900000>;
+ regulator-max-microvolt = <4900000>;
+ regulator-always-on;
+ };
+
+ /*
+ * Needed for camera, but not used yet.
+ * Define empty nodes to allow disabling the unused
+ * regulators.
+ */
+ LDO {};
+ BUCK {};
+ };
+
+ charger: charger {
+ compatible = "richtek,rt5033-charger";
+ monitored-battery = <&battery>;
+ richtek,usb-connector = <&usb_con>;
+ };
+ };
+};
+
&mpss_mem {
/* Firmware for gprimeltecan needs more space */
reg = <0x0 0x86800000 0x0 0x5400000>;
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts
index 5882b3a593b8..135df1739dbd 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts
@@ -41,6 +41,12 @@
};
};
+&battery {
+ charge-term-current-microamp = <150000>;
+ constant-charge-current-max-microamp = <1000000>;
+ constant-charge-voltage-max-microvolt = <4400000>;
+};
+
&reg_motor_vdd {
gpio = <&tlmm 72 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-grandprimelte.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-grandprimelte.dts
index a66ce4b13547..582bfcb09684 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-grandprimelte.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-grandprimelte.dts
@@ -10,6 +10,20 @@
chassis-type = "handset";
};
+&battery {
+ charge-term-current-microamp = <200000>;
+ constant-charge-current-max-microamp = <1000000>;
+ constant-charge-voltage-max-microvolt = <4350000>;
+};
+
+&bosch_accel {
+ status = "okay";
+};
+
+&bosch_magn {
+ status = "okay";
+};
+
&mpss_mem {
/* Firmware for grandprimelte needs more space */
reg = <0x0 0x86800000 0x0 0x5400000>;
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa-common.dtsi
index b438fa81886c..e7f265e3c2ab 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa-common.dtsi
@@ -15,6 +15,12 @@
interrupts-extended = <&tlmm 12 IRQ_TYPE_EDGE_FALLING>;
pinctrl-0 = <&muic_int_default>;
pinctrl-names = "default";
+
+ usb_con: connector {
+ compatible = "usb-b-connector";
+ label = "micro-USB";
+ type = "micro";
+ };
};
};
@@ -26,3 +32,15 @@
&clk_pwm_backlight {
status = "disabled";
};
+
+&s3fwrn5_nfc {
+ status = "okay";
+};
+
+&st_accel {
+ compatible = "st,lis2hh12";
+ mount-matrix = "1", "0", "0",
+ "0", "-1", "0",
+ "0", "0", "1";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa.dts
index ebaa13c6b016..1981bb71f6a9 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa.dts
@@ -10,6 +10,12 @@
chassis-type = "handset";
};
+&battery {
+ charge-term-current-microamp = <150000>;
+ constant-charge-current-max-microamp = <700000>;
+ constant-charge-voltage-max-microvolt = <4400000>;
+};
+
&mpss_mem {
/* Firmware for rossa needs more space */
reg = <0x0 0x86800000 0x0 0x5800000>;
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index cedff4166bfb..7383bcc603ab 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -308,7 +308,7 @@
smd-edge {
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 0>;
+ mboxes = <&apcs 0>;
qcom,smd-edge = <15>;
rpm_requests: rpm-requests {
@@ -360,7 +360,7 @@
interrupts = <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 14>;
+ mboxes = <&apcs 14>;
qcom,local-pid = <0>;
qcom,remote-pid = <1>;
@@ -385,7 +385,7 @@
interrupts = <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 18>;
+ mboxes = <&apcs 18>;
qcom,local-pid = <0>;
qcom,remote-pid = <4>;
@@ -410,8 +410,7 @@
#address-cells = <1>;
#size-cells = <0>;
- qcom,ipc-1 = <&apcs 8 13>;
- qcom,ipc-3 = <&apcs 8 19>;
+ mboxes = <0>, <&apcs 13>, <0>, <&apcs 19>;
apps_smsm: apps@0 {
reg = <0>;
@@ -1978,7 +1977,7 @@
interrupts = <GIC_SPI 25 IRQ_TYPE_EDGE_RISING>;
qcom,smd-edge = <0>;
- qcom,ipc = <&apcs 8 12>;
+ mboxes = <&apcs 12>;
qcom,remote-pid = <1>;
label = "hexagon";
@@ -2459,7 +2458,7 @@
smd-edge {
interrupts = <GIC_SPI 142 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 17>;
+ mboxes = <&apcs 17>;
qcom,smd-edge = <6>;
qcom,remote-pid = <4>;
@@ -2626,7 +2625,6 @@
thermal-zones {
cpu0-1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 5>;
@@ -2656,7 +2654,6 @@
cpu2-3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 4>;
@@ -2686,7 +2683,6 @@
gpu-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 2>;
@@ -2713,7 +2709,6 @@
camera-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 1>;
@@ -2728,7 +2723,6 @@
modem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 0>;
diff --git a/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts b/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts
index 0c599e71a464..91acdb160227 100644
--- a/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts
+++ b/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts
@@ -33,6 +33,15 @@
};
};
+ battery: battery {
+ compatible = "simple-battery";
+ charge-term-current-microamp = <150000>;
+ constant-charge-current-max-microamp = <1500000>;
+ constant-charge-voltage-max-microvolt = <4300000>;
+ precharge-current-microamp = <450000>;
+ precharge-upper-limit-microvolt = <3500000>;
+ };
+
gpio-hall-sensor {
compatible = "gpio-keys";
@@ -82,7 +91,7 @@
#address-cells = <1>;
#size-cells = <0>;
- battery@35 {
+ fuel-gauge@35 {
compatible = "richtek,rt5033-battery";
reg = <0x35>;
@@ -91,6 +100,8 @@
pinctrl-0 = <&fg_alert_default>;
pinctrl-names = "default";
+
+ power-supplies = <&charger>;
};
};
@@ -325,6 +336,42 @@
};
};
+&blsp_i2c6 {
+ status = "okay";
+
+ pmic@34 {
+ compatible = "richtek,rt5033";
+ reg = <0x34>;
+
+ interrupts-extended = <&tlmm 62 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-0 = <&pmic_int_default>;
+ pinctrl-names = "default";
+
+ regulators {
+ rt5033_reg_safe_ldo: SAFE_LDO {
+ regulator-min-microvolt = <4900000>;
+ regulator-max-microvolt = <4900000>;
+ regulator-always-on;
+ };
+
+ /*
+ * Needed for camera, but not used yet.
+ * Define empty nodes to allow disabling the unused
+ * regulators.
+ */
+ LDO {};
+ BUCK {};
+ };
+
+ charger: charger {
+ compatible = "richtek,rt5033-charger";
+ monitored-battery = <&battery>;
+ richtek,usb-connector = <&usb_con>;
+ };
+ };
+};
+
&blsp_uart2 {
status = "okay";
};
@@ -510,6 +557,13 @@
bias-disable;
};
+ pmic_int_default: pmic-int-default-state {
+ pins = "gpio62";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
reg_tsp_en_default: reg-tsp-en-default-state {
pins = "gpio73";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8939.dtsi b/arch/arm64/boot/dts/qcom/msm8939.dtsi
index dd45975682b2..46d9480cd464 100644
--- a/arch/arm64/boot/dts/qcom/msm8939.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8939.dtsi
@@ -248,7 +248,7 @@
smd-edge {
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs1_mbox 8 0>;
+ mboxes = <&apcs1_mbox 0>;
qcom,smd-edge = <15>;
rpm_requests: rpm-requests {
@@ -443,8 +443,7 @@
#address-cells = <1>;
#size-cells = <0>;
- qcom,ipc-1 = <&apcs1_mbox 8 13>;
- qcom,ipc-3 = <&apcs1_mbox 8 19>;
+ mboxes = <0>, <&apcs1_mbox 13>, <0>, <&apcs1_mbox 19>;
apps_smsm: apps@0 {
reg = <0>;
@@ -2067,7 +2066,7 @@
smd-edge {
interrupts = <GIC_SPI 142 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs1_mbox 8 17>;
+ mboxes = <&apcs1_mbox 17>;
qcom,smd-edge = <6>;
qcom,remote-pid = <4>;
@@ -2299,7 +2298,6 @@
thermal_zones: thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 5>;
@@ -2330,7 +2328,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 6>;
@@ -2361,7 +2358,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 7>;
@@ -2392,7 +2388,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 8>;
@@ -2423,7 +2418,6 @@
cpu4567-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 9>;
@@ -2454,7 +2448,6 @@
gpu-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 3>;
@@ -2482,7 +2475,6 @@
modem1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 0>;
@@ -2497,7 +2489,6 @@
modem2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 2>;
@@ -2512,7 +2503,6 @@
camera-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 1>;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-motorola-potter.dts b/arch/arm64/boot/dts/qcom/msm8953-motorola-potter.dts
index 711d84dad9d7..2edf804eb7c9 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-motorola-potter.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-motorola-potter.dts
@@ -301,5 +301,6 @@
};
&usb3_dwc3 {
+ /delete-property/ usb-role-switch;
dr_mode = "peripheral";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-xiaomi-daisy.dts b/arch/arm64/boot/dts/qcom/msm8953-xiaomi-daisy.dts
index a5957e79b818..336b916729e4 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-xiaomi-daisy.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-xiaomi-daisy.dts
@@ -321,5 +321,6 @@
};
&usb3_dwc3 {
+ /delete-property/ usb-role-switch;
dr_mode = "peripheral";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-xiaomi-mido.dts b/arch/arm64/boot/dts/qcom/msm8953-xiaomi-mido.dts
index 6b9245cd8b0c..bdf1bfc79c56 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-xiaomi-mido.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-xiaomi-mido.dts
@@ -326,5 +326,6 @@
};
&usb3_dwc3 {
+ /delete-property/ usb-role-switch;
dr_mode = "peripheral";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-xiaomi-tissot.dts b/arch/arm64/boot/dts/qcom/msm8953-xiaomi-tissot.dts
index 9ac4f507e321..fccb9c4360ca 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-xiaomi-tissot.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-xiaomi-tissot.dts
@@ -322,5 +322,6 @@
};
&usb3_dwc3 {
+ /delete-property/ usb-role-switch;
dr_mode = "peripheral";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-xiaomi-vince.dts b/arch/arm64/boot/dts/qcom/msm8953-xiaomi-vince.dts
index b0588f30f8f1..d46325e79917 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-xiaomi-vince.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-xiaomi-vince.dts
@@ -357,5 +357,6 @@
};
&usb3_dwc3 {
+ /delete-property/ usb-role-switch;
dr_mode = "peripheral";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index 5d818fe057dd..a4bfb624fb8a 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -195,7 +195,7 @@
smd-edge {
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 0>;
+ mboxes = <&apcs 0>;
qcom,smd-edge = <15>;
rpm_requests: rpm-requests {
@@ -361,7 +361,7 @@
interrupts = <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 14>;
+ mboxes = <&apcs 14>;
qcom,local-pid = <0>;
qcom,remote-pid = <1>;
@@ -386,7 +386,7 @@
interrupts = <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 18>;
+ mboxes = <&apcs 18>;
qcom,local-pid = <0>;
qcom,remote-pid = <4>;
@@ -411,8 +411,7 @@
#address-cells = <1>;
#size-cells = <0>;
- qcom,ipc-1 = <&apcs 8 13>;
- qcom,ipc-3 = <&apcs 8 19>;
+ mboxes = <0>, <&apcs 13>, <0>, <&apcs 19>;
apps_smsm: apps@0 {
reg = <0>;
@@ -1267,7 +1266,7 @@
interrupts = <GIC_SPI 25 IRQ_TYPE_EDGE_RISING>;
qcom,smd-edge = <0>;
- qcom,ipc = <&apcs 8 12>;
+ mboxes = <&apcs 12>;
qcom,remote-pid = <1>;
label = "modem";
@@ -1748,7 +1747,7 @@
smd-edge {
interrupts = <GIC_SPI 142 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 17>;
+ mboxes = <&apcs 17>;
qcom,smd-edge = <6>;
qcom,remote-pid = <4>;
@@ -1968,8 +1967,9 @@
thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens0 9>;
+
trips {
cpu0_alert: trip-point0 {
temperature = <80000>;
@@ -1991,8 +1991,9 @@
};
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens0 10>;
+
trips {
cpu1_alert: trip-point0 {
temperature = <80000>;
@@ -2014,8 +2015,9 @@
};
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens0 11>;
+
trips {
cpu2_alert: trip-point0 {
temperature = <80000>;
@@ -2037,8 +2039,9 @@
};
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens0 12>;
+
trips {
cpu3_alert: trip-point0 {
temperature = <80000>;
@@ -2060,7 +2063,6 @@
};
cpu4-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 4>;
trips {
cpu4_alert: trip-point0 {
@@ -2083,7 +2085,6 @@
};
cpu5-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 5>;
trips {
cpu5_alert: trip-point0 {
@@ -2106,7 +2107,6 @@
};
cpu6-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 6>;
trips {
cpu6_alert: trip-point0 {
@@ -2129,7 +2129,6 @@
};
cpu7-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 7>;
trips {
cpu7_alert: trip-point0 {
@@ -2153,7 +2152,6 @@
gpu-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 15>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/msm8956.dtsi b/arch/arm64/boot/dts/qcom/msm8956.dtsi
index 668e05185c21..fa36b62156bb 100644
--- a/arch/arm64/boot/dts/qcom/msm8956.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8956.dtsi
@@ -8,8 +8,8 @@
#include "msm8976.dtsi"
-&pmu {
- interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>;
+&pmu_a72 {
+ interrupts = <GIC_PPI 7 (GIC_CPU_MASK_RAW(0x30) | IRQ_TYPE_LEVEL_HIGH)>;
};
&tsens {
diff --git a/arch/arm64/boot/dts/qcom/msm8976.dtsi b/arch/arm64/boot/dts/qcom/msm8976.dtsi
index d2bb1ada361a..d62dcb76fa48 100644
--- a/arch/arm64/boot/dts/qcom/msm8976.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8976.dtsi
@@ -222,11 +222,17 @@
reg = <0x0 0x80000000 0x0 0x0>;
};
- pmu: pmu {
- compatible = "arm,armv8-pmuv3";
- interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+ pmu-a53 {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
+ pmu_a72: pmu-a72 {
+ compatible = "arm,cortex-a72-pmu";
+ interrupts = <GIC_PPI 7 (GIC_CPU_MASK_RAW(0xf0) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+
psci {
compatible = "arm,psci-1.0";
method = "smc";
@@ -237,7 +243,7 @@
smd-edge {
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 0>;
+ mboxes = <&apcs 0>;
qcom,smd-edge = <15>;
rpm_requests: rpm-requests {
@@ -361,7 +367,7 @@
smp2p-hexagon {
compatible = "qcom,smp2p";
interrupts = <GIC_SPI 291 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 10>;
+ mboxes = <&apcs 10>;
qcom,local-pid = <0>;
qcom,remote-pid = <2>;
@@ -384,7 +390,7 @@
smp2p-modem {
compatible = "qcom,smp2p";
interrupts = <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 14>;
+ mboxes = <&apcs 14>;
qcom,local-pid = <0>;
qcom,remote-pid = <1>;
@@ -407,7 +413,7 @@
smp2p-wcnss {
compatible = "qcom,smp2p";
interrupts = <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 18>;
+ mboxes = <&apcs 18>;
qcom,local-pid = <0>;
qcom,remote-pid = <4>;
@@ -433,9 +439,7 @@
#address-cells = <1>;
#size-cells = <0>;
- qcom,ipc-1 = <&apcs 8 13>;
- qcom,ipc-2 = <&apcs 8 9>;
- qcom,ipc-3 = <&apcs 8 19>;
+ mboxes = <0>, <&apcs 13>, <&apcs 9>, <&apcs 19>;
apps_smsm: apps@0 {
reg = <0>;
@@ -771,6 +775,36 @@
drive-strength = <2>;
bias-disable;
};
+
+ wcss_wlan_default: wcss-wlan-default-state {
+ wcss-wlan2-pins {
+ pins = "gpio40";
+ function = "wcss_wlan2";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ wcss-wlan1-pins {
+ pins = "gpio41";
+ function = "wcss_wlan1";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ wcss-wlan0-pins {
+ pins = "gpio42";
+ function = "wcss_wlan0";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ wcss-wlan-pins {
+ pins = "gpio43", "gpio44";
+ function = "wcss_wlan";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
};
gcc: clock-controller@1800000 {
@@ -785,10 +819,10 @@
clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
<&rpmcc RPM_SMD_XO_A_CLK_SRC>,
- <0>,
- <0>,
- <0>,
- <0>;
+ <&mdss_dsi0_phy 1>,
+ <&mdss_dsi0_phy 0>,
+ <&mdss_dsi1_phy 1>,
+ <&mdss_dsi1_phy 0>;
clock-names = "xo",
"xo_a",
"dsi0pll",
@@ -808,6 +842,430 @@
reg = <0x01937000 0x30000>;
};
+ mdss: display-subsystem@1a00000 {
+ compatible = "qcom,mdss";
+
+ reg = <0x01a00000 0x1000>,
+ <0x01ab0000 0x3000>;
+ reg-names = "mdss_phys", "vbif_phys";
+
+ power-domains = <&gcc MDSS_GDSC>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_VSYNC_CLK>,
+ <&gcc GCC_MDSS_MDP_CLK>;
+ clock-names = "iface",
+ "bus",
+ "vsync",
+ "core";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ status = "disabled";
+
+ mdss_mdp: display-controller@1a01000 {
+ compatible = "qcom,msm8976-mdp5", "qcom,mdp5";
+ reg = <0x01a01000 0x89000>;
+ reg-names = "mdp_phys";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_MDP_CLK>,
+ <&gcc GCC_MDSS_VSYNC_CLK>,
+ <&gcc GCC_MDP_TBU_CLK>,
+ <&gcc GCC_MDP_RT_TBU_CLK>;
+ clock-names = "iface",
+ "bus",
+ "core",
+ "vsync",
+ "tbu",
+ "tbu_rt";
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&gcc MDSS_GDSC>;
+
+ iommus = <&apps_iommu 22>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ mdss_mdp5_intf1_out: endpoint {
+ remote-endpoint = <&mdss_dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ mdss_mdp5_intf2_out: endpoint {
+ remote-endpoint = <&mdss_dsi1_in>;
+ };
+ };
+ };
+
+ mdp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-177780000 {
+ opp-hz = /bits/ 64 <177780000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+
+ opp-270000000 {
+ opp-hz = /bits/ 64 <270000000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ };
+
+ opp-320000000 {
+ opp-hz = /bits/ 64 <320000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ };
+
+ opp-360000000 {
+ opp-hz = /bits/ 64 <360000000>;
+ required-opps = <&rpmpd_opp_turbo>;
+ };
+ };
+ };
+
+ mdss_dsi0: dsi@1a94000 {
+ compatible = "qcom,msm8976-dsi-ctrl", "qcom,mdss-dsi-ctrl";
+ reg = <0x01a94000 0x300>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&gcc GCC_MDSS_MDP_CLK>,
+ <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_BYTE0_CLK>,
+ <&gcc GCC_MDSS_PCLK0_CLK>,
+ <&gcc GCC_MDSS_ESC0_CLK>;
+ clock-names = "mdp_core",
+ "iface",
+ "bus",
+ "byte",
+ "pixel",
+ "core";
+
+ assigned-clocks = <&gcc GCC_MDSS_BYTE0_CLK_SRC>,
+ <&gcc GCC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&mdss_dsi0_phy 0>,
+ <&mdss_dsi0_phy 1>;
+
+ phys = <&mdss_dsi0_phy>;
+
+ operating-points-v2 = <&dsi0_opp_table>;
+ power-domains = <&gcc MDSS_GDSC>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ mdss_dsi0_in: endpoint {
+ remote-endpoint = <&mdss_mdp5_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ mdss_dsi0_out: endpoint {
+ };
+ };
+ };
+
+ dsi0_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-125000000 {
+ opp-hz = /bits/ 64 <125000000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+
+ opp-161250000 {
+ opp-hz = /bits/ 64 <161250000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ };
+
+ opp-187500000 {
+ opp-hz = /bits/ 64 <187500000>;
+ required-opps = <&rpmpd_opp_nom>;
+ };
+ };
+ };
+
+ mdss_dsi1: dsi@1a96000 {
+ compatible = "qcom,msm8976-dsi-ctrl", "qcom,mdss-dsi-ctrl";
+ reg = <0x01a96000 0x300>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <5>;
+
+ clocks = <&gcc GCC_MDSS_MDP_CLK>,
+ <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_BYTE1_CLK>,
+ <&gcc GCC_MDSS_PCLK1_CLK>,
+ <&gcc GCC_MDSS_ESC1_CLK>;
+ clock-names = "mdp_core",
+ "iface",
+ "bus",
+ "byte",
+ "pixel",
+ "core";
+
+ assigned-clocks = <&gcc GCC_MDSS_BYTE1_CLK_SRC>,
+ <&gcc GCC_MDSS_PCLK1_CLK_SRC>;
+ assigned-clock-parents = <&mdss_dsi1_phy 0>,
+ <&mdss_dsi1_phy 1>;
+
+ phys = <&mdss_dsi1_phy>;
+
+ operating-points-v2 = <&dsi0_opp_table>;
+ power-domains = <&gcc MDSS_GDSC>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ mdss_dsi1_in: endpoint {
+ remote-endpoint = <&mdss_mdp5_intf2_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ mdss_dsi1_out: endpoint {
+ };
+ };
+ };
+ };
+
+ mdss_dsi0_phy: phy@1a94a00 {
+ compatible = "qcom,dsi-phy-28nm-hpm-fam-b";
+ reg = <0x01a94a00 0xd4>,
+ <0x01a94400 0x280>,
+ <0x01a94b80 0x30>;
+ reg-names = "dsi_pll",
+ "dsi_phy",
+ "dsi_phy_regulator";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "ref";
+
+ status = "disabled";
+ };
+
+ mdss_dsi1_phy: phy@1a96a00 {
+ compatible = "qcom,dsi-phy-28nm-hpm-fam-b";
+ reg = <0x01a96a00 0xd4>,
+ <0x01a96400 0x280>,
+ <0x01a96b80 0x30>;
+ reg-names = "dsi_pll",
+ "dsi_phy",
+ "dsi_phy_regulator";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "ref";
+
+ status = "disabled";
+ };
+ };
+
+ adreno_gpu: gpu@1c00000 {
+ compatible = "qcom,adreno-510.0", "qcom,adreno";
+
+ reg = <0x01c00000 0x40000>;
+ reg-names = "kgsl_3d0_reg_memory";
+
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "kgsl_3d0_irq";
+
+ clocks = <&gcc GCC_GFX3D_OXILI_CLK>,
+ <&gcc GCC_GFX3D_OXILI_AHB_CLK>,
+ <&gcc GCC_GFX3D_OXILI_GMEM_CLK>,
+ <&gcc GCC_GFX3D_BIMC_CLK>,
+ <&gcc GCC_GFX3D_OXILI_TIMER_CLK>,
+ <&gcc GCC_GFX3D_OXILI_AON_CLK>;
+ clock-names = "core",
+ "iface",
+ "mem",
+ "mem_iface",
+ "rbbmtimer",
+ "alwayson";
+
+ power-domains = <&gcc OXILI_GX_GDSC>;
+
+ iommus = <&gpu_iommu 0>;
+
+ operating-points-v2 = <&gpu_opp_table>;
+
+ status = "disabled";
+
+ gpu_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ opp-supported-hw = <0xff>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ required-opps = <&rpmpd_opp_svs>;
+ opp-supported-hw = <0xff>;
+ };
+
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ opp-supported-hw = <0xff>;
+ };
+
+ opp-480000000 {
+ opp-hz = /bits/ 64 <480000000>;
+ required-opps = <&rpmpd_opp_nom_plus>;
+ opp-supported-hw = <0xff>;
+ };
+
+ opp-540000000 {
+ opp-hz = /bits/ 64 <540000000>;
+ required-opps = <&rpmpd_opp_turbo>;
+ opp-supported-hw = <0xff>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ required-opps = <&rpmpd_opp_turbo>;
+ opp-supported-hw = <0xff>;
+ };
+ };
+ };
+
+ apps_iommu: iommu@1ee0000 {
+ compatible = "qcom,msm8976-iommu", "qcom,msm-iommu-v2";
+ reg = <0x01ee0000 0x3000>;
+ ranges = <0 0x01e20000 0x20000>;
+
+ clocks = <&gcc GCC_SMMU_CFG_CLK>,
+ <&gcc GCC_APSS_TCU_CLK>;
+ clock-names = "iface", "bus";
+
+ qcom,iommu-secure-id = <17>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #iommu-cells = <1>;
+
+ /* VFE */
+ iommu-ctx@15000 {
+ compatible = "qcom,msm-iommu-v2-ns";
+ reg = <0x15000 0x1000>;
+ qcom,ctx-asid = <20>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ /* VENUS NS */
+ iommu-ctx@16000 {
+ compatible = "qcom,msm-iommu-v2-ns";
+ reg = <0x16000 0x1000>;
+ qcom,ctx-asid = <21>;
+ interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ /* MDP0 */
+ iommu-ctx@17000 {
+ compatible = "qcom,msm-iommu-v2-ns";
+ reg = <0x17000 0x1000>;
+ qcom,ctx-asid = <22>;
+ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ gpu_iommu: iommu@1f08000 {
+ compatible = "qcom,msm8976-iommu", "qcom,msm-iommu-v2";
+ ranges = <0 0x01f08000 0x8000>;
+
+ clocks = <&gcc GCC_SMMU_CFG_CLK>,
+ <&gcc GCC_GFX3D_TCU_CLK>;
+ clock-names = "iface", "bus";
+
+ power-domains = <&gcc OXILI_CX_GDSC>;
+
+ qcom,iommu-secure-id = <18>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #iommu-cells = <1>;
+
+ /* gfx3d user */
+ iommu-ctx@0 {
+ compatible = "qcom,msm-iommu-v2-ns";
+ reg = <0x0 0x1000>;
+ qcom,ctx-asid = <0>;
+ interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ /* gfx3d secure */
+ iommu-ctx@1000 {
+ compatible = "qcom,msm-iommu-v2-sec";
+ reg = <0x1000 0x1000>;
+ qcom,ctx-asid = <2>;
+ interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ /* gfx3d priv */
+ iommu-ctx@2000 {
+ compatible = "qcom,msm-iommu-v2-sec";
+ reg = <0x2000 0x1000>;
+ qcom,ctx-asid = <1>;
+ interrupts = <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
spmi_bus: spmi@200f000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0x0200f000 0x1000>,
@@ -1034,6 +1492,81 @@
status = "disabled";
};
+ wcnss: remoteproc@a204000 {
+ compatible = "qcom,pronto-v3-pil", "qcom,pronto";
+ reg = <0x0a204000 0x2000>,
+ <0x0a202000 0x1000>,
+ <0x0a21b000 0x3000>;
+ reg-names = "ccu",
+ "dxe",
+ "pmu";
+
+ memory-region = <&wcnss_fw_mem>;
+
+ interrupts-extended = <&intc GIC_SPI 149 IRQ_TYPE_EDGE_RISING>,
+ <&wcnss_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&wcnss_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&wcnss_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&wcnss_smp2p_in 3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog",
+ "fatal",
+ "ready",
+ "handover",
+ "stop-ack";
+
+ power-domains = <&rpmpd MSM8976_VDDCX>,
+ <&rpmpd MSM8976_VDDMX>;
+ power-domain-names = "cx", "mx";
+
+ qcom,smem-states = <&wcnss_smp2p_out 0>;
+ qcom,smem-state-names = "stop";
+
+ pinctrl-0 = <&wcss_wlan_default>;
+ pinctrl-names = "default";
+
+ status = "disabled";
+
+ wcnss_iris: iris {
+ /* Separate chip, compatible is board-specific */
+ clocks = <&rpmcc RPM_SMD_RF_CLK2>;
+ clock-names = "xo";
+ };
+
+ smd-edge {
+ interrupts = <GIC_SPI 142 IRQ_TYPE_EDGE_RISING>;
+
+ mboxes = <&apcs 17>;
+ qcom,smd-edge = <6>;
+ qcom,remote-pid = <4>;
+
+ label = "pronto";
+
+ wcnss_ctrl: wcnss {
+ compatible = "qcom,wcnss";
+ qcom,smd-channels = "WCNSS_CTRL";
+
+ qcom,mmio = <&wcnss>;
+
+ wcnss_bt: bluetooth {
+ compatible = "qcom,wcnss-bt";
+ };
+
+ wcnss_wifi: wifi {
+ compatible = "qcom,wcnss-wlan";
+
+ interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+
+ qcom,smem-states = <&apps_smsm 10>,
+ <&apps_smsm 9>;
+ qcom,smem-state-names = "tx-enable",
+ "tx-rings-empty";
+ };
+ };
+ };
+ };
+
intc: interrupt-controller@b000000 {
compatible = "qcom,msm-qgic2";
reg = <0x0b000000 0x1000>, <0x0b002000 0x1000>;
@@ -1124,7 +1657,6 @@
thermal-zones {
aoss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 0>;
@@ -1139,7 +1671,6 @@
modem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 1>;
trips {
@@ -1153,7 +1684,6 @@
qdsp-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 2>;
trips {
@@ -1167,7 +1697,6 @@
cam-isp-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 3>;
trips {
@@ -1181,7 +1710,7 @@
cpu4-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens 4>;
trips {
@@ -1205,7 +1734,7 @@
cpu5-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens 5>;
trips {
@@ -1229,7 +1758,7 @@
cpu6-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens 6>;
trips {
@@ -1253,7 +1782,7 @@
cpu7-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens 7>;
trips {
@@ -1277,7 +1806,7 @@
big-l2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens 8>;
trips {
@@ -1301,7 +1830,7 @@
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens 9>;
trips {
@@ -1325,7 +1854,7 @@
gpu-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
+
thermal-sensors = <&tsens 10>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi
index 695e541832ad..917fa246857d 100644
--- a/arch/arm64/boot/dts/qcom/msm8994.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi
@@ -183,7 +183,7 @@
smd-edge {
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 0>;
+ mboxes = <&apcs 0>;
qcom,smd-edge = <15>;
qcom,remote-pid = <6>;
@@ -300,7 +300,7 @@
interrupts = <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 10>;
+ mboxes = <&apcs 10>;
qcom,local-pid = <0>;
qcom,remote-pid = <2>;
@@ -325,7 +325,7 @@
interrupt-parent = <&intc>;
interrupts = <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>;
- qcom,ipc = <&apcs 8 14>;
+ mboxes = <&apcs 14>;
qcom,local-pid = <0>;
qcom,remote-pid = <1>;
@@ -1093,10 +1093,10 @@
timer: timer {
compatible = "arm,armv8-timer";
- interrupts = <GIC_PPI 2 0xff08>,
- <GIC_PPI 3 0xff08>,
- <GIC_PPI 4 0xff08>,
- <GIC_PPI 1 0xff08>;
+ interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
};
vph_pwr: vph-pwr-regulator {
diff --git a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi
index 5ab583be9e0a..0386636a29f0 100644
--- a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi
@@ -405,7 +405,6 @@
&hsusb_phy1 {
status = "okay";
- extcon = <&typec>;
vdda-pll-supply = <&vreg_l12a_1p8>;
vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 8d2cb6f41095..0fd2b1b944a5 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -982,6 +982,8 @@
<&mmcc MDSS_MDP_CLK>;
clock-names = "iface", "core";
+ resets = <&mmcc MDSS_BCR>;
+
#address-cells = <1>;
#size-cells = <1>;
ranges;
@@ -2077,24 +2079,20 @@
power-domains = <&gcc UFS_GDSC>;
clock-names =
- "core_clk_src",
"core_clk",
"bus_clk",
"bus_aggr_clk",
"iface_clk",
- "core_clk_unipro_src",
"core_clk_unipro",
"core_clk_ice",
"ref_clk",
"tx_lane0_sync_clk",
"rx_lane0_sync_clk";
clocks =
- <&gcc UFS_AXI_CLK_SRC>,
<&gcc GCC_UFS_AXI_CLK>,
<&gcc GCC_SYS_NOC_UFS_AXI_CLK>,
<&gcc GCC_AGGRE2_UFS_AXI_CLK>,
<&gcc GCC_UFS_AHB_CLK>,
- <&gcc UFS_ICE_CORE_CLK_SRC>,
<&gcc GCC_UFS_UNIPRO_CORE_CLK>,
<&gcc GCC_UFS_ICE_CORE_CLK>,
<&rpmcc RPM_SMD_LN_BB_CLK>,
@@ -2105,10 +2103,8 @@
<0 0>,
<0 0>,
<0 0>,
- <0 0>,
- <150000000 300000000>,
<75000000 150000000>,
- <0 0>,
+ <150000000 300000000>,
<0 0>,
<0 0>,
<0 0>;
@@ -2483,6 +2479,13 @@
status = "disabled";
+ glink-edge {
+ interrupts = <GIC_SPI 179 IRQ_TYPE_EDGE_RISING>;
+ label = "dsps";
+ qcom,remote-pid = <3>;
+ mboxes = <&apcs_glb 27>;
+ };
+
smd-edge {
interrupts = <GIC_SPI 176 IRQ_TYPE_EDGE_RISING>;
@@ -2552,6 +2555,13 @@
memory-region = <&mdata_mem>;
};
+ glink-edge {
+ interrupts = <GIC_SPI 452 IRQ_TYPE_EDGE_RISING>;
+ label = "modem";
+ qcom,remote-pid = <1>;
+ mboxes = <&apcs_glb 15>;
+ };
+
smd-edge {
interrupts = <GIC_SPI 449 IRQ_TYPE_EDGE_RISING>;
@@ -3091,6 +3101,7 @@
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
snps,is-utmi-l1-suspend;
+ snps,parkmode-disable-ss-quirk;
tx-fifo-resize;
};
};
@@ -3497,6 +3508,14 @@
status = "disabled";
+ glink-edge {
+ interrupts = <GIC_SPI 157 IRQ_TYPE_EDGE_RISING>;
+ label = "lpass";
+ qcom,remote-pid = <2>;
+ mboxes = <&apcs_glb 9>;
+ };
+
+
smd-edge {
interrupts = <GIC_SPI 156 IRQ_TYPE_EDGE_RISING>;
@@ -3553,6 +3572,63 @@
};
};
};
+
+ fastrpc {
+ compatible = "qcom,fastrpc";
+ qcom,smd-channels = "fastrpcsmd-apps-dsp";
+ label = "adsp";
+ qcom,non-secure-domain;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cb@5 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <5>;
+ iommus = <&lpass_q6_smmu 5>;
+ };
+
+ cb@6 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <6>;
+ iommus = <&lpass_q6_smmu 6>;
+ };
+
+ cb@7 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <7>;
+ iommus = <&lpass_q6_smmu 7>;
+ };
+
+ cb@8 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <8>;
+ iommus = <&lpass_q6_smmu 8>;
+ };
+
+ cb@9 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <9>;
+ iommus = <&lpass_q6_smmu 9>;
+ };
+
+ cb@10 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <10>;
+ iommus = <&lpass_q6_smmu 10>;
+ };
+
+ cb@11 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <11>;
+ iommus = <&lpass_q6_smmu 11>;
+ };
+
+ cb@12 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <12>;
+ iommus = <&lpass_q6_smmu 12>;
+ };
+ };
};
};
@@ -3654,7 +3730,6 @@
thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 3>;
@@ -3675,7 +3750,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 5>;
@@ -3696,7 +3770,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 8>;
@@ -3717,7 +3790,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 10>;
@@ -3738,7 +3810,6 @@
gpu-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 6>;
@@ -3760,7 +3831,6 @@
gpu-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 7>;
@@ -3782,7 +3852,6 @@
m4m-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 1>;
@@ -3797,7 +3866,6 @@
l3-or-venus-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 2>;
@@ -3812,7 +3880,6 @@
cluster0-l2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 7>;
@@ -3827,7 +3894,6 @@
cluster1-l2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 12>;
@@ -3842,7 +3908,6 @@
camera-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 1>;
@@ -3857,7 +3922,6 @@
q6-dsp-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 2>;
@@ -3872,7 +3936,6 @@
mem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 3>;
@@ -3887,7 +3950,6 @@
modemtx-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 4>;
diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
index d795b2bbe133..7f44807b1b97 100644
--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
@@ -488,7 +488,6 @@
thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 1>;
@@ -509,7 +508,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 2>;
@@ -530,7 +528,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 3>;
@@ -551,7 +548,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 4>;
@@ -572,7 +568,6 @@
cpu4-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 7>;
@@ -593,7 +588,6 @@
cpu5-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 8>;
@@ -614,7 +608,6 @@
cpu6-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 9>;
@@ -635,7 +628,6 @@
cpu7-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 10>;
@@ -656,7 +648,6 @@
gpu-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 12>;
@@ -671,7 +662,6 @@
gpu-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 13>;
@@ -686,7 +676,6 @@
clust0-mhm-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 5>;
@@ -701,7 +690,6 @@
clust1-mhm-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 6>;
@@ -716,7 +704,6 @@
cluster1-l2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 11>;
@@ -731,7 +718,6 @@
modem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 1>;
@@ -746,7 +732,6 @@
mem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 2>;
@@ -761,7 +746,6 @@
wlan-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 3>;
@@ -776,7 +760,6 @@
q6-dsp-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 4>;
@@ -791,7 +774,6 @@
camera-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 5>;
@@ -806,7 +788,6 @@
multimedia-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 6>;
@@ -1590,7 +1571,6 @@
* SoC VDDMX RPM Power Domain in the Adreno driver.
*/
power-domains = <&gpucc GPU_GX_GDSC>;
- status = "disabled";
};
gpucc: clock-controller@5065000 {
@@ -2164,6 +2144,7 @@
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
+ snps,parkmode-disable-ss-quirk;
phys = <&qusb2phy>, <&usb3phy>;
phy-names = "usb2-phy", "usb3-phy";
snps,has-lpm-erratum;
@@ -3020,6 +3001,54 @@
};
};
+ venus: video-codec@cc00000 {
+ compatible = "qcom,msm8998-venus";
+ reg = <0x0cc00000 0xff000>;
+ interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&mmcc VIDEO_TOP_GDSC>;
+ clocks = <&mmcc VIDEO_CORE_CLK>,
+ <&mmcc VIDEO_AHB_CLK>,
+ <&mmcc VIDEO_AXI_CLK>,
+ <&mmcc VIDEO_MAXI_CLK>;
+ clock-names = "core", "iface", "bus", "mbus";
+ iommus = <&mmss_smmu 0x400>,
+ <&mmss_smmu 0x401>,
+ <&mmss_smmu 0x40a>,
+ <&mmss_smmu 0x407>,
+ <&mmss_smmu 0x40e>,
+ <&mmss_smmu 0x40f>,
+ <&mmss_smmu 0x408>,
+ <&mmss_smmu 0x409>,
+ <&mmss_smmu 0x40b>,
+ <&mmss_smmu 0x40c>,
+ <&mmss_smmu 0x40d>,
+ <&mmss_smmu 0x410>,
+ <&mmss_smmu 0x421>,
+ <&mmss_smmu 0x428>,
+ <&mmss_smmu 0x429>,
+ <&mmss_smmu 0x42b>,
+ <&mmss_smmu 0x42c>,
+ <&mmss_smmu 0x42d>,
+ <&mmss_smmu 0x411>,
+ <&mmss_smmu 0x431>;
+ memory-region = <&venus_mem>;
+ status = "disabled";
+
+ video-decoder {
+ compatible = "venus-decoder";
+ clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
+ clock-names = "core";
+ power-domains = <&mmcc VIDEO_SUBCORE0_GDSC>;
+ };
+
+ video-encoder {
+ compatible = "venus-encoder";
+ clocks = <&mmcc VIDEO_SUBCORE1_CLK>;
+ clock-names = "core";
+ power-domains = <&mmcc VIDEO_SUBCORE1_GDSC>;
+ };
+ };
+
mmss_smmu: iommu@cd00000 {
compatible = "qcom,msm8998-smmu-v2", "qcom,smmu-v2";
reg = <0x0cd00000 0x40000>;
@@ -3195,6 +3224,7 @@
iommus = <&anoc2_smmu 0x1900>,
<&anoc2_smmu 0x1901>;
qcom,snoc-host-cap-8bit-quirk;
+ qcom,no-msa-ready-indicator;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/pm6125.dtsi b/arch/arm64/boot/dts/qcom/pm6125.dtsi
index 99369a0cdb61..d0db28336fa9 100644
--- a/arch/arm64/boot/dts/qcom/pm6125.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6125.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pm6125-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm6125_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pm6150.dtsi b/arch/arm64/boot/dts/qcom/pm6150.dtsi
index 6de6ed562d97..59524609fb1e 100644
--- a/arch/arm64/boot/dts/qcom/pm6150.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6150.dtsi
@@ -13,7 +13,7 @@
thermal-zones {
pm6150_thermal: pm6150-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pm6150_temp>;
trips {
@@ -166,5 +166,11 @@
reg = <0x1 SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
+
+ pm6150_vib: vibrator@5300 {
+ compatible = "qcom,pm6150-vib", "qcom,pmi632-vib";
+ reg = <0x5300>;
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm64/boot/dts/qcom/pm6150l.dtsi b/arch/arm64/boot/dts/qcom/pm6150l.dtsi
index 0fce45276e5c..334f976f1154 100644
--- a/arch/arm64/boot/dts/qcom/pm6150l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6150l.dtsi
@@ -10,9 +10,6 @@
/ {
thermal-zones {
pm6150l-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&pm6150l_temp>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/pm6350.dtsi b/arch/arm64/boot/dts/qcom/pm6350.dtsi
index 3a2a841e83f1..a20ee2457101 100644
--- a/arch/arm64/boot/dts/qcom/pm6350.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6350.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pm6350-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm6350_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index 98dc04962fe3..156b2ddff0dc 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -13,7 +13,6 @@
thermal-zones {
pm660-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&pm660_temp>;
@@ -74,6 +73,23 @@
};
};
+ pm660_charger: charger@1000 {
+ compatible = "qcom,pm660-charger";
+ reg = <0x1000>;
+
+ interrupts = <0x0 0x13 0x4 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x12 0x2 IRQ_TYPE_EDGE_BOTH>,
+ <0x0 0x16 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x0 0x13 0x6 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "usb-plugin", "bat-ov", "wdog-bark", "usbin-icl-change";
+
+ io-channels = <&pm660_rradc 3>,
+ <&pm660_rradc 4>;
+ io-channel-names = "usbin_i", "usbin_v";
+
+ status = "disabled";
+ };
+
pm660_temp: temp-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
@@ -181,6 +197,14 @@
};
};
+ pm660_rradc: adc@4500 {
+ compatible = "qcom,pm660-rradc";
+ reg = <0x4500>;
+ #io-channel-cells = <1>;
+
+ status = "disabled";
+ };
+
pm660_gpios: gpio@c000 {
compatible = "qcom,pm660-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
diff --git a/arch/arm64/boot/dts/qcom/pm660l.dtsi b/arch/arm64/boot/dts/qcom/pm660l.dtsi
index 6fdbf507c262..0094e0ef058b 100644
--- a/arch/arm64/boot/dts/qcom/pm660l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660l.dtsi
@@ -13,7 +13,6 @@
thermal-zones {
pm660l-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&pm660l_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pm7250b.dtsi b/arch/arm64/boot/dts/qcom/pm7250b.dtsi
index 3bf7cf5d1700..0761e6b5fd8d 100644
--- a/arch/arm64/boot/dts/qcom/pm7250b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm7250b.dtsi
@@ -11,7 +11,6 @@
thermal-zones {
pm7250b-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm7250b_temp>;
@@ -45,6 +44,52 @@
#address-cells = <1>;
#size-cells = <0>;
+ pm7250b_vbus: usb-vbus-regulator@1100 {
+ compatible = "qcom,pm7250b-vbus-reg", "qcom,pm8150b-vbus-reg";
+ reg = <0x1100>;
+ status = "disabled";
+ };
+
+ pm7250b_typec: typec@1500 {
+ compatible = "qcom,pm7250b-typec", "qcom,pm8150b-typec";
+ reg = <0x1500>,
+ <0x1700>;
+ interrupts = <PM7250B_SID 0x15 0x00 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x15 0x01 IRQ_TYPE_EDGE_BOTH>,
+ <PM7250B_SID 0x15 0x02 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x15 0x03 IRQ_TYPE_EDGE_BOTH>,
+ <PM7250B_SID 0x15 0x04 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x15 0x05 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x15 0x06 IRQ_TYPE_EDGE_BOTH>,
+ <PM7250B_SID 0x15 0x07 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x17 0x00 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x17 0x01 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x17 0x02 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x17 0x03 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x17 0x04 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x17 0x05 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x17 0x06 IRQ_TYPE_EDGE_RISING>,
+ <PM7250B_SID 0x17 0x07 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "or-rid-detect-change",
+ "vpd-detect",
+ "cc-state-change",
+ "vconn-oc",
+ "vbus-change",
+ "attach-detach",
+ "legacy-cable-detect",
+ "try-snk-src-detect",
+ "sig-tx",
+ "sig-rx",
+ "msg-tx",
+ "msg-rx",
+ "msg-tx-failed",
+ "msg-tx-discarded",
+ "msg-rx-discarded",
+ "fr-swap";
+ vdd-vbus-supply = <&pm7250b_vbus>;
+ status = "disabled";
+ };
+
pm7250b_temp: temp-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
diff --git a/arch/arm64/boot/dts/qcom/pm7325.dtsi b/arch/arm64/boot/dts/qcom/pm7325.dtsi
index d1c5476af5ee..6e29468505b2 100644
--- a/arch/arm64/boot/dts/qcom/pm7325.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm7325.dtsi
@@ -35,7 +35,7 @@
&thermal_zones {
pm7325_thermal: pm7325-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pm7325_temp_alarm>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/pm7550ba.dtsi b/arch/arm64/boot/dts/qcom/pm7550ba.dtsi
index 8b00ece987d1..853a1d83a7f0 100644
--- a/arch/arm64/boot/dts/qcom/pm7550ba.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm7550ba.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pm7550ba-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm7550ba_temp_alarm>;
diff --git a/arch/arm64/boot/dts/qcom/pm8010.dtsi b/arch/arm64/boot/dts/qcom/pm8010.dtsi
index 0ea641e12209..ef330194946b 100644
--- a/arch/arm64/boot/dts/qcom/pm8010.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8010.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pm8010-m-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8010_m_temp_alarm>;
@@ -31,7 +30,6 @@
pm8010-n-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8010_n_temp_alarm>;
diff --git a/arch/arm64/boot/dts/qcom/pm8150.dtsi b/arch/arm64/boot/dts/qcom/pm8150.dtsi
index 3ba3ba5d8fce..a74a7ff660d2 100644
--- a/arch/arm64/boot/dts/qcom/pm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150.dtsi
@@ -13,7 +13,6 @@
thermal-zones {
pm8150-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8150_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
index 1aee3270ce7b..3f7b0b6a1d10 100644
--- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -12,7 +12,6 @@
thermal-zones {
pm8150b-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8150b_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pm8150l.dtsi b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
index ac08a09c64c2..3911d6d0d2e2 100644
--- a/arch/arm64/boot/dts/qcom/pm8150l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
@@ -12,7 +12,6 @@
thermal-zones {
pm8150l-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8150l_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pm8350.dtsi b/arch/arm64/boot/dts/qcom/pm8350.dtsi
index 9ed9ba23e81e..cb55b23688d6 100644
--- a/arch/arm64/boot/dts/qcom/pm8350.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8350.dtsi
@@ -10,7 +10,7 @@
thermal-zones {
pm8350_thermal: pm8350-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pm8350_temp_alarm>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/pm8350b.dtsi b/arch/arm64/boot/dts/qcom/pm8350b.dtsi
index 05c105898892..cf82f8a64a9b 100644
--- a/arch/arm64/boot/dts/qcom/pm8350b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8350b.dtsi
@@ -10,7 +10,7 @@
thermal-zones {
pm8350b_thermal: pm8350b-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pm8350b_temp_alarm>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/pm8350c.dtsi b/arch/arm64/boot/dts/qcom/pm8350c.dtsi
index aa74e21fe0dc..1a24e6439e36 100644
--- a/arch/arm64/boot/dts/qcom/pm8350c.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8350c.dtsi
@@ -48,7 +48,7 @@
thermal-zones {
pm8350c_thermal: pm8350c-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pm8350c_temp_alarm>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/pm8450.dtsi b/arch/arm64/boot/dts/qcom/pm8450.dtsi
index ae5bce3cf46e..decb8809fd36 100644
--- a/arch/arm64/boot/dts/qcom/pm8450.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8450.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pm8450-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8450_temp_alarm>;
diff --git a/arch/arm64/boot/dts/qcom/pm8550.dtsi b/arch/arm64/boot/dts/qcom/pm8550.dtsi
index 797a18c249a4..896bcacb6490 100644
--- a/arch/arm64/boot/dts/qcom/pm8550.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8550.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pm8550-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8550_temp_alarm>;
diff --git a/arch/arm64/boot/dts/qcom/pm8550b.dtsi b/arch/arm64/boot/dts/qcom/pm8550b.dtsi
index 72609f31c890..74d23b8970f4 100644
--- a/arch/arm64/boot/dts/qcom/pm8550b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8550b.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pm8550b-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8550b_temp_alarm>;
diff --git a/arch/arm64/boot/dts/qcom/pm8550ve.dtsi b/arch/arm64/boot/dts/qcom/pm8550ve.dtsi
index 4dc1f03ab2c7..9d4734eabf5a 100644
--- a/arch/arm64/boot/dts/qcom/pm8550ve.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8550ve.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pm8550ve-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8550ve_temp_alarm>;
diff --git a/arch/arm64/boot/dts/qcom/pm8550vs.dtsi b/arch/arm64/boot/dts/qcom/pm8550vs.dtsi
index 97b1c18aa7d8..6426b431616b 100644
--- a/arch/arm64/boot/dts/qcom/pm8550vs.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8550vs.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pm8550vs-c-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8550vs_c_temp_alarm>;
@@ -31,7 +30,6 @@
pm8550vs-d-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8550vs_d_temp_alarm>;
@@ -52,7 +50,6 @@
pm8550vs-e-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8550vs_e_temp_alarm>;
@@ -73,7 +70,6 @@
pm8550vs-g-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pm8550vs_g_temp_alarm>;
diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
index 4b2e8fb47d2d..f8e4829ff7f7 100644
--- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
@@ -4,8 +4,37 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
-&spmi_bus {
+/ {
+ thermal-zones {
+ pm8916-thermal {
+ polling-delay-passive = <100>;
+
+ thermal-sensors = <&pm8916_temp>;
+
+ trips {
+ trip0 {
+ temperature = <105000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+
+ trip2 {
+ temperature = <145000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+ };
+};
+&spmi_bus {
pm8916_0: pmic@0 {
compatible = "qcom,pm8916", "qcom,spmi-pmic";
reg = <0x0 SPMI_USID>;
diff --git a/arch/arm64/boot/dts/qcom/pm8953.dtsi b/arch/arm64/boot/dts/qcom/pm8953.dtsi
index 1067e141be6c..64258505f9ba 100644
--- a/arch/arm64/boot/dts/qcom/pm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8953.dtsi
@@ -9,9 +9,6 @@
/ {
thermal-zones {
pm8953-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&pm8953_temp>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/pm8994.dtsi b/arch/arm64/boot/dts/qcom/pm8994.dtsi
index d44a95caf04a..353e4a6bd088 100644
--- a/arch/arm64/boot/dts/qcom/pm8994.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8994.dtsi
@@ -8,7 +8,6 @@
thermal-zones {
pm8994-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&pm8994_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
index 3f82715392c6..3ecb330590e5 100644
--- a/arch/arm64/boot/dts/qcom/pm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi
@@ -11,7 +11,6 @@
thermal-zones {
pm8998-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&pm8998_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pmi632.dtsi b/arch/arm64/boot/dts/qcom/pmi632.dtsi
index 94d53b1cf6c8..8c899d148e46 100644
--- a/arch/arm64/boot/dts/qcom/pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi632.dtsi
@@ -11,7 +11,6 @@
thermal-zones {
pmi632-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pmi632_temp>;
@@ -200,5 +199,11 @@
status = "disabled";
};
+
+ pmi632_vib: vibrator@5700 {
+ compatible = "qcom,pmi632-vib";
+ reg = <0x5700>;
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm64/boot/dts/qcom/pmi8950.dtsi b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
index 1029f3b1bb9a..b4822cb17a37 100644
--- a/arch/arm64/boot/dts/qcom/pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
@@ -84,6 +84,14 @@
#address-cells = <1>;
#size-cells = <0>;
+ pmi8950_pwm: pwm@b000 {
+ compatible = "qcom,pmi8950-pwm";
+ reg = <0xb000 0x100>;
+ #pwm-cells = <2>;
+
+ status = "disabled";
+ };
+
pmi8950_wled: leds@d800 {
compatible = "qcom,pmi8950-wled";
reg = <0xd800>, <0xd900>;
diff --git a/arch/arm64/boot/dts/qcom/pmm8155au_1.dtsi b/arch/arm64/boot/dts/qcom/pmm8155au_1.dtsi
index dbd4b91dfe06..5084de66fc46 100644
--- a/arch/arm64/boot/dts/qcom/pmm8155au_1.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmm8155au_1.dtsi
@@ -12,7 +12,6 @@
thermal-zones {
pmm8155au-1-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pmm8155au_1_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pmm8155au_2.dtsi b/arch/arm64/boot/dts/qcom/pmm8155au_2.dtsi
index 1cee20ac2c9c..555e4a456ef1 100644
--- a/arch/arm64/boot/dts/qcom/pmm8155au_2.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmm8155au_2.dtsi
@@ -11,7 +11,6 @@
thermal-zones {
pmm8155au-2-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pmm8155au_2_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pmr735a.dtsi b/arch/arm64/boot/dts/qcom/pmr735a.dtsi
index febda50779f9..f8efd8e5e68f 100644
--- a/arch/arm64/boot/dts/qcom/pmr735a.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmr735a.dtsi
@@ -36,7 +36,7 @@
thermal-zones {
pmr735a_thermal: pmr735a-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pmr735a_temp_alarm>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/pmr735b.dtsi b/arch/arm64/boot/dts/qcom/pmr735b.dtsi
index f7473e247322..09affc05b397 100644
--- a/arch/arm64/boot/dts/qcom/pmr735b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmr735b.dtsi
@@ -10,7 +10,7 @@
thermal-zones {
pmr735b_thermal: pmr735b-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pmr735b_temp_alarm>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/pmr735d_a.dtsi b/arch/arm64/boot/dts/qcom/pmr735d_a.dtsi
index 37daaefe3431..f9f1793d310e 100644
--- a/arch/arm64/boot/dts/qcom/pmr735d_a.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmr735d_a.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pmr735d-k-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pmr735d_k_temp_alarm>;
diff --git a/arch/arm64/boot/dts/qcom/pmr735d_b.dtsi b/arch/arm64/boot/dts/qcom/pmr735d_b.dtsi
index 3b470f6ac46f..d91fbd3bff10 100644
--- a/arch/arm64/boot/dts/qcom/pmr735d_b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmr735d_b.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pmr735d-l-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pmr735d_l_temp_alarm>;
diff --git a/arch/arm64/boot/dts/qcom/pms405.dtsi b/arch/arm64/boot/dts/qcom/pms405.dtsi
index 461ad97032f7..3f9100c7eff4 100644
--- a/arch/arm64/boot/dts/qcom/pms405.dtsi
+++ b/arch/arm64/boot/dts/qcom/pms405.dtsi
@@ -12,7 +12,6 @@
thermal-zones {
pms405-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&pms405_temp>;
diff --git a/arch/arm64/boot/dts/qcom/pmx75.dtsi b/arch/arm64/boot/dts/qcom/pmx75.dtsi
index 373e45f63dff..2e61b7849c92 100644
--- a/arch/arm64/boot/dts/qcom/pmx75.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmx75.dtsi
@@ -10,7 +10,6 @@
thermal-zones {
pmx75-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pmx75_temp_alarm>;
diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi
index 106110a9f551..8f3be4c75db3 100644
--- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/clock/qcom,dispcc-qcm2290.h>
#include <dt-bindings/clock/qcom,gcc-qcm2290.h>
+#include <dt-bindings/clock/qcom,qcm2290-gpucc.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/dma/qcom-gpi.h>
#include <dt-bindings/firmware/qcom,scm.h>
@@ -758,6 +759,11 @@
reg = <0x25b 0x1>;
bits = <1 4>;
};
+
+ gpu_speed_bin: gpu-speed-bin@2006 {
+ reg = <0x2006 0x2>;
+ bits = <5 8>;
+ };
};
pmu@1b8e300 {
@@ -1425,6 +1431,154 @@
};
};
+ gpu: gpu@5900000 {
+ compatible = "qcom,adreno-07000200", "qcom,adreno";
+ reg = <0x0 0x05900000 0x0 0x40000>;
+ reg-names = "kgsl_3d0_reg_memory";
+
+ interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gpucc GPU_CC_GX_GFX3D_CLK>,
+ <&gpucc GPU_CC_AHB_CLK>,
+ <&gcc GCC_BIMC_GPU_AXI_CLK>,
+ <&gcc GCC_GPU_MEMNOC_GFX_CLK>,
+ <&gpucc GPU_CC_CX_GMU_CLK>,
+ <&gpucc GPU_CC_CXO_CLK>;
+ clock-names = "core",
+ "iface",
+ "mem_iface",
+ "alt_mem_iface",
+ "gmu",
+ "xo";
+
+ interconnects = <&bimc MASTER_GFX3D RPM_ALWAYS_TAG
+ &bimc SLAVE_EBI1 RPM_ALWAYS_TAG>;
+ interconnect-names = "gfx-mem";
+
+ iommus = <&adreno_smmu 0 1>,
+ <&adreno_smmu 2 0>;
+ operating-points-v2 = <&gpu_opp_table>;
+ power-domains = <&rpmpd QCM2290_VDDCX>;
+ qcom,gmu = <&gmu_wrapper>;
+
+ nvmem-cells = <&gpu_speed_bin>;
+ nvmem-cell-names = "speed_bin";
+ #cooling-cells = <2>;
+
+ status = "disabled";
+
+ zap-shader {
+ memory-region = <&pil_gpu_mem>;
+ };
+
+ gpu_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ /* TODO: Scale RPM_SMD_BIMC_GPU_CLK w/ turbo freqs */
+ opp-1123200000 {
+ opp-hz = /bits/ 64 <1123200000>;
+ required-opps = <&rpmpd_opp_turbo_plus>;
+ opp-peak-kBps = <6881000>;
+ opp-supported-hw = <0x3>;
+ turbo-mode;
+ };
+
+ opp-1017600000 {
+ opp-hz = /bits/ 64 <1017600000>;
+ required-opps = <&rpmpd_opp_turbo>;
+ opp-peak-kBps = <6881000>;
+ opp-supported-hw = <0x3>;
+ turbo-mode;
+ };
+
+ opp-921600000 {
+ opp-hz = /bits/ 64 <921600000>;
+ required-opps = <&rpmpd_opp_nom_plus>;
+ opp-peak-kBps = <6881000>;
+ opp-supported-hw = <0x3>;
+ };
+
+ opp-844800000 {
+ opp-hz = /bits/ 64 <844800000>;
+ required-opps = <&rpmpd_opp_nom>;
+ opp-peak-kBps = <6881000>;
+ opp-supported-hw = <0x7>;
+ };
+
+ opp-672000000 {
+ opp-hz = /bits/ 64 <672000000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ opp-peak-kBps = <3879000>;
+ opp-supported-hw = <0xf>;
+ };
+
+ opp-537600000 {
+ opp-hz = /bits/ 64 <537600000>;
+ required-opps = <&rpmpd_opp_svs>;
+ opp-peak-kBps = <2929000>;
+ opp-supported-hw = <0xf>;
+ };
+
+ opp-355200000 {
+ opp-hz = /bits/ 64 <355200000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ opp-peak-kBps = <1720000>;
+ opp-supported-hw = <0xf>;
+ };
+ };
+ };
+
+ gmu_wrapper: gmu@596a000 {
+ compatible = "qcom,adreno-gmu-wrapper";
+ reg = <0x0 0x0596a000 0x0 0x30000>;
+ reg-names = "gmu";
+ power-domains = <&gpucc GPU_CX_GDSC>,
+ <&gpucc GPU_GX_GDSC>;
+ power-domain-names = "cx",
+ "gx";
+ };
+
+ gpucc: clock-controller@5990000 {
+ compatible = "qcom,qcm2290-gpucc";
+ reg = <0x0 0x05990000 0x0 0x9000>;
+ clocks = <&gcc GCC_GPU_CFG_AHB_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>;
+ power-domains = <&rpmpd QCM2290_VDDCX>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ adreno_smmu: iommu@59a0000 {
+ compatible = "qcom,qcm2290-smmu-500", "qcom,adreno-smmu",
+ "qcom,smmu-500", "arm,mmu-500";
+ reg = <0x0 0x059a0000 0x0 0x10000>;
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_GPU_MEMNOC_GFX_CLK>,
+ <&gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>,
+ <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>;
+ clock-names = "mem",
+ "hlos",
+ "iface";
+
+ power-domains = <&gpucc GPU_CX_GDSC>;
+
+ #global-interrupts = <1>;
+ #iommu-cells = <2>;
+ };
+
mdss: display-subsystem@5e00000 {
compatible = "qcom,qcm2290-mdss";
reg = <0x0 0x05e00000 0x0 0x1000>;
@@ -1924,9 +2078,6 @@
thermal-zones {
mapss-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 0>;
trips {
@@ -1951,9 +2102,6 @@
};
video-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 1>;
trips {
@@ -1978,9 +2126,6 @@
};
wlan-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 2>;
trips {
@@ -2005,9 +2150,6 @@
};
cpuss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 3>;
trips {
@@ -2032,9 +2174,6 @@
};
cpuss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 4>;
trips {
@@ -2059,9 +2198,6 @@
};
mdm0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 5>;
trips {
@@ -2086,9 +2222,6 @@
};
mdm1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 6>;
trips {
@@ -2113,9 +2246,6 @@
};
gpu-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 7>;
trips {
@@ -2140,9 +2270,6 @@
};
hm-center-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 8>;
trips {
@@ -2167,9 +2294,6 @@
};
camera-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 9>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
index f3432701945f..8ab30c01712e 100644
--- a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
+++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
@@ -167,7 +167,7 @@
thermal-zones {
camera-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 2>;
trips {
@@ -181,7 +181,7 @@
chg-skin-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
+
thermal-sensors = <&pm7250b_adc_tm 0>;
trips {
@@ -195,7 +195,7 @@
conn-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
+
thermal-sensors = <&pm7250b_adc_tm 1>;
trips {
@@ -207,9 +207,28 @@
};
};
+ pm8008-thermal {
+ polling-delay-passive = <100>;
+ thermal-sensors = <&pm8008>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
quiet-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 1>;
trips {
@@ -223,7 +242,7 @@
rear-cam-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 4>;
trips {
@@ -237,7 +256,7 @@
sdm-skin-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 3>;
trips {
@@ -251,7 +270,7 @@
xo-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 0>;
trips {
@@ -271,46 +290,54 @@
qcom,pmic-id = "b";
vreg_s1b: smps1 {
+ regulator-name = "vreg_s1b";
regulator-min-microvolt = <1840000>;
regulator-max-microvolt = <2040000>;
};
vreg_s7b: smps7 {
+ regulator-name = "vreg_s7b";
regulator-min-microvolt = <535000>;
regulator-max-microvolt = <1120000>;
};
vreg_s8b: smps8 {
+ regulator-name = "vreg_s8b";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1500000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_RET>;
};
vreg_l1b: ldo1 {
+ regulator-name = "vreg_l1b";
regulator-min-microvolt = <825000>;
regulator-max-microvolt = <925000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l2b: ldo2 {
+ regulator-name = "vreg_l2b";
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <3544000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l3b: ldo3 {
+ regulator-name = "vreg_l3b";
regulator-min-microvolt = <312000>;
regulator-max-microvolt = <910000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l6b: ldo6 {
+ regulator-name = "vreg_l6b";
regulator-min-microvolt = <1140000>;
regulator-max-microvolt = <1260000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l7b: ldo7 {
+ regulator-name = "vreg_l7b";
/* Constrained for UFS VCC, at least until UFS driver scales voltage */
regulator-min-microvolt = <2952000>;
regulator-max-microvolt = <2952000>;
@@ -318,66 +345,77 @@
};
vreg_l8b: ldo8 {
+ regulator-name = "vreg_l8b";
regulator-min-microvolt = <870000>;
regulator-max-microvolt = <970000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l9b: ldo9 {
+ regulator-name = "vreg_l9b";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1304000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l11b: ldo11 {
+ regulator-name = "vreg_l11b";
regulator-min-microvolt = <1504000>;
regulator-max-microvolt = <2000000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l12b: ldo12 {
+ regulator-name = "vreg_l12b";
regulator-min-microvolt = <751000>;
regulator-max-microvolt = <824000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l13b: ldo13 {
+ regulator-name = "vreg_l13b";
regulator-min-microvolt = <530000>;
regulator-max-microvolt = <824000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l14b: ldo14 {
+ regulator-name = "vreg_l14b";
regulator-min-microvolt = <1080000>;
regulator-max-microvolt = <1304000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l15b: ldo15 {
+ regulator-name = "vreg_l15b";
regulator-min-microvolt = <765000>;
regulator-max-microvolt = <1020000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l16b: ldo16 {
+ regulator-name = "vreg_l16b";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1300000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l17b: ldo17 {
+ regulator-name = "vreg_l17b";
regulator-min-microvolt = <1700000>;
regulator-max-microvolt = <1900000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l18b: ldo18 {
+ regulator-name = "vreg_l18b";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <2000000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l19b: ldo19 {
+ regulator-name = "vreg_l19b";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <2000000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
@@ -389,60 +427,70 @@
qcom,pmic-id = "c";
vreg_s1c: smps1 {
+ regulator-name = "vreg_s1c";
regulator-min-microvolt = <2190000>;
regulator-max-microvolt = <2210000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_s9c: smps9 {
+ regulator-name = "vreg_s9c";
regulator-min-microvolt = <1010000>;
regulator-max-microvolt = <1170000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l1c: ldo1 {
+ regulator-name = "vreg_l1c";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1980000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l2c: ldo2 {
+ regulator-name = "vreg_l2c";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1950000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l3c: ldo3 {
+ regulator-name = "vreg_l3c";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3400000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l4c: ldo4 {
+ regulator-name = "vreg_l4c";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <3300000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l5c: ldo5 {
+ regulator-name = "vreg_l5c";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <3300000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l6c: ldo6 {
+ regulator-name = "vreg_l6c";
regulator-min-microvolt = <1650000>;
regulator-max-microvolt = <3544000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l7c: ldo7 {
+ regulator-name = "vreg_l7c";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3544000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l8c: ldo8 {
+ regulator-name = "vreg_l8c";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <2000000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
@@ -451,36 +499,42 @@
};
vreg_l9c: ldo9 {
+ regulator-name = "vreg_l9c";
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <3544000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l10c: ldo10 {
+ regulator-name = "vreg_l10c";
regulator-min-microvolt = <720000>;
regulator-max-microvolt = <1050000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l11c: ldo11 {
+ regulator-name = "vreg_l11c";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <3544000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l12c: ldo12 {
+ regulator-name = "vreg_l12c";
regulator-min-microvolt = <1650000>;
regulator-max-microvolt = <2000000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l13c: ldo13 {
+ regulator-name = "vreg_l13c";
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <3544000>;
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>;
@@ -522,7 +576,76 @@
&i2c1 {
status = "okay";
- /* PM8008 PMIC @ 8 and 9 */
+ pm8008: pmic@8 {
+ compatible = "qcom,pm8008";
+ reg = <0x8>;
+
+ interrupts-extended = <&tlmm 25 IRQ_TYPE_EDGE_RISING>;
+ reset-gpios = <&pm8350c_gpios 3 GPIO_ACTIVE_LOW>;
+
+ vdd-l1-l2-supply = <&vreg_s8b>;
+ vdd-l3-l4-supply = <&vreg_bob>;
+ vdd-l5-supply = <&vreg_bob>;
+ vdd-l6-supply = <&vreg_s1b>;
+ vdd-l7-supply = <&vreg_bob>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pm8008_int_default>, <&pm8008_reset_n_default>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pm8008 0 0 2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ #thermal-sensor-cells = <0>;
+
+ regulators {
+ vreg_l1p: ldo1 {
+ regulator-name = "vreg_l1p";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l2p: ldo2 {
+ regulator-name = "vreg_l2p";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1152000>;
+ };
+
+ vreg_l3p: ldo3 {
+ regulator-name = "vreg_l3p";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ vreg_l4p: ldo4 {
+ regulator-name = "vreg_l4p";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ vreg_l5p: ldo5 {
+ regulator-name = "vreg_l5p";
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ vreg_l6p: ldo6 {
+ regulator-name = "vreg_l6p";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1904000>;
+ };
+
+ vreg_l7p: ldo7 {
+ regulator-name = "vreg_l7p";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3000000>;
+ };
+ };
+ };
+
/* Pixelworks @ 26 */
/* FSA4480 USB audio switch @ 42 */
/* AW86927FCR haptics @ 5a */
@@ -551,7 +674,7 @@
&ipa {
qcom,gsi-loader = "self";
memory-region = <&ipa_fw_mem>;
- firmware-name = "qcom/qcm6490/fairphone5/ipa_fws.mdt";
+ firmware-name = "qcom/qcm6490/fairphone5/ipa_fws.mbn";
status = "okay";
};
@@ -653,6 +776,14 @@
};
};
+&pm8350c_gpios {
+ pm8008_reset_n_default: pm8008-reset-n-default-state {
+ pins = "gpio3";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ bias-pull-down;
+ };
+};
+
&pmk8350_rtc {
status = "okay";
};
@@ -810,6 +941,13 @@
bias-pull-up;
};
+ pm8008_int_default: pm8008-int-default-state {
+ pins = "gpio25";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
qup_uart7_sleep_cts: qup-uart7-sleep-cts-state {
pins = "gpio28";
function = "gpio";
@@ -864,7 +1002,6 @@
};
&uart5 {
- compatible = "qcom,geni-debug-uart";
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
index 47ca2d000341..a0668f767e4b 100644
--- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
+++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
@@ -658,7 +658,6 @@
};
&uart5 {
- compatible = "qcom,geni-debug-uart";
status = "okay";
};
@@ -667,6 +666,7 @@
};
&usb_1_dwc3 {
+ /delete-property/ usb-role-switch;
dr_mode = "peripheral";
};
diff --git a/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts b/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts
new file mode 100644
index 000000000000..4667e47a74bc
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts
@@ -0,0 +1,961 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023, Luca Weiss <[email protected]>
+ * Copyright (c) 2024, Caleb Connolly <[email protected]>
+ */
+
+/dts-v1/;
+
+#define PM7250B_SID 8
+#define PM7250B_SID1 9
+
+#include <dt-bindings/iio/qcom,spmi-adc7-pm7325.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 "sc7280.dtsi"
+#include "pm7250b.dtsi"
+#include "pm7325.dtsi"
+#include "pm8350c.dtsi" /* PM7350C */
+#include "pmk8350.dtsi" /* PMK7325 */
+
+/delete-node/ &rmtfs_mem;
+
+/ {
+ model = "SHIFT SHIFTphone 8";
+ compatible = "shift,otter", "qcom,qcm6490";
+ chassis-type = "handset";
+
+ aliases {
+ serial0 = &uart5;
+ serial1 = &uart7;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ stdout-path = "serial0:115200n8";
+
+ framebuffer0: framebuffer@a000000 {
+ compatible = "simple-framebuffer";
+ reg = <0x0 0xe1000000 0x0 (2400 * 1080 * 4)>;
+ width = <1080>;
+ height = <2400>;
+ stride = <(1080 * 4)>;
+ format = "a8r8g8b8";
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&volume_down_default>;
+ pinctrl-names = "default";
+
+ key-volume-up {
+ label = "Volume up";
+ gpios = <&pm7325_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <15>;
+ };
+ };
+
+ pmic-glink {
+ compatible = "qcom,qcm6490-pmic-glink", "qcom,pmic-glink";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ 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_ss_in: endpoint {
+ remote-endpoint = <&usb_dp_qmpphy_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ pmic_glink_sbu: endpoint {
+ remote-endpoint = <&fsa4480_sbu_mux>;
+ };
+ };
+ };
+ };
+ };
+
+ reserved-memory {
+ cont_splash_mem: cont-splash@e1000000 {
+ reg = <0x0 0xe1000000 0x0 0x2300000>;
+ no-map;
+ };
+
+ cdsp_mem: cdsp@88f00000 {
+ reg = <0x0 0x88f00000 0x0 0x1e00000>;
+ 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>;
+ polling-delay = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 2>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ chg-skin-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm7250b_adc_tm 0>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ conn-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm7250b_adc_tm 1>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ quiet-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 1>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ rear-cam-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 4>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ sdm-skin-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 3>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ xo-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 0>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm7325-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vreg_s1b: smps1 {
+ regulator-name = "vreg_s1b";
+ regulator-min-microvolt = <1840000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ vreg_s7b: smps7 {
+ regulator-name = "vreg_s7b";
+ regulator-min-microvolt = <535000>;
+ regulator-max-microvolt = <1120000>;
+ };
+
+ vreg_s8b: smps8 {
+ regulator-name = "vreg_s8b";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_RET>;
+ };
+
+ vreg_l1b: ldo1 {
+ regulator-name = "vreg_l1b";
+ regulator-min-microvolt = <825000>;
+ regulator-max-microvolt = <925000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2b: ldo2 {
+ regulator-name = "vreg_l2b";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3b: ldo3 {
+ regulator-name = "vreg_l3b";
+ regulator-min-microvolt = <312000>;
+ regulator-max-microvolt = <910000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6b: ldo6 {
+ regulator-name = "vreg_l6b";
+ regulator-min-microvolt = <1140000>;
+ regulator-max-microvolt = <1260000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7b: ldo7 {
+ regulator-name = "vreg_l7b";
+ /* Constrained for UFS VCC, at least until UFS driver scales voltage */
+ regulator-min-microvolt = <2952000>;
+ regulator-max-microvolt = <2952000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8b: ldo8 {
+ regulator-name = "vreg_l8b";
+ regulator-min-microvolt = <870000>;
+ regulator-max-microvolt = <970000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9b: ldo9 {
+ regulator-name = "vreg_l9b";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11b: ldo11 {
+ regulator-name = "vreg_l11b";
+ regulator-min-microvolt = <1504000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12b: ldo12 {
+ regulator-name = "vreg_l12b";
+ regulator-min-microvolt = <751000>;
+ regulator-max-microvolt = <824000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13b: ldo13 {
+ regulator-name = "vreg_l13b";
+ regulator-min-microvolt = <530000>;
+ regulator-max-microvolt = <824000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14b: ldo14 {
+ regulator-name = "vreg_l14b";
+ regulator-min-microvolt = <1080000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l15b: ldo15 {
+ regulator-name = "vreg_l15b";
+ regulator-min-microvolt = <765000>;
+ regulator-max-microvolt = <1020000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l16b: ldo16 {
+ regulator-name = "vreg_l16b";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l17b: ldo17 {
+ regulator-name = "vreg_l17b";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l18b: ldo18 {
+ regulator-name = "vreg_l18b";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l19b: ldo19 {
+ regulator-name = "vreg_l19b";
+ 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";
+
+ vreg_s1c: smps1 {
+ regulator-name = "vreg_s1c";
+ regulator-min-microvolt = <2190000>;
+ regulator-max-microvolt = <2210000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s9c: smps9 {
+ regulator-name = "vreg_s9c";
+ regulator-min-microvolt = <1010000>;
+ regulator-max-microvolt = <1170000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1c: ldo1 {
+ regulator-name = "vreg_l1c";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2c: ldo2 {
+ regulator-name = "vreg_l2c";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1950000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3c: ldo3 {
+ regulator-name = "vreg_l3c";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4c: ldo4 {
+ regulator-name = "vreg_l4c";
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5c: ldo5 {
+ regulator-name = "vreg_l5c";
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6c: ldo6 {
+ regulator-name = "vreg_l6c";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7c: ldo7 {
+ regulator-name = "vreg_l7c";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8c: ldo8 {
+ regulator-name = "vreg_l8c";
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9c: ldo9 {
+ regulator-name = "vreg_l9c";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10c: ldo10 {
+ regulator-name = "vreg_l10c";
+ regulator-min-microvolt = <720000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11c: ldo11 {
+ regulator-name = "vreg_l11c";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12c: ldo12 {
+ regulator-name = "vreg_l12c";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13c: ldo13 {
+ regulator-name = "vreg_l13c";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ 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>;
+ };
+ };
+};
+
+&gcc {
+ protected-clocks = <GCC_CFG_NOC_LPASS_CLK>,
+ <GCC_EDP_CLKREF_EN>,
+ <GCC_MSS_CFG_AHB_CLK>,
+ <GCC_MSS_GPLL0_MAIN_DIV_CLK_SRC>,
+ <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 {
+ status = "okay";
+};
+
+&gpu_zap_shader {
+ firmware-name = "qcom/qcm6490/SHIFT/otter/a660_zap.mbn";
+};
+
+&i2c1 {
+ status = "okay";
+
+ /* PM8008 PMIC @ 8 and 9 */
+ /* rtc6226 FM receiver @ 64 */
+
+ 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>;
+ };
+ };
+ };
+};
+
+&i2c4 {
+ status = "okay";
+
+ /* tas2563 audio codec @ 4d */
+};
+
+&i2c9 {
+ status = "okay";
+
+ /* TMS(?) NFC @ 28 */
+ /* Ti drv2624 haptics @ 5a */
+};
+
+&i2c13 {
+ status = "okay";
+
+ /* focaltech FT3658U @ 38 */
+};
+
+&ipa {
+ qcom,gsi-loader = "self";
+ memory-region = <&ipa_fw_mem>;
+ firmware-name = "qcom/qcm6490/SHIFT/otter/ipa_fws.mbn";
+ status = "okay";
+};
+
+&pm7250b_adc {
+ channel@4d {
+ reg = <ADC5_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "charger_skin_therm";
+ };
+
+ channel@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "conn_therm";
+ };
+};
+
+&pm7250b_adc_tm {
+ status = "okay";
+
+ charger-skin-therm@0 {
+ reg = <0>;
+ io-channels = <&pm7250b_adc ADC5_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ conn-therm@1 {
+ reg = <1>;
+ io-channels = <&pm7250b_adc ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+};
+
+&pm7325_gpios {
+ volume_down_default: volume-down-default-state {
+ pins = "gpio6";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ power-source = <1>;
+ bias-pull-up;
+ input-enable;
+ };
+};
+
+&pmk8350_adc_tm {
+ status = "okay";
+
+ xo-therm@0 {
+ reg = <0>;
+ io-channels = <&pmk8350_vadc PMK8350_ADC7_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ 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>;
+ };
+};
+
+&pmk8350_rtc {
+ status = "okay";
+};
+
+&pmk8350_vadc {
+ status = "okay";
+
+ 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";
+ };
+
+ 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";
+ };
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&qup_spi13_cs {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&qup_spi13_data_clk {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&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/qcm6490/SHIFT/otter/adsp.mbn";
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/qcm6490/SHIFT/otter/cdsp.mbn";
+ status = "okay";
+};
+
+&remoteproc_mpss {
+ firmware-name = "qcom/qcm6490/SHIFT/otter/modem.mbn";
+ status = "okay";
+};
+
+&remoteproc_wpss {
+ firmware-name = "qcom/qcm6490/SHIFT/otter/wpss.mbn";
+ status = "okay";
+};
+
+&sdc2_clk {
+ drive-strength = <16>;
+ bias-disable;
+};
+
+&sdc2_cmd {
+ drive-strength = <10>;
+ bias-pull-up;
+};
+
+&sdc2_data {
+ drive-strength = <10>;
+ bias-pull-up;
+};
+
+&sdhc_2 {
+ vmmc-supply = <&vreg_l9c>;
+ vqmmc-supply = <&vreg_l6c>;
+
+ pinctrl-0 = <&sdc2_clk>, <&sdc2_cmd>, <&sdc2_data>;
+ pinctrl-1 = <&sdc2_clk_sleep>, <&sdc2_cmd_sleep>, <&sdc2_data_sleep>;
+
+ status = "okay";
+};
+
+&tlmm {
+ /*
+ * 48-52: protected by XPU, not sure why.
+ */
+ gpio-reserved-ranges = <48 4>;
+
+ bluetooth_enable_default: bluetooth-enable-default-state {
+ pins = "gpio85";
+ function = "gpio";
+ output-low;
+ bias-disable;
+ };
+
+ qup_uart7_sleep_cts: qup-uart7-sleep-cts-state {
+ pins = "gpio28";
+ function = "gpio";
+ /*
+ * Configure a bias-bus-hold on CTS to lower power
+ * usage when Bluetooth is turned off. Bus hold will
+ * maintain a low power state regardless of whether
+ * the Bluetooth module drives the pin in either
+ * direction or leaves the pin fully unpowered.
+ */
+ bias-bus-hold;
+ };
+
+ qup_uart7_sleep_rts: qup-uart7-sleep-rts-state {
+ pins = "gpio29";
+ function = "gpio";
+ /*
+ * Configure pull-down on RTS. As RTS is active low
+ * signal, pull it low to indicate the BT SoC that it
+ * can wakeup the system anytime from suspend state by
+ * pulling RX low (by sending wakeup bytes).
+ */
+ bias-pull-down;
+ };
+
+ qup_uart7_sleep_tx: qup-uart7-sleep-tx-state {
+ pins = "gpio30";
+ function = "gpio";
+ /*
+ * Configure pull-up on TX when it isn't actively driven
+ * to prevent BT SoC from receiving garbage during sleep.
+ */
+ bias-pull-up;
+ };
+
+ qup_uart7_sleep_rx: qup-uart7-sleep-rx-state {
+ pins = "gpio31";
+ function = "gpio";
+ /*
+ * Configure a pull-up on RX. This is needed to avoid
+ * garbage data when the TX pin of the Bluetooth module
+ * is floating which may cause spurious wakeups.
+ */
+ bias-pull-up;
+ };
+
+ sw_ctrl_default: sw-ctrl-default-state {
+ pins = "gpio86";
+ function = "gpio";
+ bias-pull-down;
+ };
+};
+
+&uart5 {
+ compatible = "qcom,geni-debug-uart";
+ status = "okay";
+};
+
+&uart7 {
+ /delete-property/interrupts;
+ interrupts-extended = <&intc GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH>,
+ <&tlmm 31 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-1 = <&qup_uart7_sleep_cts>, <&qup_uart7_sleep_rts>, <&qup_uart7_sleep_tx>, <&qup_uart7_sleep_rx>;
+ pinctrl-names = "default", "sleep";
+
+ status = "okay";
+
+ bluetooth: bluetooth {
+ compatible = "qcom,wcn6750-bt";
+
+ pinctrl-0 = <&bluetooth_enable_default>, <&sw_ctrl_default>;
+ pinctrl-names = "default";
+
+ enable-gpios = <&tlmm 85 GPIO_ACTIVE_HIGH>;
+ swctrl-gpios = <&tlmm 86 GPIO_ACTIVE_HIGH>;
+
+ vddio-supply = <&vreg_l19b>;
+ vddaon-supply = <&vreg_s7b>;
+ vddbtcxmx-supply = <&vreg_s7b>;
+ vddrfacmn-supply = <&vreg_s7b>;
+ vddrfa0p8-supply = <&vreg_s7b>;
+ vddrfa1p7-supply = <&vreg_s1b>;
+ vddrfa1p2-supply = <&vreg_s8b>;
+ vddrfa2p2-supply = <&vreg_s1c>;
+ vddasd-supply = <&vreg_l11c>;
+
+ max-speed = <3200000>;
+ };
+};
+
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 175 GPIO_ACTIVE_LOW>;
+
+ vcc-supply = <&vreg_l7b>;
+ vcc-max-microamp = <800000>;
+ /*
+ * Technically l9b enables an eLDO (supplied by s1b) which then powers
+ * VCCQ2 of the UFS.
+ */
+ vccq-supply = <&vreg_l9b>;
+ vccq-max-microamp = <900000>;
+
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vreg_l10c>;
+ vdda-pll-supply = <&vreg_l6b>;
+
+ status = "okay";
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "otg";
+ usb-role-switch;
+};
+
+&usb_1_dwc3_hs {
+ remote-endpoint = <&pmic_glink_hs_in>;
+};
+
+&usb_dp_qmpphy_out {
+ remote-endpoint = <&pmic_glink_ss_in>;
+};
+
+&usb_1_hsphy {
+ vdda-pll-supply = <&vreg_l10c>;
+ vdda18-supply = <&vreg_l1c>;
+ vdda33-supply = <&vreg_l2b>;
+
+ qcom,hs-crossover-voltage-microvolt = <28000>;
+ qcom,hs-output-impedance-micro-ohms = <2600000>;
+ qcom,hs-rise-fall-time-bp = <5430>;
+ qcom,hs-disconnect-bp = <1743>;
+ qcom,hs-amplitude-bp = <2430>;
+
+ qcom,pre-emphasis-amplitude-bp = <20000>;
+ qcom,pre-emphasis-duration-bp = <20000>;
+
+ qcom,squelch-detector-bp = <(-2090)>;
+
+ orientation-switch;
+
+ status = "okay";
+};
+
+&usb_1_qmpphy {
+ vdda-phy-supply = <&vreg_l6b>;
+ vdda-pll-supply = <&vreg_l1b>;
+
+ status = "okay";
+};
+
+&wifi {
+ qcom,ath11k-calibration-variant = "SHIFTphone_8";
+
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi
index ac451f378056..c291bbed6073 100644
--- a/arch/arm64/boot/dts/qcom/qcs404.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi
@@ -1324,7 +1324,7 @@
};
apcs_hfpll: clock-controller@b016000 {
- compatible = "qcom,hfpll";
+ compatible = "qcom,qcs404-hfpll";
reg = <0x0b016000 0x30>;
#clock-cells = <0>;
clock-output-names = "apcs_hfpll";
@@ -1531,10 +1531,10 @@
timer {
compatible = "arm,armv8-timer";
- interrupts = <GIC_PPI 2 0xff08>,
- <GIC_PPI 3 0xff08>,
- <GIC_PPI 4 0xff08>,
- <GIC_PPI 1 0xff08>;
+ interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
};
smp2p-adsp {
@@ -1600,7 +1600,6 @@
thermal-zones {
aoss-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 0>;
@@ -1615,7 +1614,6 @@
q6-hvx-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 1>;
@@ -1630,7 +1628,6 @@
lpass-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 2>;
@@ -1645,7 +1642,6 @@
wlan-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 3>;
@@ -1660,7 +1656,6 @@
cluster-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 4>;
@@ -1694,7 +1689,6 @@
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 5>;
@@ -1728,7 +1722,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 6>;
@@ -1762,7 +1755,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 7>;
@@ -1796,7 +1788,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 8>;
@@ -1830,7 +1821,6 @@
gpu-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 9>;
diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
index a085ff5b5fb2..0d45662b8028 100644
--- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
+++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
@@ -52,6 +52,25 @@
};
};
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con: endpoint {
+ remote-endpoint = <&lt9611_out>;
+ };
+ };
+ };
+
+ lt9611_1v2: lt9611-vdd12-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "LT9611_1V2";
+
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
reserved-memory {
xbl_mem: xbl@80700000 {
reg = <0x0 0x80700000 0x0 0x100000>;
@@ -530,6 +549,54 @@
<GCC_WPSS_RSCP_CLK>;
};
+&gpi_dma0 {
+ status = "okay";
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ lt9611_codec: hdmi-bridge@2b {
+ compatible = "lontium,lt9611uxc";
+ reg = <0x2b>;
+
+ interrupts-extended = <&tlmm 24 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&pm7250b_gpios 2 GPIO_ACTIVE_HIGH>;
+
+ vdd-supply = <&lt9611_1v2>;
+ vcc-supply = <&vreg_l11c_2p8>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&lt9611_irq_pin &lt9611_rst_pin>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ lt9611_a: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ lt9611_out: endpoint {
+ remote-endpoint = <&hdmi_con>;
+ };
+ };
+ };
+ };
+};
+
&i2c1 {
status = "okay";
@@ -587,6 +654,21 @@
remote-endpoint = <&usb_dp_qmpphy_dp_in>;
};
+&mdss_dsi {
+ vdda-supply = <&vreg_l6b_1p2>;
+ status = "okay";
+};
+
+&mdss_dsi0_out {
+ remote-endpoint = <&lt9611_a>;
+ data-lanes = <0 1 2 3>;
+};
+
+&mdss_dsi_phy {
+ vdds-supply = <&vreg_l10c_0p88>;
+ status = "okay";
+};
+
&mdss_edp {
status = "okay";
};
@@ -602,10 +684,18 @@
status = "okay";
};
+&pmk8350_rtc {
+ status = "okay";
+};
+
&qupv3_id_0 {
status = "okay";
};
+&qupv3_id_1 {
+ status = "okay";
+};
+
&remoteproc_adsp {
firmware-name = "qcom/qcs6490/adsp.mbn";
status = "okay";
@@ -632,7 +722,6 @@
};
&uart5 {
- compatible = "qcom,geni-debug-uart";
status = "okay";
};
@@ -711,3 +800,23 @@
function = "gpio";
bias-disable;
};
+
+&pm7250b_gpios {
+ lt9611_rst_pin: lt9611-rst-state {
+ pins = "gpio2";
+ function = "normal";
+
+ output-high;
+ input-disable;
+ power-source = <0>;
+ };
+};
+
+&tlmm {
+ lt9611_irq_pin: lt9611-irq-state {
+ pins = "gpio24";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dts b/arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dts
new file mode 100644
index 000000000000..2e2e46f214c7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs8550-aim300-aiot.dts
@@ -0,0 +1,315 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include "qcs8550-aim300.dtsi"
+#include "pm8010.dtsi"
+#include "pmr735d_a.dtsi"
+#include "pmr735d_b.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. QCS8550 AIM300 AIOT";
+ compatible = "qcom,qcs8550-aim300-aiot", "qcom,qcs8550-aim300", "qcom,qcs8550",
+ "qcom,sm8550";
+
+ aliases {
+ serial0 = &uart7;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&volume_up_n>;
+ pinctrl-names = "default";
+
+ key-volume-up {
+ label = "Volume Up";
+ debounce-interval = <15>;
+ gpios = <&pm8550_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ linux,can-disable;
+ wakeup-source;
+ };
+ };
+
+ pmic-glink {
+ compatible = "qcom,sm8550-pmic-glink", "qcom,pmic-glink";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ orientation-gpios = <&tlmm 11 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_ss_in: endpoint {
+ remote-endpoint = <&redriver_ss_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ pmic_glink_sbu: endpoint {
+ remote-endpoint = <&fsa4480_sbu_mux>;
+ };
+ };
+ };
+ };
+ };
+
+ 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 {
+ vdd-bob1-supply = <&vph_pwr>;
+ vdd-bob2-supply = <&vph_pwr>;
+ };
+
+ regulators-3 {
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ };
+
+ regulators-4 {
+ vdd-s4-supply = <&vph_pwr>;
+ };
+
+ regulators-5 {
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ };
+};
+
+&i2c_hub_2 {
+ status = "okay";
+
+ typec-mux@42 {
+ compatible = "fcs,fsa4480";
+ reg = <0x42>;
+
+ vcc-supply = <&vreg_bob1>;
+
+ mode-switch;
+ orientation-switch;
+
+ port {
+ fsa4480_sbu_mux: endpoint {
+ remote-endpoint = <&pmic_glink_sbu>;
+ };
+ };
+ };
+
+ typec-retimer@1c {
+ compatible = "onnn,nb7vpq904m";
+ reg = <0x1c>;
+
+ vcc-supply = <&vreg_l15b_1p8>;
+
+ orientation-switch;
+ retimer-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ redriver_ss_out: endpoint {
+ remote-endpoint = <&pmic_glink_ss_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ redriver_ss_in: endpoint {
+ data-lanes = <3 2 1 0>;
+ remote-endpoint = <&usb_dp_qmpphy_out>;
+ };
+ };
+ };
+ };
+};
+
+&mdss_dsi0 {
+ status = "okay";
+
+ panel@0 {
+ compatible = "visionox,vtdr6130";
+ reg = <0>;
+
+ pinctrl-0 = <&dsi_active>, <&te_default>;
+ pinctrl-1 = <&dsi_suspend>, <&te_default>;
+ pinctrl-names = "default", "sleep";
+
+ reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>;
+
+ vci-supply = <&vreg_l13b_3p0>;
+ vdd-supply = <&vreg_l11b_1p2>;
+ vddio-supply = <&vreg_l12b_1p8>;
+
+ port {
+ panel0_in: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+ };
+};
+
+&mdss_dsi0_out {
+ remote-endpoint = <&panel0_in>;
+ data-lanes = <0 1 2 3>;
+};
+
+&mdss_dsi0_phy {
+ status = "okay";
+};
+
+&pcie0 {
+ status = "okay";
+};
+
+&pcie0_phy {
+ status = "okay";
+};
+
+&pcie1 {
+ status = "okay";
+};
+
+&pcie1_phy {
+ status = "okay";
+};
+
+&pm8550_gpios {
+ volume_up_n: volume-up-n-state {
+ pins = "gpio6";
+ function = "normal";
+ power-source = <1>;
+ bias-pull-up;
+ input-enable;
+ };
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+
+ status = "okay";
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&remoteproc_adsp {
+ firmware-name = "qcom/qcs8550/adsp.mbn",
+ "qcom/qcs8550/adsp_dtb.mbn";
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/qcs8550/cdsp.mbn",
+ "qcom/qcs8550/cdsp_dtb.mbn";
+ status = "okay";
+};
+
+&swr1 {
+ status = "okay";
+};
+
+&swr2 {
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <32 8>;
+
+ dsi_active: dsi-active-state {
+ pins = "gpio133";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ dsi_suspend: dsi-suspend-state {
+ pins = "gpio133";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ te_default: te-default-state {
+ pins = "gpio86";
+ function = "mdp_vsync";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+};
+
+&uart7 {
+ status = "okay";
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3_hs {
+ remote-endpoint = <&pmic_glink_hs_in>;
+};
+
+&usb_1_hsphy {
+ status = "okay";
+};
+
+&usb_dp_qmpphy {
+ status = "okay";
+};
+
+&usb_dp_qmpphy_out {
+ remote-endpoint = <&redriver_ss_in>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi b/arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi
new file mode 100644
index 000000000000..f6960e2d466a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs8550-aim300.dtsi
@@ -0,0 +1,405 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include "qcs8550.dtsi"
+#include "pm8550.dtsi"
+#include "pm8550b.dtsi"
+#define PMK8550VE_SID 5
+#include "pm8550ve.dtsi"
+#include "pm8550vs.dtsi"
+#include "pmk8550.dtsi"
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8550-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vdd-l1-l4-l10-supply = <&vreg_s6g_1p86>;
+ vdd-l2-l13-l14-supply = <&vreg_bob1>;
+ vdd-l3-supply = <&vreg_s4g_1p25>;
+ vdd-l5-l16-supply = <&vreg_bob1>;
+ vdd-l6-l7-supply = <&vreg_bob1>;
+ vdd-l8-l9-supply = <&vreg_bob1>;
+ vdd-l11-supply = <&vreg_s4g_1p25>;
+ vdd-l12-supply = <&vreg_s6g_1p86>;
+ vdd-l15-supply = <&vreg_s6g_1p86>;
+ vdd-l17-supply = <&vreg_bob2>;
+
+ vreg_bob1: bob1 {
+ regulator-name = "vreg_bob1";
+ regulator-min-microvolt = <3296000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob2: bob2 {
+ regulator-name = "vreg_bob2";
+ regulator-min-microvolt = <2720000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1b_1p8: ldo1 {
+ regulator-name = "vreg_l1b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2b_3p0: ldo2 {
+ regulator-name = "vreg_l2b_3p0";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5b_3p1: ldo5 {
+ regulator-name = "vreg_l5b_3p1";
+ regulator-min-microvolt = <3104000>;
+ regulator-max-microvolt = <3104000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6b_1p8: ldo6 {
+ regulator-name = "vreg_l6b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7b_1p8: ldo7 {
+ regulator-name = "vreg_l7b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8b_1p8: ldo8 {
+ regulator-name = "vreg_l8b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9b_2p9: ldo9 {
+ regulator-name = "vreg_l9b_2p9";
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11b_1p2: ldo11 {
+ regulator-name = "vreg_l11b_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1504000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12b_1p8: ldo12 {
+ regulator-name = "vreg_l12b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13b_3p0: ldo13 {
+ regulator-name = "vreg_l13b_3p0";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14b_3p2: ldo14 {
+ regulator-name = "vreg_l14b_3p2";
+ regulator-min-microvolt = <3200000>;
+ regulator-max-microvolt = <3200000>;
+ 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_l16b_2p8: ldo16 {
+ regulator-name = "vreg_l16b_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ 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,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vdd-l1-supply = <&vreg_s4g_1p25>;
+ vdd-l2-supply = <&vreg_s4e_0p95>;
+ vdd-l3-supply = <&vreg_s4e_0p95>;
+
+ vreg_l3c_0p9: ldo3 {
+ regulator-name = "vreg_l3c_0p9";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-2 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "d";
+
+ vdd-l1-supply = <&vreg_s4e_0p95>;
+ vdd-l2-supply = <&vreg_s4e_0p95>;
+ vdd-l3-supply = <&vreg_s4e_0p95>;
+
+ vreg_l1d_0p88: ldo1 {
+ regulator-name = "vreg_l1d_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-3 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "e";
+
+ vdd-l1-supply = <&vreg_s4e_0p95>;
+ vdd-l2-supply = <&vreg_s4e_0p95>;
+ vdd-l3-supply = <&vreg_s4g_1p25>;
+
+ vreg_s4e_0p95: smps4 {
+ regulator-name = "vreg_s4e_0p95";
+ regulator-min-microvolt = <904000>;
+ regulator-max-microvolt = <984000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s5e_1p08: smps5 {
+ regulator-name = "vreg_s5e_1p08";
+ regulator-min-microvolt = <1010000>;
+ regulator-max-microvolt = <1120000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1e_0p88: ldo1 {
+ regulator-name = "vreg_l1e_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2e_0p9: ldo2 {
+ regulator-name = "vreg_l2e_0p9";
+ regulator-min-microvolt = <870000>;
+ regulator-max-microvolt = <970000>;
+ 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,pm8550ve-rpmh-regulators";
+ qcom,pmic-id = "f";
+
+ vdd-l1-supply = <&vreg_s4e_0p95>;
+ vdd-l2-supply = <&vreg_s4e_0p95>;
+ vdd-l3-supply = <&vreg_s4e_0p95>;
+
+ vreg_s4f_0p5: smps4 {
+ regulator-name = "vreg_s4f_0p5";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <700000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1f_0p9: ldo1 {
+ regulator-name = "vreg_l1f_0p9";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2f_0p88: ldo2 {
+ regulator-name = "vreg_l2f_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3f_0p88: ldo3 {
+ regulator-name = "vreg_l3f_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-5 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "g";
+ vdd-l1-supply = <&vreg_s4g_1p25>;
+ vdd-l2-supply = <&vreg_s4g_1p25>;
+ vdd-l3-supply = <&vreg_s4g_1p25>;
+
+ vreg_s1g_1p25: smps1 {
+ regulator-name = "vreg_s1g_1p25";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s2g_0p85: smps2 {
+ regulator-name = "vreg_s2g_0p85";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1036000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s3g_0p8: smps3 {
+ regulator-name = "vreg_s3g_0p8";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1004000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s4g_1p25: smps4 {
+ regulator-name = "vreg_s4g_1p25";
+ regulator-min-microvolt = <1256000>;
+ regulator-max-microvolt = <1408000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s5g_0p85: smps5 {
+ regulator-name = "vreg_s5g_0p85";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1004000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s6g_1p86: smps6 {
+ regulator-name = "vreg_s6g_1p86";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1g_1p2: ldo1 {
+ regulator-name = "vreg_l1g_1p2";
+ regulator-min-microvolt = <1128000>;
+ regulator-max-microvolt = <1272000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2g_1p2: ldo2 {
+ regulator-name = "vreg_l2g_1p2";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3g_1p2: ldo3 {
+ regulator-name = "vreg_l3g_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&mdss_dsi0 {
+ vdda-supply = <&vreg_l3e_1p2>;
+};
+
+&mdss_dsi0_phy {
+ vdds-supply = <&vreg_l1e_0p88>;
+};
+
+&pcie0 {
+ perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&pcie0_default_state>;
+ pinctrl-names = "default";
+};
+
+&pcie0_phy {
+ vdda-phy-supply = <&vreg_l1e_0p88>;
+ vdda-pll-supply = <&vreg_l3e_1p2>;
+};
+
+&pcie1 {
+ perst-gpios = <&tlmm 97 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 99 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&pcie1_default_state>;
+ pinctrl-names = "default";
+};
+
+&pcie1_phy {
+ vdda-phy-supply = <&vreg_l3c_0p9>;
+ vdda-pll-supply = <&vreg_l3e_1p2>;
+ vdda-qref-supply = <&vreg_l1e_0p88>;
+};
+
+&pm8550b_eusb2_repeater {
+ vdd18-supply = <&vreg_l15b_1p8>;
+ vdd3-supply = <&vreg_l5b_3p1>;
+};
+
+&sleep_clk {
+ clock-frequency = <32000>;
+};
+
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 210 GPIO_ACTIVE_LOW>;
+ vcc-supply = <&vreg_l17b_2p5>;
+ vcc-max-microamp = <1300000>;
+ vccq-supply = <&vreg_l1g_1p2>;
+ vccq-max-microamp = <1200000>;
+ vdd-hba-supply = <&vreg_l3g_1p2>;
+
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vreg_l1d_0p88>;
+ vdda-pll-supply = <&vreg_l3e_1p2>;
+
+ status = "okay";
+};
+
+&usb_1_hsphy {
+ phys = <&pm8550b_eusb2_repeater>;
+
+ vdd-supply = <&vreg_l1e_0p88>;
+ vdda12-supply = <&vreg_l3e_1p2>;
+};
+
+&usb_dp_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l3f_0p88>;
+};
+
+&xo_board {
+ clock-frequency = <76800000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs8550.dtsi b/arch/arm64/boot/dts/qcom/qcs8550.dtsi
new file mode 100644
index 000000000000..07b314834d88
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs8550.dtsi
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "sm8550.dtsi"
+
+/delete-node/ &reserved_memory;
+
+/ {
+ reserved_memory: reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+
+ /* These are 3 types of reserved memory regions here:
+ * 1. Firmware related regions which aren't shared with kernel.
+ * The device tree source in kernel doesn't need to have node to
+ * indicate the firmware related reserved information. Bootloader
+ * conveys the information by updating devicetree at runtime.
+ * This will be described as: UEFI saves the physical address of
+ * the UEFI System Table to dts file's chosen node. Kernel read this
+ * table and add reserved memory regions to efi config table. Current
+ * reserved memory region may have reserved region which was not yet
+ * used, release note of the firmware have such kind of information.
+ * 2. Firmware related memory regions which are shared with Kernel
+ * The device tree source in the kernel needs to include nodes
+ * that indicate fimware-related shared information. A label name
+ * is suggested because this type of shared information needs to
+ * be referenced by specific drivers for handling purposes.
+ * Unlike previous platforms, QCS8550 boots using EFI and describes
+ * most reserved regions in the ESRT memory map. As a result, reserved
+ * memory regions which aren't relevant to the kernel(like the hypervisor
+ ( region) don't need to be described in DT.
+ * 3. Remoteproc regions.
+ * Remoteproc regions will be reserved and then assigned to
+ * subsystem firmware later.
+ * Here is a reserved memory map for this platform:
+ * 0x80000000 +-------------------+
+ * | |
+ * | Firmware Related |
+ * | |
+ * 0x8a800000 +-------------------+
+ * | |
+ * | Remoteproc Region |
+ * | |
+ * 0xa7000000 +-------------------+
+ * | |
+ * | Kernel Available |
+ * | |
+ * 0xd4d00000 +-------------------+
+ * | |
+ * | Firmware Related |
+ * | |
+ * 0x100000000 +-------------------+
+ */
+
+ aop_image_mem: aop-image-region@81c00000 {
+ reg = <0x0 0x81c00000 0x0 0x60000>;
+ no-map;
+ };
+
+ aop_cmd_db_mem: aop-cmd-db-region@81c60000 {
+ compatible = "qcom,cmd-db";
+ reg = <0x0 0x81c60000 0x0 0x20000>;
+ no-map;
+ };
+
+ aop_config_mem: aop-config-region@81c80000 {
+ no-map;
+ reg = <0x0 0x81c80000 0x0 0x20000>;
+ };
+
+ smem_mem: smem-region@81d00000 {
+ compatible = "qcom,smem";
+ reg = <0x0 0x81d00000 0x0 0x200000>;
+ hwlocks = <&tcsr_mutex 3>;
+ no-map;
+ };
+
+ adsp_mhi_mem: adsp-mhi-region@81f00000 {
+ reg = <0x0 0x81f00000 0x0 0x20000>;
+ no-map;
+ };
+
+ mpss_mem: mpss-region@8a800000 {
+ reg = <0x0 0x8a800000 0x0 0x10800000>;
+ no-map;
+ };
+
+ q6_mpss_dtb_mem: q6-mpss-dtb-region@9b000000 {
+ reg = <0x0 0x9b000000 0x0 0x80000>;
+ no-map;
+ };
+
+ ipa_fw_mem: ipa-fw-region@9b080000 {
+ reg = <0x0 0x9b080000 0x0 0x10000>;
+ no-map;
+ };
+
+ ipa_gsi_mem: ipa-gsi-region@9b090000 {
+ reg = <0x0 0x9b090000 0x0 0xa000>;
+ no-map;
+ };
+
+ gpu_micro_code_mem: gpu-micro-code-region@9b09a000 {
+ reg = <0x0 0x9b09a000 0x0 0x2000>;
+ no-map;
+ };
+
+ spss_region_mem: spss-region@9b100000 {
+ reg = <0x0 0x9b100000 0x0 0x180000>;
+ no-map;
+ };
+
+ spu_secure_shared_memory_mem: spu-secure-shared-memory-region@9b280000 {
+ reg = <0x0 0x9b280000 0x0 0x80000>;
+ no-map;
+ };
+
+ camera_mem: camera-region@9b300000 {
+ reg = <0x0 0x9b300000 0x0 0x800000>;
+ no-map;
+ };
+
+ video_mem: video-region@9bb00000 {
+ reg = <0x0 0x9bb00000 0x0 0x700000>;
+ no-map;
+ };
+
+ cvp_mem: cvp-region@9c200000 {
+ reg = <0x0 0x9c200000 0x0 0x700000>;
+ no-map;
+ };
+
+ cdsp_mem: cdsp-region@9c900000 {
+ reg = <0x0 0x9c900000 0x0 0x2000000>;
+ no-map;
+ };
+
+ q6_cdsp_dtb_mem: q6-cdsp-dtb-region@9e900000 {
+ reg = <0x0 0x9e900000 0x0 0x80000>;
+ no-map;
+ };
+
+ q6_adsp_dtb_mem: q6-adsp-dtb-region@9e980000 {
+ reg = <0x0 0x9e980000 0x0 0x80000>;
+ no-map;
+ };
+
+ adspslpi_mem: adspslpi-region@9ea00000 {
+ reg = <0x0 0x9ea00000 0x0 0x4080000>;
+ no-map;
+ };
+
+ mpss_dsm_mem: mpss_dsm_region@d4d00000 {
+ reg = <0x0 0xd4d00000 0x0 0x3300000>;
+ no-map;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/qdu1000-idp.dts b/arch/arm64/boot/dts/qcom/qdu1000-idp.dts
index 5a25cdec969e..e65305f8136c 100644
--- a/arch/arm64/boot/dts/qcom/qdu1000-idp.dts
+++ b/arch/arm64/boot/dts/qcom/qdu1000-idp.dts
@@ -500,3 +500,26 @@
&uart7 {
status = "okay";
};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+ vdda-pll-supply = <&vreg_l8a_0p91>;
+ vdda18-supply = <&vreg_l14a_1p8>;
+ vdda33-supply = <&vreg_l2a_2p3>;
+
+ status = "okay";
+};
+
+&usb_1_qmpphy {
+ vdda-phy-supply = <&vreg_l8a_0p91>;
+ vdda-pll-supply = <&vreg_l3a_1p2>;
+
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/qdu1000.dtsi b/arch/arm64/boot/dts/qcom/qdu1000.dtsi
index f2a5e2e40461..642ca8f0236b 100644
--- a/arch/arm64/boot/dts/qcom/qdu1000.dtsi
+++ b/arch/arm64/boot/dts/qcom/qdu1000.dtsi
@@ -6,6 +6,8 @@
#include <dt-bindings/clock/qcom,qdu1000-gcc.h>
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interconnect/qcom,icc.h>
#include <dt-bindings/interconnect/qcom,qdu1000-rpmh.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/qcom-rpmpd.h>
@@ -913,6 +915,126 @@
};
};
+ usb_1_hsphy: phy@88e3000 {
+ compatible = "qcom,qdu1000-usb-hs-phy",
+ "qcom,usb-snps-hs-7nm-phy";
+ reg = <0x0 0x088e3000 0x0 0x120>;
+ #phy-cells = <0>;
+
+ clocks =<&gcc GCC_USB2_CLKREF_EN>;
+ clock-names = "ref";
+
+ resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+
+ status = "disabled";
+ };
+
+ usb_1_qmpphy: phy@88e5000 {
+ compatible = "qcom,qdu1000-qmp-usb3-uni-phy";
+ reg = <0x0 0x088e5000 0x0 0x2000>;
+
+ clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
+ <&gcc GCC_USB2_CLKREF_EN>,
+ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+ <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+ clock-names = "aux",
+ "ref",
+ "com_aux",
+ "pipe";
+
+ resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
+ <&gcc GCC_USB3PHY_PHY_PRIM_BCR>;
+ reset-names = "phy",
+ "phy_phy";
+
+ #clock-cells = <0>;
+ clock-output-names = "usb3_uni_phy_pipe_clk_src";
+
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+
+ usb_1: usb@a6f8800 {
+ compatible = "qcom,qdu1000-dwc3", "qcom,dwc3";
+ reg = <0 0x0a6f8800 0 0x400>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>,
+ <&gcc GCC_USB30_PRIM_SLEEP_CLK>,
+ <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>;
+ clock-names = "cfg_noc",
+ "core",
+ "sleep",
+ "mock_utmi";
+
+ assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>;
+ assigned-clock-rates = <19200000>, <200000000>;
+
+ interrupts-extended = <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 8 IRQ_TYPE_EDGE_BOTH>,
+ <&pdc 9 IRQ_TYPE_EDGE_BOTH>,
+ <&pdc 6 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "pwr_event",
+ "hs_phy_irq",
+ "dp_hs_phy_irq",
+ "dm_hs_phy_irq",
+ "ss_phy_irq";
+
+ power-domains = <&gcc USB30_PRIM_GDSC>;
+ required-opps = <&rpmhpd_opp_nom>;
+
+ resets = <&gcc GCC_USB30_PRIM_BCR>;
+
+ interconnects = <&system_noc MASTER_USB3 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &system_noc SLAVE_USB3_0 QCOM_ICC_TAG_ALWAYS>;
+
+ interconnect-names = "usb-ddr",
+ "apps-usb";
+
+ status = "disabled";
+
+ usb_1_dwc3: usb@a600000 {
+ compatible = "snps,dwc3";
+ reg = <0 0x0a600000 0 0xcd00>;
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+
+ iommus = <&apps_smmu 0xc0 0x0>;
+ snps,dis_u2_susphy_quirk;
+ snps,dis_enblslpm_quirk;
+ phys = <&usb_1_hsphy>,
+ <&usb_1_qmpphy>;
+ phy-names = "usb2-phy",
+ "usb3-phy";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_dwc3_hs: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_dwc3_ss: endpoint {
+ };
+ };
+ };
+ };
+ };
+
pdc: interrupt-controller@b220000 {
compatible = "qcom,qdu1000-pdc", "qcom,pdc";
reg = <0x0 0xb220000 0x0 0x30000>, <0x0 0x174000f0 0x0 0x64>;
@@ -1459,11 +1581,40 @@
system-cache-controller@19200000 {
compatible = "qcom,qdu1000-llcc";
- reg = <0 0x19200000 0 0xd80000>,
+ reg = <0 0x19200000 0 0x80000>,
+ <0 0x19300000 0 0x80000>,
+ <0 0x19600000 0 0x80000>,
+ <0 0x19700000 0 0x80000>,
+ <0 0x19a00000 0 0x80000>,
+ <0 0x19b00000 0 0x80000>,
+ <0 0x19e00000 0 0x80000>,
+ <0 0x19f00000 0 0x80000>,
<0 0x1a200000 0 0x80000>;
reg-names = "llcc0_base",
+ "llcc1_base",
+ "llcc2_base",
+ "llcc3_base",
+ "llcc4_base",
+ "llcc5_base",
+ "llcc6_base",
+ "llcc7_base",
"llcc_broadcast_base";
interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
+
+ nvmem-cells = <&multi_chan_ddr>;
+ nvmem-cell-names = "multi-chan-ddr";
+ };
+
+ sec_qfprom: efuse@221c8000 {
+ compatible = "qcom,qdu1000-sec-qfprom", "qcom,sec-qfprom";
+ reg = <0 0x221c8000 0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ multi_chan_ddr: multi-chan-ddr@12b {
+ reg = <0x12b 0x1>;
+ bits = <0 2>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
index bb5191422660..e19790464a11 100644
--- a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
+++ b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
@@ -59,6 +59,17 @@
};
};
+ i2c2_gpio: i2c {
+ compatible = "i2c-gpio";
+
+ sda-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>;
+ scl-gpios = <&tlmm 7 GPIO_ACTIVE_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+ };
+
leds {
compatible = "gpio-leds";
@@ -199,7 +210,15 @@
status = "okay";
};
-&i2c2 {
+&gpu {
+ status = "okay";
+
+ zap-shader {
+ firmware-name = "qcom/qcm2290/a702_zap.mbn";
+ };
+};
+
+&i2c2_gpio {
clock-frequency = <400000>;
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts b/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
index 2c39bb1b97db..1888d99d398b 100644
--- a/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
+++ b/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
@@ -60,6 +60,17 @@
};
};
+ i2c2_gpio: i2c {
+ compatible = "i2c-gpio";
+
+ sda-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>;
+ scl-gpios = <&tlmm 7 GPIO_ACTIVE_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+ };
+
leds {
compatible = "gpio-leds";
@@ -190,7 +201,7 @@
};
};
-&i2c2 {
+&i2c2_gpio {
clock-frequency = <400000>;
status = "okay";
@@ -294,7 +305,7 @@
&pmi632_vbus {
regulator-min-microamp = <500000>;
- regulator-max-microamp = <3000000>;
+ regulator-max-microamp = <1000000>;
status = "okay";
};
@@ -403,6 +414,8 @@
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-allow-set-load;
+ regulator-always-on;
+ regulator-boot-on;
};
vreg_l10a_1p8: l10 {
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
index cd0db4f31d4a..ccff6cd73fdf 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
@@ -108,10 +108,69 @@
regulator-always-on;
};
+ qca6390-pmu {
+ compatible = "qcom,qca6390-pmu";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_en_state>, <&wlan_en_state>;
+
+ vddaon-supply = <&vreg_s6a_0p95>;
+ vddpmu-supply = <&vreg_s2f_0p95>;
+ vddrfa0p95-supply = <&vreg_s2f_0p95>;
+ vddrfa1p3-supply = <&vreg_s8c_1p3>;
+ vddrfa1p9-supply = <&vreg_s5a_1p9>;
+ vddpcie1p3-supply = <&vreg_s8c_1p3>;
+ vddpcie1p9-supply = <&vreg_s5a_1p9>;
+ vddio-supply = <&vreg_s4a_1p8>;
+
+ wlan-enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>;
+ bt-enable-gpios = <&tlmm 21 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";
+ };
+ };
+ };
+
thermal-zones {
conn-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150b_adc_tm 0>;
trips {
@@ -124,8 +183,6 @@
};
pm8150l-pcb-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150l_adc_tm 1>;
trips {
@@ -138,8 +195,6 @@
};
skin-msm-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150l_adc_tm 0>;
trips {
@@ -152,8 +207,6 @@
};
wifi-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150_adc_tm 1>;
trips {
@@ -166,8 +219,6 @@
};
xo-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150_adc_tm 0>;
trips {
@@ -734,6 +785,23 @@
vdda-pll-supply = <&vreg_l9a_1p2>;
};
+&pcieport0 {
+ wifi@0 {
+ compatible = "pci17cb,1101";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ 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>;
+ };
+};
+
&pcie1 {
status = "okay";
};
@@ -1303,6 +1371,14 @@
function = "gpio";
bias-pull-up;
};
+
+ wlan_en_state: wlan-default-state {
+ pins = "gpio20";
+ function = "gpio";
+ drive-strength = <16>;
+ output-low;
+ bias-pull-up;
+ };
};
&uart6 {
@@ -1311,17 +1387,12 @@
bluetooth {
compatible = "qcom,qca6390-bt";
- pinctrl-names = "default";
- pinctrl-0 = <&bt_en_state>;
-
- enable-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>;
-
- vddio-supply = <&vreg_s4a_1p8>;
- vddpmu-supply = <&vreg_s2f_0p95>;
- vddaon-supply = <&vreg_s6a_0p95>;
- vddrfa0p9-supply = <&vreg_s2f_0p95>;
- vddrfa1p3-supply = <&vreg_s8c_1p3>;
- vddrfa1p9-supply = <&vreg_s5a_1p9>;
+ 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>;
};
};
@@ -1356,8 +1427,8 @@
usb-role-switch;
};
-&usb_1_role_switch_out {
- remote-endpoint = <&pm8150b_role_switch_in>;
+&usb_1_dwc3_hs_out {
+ remote-endpoint = <&pm8150b_hs_in>;
};
&usb_1_hsphy {
@@ -1373,7 +1444,6 @@
vdda-phy-supply = <&vreg_l9a_1p2>;
vdda-pll-supply = <&vreg_l18a_0p92>;
- orientation-switch;
};
&usb_1_qmpphy_out {
@@ -1465,8 +1535,8 @@
port@0 {
reg = <0>;
- pm8150b_role_switch_in: endpoint {
- remote-endpoint = <&usb_1_role_switch_out>;
+ pm8150b_hs_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_hs_out>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/qru1000-idp.dts b/arch/arm64/boot/dts/qcom/qru1000-idp.dts
index 2a862c83309e..1c781d9e24cf 100644
--- a/arch/arm64/boot/dts/qcom/qru1000-idp.dts
+++ b/arch/arm64/boot/dts/qcom/qru1000-idp.dts
@@ -467,3 +467,26 @@
&uart7 {
status = "okay";
};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+ vdda-pll-supply = <&vreg_l8a_0p91>;
+ vdda18-supply = <&vreg_l14a_1p8>;
+ vdda33-supply = <&vreg_l2a_2p3>;
+
+ status = "okay";
+};
+
+&usb_1_qmpphy {
+ vdda-phy-supply = <&vreg_l8a_0p91>;
+ vdda-pll-supply = <&vreg_l3a_1p2>;
+
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8155p.dtsi b/arch/arm64/boot/dts/qcom/sa8155p.dtsi
index ffb7ab695213..9e70effc72e1 100644
--- a/arch/arm64/boot/dts/qcom/sa8155p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8155p.dtsi
@@ -38,3 +38,7 @@
*/
compatible = "qcom,sa8155p-rpmhpd";
};
+
+&videocc {
+ power-domains = <&rpmhpd SA8155P_CX>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi b/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi
index eaa43f022a65..1369c3d43f86 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi
@@ -10,7 +10,7 @@
thermal-zones {
pmm8654au_0_thermal: pm8775-0-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pmm8654au_0_temp_alarm>;
trips {
@@ -30,7 +30,7 @@
pmm8654au_1_thermal: pm8775-1-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pmm8654au_1_temp_alarm>;
trips {
@@ -50,7 +50,7 @@
pmm8654au_2_thermal: pm8775-2-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pmm8654au_2_temp_alarm>;
trips {
@@ -70,7 +70,7 @@
pmm8654au_3_thermal: pm8775-3-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pmm8654au_3_temp_alarm>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride-r3.dts b/arch/arm64/boot/dts/qcom/sa8775p-ride-r3.dts
new file mode 100644
index 000000000000..ae065ae92478
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa8775p-ride-r3.dts
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+/dts-v1/;
+
+#include "sa8775p-ride.dtsi"
+
+/ {
+ model = "Qualcomm SA8775P Ride Rev3";
+ compatible = "qcom,sa8775p-ride-r3", "qcom,sa8775p";
+};
+
+&ethernet0 {
+ phy-mode = "2500base-x";
+};
+
+&ethernet1 {
+ phy-mode = "2500base-x";
+};
+
+&mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sgmii_phy0: phy@8 {
+ compatible = "ethernet-phy-id31c3.1c33";
+ reg = <0x8>;
+ device_type = "ethernet-phy";
+ interrupts-extended = <&tlmm 7 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&pmm8654au_2_gpios 8 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <11000>;
+ reset-deassert-us = <70000>;
+ };
+
+ sgmii_phy1: phy@0 {
+ compatible = "ethernet-phy-id31c3.1c33";
+ reg = <0x0>;
+ device_type = "ethernet-phy";
+ interrupts-extended = <&tlmm 26 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&pmm8654au_2_gpios 9 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <11000>;
+ reset-deassert-us = <70000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dts b/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
index 26ad05bd3b3f..2e87fd760dbd 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
+++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
@@ -5,835 +5,43 @@
/dts-v1/;
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
-
-#include "sa8775p.dtsi"
-#include "sa8775p-pmics.dtsi"
+#include "sa8775p-ride.dtsi"
/ {
model = "Qualcomm SA8775P Ride";
compatible = "qcom,sa8775p-ride", "qcom,sa8775p";
-
- aliases {
- ethernet0 = &ethernet0;
- ethernet1 = &ethernet1;
- i2c11 = &i2c11;
- i2c18 = &i2c18;
- serial0 = &uart10;
- serial1 = &uart12;
- serial2 = &uart17;
- spi16 = &spi16;
- ufshc1 = &ufs_mem_hc;
- };
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-};
-
-&apps_rsc {
- regulators-0 {
- compatible = "qcom,pmm8654au-rpmh-regulators";
- qcom,pmic-id = "a";
-
- vreg_s4a: smps4 {
- regulator-name = "vreg_s4a";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1816000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_s5a: smps5 {
- regulator-name = "vreg_s5a";
- regulator-min-microvolt = <1850000>;
- regulator-max-microvolt = <1996000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_s9a: smps9 {
- regulator-name = "vreg_s9a";
- regulator-min-microvolt = <535000>;
- regulator-max-microvolt = <1120000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l4a: ldo4 {
- regulator-name = "vreg_l4a";
- regulator-min-microvolt = <788000>;
- 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>;
- };
-
- vreg_l5a: ldo5 {
- regulator-name = "vreg_l5a";
- regulator-min-microvolt = <870000>;
- regulator-max-microvolt = <950000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l6a: ldo6 {
- regulator-name = "vreg_l6a";
- regulator-min-microvolt = <870000>;
- regulator-max-microvolt = <970000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l7a: ldo7 {
- regulator-name = "vreg_l7a";
- regulator-min-microvolt = <720000>;
- regulator-max-microvolt = <950000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l8a: ldo8 {
- regulator-name = "vreg_l8a";
- regulator-min-microvolt = <2504000>;
- regulator-max-microvolt = <3300000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l9a: ldo9 {
- regulator-name = "vreg_l9a";
- regulator-min-microvolt = <2970000>;
- 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>;
- };
- };
-
- regulators-1 {
- compatible = "qcom,pmm8654au-rpmh-regulators";
- qcom,pmic-id = "c";
-
- vreg_l1c: ldo1 {
- regulator-name = "vreg_l1c";
- 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_l2c: ldo2 {
- regulator-name = "vreg_l2c";
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1100000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l3c: ldo3 {
- regulator-name = "vreg_l3c";
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1300000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l4c: ldo4 {
- regulator-name = "vreg_l4c";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- /*
- * FIXME: This should have regulator-allow-set-load but
- * we're getting an over-current fault from the PMIC
- * when switching to LPM.
- */
- };
-
- vreg_l5c: ldo5 {
- regulator-name = "vreg_l5c";
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1300000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l6c: ldo6 {
- regulator-name = "vreg_l6c";
- regulator-min-microvolt = <1620000>;
- regulator-max-microvolt = <1980000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l7c: ldo7 {
- regulator-name = "vreg_l7c";
- regulator-min-microvolt = <1620000>;
- regulator-max-microvolt = <2000000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l8c: ldo8 {
- regulator-name = "vreg_l8c";
- regulator-min-microvolt = <2400000>;
- regulator-max-microvolt = <3300000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l9c: ldo9 {
- regulator-name = "vreg_l9c";
- regulator-min-microvolt = <1650000>;
- regulator-max-microvolt = <2700000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
- };
-
- regulators-2 {
- compatible = "qcom,pmm8654au-rpmh-regulators";
- qcom,pmic-id = "e";
-
- vreg_s4e: smps4 {
- regulator-name = "vreg_s4e";
- regulator-min-microvolt = <970000>;
- regulator-max-microvolt = <1520000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_s7e: smps7 {
- regulator-name = "vreg_s7e";
- regulator-min-microvolt = <1010000>;
- regulator-max-microvolt = <1170000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_s9e: smps9 {
- regulator-name = "vreg_s9e";
- regulator-min-microvolt = <300000>;
- regulator-max-microvolt = <570000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l6e: ldo6 {
- regulator-name = "vreg_l6e";
- regulator-min-microvolt = <1280000>;
- regulator-max-microvolt = <1450000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
-
- vreg_l8e: ldo8 {
- regulator-name = "vreg_l8e";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1950000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allow-set-load;
- regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
- };
- };
};
&ethernet0 {
phy-mode = "sgmii";
- phy-handle = <&sgmii_phy0>;
-
- pinctrl-0 = <&ethernet0_default>;
- pinctrl-names = "default";
-
- snps,mtl-rx-config = <&mtl_rx_setup>;
- snps,mtl-tx-config = <&mtl_tx_setup>;
- snps,ps-speed = <1000>;
-
- status = "okay";
-
- mdio {
- compatible = "snps,dwmac-mdio";
- #address-cells = <1>;
- #size-cells = <0>;
-
- sgmii_phy0: phy@8 {
- compatible = "ethernet-phy-id0141.0dd4";
- reg = <0x8>;
- device_type = "ethernet-phy";
- interrupts-extended = <&tlmm 7 IRQ_TYPE_EDGE_FALLING>;
- reset-gpios = <&pmm8654au_2_gpios 8 GPIO_ACTIVE_LOW>;
- reset-assert-us = <11000>;
- reset-deassert-us = <70000>;
- };
-
- sgmii_phy1: phy@a {
- compatible = "ethernet-phy-id0141.0dd4";
- reg = <0xa>;
- device_type = "ethernet-phy";
- interrupts-extended = <&tlmm 26 IRQ_TYPE_EDGE_FALLING>;
- reset-gpios = <&pmm8654au_2_gpios 9 GPIO_ACTIVE_LOW>;
- reset-assert-us = <11000>;
- reset-deassert-us = <70000>;
- };
- };
-
- 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>;
- snps,route-up;
- snps,priority = <0x1>;
- };
-
- queue1 {
- snps,dcb-algorithm;
- snps,map-to-dma-channel = <0x1>;
- snps,route-ptp;
- };
-
- queue2 {
- snps,avb-algorithm;
- snps,map-to-dma-channel = <0x2>;
- snps,route-avcp;
- };
-
- queue3 {
- snps,avb-algorithm;
- snps,map-to-dma-channel = <0x3>;
- snps,priority = <0xc>;
- };
- };
-
- mtl_tx_setup: tx-queues-config {
- snps,tx-queues-to-use = <4>;
- snps,tx-sched-sp;
-
- queue0 {
- snps,dcb-algorithm;
- };
-
- queue1 {
- snps,dcb-algorithm;
- };
-
- queue2 {
- snps,avb-algorithm;
- snps,send_slope = <0x1000>;
- snps,idle_slope = <0x1000>;
- snps,high_credit = <0x3e800>;
- snps,low_credit = <0xffc18000>;
- };
-
- queue3 {
- snps,avb-algorithm;
- snps,send_slope = <0x1000>;
- snps,idle_slope = <0x1000>;
- snps,high_credit = <0x3e800>;
- snps,low_credit = <0xffc18000>;
- };
- };
};
&ethernet1 {
phy-mode = "sgmii";
- phy-handle = <&sgmii_phy1>;
-
- snps,mtl-rx-config = <&mtl_rx_setup1>;
- snps,mtl-tx-config = <&mtl_tx_setup1>;
- snps,ps-speed = <1000>;
-
- status = "okay";
-
- mtl_rx_setup1: rx-queues-config {
- snps,rx-queues-to-use = <4>;
- snps,rx-sched-sp;
-
- queue0 {
- snps,dcb-algorithm;
- snps,map-to-dma-channel = <0x0>;
- snps,route-up;
- snps,priority = <0x1>;
- };
-
- queue1 {
- snps,dcb-algorithm;
- snps,map-to-dma-channel = <0x1>;
- snps,route-ptp;
- };
-
- queue2 {
- snps,avb-algorithm;
- snps,map-to-dma-channel = <0x2>;
- snps,route-avcp;
- };
-
- queue3 {
- snps,avb-algorithm;
- snps,map-to-dma-channel = <0x3>;
- snps,priority = <0xc>;
- };
- };
-
- mtl_tx_setup1: tx-queues-config {
- snps,tx-queues-to-use = <4>;
- snps,tx-sched-sp;
-
- queue0 {
- snps,dcb-algorithm;
- };
-
- queue1 {
- snps,dcb-algorithm;
- };
-
- queue2 {
- snps,avb-algorithm;
- snps,send_slope = <0x1000>;
- snps,idle_slope = <0x1000>;
- snps,high_credit = <0x3e800>;
- snps,low_credit = <0xffc18000>;
- };
-
- queue3 {
- snps,avb-algorithm;
- snps,send_slope = <0x1000>;
- snps,idle_slope = <0x1000>;
- snps,high_credit = <0x3e800>;
- snps,low_credit = <0xffc18000>;
- };
- };
-};
-
-&i2c11 {
- clock-frequency = <400000>;
- pinctrl-0 = <&qup_i2c11_default>;
- pinctrl-names = "default";
- status = "okay";
-};
-
-&i2c18 {
- clock-frequency = <400000>;
- pinctrl-0 = <&qup_i2c18_default>;
- pinctrl-names = "default";
- status = "okay";
-};
-
-&pmm8654au_0_gpios {
- gpio-line-names = "DS_EN",
- "POFF_COMPLETE",
- "UFS0_VER_ID",
- "FAST_POFF",
- "DBU1_PON_DONE",
- "AOSS_SLEEP",
- "CAM_DES0_EN",
- "CAM_DES1_EN",
- "CAM_DES2_EN",
- "CAM_DES3_EN",
- "UEFI",
- "ANALOG_PON_OPT";
-};
-
-&pmm8654au_0_pon_resin {
- linux,code = <KEY_VOLUMEDOWN>;
- status = "okay";
-};
-
-&pmm8654au_1_gpios {
- gpio-line-names = "PMIC_C_ID0",
- "PMIC_C_ID1",
- "UFS1_VER_ID",
- "IPA_PWR",
- "",
- "WLAN_DBU4_EN",
- "WLAN_EN",
- "BT_EN",
- "USB2_PWR_EN",
- "USB2_FAULT";
-
- usb2_en_state: usb2-en-state {
- pins = "gpio9";
- function = "normal";
- output-high;
- power-source = <0>;
- };
-};
-
-&pmm8654au_2_gpios {
- gpio-line-names = "PMIC_E_ID0",
- "PMIC_E_ID1",
- "USB0_PWR_EN",
- "USB0_FAULT",
- "SENSOR_IRQ_1",
- "SENSOR_IRQ_2",
- "SENSOR_RST",
- "SGMIIO0_RST",
- "SGMIIO1_RST",
- "USB1_PWR_ENABLE",
- "USB1_FAULT",
- "VMON_SPX8";
-
- usb0_en_state: usb0-en-state {
- pins = "gpio3";
- function = "normal";
- output-high;
- power-source = <0>;
- };
-
- usb1_en_state: usb1-en-state {
- pins = "gpio10";
- function = "normal";
- output-high;
- power-source = <0>;
- };
-};
-
-&pmm8654au_3_gpios {
- gpio-line-names = "PMIC_G_ID0",
- "PMIC_G_ID1",
- "GNSS_RST",
- "GNSS_EN",
- "GNSS_BOOT_MODE";
-};
-
-&qupv3_id_1 {
- status = "okay";
-};
-
-&qupv3_id_2 {
- status = "okay";
-};
-
-&serdes0 {
- phy-supply = <&vreg_l5a>;
- status = "okay";
-};
-
-&serdes1 {
- phy-supply = <&vreg_l5a>;
- status = "okay";
-};
-
-&sleep_clk {
- clock-frequency = <32764>;
-};
-
-&spi16 {
- pinctrl-0 = <&qup_spi16_default>;
- pinctrl-names = "default";
- status = "okay";
};
-&tlmm {
- ethernet0_default: ethernet0-default-state {
- ethernet0_mdc: ethernet0-mdc-pins {
- pins = "gpio8";
- function = "emac0_mdc";
- drive-strength = <16>;
- bias-pull-up;
- };
-
- ethernet0_mdio: ethernet0-mdio-pins {
- pins = "gpio9";
- function = "emac0_mdio";
- drive-strength = <16>;
- bias-pull-up;
- };
- };
-
- qup_uart10_default: qup-uart10-state {
- pins = "gpio46", "gpio47";
- function = "qup1_se3";
- };
-
- qup_spi16_default: qup-spi16-state {
- pins = "gpio86", "gpio87", "gpio88", "gpio89";
- function = "qup2_se2";
- drive-strength = <6>;
- bias-disable;
- };
-
- qup_i2c11_default: qup-i2c11-state {
- pins = "gpio48", "gpio49";
- function = "qup1_se4";
- drive-strength = <2>;
- bias-pull-up;
- };
-
- qup_i2c18_default: qup-i2c18-state {
- pins = "gpio95", "gpio96";
- function = "qup2_se4";
- drive-strength = <2>;
- bias-pull-up;
- };
-
- qup_uart12_default: qup-uart12-state {
- qup_uart12_cts: qup-uart12-cts-pins {
- pins = "gpio52";
- function = "qup1_se5";
- bias-disable;
- };
-
- qup_uart12_rts: qup-uart12-rts-pins {
- pins = "gpio53";
- function = "qup1_se5";
- bias-pull-down;
- };
-
- qup_uart12_tx: qup-uart12-tx-pins {
- pins = "gpio54";
- function = "qup1_se5";
- bias-pull-up;
- };
-
- qup_uart12_rx: qup-uart12-rx-pins {
- pins = "gpio55";
- function = "qup1_se5";
- bias-pull-down;
- };
- };
-
- qup_uart17_default: qup-uart17-state {
- qup_uart17_cts: qup-uart17-cts-pins {
- pins = "gpio91";
- function = "qup2_se3";
- bias-disable;
- };
-
- qup_uart17_rts: qup0-uart17-rts-pins {
- pins = "gpio92";
- function = "qup2_se3";
- bias-pull-down;
- };
-
- qup_uart17_tx: qup0-uart17-tx-pins {
- pins = "gpio93";
- function = "qup2_se3";
- bias-pull-up;
- };
-
- qup_uart17_rx: qup0-uart17-rx-pins {
- pins = "gpio94";
- function = "qup2_se3";
- bias-pull-down;
- };
- };
+&mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
- pcie0_default_state: pcie0-default-state {
- perst-pins {
- pins = "gpio2";
- function = "gpio";
- drive-strength = <2>;
- bias-pull-down;
- };
-
- clkreq-pins {
- pins = "gpio1";
- function = "pcie0_clkreq";
- drive-strength = <2>;
- bias-pull-up;
- };
-
- wake-pins {
- pins = "gpio0";
- function = "gpio";
- drive-strength = <2>;
- bias-pull-up;
- };
+ sgmii_phy0: phy@8 {
+ compatible = "ethernet-phy-id0141.0dd4";
+ reg = <0x8>;
+ device_type = "ethernet-phy";
+ interrupts-extended = <&tlmm 7 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&pmm8654au_2_gpios 8 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <11000>;
+ reset-deassert-us = <70000>;
};
- pcie1_default_state: pcie1-default-state {
- perst-pins {
- pins = "gpio4";
- function = "gpio";
- drive-strength = <2>;
- bias-pull-down;
- };
-
- clkreq-pins {
- pins = "gpio3";
- function = "pcie1_clkreq";
- drive-strength = <2>;
- bias-pull-up;
- };
-
- wake-pins {
- pins = "gpio5";
- function = "gpio";
- drive-strength = <2>;
- bias-pull-up;
- };
+ sgmii_phy1: phy@a {
+ compatible = "ethernet-phy-id0141.0dd4";
+ reg = <0xa>;
+ device_type = "ethernet-phy";
+ interrupts-extended = <&tlmm 26 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&pmm8654au_2_gpios 9 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <11000>;
+ reset-deassert-us = <70000>;
};
};
-
-&pcie0 {
- perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>;
- wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&pcie0_default_state>;
-
- status = "okay";
-};
-
-&pcie1 {
- perst-gpios = <&tlmm 4 GPIO_ACTIVE_LOW>;
- wake-gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&pcie1_default_state>;
-
- status = "okay";
-};
-
-&pcie0_phy {
- vdda-phy-supply = <&vreg_l5a>;
- vdda-pll-supply = <&vreg_l1c>;
-
- status = "okay";
-};
-
-&pcie1_phy {
- vdda-phy-supply = <&vreg_l5a>;
- vdda-pll-supply = <&vreg_l1c>;
-
- status = "okay";
-};
-
-&uart10 {
- compatible = "qcom,geni-debug-uart";
- pinctrl-0 = <&qup_uart10_default>;
- pinctrl-names = "default";
- status = "okay";
-};
-
-&uart12 {
- pinctrl-0 = <&qup_uart12_default>;
- pinctrl-names = "default";
- status = "okay";
-};
-
-&uart17 {
- pinctrl-0 = <&qup_uart17_default>;
- pinctrl-names = "default";
- status = "okay";
-};
-
-&ufs_mem_hc {
- reset-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>;
- vcc-supply = <&vreg_l8a>;
- vcc-max-microamp = <1100000>;
- vccq-supply = <&vreg_l4c>;
- vccq-max-microamp = <1200000>;
-
- status = "okay";
-};
-
-&ufs_mem_phy {
- vdda-phy-supply = <&vreg_l4a>;
- vdda-pll-supply = <&vreg_l1c>;
-
- status = "okay";
-};
-
-&usb_0 {
- pinctrl-names = "default";
- pinctrl-0 = <&usb0_en_state>;
-
- status = "okay";
-};
-
-&usb_0_dwc3 {
- dr_mode = "peripheral";
-};
-
-&usb_0_hsphy {
- vdda-pll-supply = <&vreg_l7a>;
- vdda18-supply = <&vreg_l6c>;
- vdda33-supply = <&vreg_l9a>;
-
- status = "okay";
-};
-
-&usb_0_qmpphy {
- vdda-phy-supply = <&vreg_l1c>;
- vdda-pll-supply = <&vreg_l7a>;
-
- status = "okay";
-};
-
-&usb_1 {
- pinctrl-names = "default";
- pinctrl-0 = <&usb1_en_state>;
-
- status = "okay";
-};
-
-&usb_1_dwc3 {
- dr_mode = "host";
-};
-
-&usb_1_hsphy {
- vdda-pll-supply = <&vreg_l7a>;
- vdda18-supply = <&vreg_l6c>;
- vdda33-supply = <&vreg_l9a>;
-
- status = "okay";
-};
-
-&usb_1_qmpphy {
- vdda-phy-supply = <&vreg_l1c>;
- vdda-pll-supply = <&vreg_l7a>;
-
- status = "okay";
-};
-
-&usb_2 {
- pinctrl-names = "default";
- pinctrl-0 = <&usb2_en_state>;
-
- status = "okay";
-};
-
-&usb_2_dwc3 {
- dr_mode = "host";
-};
-
-&usb_2_hsphy {
- vdda-pll-supply = <&vreg_l7a>;
- vdda18-supply = <&vreg_l6c>;
- vdda33-supply = <&vreg_l9a>;
-
- status = "okay";
-};
-
-&xo_board_clk {
- clock-frequency = <38400000>;
-};
diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
new file mode 100644
index 000000000000..2a6170623ea9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
@@ -0,0 +1,814 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+#include "sa8775p.dtsi"
+#include "sa8775p-pmics.dtsi"
+
+/ {
+ aliases {
+ ethernet0 = &ethernet0;
+ ethernet1 = &ethernet1;
+ i2c11 = &i2c11;
+ i2c18 = &i2c18;
+ serial0 = &uart10;
+ serial1 = &uart12;
+ serial2 = &uart17;
+ spi16 = &spi16;
+ ufshc1 = &ufs_mem_hc;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pmm8654au-rpmh-regulators";
+ qcom,pmic-id = "a";
+
+ vreg_s4a: smps4 {
+ regulator-name = "vreg_s4a";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1816000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s5a: smps5 {
+ regulator-name = "vreg_s5a";
+ regulator-min-microvolt = <1850000>;
+ regulator-max-microvolt = <1996000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s9a: smps9 {
+ regulator-name = "vreg_s9a";
+ regulator-min-microvolt = <535000>;
+ regulator-max-microvolt = <1120000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4a: ldo4 {
+ regulator-name = "vreg_l4a";
+ regulator-min-microvolt = <788000>;
+ 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>;
+ };
+
+ vreg_l5a: ldo5 {
+ regulator-name = "vreg_l5a";
+ regulator-min-microvolt = <870000>;
+ regulator-max-microvolt = <950000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6a: ldo6 {
+ regulator-name = "vreg_l6a";
+ regulator-min-microvolt = <870000>;
+ regulator-max-microvolt = <970000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7a: ldo7 {
+ regulator-name = "vreg_l7a";
+ regulator-min-microvolt = <720000>;
+ regulator-max-microvolt = <950000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8a: ldo8 {
+ regulator-name = "vreg_l8a";
+ regulator-min-microvolt = <2504000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9a: ldo9 {
+ regulator-name = "vreg_l9a";
+ regulator-min-microvolt = <2970000>;
+ 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>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pmm8654au-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vreg_l1c: ldo1 {
+ regulator-name = "vreg_l1c";
+ 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_l2c: ldo2 {
+ regulator-name = "vreg_l2c";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3c: ldo3 {
+ regulator-name = "vreg_l3c";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4c: ldo4 {
+ regulator-name = "vreg_l4c";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ /*
+ * FIXME: This should have regulator-allow-set-load but
+ * we're getting an over-current fault from the PMIC
+ * when switching to LPM.
+ */
+ };
+
+ vreg_l5c: ldo5 {
+ regulator-name = "vreg_l5c";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6c: ldo6 {
+ regulator-name = "vreg_l6c";
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7c: ldo7 {
+ regulator-name = "vreg_l7c";
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8c: ldo8 {
+ regulator-name = "vreg_l8c";
+ regulator-min-microvolt = <2400000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9c: ldo9 {
+ regulator-name = "vreg_l9c";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <2700000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-2 {
+ compatible = "qcom,pmm8654au-rpmh-regulators";
+ qcom,pmic-id = "e";
+
+ vreg_s4e: smps4 {
+ regulator-name = "vreg_s4e";
+ regulator-min-microvolt = <970000>;
+ regulator-max-microvolt = <1520000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s7e: smps7 {
+ regulator-name = "vreg_s7e";
+ regulator-min-microvolt = <1010000>;
+ regulator-max-microvolt = <1170000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s9e: smps9 {
+ regulator-name = "vreg_s9e";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <570000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6e: ldo6 {
+ regulator-name = "vreg_l6e";
+ regulator-min-microvolt = <1280000>;
+ regulator-max-microvolt = <1450000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8e: ldo8 {
+ regulator-name = "vreg_l8e";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1950000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&ethernet0 {
+ phy-handle = <&sgmii_phy0>;
+
+ pinctrl-0 = <&ethernet0_default>;
+ pinctrl-names = "default";
+
+ snps,mtl-rx-config = <&mtl_rx_setup>;
+ snps,mtl-tx-config = <&mtl_tx_setup>;
+ snps,ps-speed = <1000>;
+
+ status = "okay";
+
+ mdio: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ 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>;
+ snps,route-up;
+ snps,priority = <0x1>;
+ };
+
+ queue1 {
+ snps,dcb-algorithm;
+ snps,map-to-dma-channel = <0x1>;
+ snps,route-ptp;
+ };
+
+ queue2 {
+ snps,avb-algorithm;
+ snps,map-to-dma-channel = <0x2>;
+ snps,route-avcp;
+ };
+
+ queue3 {
+ snps,avb-algorithm;
+ snps,map-to-dma-channel = <0x3>;
+ snps,priority = <0xc>;
+ };
+ };
+
+ mtl_tx_setup: tx-queues-config {
+ snps,tx-queues-to-use = <4>;
+ snps,tx-sched-sp;
+
+ queue0 {
+ snps,dcb-algorithm;
+ };
+
+ queue1 {
+ snps,dcb-algorithm;
+ };
+
+ queue2 {
+ snps,avb-algorithm;
+ snps,send_slope = <0x1000>;
+ snps,idle_slope = <0x1000>;
+ snps,high_credit = <0x3e800>;
+ snps,low_credit = <0xffc18000>;
+ };
+
+ queue3 {
+ snps,avb-algorithm;
+ snps,send_slope = <0x1000>;
+ snps,idle_slope = <0x1000>;
+ snps,high_credit = <0x3e800>;
+ snps,low_credit = <0xffc18000>;
+ };
+ };
+};
+
+&ethernet1 {
+ phy-handle = <&sgmii_phy1>;
+
+ snps,mtl-rx-config = <&mtl_rx_setup1>;
+ snps,mtl-tx-config = <&mtl_tx_setup1>;
+ snps,ps-speed = <1000>;
+
+ status = "okay";
+
+ mtl_rx_setup1: rx-queues-config {
+ snps,rx-queues-to-use = <4>;
+ snps,rx-sched-sp;
+
+ queue0 {
+ snps,dcb-algorithm;
+ snps,map-to-dma-channel = <0x0>;
+ snps,route-up;
+ snps,priority = <0x1>;
+ };
+
+ queue1 {
+ snps,dcb-algorithm;
+ snps,map-to-dma-channel = <0x1>;
+ snps,route-ptp;
+ };
+
+ queue2 {
+ snps,avb-algorithm;
+ snps,map-to-dma-channel = <0x2>;
+ snps,route-avcp;
+ };
+
+ queue3 {
+ snps,avb-algorithm;
+ snps,map-to-dma-channel = <0x3>;
+ snps,priority = <0xc>;
+ };
+ };
+
+ mtl_tx_setup1: tx-queues-config {
+ snps,tx-queues-to-use = <4>;
+ snps,tx-sched-sp;
+
+ queue0 {
+ snps,dcb-algorithm;
+ };
+
+ queue1 {
+ snps,dcb-algorithm;
+ };
+
+ queue2 {
+ snps,avb-algorithm;
+ snps,send_slope = <0x1000>;
+ snps,idle_slope = <0x1000>;
+ snps,high_credit = <0x3e800>;
+ snps,low_credit = <0xffc18000>;
+ };
+
+ queue3 {
+ snps,avb-algorithm;
+ snps,send_slope = <0x1000>;
+ snps,idle_slope = <0x1000>;
+ snps,high_credit = <0x3e800>;
+ snps,low_credit = <0xffc18000>;
+ };
+ };
+};
+
+&i2c11 {
+ clock-frequency = <400000>;
+ pinctrl-0 = <&qup_i2c11_default>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&i2c18 {
+ clock-frequency = <400000>;
+ pinctrl-0 = <&qup_i2c18_default>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pmm8654au_0_gpios {
+ gpio-line-names = "DS_EN",
+ "POFF_COMPLETE",
+ "UFS0_VER_ID",
+ "FAST_POFF",
+ "DBU1_PON_DONE",
+ "AOSS_SLEEP",
+ "CAM_DES0_EN",
+ "CAM_DES1_EN",
+ "CAM_DES2_EN",
+ "CAM_DES3_EN",
+ "UEFI",
+ "ANALOG_PON_OPT";
+};
+
+&pmm8654au_0_pon_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&pmm8654au_1_gpios {
+ gpio-line-names = "PMIC_C_ID0",
+ "PMIC_C_ID1",
+ "UFS1_VER_ID",
+ "IPA_PWR",
+ "",
+ "WLAN_DBU4_EN",
+ "WLAN_EN",
+ "BT_EN",
+ "USB2_PWR_EN",
+ "USB2_FAULT";
+
+ usb2_en_state: usb2-en-state {
+ pins = "gpio9";
+ function = "normal";
+ output-high;
+ power-source = <0>;
+ };
+};
+
+&pmm8654au_2_gpios {
+ gpio-line-names = "PMIC_E_ID0",
+ "PMIC_E_ID1",
+ "USB0_PWR_EN",
+ "USB0_FAULT",
+ "SENSOR_IRQ_1",
+ "SENSOR_IRQ_2",
+ "SENSOR_RST",
+ "SGMIIO0_RST",
+ "SGMIIO1_RST",
+ "USB1_PWR_ENABLE",
+ "USB1_FAULT",
+ "VMON_SPX8";
+
+ usb0_en_state: usb0-en-state {
+ pins = "gpio3";
+ function = "normal";
+ output-high;
+ power-source = <0>;
+ };
+
+ usb1_en_state: usb1-en-state {
+ pins = "gpio10";
+ function = "normal";
+ output-high;
+ power-source = <0>;
+ };
+};
+
+&pmm8654au_3_gpios {
+ gpio-line-names = "PMIC_G_ID0",
+ "PMIC_G_ID1",
+ "GNSS_RST",
+ "GNSS_EN",
+ "GNSS_BOOT_MODE";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&qupv3_id_2 {
+ status = "okay";
+};
+
+&serdes0 {
+ phy-supply = <&vreg_l5a>;
+ status = "okay";
+};
+
+&serdes1 {
+ phy-supply = <&vreg_l5a>;
+ status = "okay";
+};
+
+&sleep_clk {
+ clock-frequency = <32764>;
+};
+
+&spi16 {
+ pinctrl-0 = <&qup_spi16_default>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&tlmm {
+ ethernet0_default: ethernet0-default-state {
+ ethernet0_mdc: ethernet0-mdc-pins {
+ pins = "gpio8";
+ function = "emac0_mdc";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ ethernet0_mdio: ethernet0-mdio-pins {
+ pins = "gpio9";
+ function = "emac0_mdio";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+ };
+
+ qup_uart10_default: qup-uart10-state {
+ pins = "gpio46", "gpio47";
+ function = "qup1_se3";
+ };
+
+ qup_spi16_default: qup-spi16-state {
+ pins = "gpio86", "gpio87", "gpio88", "gpio89";
+ function = "qup2_se2";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
+ qup_i2c11_default: qup-i2c11-state {
+ pins = "gpio48", "gpio49";
+ function = "qup1_se4";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c18_default: qup-i2c18-state {
+ pins = "gpio95", "gpio96";
+ function = "qup2_se4";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_uart12_default: qup-uart12-state {
+ qup_uart12_cts: qup-uart12-cts-pins {
+ pins = "gpio52";
+ function = "qup1_se5";
+ bias-disable;
+ };
+
+ qup_uart12_rts: qup-uart12-rts-pins {
+ pins = "gpio53";
+ function = "qup1_se5";
+ bias-pull-down;
+ };
+
+ qup_uart12_tx: qup-uart12-tx-pins {
+ pins = "gpio54";
+ function = "qup1_se5";
+ bias-pull-up;
+ };
+
+ qup_uart12_rx: qup-uart12-rx-pins {
+ pins = "gpio55";
+ function = "qup1_se5";
+ bias-pull-down;
+ };
+ };
+
+ qup_uart17_default: qup-uart17-state {
+ qup_uart17_cts: qup-uart17-cts-pins {
+ pins = "gpio91";
+ function = "qup2_se3";
+ bias-disable;
+ };
+
+ qup_uart17_rts: qup0-uart17-rts-pins {
+ pins = "gpio92";
+ function = "qup2_se3";
+ bias-pull-down;
+ };
+
+ qup_uart17_tx: qup0-uart17-tx-pins {
+ pins = "gpio93";
+ function = "qup2_se3";
+ bias-pull-up;
+ };
+
+ qup_uart17_rx: qup0-uart17-rx-pins {
+ pins = "gpio94";
+ function = "qup2_se3";
+ bias-pull-down;
+ };
+ };
+
+ pcie0_default_state: pcie0-default-state {
+ perst-pins {
+ pins = "gpio2";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ clkreq-pins {
+ pins = "gpio1";
+ function = "pcie0_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ wake-pins {
+ pins = "gpio0";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie1_default_state: pcie1-default-state {
+ perst-pins {
+ pins = "gpio4";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ clkreq-pins {
+ pins = "gpio3";
+ function = "pcie1_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ wake-pins {
+ pins = "gpio5";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+};
+
+&pcie0 {
+ perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_default_state>;
+
+ status = "okay";
+};
+
+&pcie1 {
+ perst-gpios = <&tlmm 4 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_default_state>;
+
+ status = "okay";
+};
+
+&pcie0_phy {
+ vdda-phy-supply = <&vreg_l5a>;
+ vdda-pll-supply = <&vreg_l1c>;
+
+ status = "okay";
+};
+
+&pcie1_phy {
+ vdda-phy-supply = <&vreg_l5a>;
+ vdda-pll-supply = <&vreg_l1c>;
+
+ status = "okay";
+};
+
+&uart10 {
+ compatible = "qcom,geni-debug-uart";
+ pinctrl-0 = <&qup_uart10_default>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart12 {
+ pinctrl-0 = <&qup_uart12_default>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart17 {
+ pinctrl-0 = <&qup_uart17_default>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>;
+ vcc-supply = <&vreg_l8a>;
+ vcc-max-microamp = <1100000>;
+ vccq-supply = <&vreg_l4c>;
+ vccq-max-microamp = <1200000>;
+
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vreg_l4a>;
+ vdda-pll-supply = <&vreg_l1c>;
+
+ status = "okay";
+};
+
+&usb_0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb0_en_state>;
+
+ status = "okay";
+};
+
+&usb_0_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&usb_0_hsphy {
+ vdda-pll-supply = <&vreg_l7a>;
+ vdda18-supply = <&vreg_l6c>;
+ vdda33-supply = <&vreg_l9a>;
+
+ status = "okay";
+};
+
+&usb_0_qmpphy {
+ vdda-phy-supply = <&vreg_l1c>;
+ vdda-pll-supply = <&vreg_l7a>;
+
+ status = "okay";
+};
+
+&usb_1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb1_en_state>;
+
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_1_hsphy {
+ vdda-pll-supply = <&vreg_l7a>;
+ vdda18-supply = <&vreg_l6c>;
+ vdda33-supply = <&vreg_l9a>;
+
+ status = "okay";
+};
+
+&usb_1_qmpphy {
+ vdda-phy-supply = <&vreg_l1c>;
+ vdda-pll-supply = <&vreg_l7a>;
+
+ status = "okay";
+};
+
+&usb_2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2_en_state>;
+
+ status = "okay";
+};
+
+&usb_2_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_2_hsphy {
+ vdda-pll-supply = <&vreg_l7a>;
+ vdda18-supply = <&vreg_l6c>;
+ vdda33-supply = <&vreg_l9a>;
+
+ status = "okay";
+};
+
+&xo_board_clk {
+ clock-frequency = <38400000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
index 31de73594839..23f1b2e5e624 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
@@ -205,9 +205,23 @@
};
};
+ dummy-sink {
+ compatible = "arm,coresight-dummy-sink";
+
+ in-ports {
+ port {
+ eud_in: endpoint {
+ remote-endpoint =
+ <&swao_rep_out1>;
+ };
+ };
+ };
+ };
+
firmware {
scm {
compatible = "qcom,scm-sa8775p", "qcom,scm";
+ memory-region = <&tz_ffi_mem>;
};
};
@@ -418,6 +432,12 @@
no-map;
};
+ tz_ffi_mem: tz-ffi@91c00000 {
+ compatible = "shared-dma-pool";
+ reg = <0x0 0x91c00000 0x0 0x1400000>;
+ no-map;
+ };
+
lpass_machine_learning_mem: lpass-machine-learning@93b00000 {
reg = <0x0 0x93b00000 0x0 0xf00000>;
no-map;
@@ -1644,6 +1664,919 @@
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
};
+ stm: stm@4002000 {
+ compatible = "arm,coresight-stm", "arm,primecell";
+ reg = <0x0 0x4002000 0x0 0x1000>,
+ <0x0 0x16280000 0x0 0x180000>;
+ reg-names = "stm-base", "stm-stimulus-base";
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ stm_out: endpoint {
+ remote-endpoint =
+ <&funnel0_in7>;
+ };
+ };
+ };
+ };
+
+ tpdm@4003000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x4003000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,cmb-element-bits = <32>;
+ qcom,cmb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ qdss_tpdm0_out: endpoint {
+ remote-endpoint =
+ <&qdss_tpda_in0>;
+ };
+ };
+ };
+ };
+
+ tpda@4004000 {
+ compatible = "qcom,coresight-tpda", "arm,primecell";
+ reg = <0x0 0x4004000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ qdss_tpda_out: endpoint {
+ remote-endpoint =
+ <&funnel0_in6>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ qdss_tpda_in0: endpoint {
+ remote-endpoint =
+ <&qdss_tpdm0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ qdss_tpda_in1: endpoint {
+ remote-endpoint =
+ <&qdss_tpdm1_out>;
+ };
+ };
+ };
+ };
+
+ tpdm@400f000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x400f000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,cmb-element-bits = <32>;
+ qcom,cmb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ qdss_tpdm1_out: endpoint {
+ remote-endpoint =
+ <&qdss_tpda_in1>;
+ };
+ };
+ };
+ };
+
+ funnel@4041000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x0 0x4041000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ funnel0_out: endpoint {
+ remote-endpoint =
+ <&qdss_funnel_in0>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@6 {
+ reg = <6>;
+ funnel0_in6: endpoint {
+ remote-endpoint =
+ <&qdss_tpda_out>;
+ };
+ };
+
+ port@7 {
+ reg = <7>;
+ funnel0_in7: endpoint {
+ remote-endpoint =
+ <&stm_out>;
+ };
+ };
+ };
+ };
+
+ funnel@4042000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x0 0x4042000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ funnel1_out: endpoint {
+ remote-endpoint =
+ <&qdss_funnel_in1>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@4 {
+ reg = <4>;
+ funnel1_in4: endpoint {
+ remote-endpoint =
+ <&apss_funnel1_out>;
+ };
+ };
+ };
+ };
+
+ funnel@4045000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x0 0x4045000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ qdss_funnel_out: endpoint {
+ remote-endpoint =
+ <&aoss_funnel_in7>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ qdss_funnel_in0: endpoint {
+ remote-endpoint =
+ <&funnel0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ qdss_funnel_in1: endpoint {
+ remote-endpoint =
+ <&funnel1_out>;
+ };
+ };
+ };
+ };
+
+ funnel@4b04000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x0 0x4b04000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ aoss_funnel_out: endpoint {
+ remote-endpoint =
+ <&etf0_in>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@6 {
+ reg = <6>;
+ aoss_funnel_in6: endpoint {
+ remote-endpoint =
+ <&aoss_tpda_out>;
+ };
+ };
+
+ port@7 {
+ reg = <7>;
+ aoss_funnel_in7: endpoint {
+ remote-endpoint =
+ <&qdss_funnel_out>;
+ };
+ };
+ };
+ };
+
+ tmc_etf: tmc@4b05000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x0 0x4b05000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etf0_out: endpoint {
+ remote-endpoint =
+ <&swao_rep_in>;
+ };
+ };
+ };
+
+ in-ports {
+ port {
+ etf0_in: endpoint {
+ remote-endpoint =
+ <&aoss_funnel_out>;
+ };
+ };
+ };
+ };
+
+ replicator@4b06000 {
+ compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
+ reg = <0x0 0x4b06000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ reg = <1>;
+ swao_rep_out1: endpoint {
+ remote-endpoint =
+ <&eud_in>;
+ };
+ };
+ };
+
+ in-ports {
+ port {
+ swao_rep_in: endpoint {
+ remote-endpoint =
+ <&etf0_out>;
+ };
+ };
+ };
+ };
+
+ tpda@4b08000 {
+ compatible = "qcom,coresight-tpda", "arm,primecell";
+ reg = <0x0 0x4b08000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ aoss_tpda_out: endpoint {
+ remote-endpoint =
+ <&aoss_funnel_in6>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ aoss_tpda_in0: endpoint {
+ remote-endpoint =
+ <&aoss_tpdm0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ aoss_tpda_in1: endpoint {
+ remote-endpoint =
+ <&aoss_tpdm1_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ aoss_tpda_in2: endpoint {
+ remote-endpoint =
+ <&aoss_tpdm2_out>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ aoss_tpda_in3: endpoint {
+ remote-endpoint =
+ <&aoss_tpdm3_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+ aoss_tpda_in4: endpoint {
+ remote-endpoint =
+ <&aoss_tpdm4_out>;
+ };
+ };
+ };
+ };
+
+ tpdm@4b09000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x4b09000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,cmb-element-bits = <64>;
+ qcom,cmb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ aoss_tpdm0_out: endpoint {
+ remote-endpoint =
+ <&aoss_tpda_in0>;
+ };
+ };
+ };
+ };
+
+ tpdm@4b0a000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x4b0a000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,cmb-element-bits = <64>;
+ qcom,cmb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ aoss_tpdm1_out: endpoint {
+ remote-endpoint =
+ <&aoss_tpda_in1>;
+ };
+ };
+ };
+ };
+
+ tpdm@4b0b000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x4b0b000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,cmb-element-bits = <64>;
+ qcom,cmb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ aoss_tpdm2_out: endpoint {
+ remote-endpoint =
+ <&aoss_tpda_in2>;
+ };
+ };
+ };
+ };
+
+ tpdm@4b0c000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x4b0c000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,cmb-element-bits = <64>;
+ qcom,cmb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ aoss_tpdm3_out: endpoint {
+ remote-endpoint =
+ <&aoss_tpda_in3>;
+ };
+ };
+ };
+ };
+
+ tpdm@4b0d000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x4b0d000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,dsb-element-bits = <32>;
+ qcom,dsb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ aoss_tpdm4_out: endpoint {
+ remote-endpoint =
+ <&aoss_tpda_in4>;
+ };
+ };
+ };
+ };
+
+ aoss_cti: cti@4b13000 {
+ compatible = "arm,coresight-cti", "arm,primecell";
+ reg = <0x0 0x4b13000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ };
+
+ etm@6040000 {
+ compatible = "arm,primecell";
+ reg = <0x0 0x6040000 0x0 0x1000>;
+ cpu = <&CPU0>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+ qcom,skip-power-up;
+
+ out-ports {
+ port {
+ etm0_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_in0>;
+ };
+ };
+ };
+ };
+
+ etm@6140000 {
+ compatible = "arm,primecell";
+ reg = <0x0 0x6140000 0x0 0x1000>;
+ cpu = <&CPU1>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+ qcom,skip-power-up;
+
+ out-ports {
+ port {
+ etm1_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_in1>;
+ };
+ };
+ };
+ };
+
+ etm@6240000 {
+ compatible = "arm,primecell";
+ reg = <0x0 0x6240000 0x0 0x1000>;
+ cpu = <&CPU2>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+ qcom,skip-power-up;
+
+ out-ports {
+ port {
+ etm2_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_in2>;
+ };
+ };
+ };
+ };
+
+ etm@6340000 {
+ compatible = "arm,primecell";
+ reg = <0x0 0x6340000 0x0 0x1000>;
+ cpu = <&CPU3>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+ qcom,skip-power-up;
+
+ out-ports {
+ port {
+ etm3_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_in3>;
+ };
+ };
+ };
+ };
+
+ etm@6440000 {
+ compatible = "arm,primecell";
+ reg = <0x0 0x6440000 0x0 0x1000>;
+ cpu = <&CPU4>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+ qcom,skip-power-up;
+
+ out-ports {
+ port {
+ etm4_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_in4>;
+ };
+ };
+ };
+ };
+
+ etm@6540000 {
+ compatible = "arm,primecell";
+ reg = <0x0 0x6540000 0x0 0x1000>;
+ cpu = <&CPU5>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+ qcom,skip-power-up;
+
+ out-ports {
+ port {
+ etm5_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_in5>;
+ };
+ };
+ };
+ };
+
+ etm@6640000 {
+ compatible = "arm,primecell";
+ reg = <0x0 0x6640000 0x0 0x1000>;
+ cpu = <&CPU6>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+ qcom,skip-power-up;
+
+ out-ports {
+ port {
+ etm6_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_in6>;
+ };
+ };
+ };
+ };
+
+ etm@6740000 {
+ compatible = "arm,primecell";
+ reg = <0x0 0x6740000 0x0 0x1000>;
+ cpu = <&CPU7>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+ qcom,skip-power-up;
+
+ out-ports {
+ port {
+ etm7_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_in7>;
+ };
+ };
+ };
+ };
+
+ funnel@6800000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x0 0x6800000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ apss_funnel0_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel1_in0>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ apss_funnel0_in0: endpoint {
+ remote-endpoint =
+ <&etm0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ apss_funnel0_in1: endpoint {
+ remote-endpoint =
+ <&etm1_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ apss_funnel0_in2: endpoint {
+ remote-endpoint =
+ <&etm2_out>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ apss_funnel0_in3: endpoint {
+ remote-endpoint =
+ <&etm3_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+ apss_funnel0_in4: endpoint {
+ remote-endpoint =
+ <&etm4_out>;
+ };
+ };
+
+ port@5 {
+ reg = <5>;
+ apss_funnel0_in5: endpoint {
+ remote-endpoint =
+ <&etm5_out>;
+ };
+ };
+
+ port@6 {
+ reg = <6>;
+ apss_funnel0_in6: endpoint {
+ remote-endpoint =
+ <&etm6_out>;
+ };
+ };
+
+ port@7 {
+ reg = <7>;
+ apss_funnel0_in7: endpoint {
+ remote-endpoint =
+ <&etm7_out>;
+ };
+ };
+ };
+ };
+
+ funnel@6810000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x0 0x6810000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ apss_funnel1_out: endpoint {
+ remote-endpoint =
+ <&funnel1_in4>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ apss_funnel1_in0: endpoint {
+ remote-endpoint =
+ <&apss_funnel0_out>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ apss_funnel1_in3: endpoint {
+ remote-endpoint =
+ <&apss_tpda_out>;
+ };
+ };
+ };
+ };
+
+ tpdm@6860000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x6860000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,cmb-element-bits = <64>;
+ qcom,cmb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ apss_tpdm3_out: endpoint {
+ remote-endpoint =
+ <&apss_tpda_in3>;
+ };
+ };
+ };
+ };
+
+ tpdm@6861000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x6861000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,dsb-element-bits = <32>;
+ qcom,dsb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ apss_tpdm4_out: endpoint {
+ remote-endpoint =
+ <&apss_tpda_in4>;
+ };
+ };
+ };
+ };
+
+ tpda@6863000 {
+ compatible = "qcom,coresight-tpda", "arm,primecell";
+ reg = <0x0 0x6863000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ apss_tpda_out: endpoint {
+ remote-endpoint =
+ <&apss_funnel1_in3>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ apss_tpda_in0: endpoint {
+ remote-endpoint =
+ <&apss_tpdm0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ apss_tpda_in1: endpoint {
+ remote-endpoint =
+ <&apss_tpdm1_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ apss_tpda_in2: endpoint {
+ remote-endpoint =
+ <&apss_tpdm2_out>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ apss_tpda_in3: endpoint {
+ remote-endpoint =
+ <&apss_tpdm3_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+ apss_tpda_in4: endpoint {
+ remote-endpoint =
+ <&apss_tpdm4_out>;
+ };
+ };
+ };
+ };
+
+ tpdm@68a0000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x68a0000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,cmb-element-bits = <32>;
+ qcom,cmb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ apss_tpdm0_out: endpoint {
+ remote-endpoint =
+ <&apss_tpda_in0>;
+ };
+ };
+ };
+ };
+
+ tpdm@68b0000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x68b0000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,cmb-element-bits = <32>;
+ qcom,cmb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ apss_tpdm1_out: endpoint {
+ remote-endpoint =
+ <&apss_tpda_in1>;
+ };
+ };
+ };
+ };
+
+ tpdm@68c0000 {
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
+ reg = <0x0 0x68c0000 0x0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ qcom,dsb-element-bits = <32>;
+ qcom,dsb-msrs-num = <32>;
+
+ out-ports {
+ port {
+ apss_tpdm2_out: endpoint {
+ remote-endpoint =
+ <&apss_tpda_in2>;
+ };
+ };
+ };
+ };
+
usb_0_hsphy: phy@88e4000 {
compatible = "qcom,sa8775p-usb-hs-phy",
"qcom,usb-snps-hs-5nm-phy";
@@ -1959,6 +2892,25 @@
status = "disabled";
};
+ llcc: system-cache-controller@9200000 {
+ compatible = "qcom,sa8775p-llcc";
+ reg = <0x0 0x09200000 0x0 0x80000>,
+ <0x0 0x09300000 0x0 0x80000>,
+ <0x0 0x09400000 0x0 0x80000>,
+ <0x0 0x09500000 0x0 0x80000>,
+ <0x0 0x09600000 0x0 0x80000>,
+ <0x0 0x09700000 0x0 0x80000>,
+ <0x0 0x09a00000 0x0 0x80000>;
+ reg-names = "llcc0_base",
+ "llcc1_base",
+ "llcc2_base",
+ "llcc3_base",
+ "llcc4_base",
+ "llcc5_base",
+ "llcc_broadcast_base";
+ interrupts = <GIC_SPI 580 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
pdc: interrupt-controller@b220000 {
compatible = "qcom,sa8775p-pdc", "qcom,pdc";
reg = <0x0 0x0b220000 0x0 0x30000>,
@@ -2099,6 +3051,20 @@
wakeup-parent = <&pdc>;
};
+ sram: sram@146d8000 {
+ compatible = "qcom,sa8775p-imem", "syscon", "simple-mfd";
+ reg = <0x0 0x146d8000 0x0 0x1000>;
+ ranges = <0x0 0x0 0x146d8000 0x1000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pil-reloc@94c {
+ compatible = "qcom,pil-reloc-info";
+ reg = <0x94c 0xc8>;
+ };
+ };
+
apps_smmu: iommu@15000000 {
compatible = "qcom,sa8775p-smmu-500", "qcom,smmu-500", "arm,mmu-500";
reg = <0x0 0x15000000 0x0 0x100000>;
@@ -2504,6 +3470,7 @@
phy-names = "serdes";
iommus = <&apps_smmu 0x140 0xf>;
+ dma-coherent;
snps,tso;
snps,pbl = <32>;
@@ -2538,6 +3505,7 @@
phy-names = "serdes";
iommus = <&apps_smmu 0x120 0xf>;
+ dma-coherent;
snps,tso;
snps,pbl = <32>;
@@ -2550,9 +3518,6 @@
thermal-zones {
aoss-0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 0>;
trips {
@@ -2572,7 +3537,6 @@
cpu-0-0-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 1>;
@@ -2593,7 +3557,6 @@
cpu-0-1-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 2>;
@@ -2614,7 +3577,6 @@
cpu-0-2-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 3>;
@@ -2635,7 +3597,6 @@
cpu-0-3-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 4>;
@@ -2656,7 +3617,6 @@
gpuss-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 5>;
@@ -2677,7 +3637,6 @@
gpuss-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 6>;
@@ -2698,7 +3657,6 @@
gpuss-2-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 7>;
@@ -2718,9 +3676,6 @@
};
audio-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 8>;
trips {
@@ -2739,9 +3694,6 @@
};
camss-0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 9>;
trips {
@@ -2760,9 +3712,6 @@
};
pcie-0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 10>;
trips {
@@ -2781,9 +3730,6 @@
};
cpuss-0-0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 11>;
trips {
@@ -2802,9 +3748,6 @@
};
aoss-1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 0>;
trips {
@@ -2824,7 +3767,6 @@
cpu-0-0-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 1>;
@@ -2845,7 +3787,6 @@
cpu-0-1-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 2>;
@@ -2866,7 +3807,6 @@
cpu-0-2-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 3>;
@@ -2887,7 +3827,6 @@
cpu-0-3-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 4>;
@@ -2908,7 +3847,6 @@
gpuss-3-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 5>;
@@ -2929,7 +3867,6 @@
gpuss-4-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 6>;
@@ -2950,7 +3887,6 @@
gpuss-5-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 7>;
@@ -2970,9 +3906,6 @@
};
video-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 8>;
trips {
@@ -2991,9 +3924,6 @@
};
camss-1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 9>;
trips {
@@ -3012,9 +3942,6 @@
};
pcie-1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 10>;
trips {
@@ -3033,9 +3960,6 @@
};
cpuss-0-1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 11>;
trips {
@@ -3054,9 +3978,6 @@
};
aoss-2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens2 0>;
trips {
@@ -3076,7 +3997,6 @@
cpu-1-0-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 1>;
@@ -3097,7 +4017,6 @@
cpu-1-1-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 2>;
@@ -3118,7 +4037,6 @@
cpu-1-2-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 3>;
@@ -3139,7 +4057,6 @@
cpu-1-3-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 4>;
@@ -3160,7 +4077,6 @@
nsp-0-0-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 5>;
@@ -3181,7 +4097,6 @@
nsp-0-1-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 6>;
@@ -3202,7 +4117,6 @@
nsp-0-2-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 7>;
@@ -3223,7 +4137,6 @@
nsp-1-0-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 8>;
@@ -3244,7 +4157,6 @@
nsp-1-1-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 9>;
@@ -3265,7 +4177,6 @@
nsp-1-2-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 10>;
@@ -3285,9 +4196,6 @@
};
ddrss-0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens2 11>;
trips {
@@ -3306,9 +4214,6 @@
};
cpuss-1-0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens2 12>;
trips {
@@ -3327,9 +4232,6 @@
};
aoss-3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens3 0>;
trips {
@@ -3349,7 +4251,6 @@
cpu-1-0-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens3 1>;
@@ -3370,7 +4271,6 @@
cpu-1-1-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens3 2>;
@@ -3391,7 +4291,6 @@
cpu-1-2-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens3 3>;
@@ -3412,7 +4311,6 @@
cpu-1-3-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens3 4>;
@@ -3433,7 +4331,6 @@
nsp-0-0-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens3 5>;
@@ -3454,7 +4351,6 @@
nsp-0-1-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens3 6>;
@@ -3475,7 +4371,6 @@
nsp-0-2-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens3 7>;
@@ -3496,7 +4391,6 @@
nsp-1-0-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens3 8>;
@@ -3517,7 +4411,6 @@
nsp-1-1-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens3 9>;
@@ -3538,7 +4431,6 @@
nsp-1-2-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
thermal-sensors = <&tsens3 10>;
@@ -3558,9 +4450,6 @@
};
ddrss-1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens3 11>;
trips {
@@ -3579,9 +4468,6 @@
};
cpuss-1-1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens3 12>;
trips {
@@ -3605,7 +4491,7 @@
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 12 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
};
pcie0: pcie@1c00000 {
@@ -3689,6 +4575,53 @@
};
};
+ pcie0_ep: pcie-ep@1c00000 {
+ compatible = "qcom,sa8775p-pcie-ep";
+ reg = <0x0 0x01c00000 0x0 0x3000>,
+ <0x0 0x40000000 0x0 0xf20>,
+ <0x0 0x40000f20 0x0 0xa8>,
+ <0x0 0x40001000 0x0 0x4000>,
+ <0x0 0x40200000 0x0 0x100000>,
+ <0x0 0x01c03000 0x0 0x1000>,
+ <0x0 0x40005000 0x0 0x2000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "addr_space",
+ "mmio", "dma";
+
+ clocks = <&gcc GCC_PCIE_0_AUX_CLK>,
+ <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>;
+
+ clock-names = "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a";
+
+ interrupts = <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 630 IRQ_TYPE_LEVEL_HIGH>;
+
+ interrupt-names = "global", "doorbell", "dma";
+
+ interconnects = <&pcie_anoc MASTER_PCIE_0 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_PCIE_0 0>;
+ interconnect-names = "pcie-mem", "cpu-pcie";
+
+ dma-coherent;
+ iommus = <&pcie_smmu 0x0000 0x7f>;
+ resets = <&gcc GCC_PCIE_0_BCR>;
+ reset-names = "core";
+ power-domains = <&gcc PCIE_0_GDSC>;
+ phys = <&pcie0_phy>;
+ phy-names = "pciephy";
+ max-link-speed = <3>; /* FIXME: Limiting the Gen speed due to stability issues */
+ num-lanes = <2>;
+
+ status = "disabled";
+ };
+
pcie0_phy: phy@1c04000 {
compatible = "qcom,sa8775p-qmp-gen4x2-pcie-phy";
reg = <0x0 0x1c04000 0x0 0x2000>;
@@ -3799,6 +4732,53 @@
};
};
+ pcie1_ep: pcie-ep@1c10000 {
+ compatible = "qcom,sa8775p-pcie-ep";
+ reg = <0x0 0x01c10000 0x0 0x3000>,
+ <0x0 0x60000000 0x0 0xf20>,
+ <0x0 0x60000f20 0x0 0xa8>,
+ <0x0 0x60001000 0x0 0x4000>,
+ <0x0 0x60200000 0x0 0x100000>,
+ <0x0 0x01c13000 0x0 0x1000>,
+ <0x0 0x60005000 0x0 0x2000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "addr_space",
+ "mmio", "dma";
+
+ clocks = <&gcc GCC_PCIE_1_AUX_CLK>,
+ <&gcc GCC_PCIE_1_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_1_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_1_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_1_SLV_Q2A_AXI_CLK>;
+
+ clock-names = "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a";
+
+ interrupts = <GIC_SPI 518 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>;
+
+ interrupt-names = "global", "doorbell", "dma";
+
+ interconnects = <&pcie_anoc MASTER_PCIE_1 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_PCIE_1 0>;
+ interconnect-names = "pcie-mem", "cpu-pcie";
+
+ dma-coherent;
+ iommus = <&pcie_smmu 0x80 0x7f>;
+ resets = <&gcc GCC_PCIE_1_BCR>;
+ reset-names = "core";
+ power-domains = <&gcc PCIE_1_GDSC>;
+ phys = <&pcie1_phy>;
+ phy-names = "pciephy";
+ max-link-speed = <3>; /* FIXME: Limiting the Gen speed due to stability issues */
+ num-lanes = <4>;
+
+ status = "disabled";
+ };
+
pcie1_phy: phy@1c14000 {
compatible = "qcom,sa8775p-qmp-gen4x4-pcie-phy";
reg = <0x0 0x1c14000 0x0 0x4000>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-clamshell.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-clamshell.dtsi
new file mode 100644
index 000000000000..d91533b80e76
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-clamshell.dtsi
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Trogdor dts fragment for clamshells
+ *
+ * Copyright 2024 Google LLC.
+ */
+
+/* This file must be included after sc7180-trogdor.dtsi to modify cros_ec */
+#include <arm/cros-ec-keyboard.dtsi>
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
index 7765c8f64905..3c124bbe2f4c 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
@@ -7,6 +7,7 @@
#include "sc7180-trogdor.dtsi"
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
+#include "sc7180-trogdor-detachable.dtsi"
/* Deleted nodes from sc7180-trogdor.dtsi */
@@ -25,7 +26,6 @@
thermal-zones {
skin_temp_thermal: skin-temp-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&pm6150_adc_tm 1>;
sustainable-power = <965>;
@@ -80,10 +80,6 @@
};
&cros_ec {
- keyboard-controller {
- compatible = "google,cros-ec-keyb-switches";
- };
-
cros_ec_proximity: proximity {
compatible = "google,cros-ec-mkbp-proximity";
label = "proximity-wifi";
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-detachable.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-detachable.dtsi
new file mode 100644
index 000000000000..7c5d8a57ef7f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-detachable.dtsi
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Trogdor dts fragment for detachables
+ *
+ * Copyright 2024 Google LLC.
+ */
+
+/* This file must be included after sc7180-trogdor.dtsi to modify cros_ec */
+&cros_ec {
+ keyboard-controller {
+ compatible = "google,cros-ec-keyb-switches";
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
index 2ba3bbf3b9ad..b2df22faafe8 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
@@ -5,9 +5,8 @@
* Copyright 2021 Google LLC.
*/
-/* This file must be included after sc7180-trogdor.dtsi */
-
#include "sc7180-trogdor-rt5682i-sku.dtsi"
+#include "sc7180-trogdor-detachable.dtsi"
/ {
/* BOARD-SPECIFIC TOP LEVEL NODES */
@@ -45,7 +44,6 @@
thermal-zones {
skin_temp_thermal: skin-temp-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&pm6150_adc_tm 1>;
sustainable-power = <965>;
@@ -135,12 +133,6 @@ ap_ts_pen_1v8: &i2c4 {
status = "okay";
};
-&cros_ec {
- keyboard-controller {
- compatible = "google,cros-ec-keyb-switches";
- };
-};
-
&panel {
compatible = "samsung,atna33xc20";
enable-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dts
index d6db7d83adcf..655bea928e52 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dts
@@ -9,7 +9,7 @@
#include "sc7180-trogdor.dtsi"
#include "sc7180-trogdor-parade-ps8640.dtsi"
-#include <arm/cros-ec-keyboard.dtsi>
+#include "sc7180-trogdor-clamshell.dtsi"
#include "sc7180-trogdor-lte-sku.dtsi"
#include "sc7180-trogdor-rt5682s-sku.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1-kb.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1-kb.dts
index 919bfaea6189..340cb119d0a0 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1-kb.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1-kb.dts
@@ -12,6 +12,6 @@
compatible = "google,lazor-rev1-sku2", "google,lazor-rev2-sku2", "qcom,sc7180";
};
-&keyboard_backlight {
+&pwmleds {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1-lte.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1-lte.dts
index eb20157f6af9..d45e60e3eb9e 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1-lte.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r1-lte.dts
@@ -17,6 +17,6 @@
status = "okay";
};
-&keyboard_backlight {
+&pwmleds {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-kb.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-kb.dts
index 45d34718a1bc..e906ce877b8c 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-kb.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-kb.dts
@@ -18,6 +18,6 @@
compatible = "google,lazor-sku2", "qcom,sc7180";
};
-&keyboard_backlight {
+&pwmleds {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-lte.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-lte.dts
index 79028d0dd1b0..4b9ee15b09f6 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-lte.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r10-lte.dts
@@ -22,6 +22,6 @@
status = "okay";
};
-&keyboard_backlight {
+&pwmleds {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-kb.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-kb.dts
index 3459b81c5628..a960553f3994 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-kb.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-kb.dts
@@ -21,6 +21,6 @@
"qcom,sc7180";
};
-&keyboard_backlight {
+&pwmleds {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-lte.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-lte.dts
index ff8f47da109d..82bd9ed7e21a 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-lte.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r3-lte.dts
@@ -25,6 +25,6 @@
status = "okay";
};
-&keyboard_backlight {
+&pwmleds {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-kb.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-kb.dts
index faf527972977..6278c1715d3f 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-kb.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-kb.dts
@@ -18,6 +18,6 @@
compatible = "google,lazor-rev9-sku2", "qcom,sc7180";
};
-&keyboard_backlight {
+&pwmleds {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-lte.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-lte.dts
index d737fd0637fb..0ec1697ae2c9 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-lte.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-r9-lte.dts
@@ -22,6 +22,6 @@
status = "okay";
};
-&keyboard_backlight {
+&pwmleds {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi
index e9f213d27711..c3fd6760de7a 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi
@@ -5,8 +5,7 @@
* Copyright 2020 Google LLC.
*/
-/* This file must be included after sc7180-trogdor.dtsi */
-#include <arm/cros-ec-keyboard.dtsi>
+#include "sc7180-trogdor-clamshell.dtsi"
&ap_sar_sensor {
semtech,cs0-ground;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel.dtsi
index 8823edbb4d6e..cc2c5610a279 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel.dtsi
@@ -5,8 +5,7 @@
* Copyright 2021 Google LLC.
*/
-/* This file must be included after sc7180-trogdor.dtsi */
-#include <arm/cros-ec-keyboard.dtsi>
+#include "sc7180-trogdor-clamshell.dtsi"
&ap_sar_sensor {
compatible = "semtech,sx9324";
@@ -83,6 +82,8 @@
gpio = <&tlmm 67 GPIO_ACTIVE_HIGH>;
};
+/* PINCTRL - modifications to sc7180-trogdor.dtsi */
+
&en_pp3300_dx_edp {
pins = "gpio67";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi
index 067813f5f437..ac8d4589e3fb 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi
@@ -6,17 +6,13 @@
*/
#include "sc7180-trogdor.dtsi"
-/* Must come after sc7180-trogdor.dtsi to modify cros_ec */
-#include <arm/cros-ec-keyboard.dtsi>
+#include "sc7180-trogdor-clamshell.dtsi"
#include "sc7180-trogdor-rt5682i-sku.dtsi"
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
/ {
thermal-zones {
5v-choke-thermal {
- polling-delay-passive = <0>;
- polling-delay = <250>;
-
thermal-sensors = <&pm6150_adc_tm 1>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi
index 5f06842c683b..00229b1515e6 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi
@@ -9,9 +9,7 @@
#include "sc7180-trogdor.dtsi"
#include "sc7180-trogdor-rt5682i-sku.dtsi"
-
-/* This board only has 1 USB Type-C port. */
-/delete-node/ &usb_c1;
+#include "sc7180-trogdor-detachable.dtsi"
/ {
ppvar_lcd: ppvar-lcd-regulator {
@@ -47,12 +45,6 @@
status = "okay";
};
-&cros_ec {
- keyboard-controller {
- compatible = "google,cros-ec-keyb-switches";
- };
-};
-
&gpio_keys {
status = "okay";
};
@@ -136,6 +128,11 @@ pp3300_disp_on: &pp3300_dx_edp {
gpio = <&tlmm 67 GPIO_ACTIVE_HIGH>;
};
+/* This board only has 1 USB Type-C port. */
+&usb_c1 {
+ status = "disabled";
+};
+
/* PINCTRL - modifications to sc7180-trogdor.dtsi */
/*
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts
index c9667751a990..d393a2712ce6 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts
@@ -8,8 +8,7 @@
/dts-v1/;
#include "sc7180-trogdor.dtsi"
-/* Must come after sc7180-trogdor.dtsi to modify cros_ec */
-#include <arm/cros-ec-keyboard.dtsi>
+#include "sc7180-trogdor-clamshell.dtsi"
#include "sc7180-trogdor-rt5682i-sku.dtsi"
#include "sc7180-trogdor-ti-sn65dsi86.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
index 305ad127246e..af89d80426ab 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
@@ -8,6 +8,7 @@
/dts-v1/;
#include "sc7180-trogdor.dtsi"
+#include "sc7180-trogdor-detachable.dtsi"
/ {
avdd_lcd: avdd-lcd-regulator {
@@ -50,7 +51,6 @@
thermal-zones {
skin_temp_thermal: skin-temp-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&pm6150_adc_tm 1>;
sustainable-power = <574>;
@@ -104,10 +104,6 @@
base_detection: cbas {
compatible = "google,cros-cbas";
};
-
- keyboard-controller {
- compatible = "google,cros-ec-keyb-switches";
- };
};
&i2c4 {
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
index 8513be297120..74ab321d3333 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
@@ -21,9 +21,6 @@
/ {
thermal-zones {
charger_thermal: charger-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&pm6150_adc_tm 0>;
trips {
@@ -359,10 +356,11 @@
#sound-dai-cells = <0>;
};
- pwmleds {
+ pwmleds: pwmleds {
compatible = "pwm-leds";
+ status = "disabled";
+
keyboard_backlight: led-0 {
- status = "disabled";
label = "cros_ec::kbd_backlight";
function = LED_FUNCTION_KBD_BACKLIGHT;
pwms = <&cros_ec_pwm 0>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
index 4774a859bd7e..b5ebf8980325 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -1582,8 +1582,7 @@
};
ufs_mem_phy: phy@1d87000 {
- compatible = "qcom,sc7180-qmp-ufs-phy",
- "qcom,sm7150-qmp-ufs-phy";
+ compatible = "qcom,sc7180-qmp-ufs-phy";
reg = <0 0x01d87000 0 0x1000>;
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_UFS_PHY_PHY_AUX_CLK>,
@@ -3067,6 +3066,7 @@
iommus = <&apps_smmu 0x540 0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
+ snps,parkmode-disable-ss-quirk;
phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
maximum-speed = "super-speed";
@@ -4036,7 +4036,6 @@
thermal-zones {
cpu0_thermal: cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 1>;
sustainable-power = <1052>;
@@ -4085,7 +4084,6 @@
cpu1_thermal: cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 2>;
sustainable-power = <1052>;
@@ -4134,7 +4132,6 @@
cpu2_thermal: cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 3>;
sustainable-power = <1052>;
@@ -4183,7 +4180,6 @@
cpu3_thermal: cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 4>;
sustainable-power = <1052>;
@@ -4232,7 +4228,6 @@
cpu4_thermal: cpu4-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 5>;
sustainable-power = <1052>;
@@ -4281,7 +4276,6 @@
cpu5_thermal: cpu5-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 6>;
sustainable-power = <1052>;
@@ -4330,7 +4324,6 @@
cpu6_thermal: cpu6-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 9>;
sustainable-power = <1425>;
@@ -4371,7 +4364,6 @@
cpu7_thermal: cpu7-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 10>;
sustainable-power = <1425>;
@@ -4412,7 +4404,6 @@
cpu8_thermal: cpu8-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 11>;
sustainable-power = <1425>;
@@ -4453,7 +4444,6 @@
cpu9_thermal: cpu9-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 12>;
sustainable-power = <1425>;
@@ -4494,7 +4484,6 @@
aoss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 0>;
@@ -4515,7 +4504,6 @@
cpuss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 7>;
@@ -4535,7 +4523,6 @@
cpuss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 8>;
@@ -4555,7 +4542,6 @@
gpuss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 13>;
@@ -4583,7 +4569,6 @@
gpuss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 14>;
@@ -4611,7 +4596,6 @@
aoss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 0>;
@@ -4632,7 +4616,6 @@
cwlan-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 1>;
@@ -4653,7 +4636,6 @@
audio-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 2>;
@@ -4674,7 +4656,6 @@
ddr-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 3>;
@@ -4695,7 +4676,6 @@
q6-hvx-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 4>;
@@ -4716,7 +4696,6 @@
camera-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 5>;
@@ -4737,7 +4716,6 @@
mdm-core-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 6>;
@@ -4758,7 +4736,6 @@
mdm-dsp-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 7>;
@@ -4779,7 +4756,6 @@
npu-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 8>;
@@ -4800,7 +4776,6 @@
video-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 9>;
diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
index a0059527d9e4..7370aa0dbf0e 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
@@ -495,7 +495,6 @@
};
&uart5 {
- compatible = "qcom,geni-debug-uart";
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi b/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
index f9b96bd2477e..7d1d5bbbbbd9 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
@@ -427,7 +427,6 @@
};
uart_dbg: &uart5 {
- compatible = "qcom,geni-debug-uart";
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
index fc9ec367e3a5..3d8410683402 100644
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -24,6 +24,7 @@
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/reset/qcom,sdm845-aoss.h>
#include <dt-bindings/reset/qcom,sdm845-pdc.h>
+#include <dt-bindings/soc/qcom,apr.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
#include <dt-bindings/sound/qcom,lpass.h>
#include <dt-bindings/thermal/thermal.h>
@@ -710,6 +711,7 @@
firmware {
scm: scm {
compatible = "qcom,scm-sc7280", "qcom,scm";
+ qcom,dload-mode = <&tcsr_2 0x13000>;
};
};
@@ -1440,12 +1442,12 @@
};
uart5: serial@994000 {
- compatible = "qcom,geni-uart";
+ compatible = "qcom,geni-debug-uart";
reg = <0 0x00994000 0 0x4000>;
clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
clock-names = "se";
pinctrl-names = "default";
- pinctrl-0 = <&qup_uart5_cts>, <&qup_uart5_rts>, <&qup_uart5_tx>, <&qup_uart5_rx>;
+ pinctrl-0 = <&qup_uart5_tx>, <&qup_uart5_rx>;
interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&rpmhpd SC7280_CX>;
operating-points-v2 = <&qup_opp_table>;
@@ -2129,6 +2131,8 @@
reg = <0 0x016e0000 0 0x1c080>;
#interconnect-cells = <2>;
qcom,bcm-voters = <&apps_bcm_voter>;
+ clocks = <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>,
+ <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>;
};
aggre2_noc: interconnect@1700000 {
@@ -2136,6 +2140,7 @@
compatible = "qcom,sc7280-aggre2-noc";
#interconnect-cells = <2>;
qcom,bcm-voters = <&apps_bcm_voter>;
+ clocks = <&rpmhcc RPMH_IPA_CLK>;
};
mmss_noc: interconnect@1740000 {
@@ -2989,6 +2994,18 @@
dma-coherent;
};
+ gfx_0_tbu: tbu@3dd9000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x3dd9000 0x0 0x1000>;
+ qcom,stream-id-range = <&adreno_smmu 0x0 0x400>;
+ };
+
+ gfx_1_tbu: tbu@3ddd000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x3ddd000 0x0 0x1000>;
+ qcom,stream-id-range = <&adreno_smmu 0x400 0x400>;
+ };
+
remoteproc_mpss: remoteproc@4080000 {
compatible = "qcom,sc7280-mpss-pas";
reg = <0 0x04080000 0 0x10000>;
@@ -3762,6 +3779,75 @@
label = "lpass";
qcom,remote-pid = <2>;
+ apr {
+ compatible = "qcom,apr-v2";
+ qcom,glink-channels = "apr_audio_svc";
+ qcom,domain = <APR_DOMAIN_ADSP>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ service@3 {
+ reg = <APR_SVC_ADSP_CORE>;
+ compatible = "qcom,q6core";
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ };
+
+ q6afe: service@4 {
+ compatible = "qcom,q6afe";
+ reg = <APR_SVC_AFE>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ q6afedai: dais {
+ compatible = "qcom,q6afe-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ };
+
+ q6afecc: clock-controller {
+ compatible = "qcom,q6afe-clocks";
+ #clock-cells = <2>;
+ };
+ };
+
+ q6asm: service@7 {
+ compatible = "qcom,q6asm";
+ reg = <APR_SVC_ASM>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ q6asmdai: dais {
+ compatible = "qcom,q6asm-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ iommus = <&apps_smmu 0x1801 0x0>;
+
+ dai@0 {
+ reg = <0>;
+ };
+
+ dai@1 {
+ reg = <1>;
+ };
+
+ dai@2 {
+ reg = <2>;
+ };
+ };
+ };
+
+ q6adm: service@8 {
+ compatible = "qcom,q6adm";
+ reg = <APR_SVC_ADM>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ q6routing: routing {
+ compatible = "qcom,q6adm-routing";
+ #sound-dai-cells = <0>;
+ };
+ };
+ };
+
fastrpc {
compatible = "qcom,fastrpc";
qcom,glink-channels = "fastrpcglink-apps-dsp";
@@ -4150,6 +4236,7 @@
iommus = <&apps_smmu 0xe0 0x0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
+ snps,parkmode-disable-ss-quirk;
phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
maximum-speed = "super-speed";
@@ -5407,16 +5494,6 @@
function = "qup04";
};
- qup_uart5_cts: qup-uart5-cts-state {
- pins = "gpio20";
- function = "qup05";
- };
-
- qup_uart5_rts: qup-uart5-rts-state {
- pins = "gpio21";
- function = "qup05";
- };
-
qup_uart5_tx: qup-uart5-tx-state {
pins = "gpio22";
function = "qup05";
@@ -5802,6 +5879,83 @@
<GIC_SPI 408 IRQ_TYPE_LEVEL_HIGH>;
};
+ anoc_1_tbu: tbu@151dd000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x151dd000 0x0 0x1000>;
+ interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+ &cnoc3 SLAVE_TCU QCOM_ICC_TAG_ACTIVE_ONLY>;
+ qcom,stream-id-range = <&apps_smmu 0x0 0x400>;
+ };
+
+ anoc_2_tbu: tbu@151e1000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x151e1000 0x0 0x1000>;
+ interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+ &cnoc3 SLAVE_TCU QCOM_ICC_TAG_ACTIVE_ONLY>;
+ qcom,stream-id-range = <&apps_smmu 0x400 0x400>;
+ };
+
+ mnoc_hf_0_tbu: tbu@151e5000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x151e5000 0x0 0x1000>;
+ interconnects = <&mmss_noc MASTER_MDP0 QCOM_ICC_TAG_ACTIVE_ONLY
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0x800 0x400>;
+ };
+
+ mnoc_hf_1_tbu: tbu@151e9000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x151e9000 0x0 0x1000>;
+ interconnects = <&mmss_noc MASTER_MDP0 QCOM_ICC_TAG_ACTIVE_ONLY
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_MMNOC_MMU_TBU_HF1_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0xc00 0x400>;
+ };
+
+ compute_dsp_1_tbu: tbu@151ed000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x151ed000 0x0 0x1000>;
+ interconnects = <&nsp_noc MASTER_CDSP_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_TURING_MMU_TBU1_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0x1000 0x400>;
+ };
+
+ compute_dsp_0_tbu: tbu@151f1000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x151f1000 0x0 0x1000>;
+ interconnects = <&nsp_noc MASTER_CDSP_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_TURING_MMU_TBU0_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0x1400 0x400>;
+ };
+
+ adsp_tbu: tbu@151f5000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x151f5000 0x0 0x1000>;
+ interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+ &lpass_ag_noc SLAVE_LPASS_CORE_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
+ qcom,stream-id-range = <&apps_smmu 0x1800 0x400>;
+ };
+
+ anoc_1_pcie_tbu: tbu@151f9000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x151f9000 0x0 0x1000>;
+ interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+ &cnoc3 SLAVE_TCU QCOM_ICC_TAG_ACTIVE_ONLY>;
+ qcom,stream-id-range = <&apps_smmu 0x1c00 0x400>;
+ };
+
+ mnoc_sf_0_tbu: tbu@151fd000 {
+ compatible = "qcom,sc7280-tbu";
+ reg = <0x0 0x151fd000 0x0 0x1000>;
+ interconnects = <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ACTIVE_ONLY
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_MMNOC_MMU_TBU_SF0_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0x2000 0x400>;
+ };
+
intc: interrupt-controller@17a00000 {
compatible = "arm,gic-v3";
reg = <0 0x17a00000 0 0x10000>, /* GICD */
@@ -5991,10 +6145,12 @@
};
};
+ sound: sound {
+ };
+
thermal_zones: thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 1>;
@@ -6038,7 +6194,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 2>;
@@ -6082,7 +6237,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 3>;
@@ -6126,7 +6280,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 4>;
@@ -6170,7 +6323,6 @@
cpu4-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 7>;
@@ -6214,7 +6366,6 @@
cpu5-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 8>;
@@ -6258,7 +6409,6 @@
cpu6-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 9>;
@@ -6302,7 +6452,6 @@
cpu7-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 10>;
@@ -6346,7 +6495,6 @@
cpu8-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 11>;
@@ -6390,7 +6538,6 @@
cpu9-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 12>;
@@ -6434,7 +6581,6 @@
cpu10-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 13>;
@@ -6478,7 +6624,6 @@
cpu11-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 14>;
@@ -6522,7 +6667,6 @@
aoss0-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 0>;
@@ -6543,7 +6687,6 @@
aoss1-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 0>;
@@ -6564,7 +6707,6 @@
cpuss0-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 5>;
@@ -6584,7 +6726,6 @@
cpuss1-thermal {
polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 6>;
@@ -6604,7 +6745,6 @@
gpuss0-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 1>;
@@ -6632,7 +6772,6 @@
gpuss1-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 2>;
@@ -6659,9 +6798,6 @@
};
nspss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 3>;
trips {
@@ -6680,9 +6816,6 @@
};
nspss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 4>;
trips {
@@ -6701,9 +6834,6 @@
};
video-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 5>;
trips {
@@ -6722,9 +6852,6 @@
};
ddr-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 6>;
trips {
@@ -6743,9 +6870,6 @@
};
mdmss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 7>;
trips {
@@ -6764,9 +6888,6 @@
};
mdmss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 8>;
trips {
@@ -6785,9 +6906,6 @@
};
mdmss2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 9>;
trips {
@@ -6806,9 +6924,6 @@
};
mdmss3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 10>;
trips {
@@ -6827,9 +6942,6 @@
};
camera0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 11>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
index 6af99116c715..5b226577f9d8 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
+++ b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
@@ -68,7 +68,7 @@
reg = <0>;
pmic_glink_con0_hs: endpoint {
- remote-endpoint = <&usb_prim_role_switch>;
+ remote-endpoint = <&usb_prim_dwc3_hs>;
};
};
@@ -103,7 +103,7 @@
reg = <0>;
pmic_glink_con1_hs: endpoint {
- remote-endpoint = <&usb_sec_role_switch>;
+ remote-endpoint = <&usb_sec_dwc3_hs>;
};
};
@@ -582,6 +582,10 @@
dr_mode = "host";
};
+&usb_prim_dwc3_hs {
+ remote-endpoint = <&pmic_glink_con0_hs>;
+};
+
&usb_prim_qmpphy_dp_in {
remote-endpoint = <&mdss_dp0_out>;
};
@@ -590,8 +594,8 @@
remote-endpoint = <&pmic_glink_con0_ss>;
};
-&usb_prim_role_switch {
- remote-endpoint = <&pmic_glink_con0_hs>;
+&usb_sec_dwc3_hs {
+ remote-endpoint = <&pmic_glink_con1_hs>;
};
&usb_sec_hsphy {
@@ -619,10 +623,6 @@
remote-endpoint = <&pmic_glink_con1_ss>;
};
-&usb_sec_role_switch {
- remote-endpoint = <&pmic_glink_con1_hs>;
-};
-
&usb_sec {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi b/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi
index ddc84282f142..1c6f12fafe1d 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi
@@ -13,7 +13,6 @@
thermal-zones {
pmc8180-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pmc8180_temp>;
@@ -40,7 +39,6 @@
pmc8180c-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
thermal-sensors = <&pmc8180c_temp>;
diff --git a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
index bfee60c93ccc..65d923497a05 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
+++ b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
@@ -71,7 +71,7 @@
reg = <0>;
pmic_glink_con0_hs: endpoint {
- remote-endpoint = <&usb_prim_role_switch>;
+ remote-endpoint = <&usb_prim_dwc3_hs>;
};
};
@@ -106,7 +106,7 @@
reg = <0>;
pmic_glink_con1_hs: endpoint {
- remote-endpoint = <&usb_sec_role_switch>;
+ remote-endpoint = <&usb_sec_dwc3_hs>;
};
};
@@ -648,6 +648,10 @@
dr_mode = "host";
};
+&usb_prim_dwc3_hs {
+ remote-endpoint = <&pmic_glink_con0_hs>;
+};
+
&usb_prim_qmpphy_dp_in {
remote-endpoint = <&mdss_dp0_out>;
};
@@ -656,10 +660,6 @@
remote-endpoint = <&pmic_glink_con0_ss>;
};
-&usb_prim_role_switch {
- remote-endpoint = <&pmic_glink_con0_hs>;
-};
-
&usb_sec_hsphy {
vdda-pll-supply = <&vreg_l5e_0p88>;
vdda18-supply = <&vreg_l12a_1p8>;
@@ -685,10 +685,6 @@
remote-endpoint = <&pmic_glink_con1_ss>;
};
-&usb_sec_role_switch {
- remote-endpoint = <&pmic_glink_con1_hs>;
-};
-
&usb_sec {
status = "okay";
};
@@ -697,6 +693,10 @@
dr_mode = "host";
};
+&usb_sec_dwc3_hs {
+ remote-endpoint = <&pmic_glink_con1_hs>;
+};
+
&wifi {
memory-region = <&wlan_mem>;
diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
index 067712310560..6e707d993aeb 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
@@ -12,6 +12,7 @@
#include <dt-bindings/interconnect/qcom,osm-l3.h>
#include <dt-bindings/interconnect/qcom,sc8180x.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
#include <dt-bindings/thermal/thermal.h>
@@ -1890,7 +1891,7 @@
power-domains = <&gcc PCIE_3_GDSC>;
interconnects = <&aggre2_noc MASTER_PCIE_3 0 &mc_virt SLAVE_EBI_CH0 0>,
- <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>;
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_3 0>;
interconnect-names = "pcie-mem", "cpu-pcie";
phys = <&pcie3_phy>;
@@ -2012,7 +2013,7 @@
power-domains = <&gcc PCIE_1_GDSC>;
interconnects = <&aggre2_noc MASTER_PCIE_1 0 &mc_virt SLAVE_EBI_CH0 0>,
- <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>;
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_1 0>;
interconnect-names = "pcie-mem", "cpu-pcie";
phys = <&pcie1_phy>;
@@ -2134,7 +2135,7 @@
power-domains = <&gcc PCIE_2_GDSC>;
interconnects = <&aggre2_noc MASTER_PCIE_2 0 &mc_virt SLAVE_EBI_CH0 0>,
- <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>;
+ <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_2 0>;
interconnect-names = "pcie-mem", "cpu-pcie";
phys = <&pcie2_phy>;
@@ -2245,18 +2246,13 @@
resets = <&ufs_mem_hc 0>;
reset-names = "ufsphy";
+ power-domains = <&gcc UFS_PHY_GDSC>;
+
#phy-cells = <0>;
status = "disabled";
};
- ipa_virt: interconnect@1e00000 {
- compatible = "qcom,sc8180x-ipa-virt";
- reg = <0 0x01e00000 0 0x1000>;
- #interconnect-cells = <2>;
- qcom,bcm-voters = <&apps_bcm_voter>;
- };
-
tcsr_mutex: hwlock@1f40000 {
compatible = "qcom,tcsr-mutex";
reg = <0x0 0x01f40000 0x0 0x40000>;
@@ -2511,28 +2507,25 @@
status = "disabled";
};
- usb_prim_qmpphy: phy@88e9000 {
+ usb_prim_qmpphy: phy@88e8000 {
compatible = "qcom,sc8180x-qmp-usb3-dp-phy";
- reg = <0 0x088e9000 0 0x18c>,
- <0 0x088e8000 0 0x38>,
- <0 0x088ea000 0 0x40>;
- reg-names = "reg-base", "dp_com";
+ reg = <0 0x088e8000 0 0x3000>;
+
clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
- <&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_USB3_PRIM_CLKREF_CLK>,
- <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
+ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+ <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
clock-names = "aux",
- "ref_clk_src",
"ref",
- "com_aux";
+ "com_aux",
+ "usb3_pipe";
+
resets = <&gcc GCC_USB3_DP_PHY_PRIM_SP0_BCR>,
<&gcc GCC_USB3_PHY_PRIM_SP0_BCR>;
reset-names = "phy", "common";
#clock-cells = <1>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ #phy-cells = <1>;
status = "disabled";
@@ -2546,59 +2539,40 @@
usb_prim_qmpphy_out: endpoint {};
};
+ port@1 {
+ reg = <1>;
+
+ usb_prim_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_prim_dwc3_ss>;
+ };
+ };
+
port@2 {
reg = <2>;
usb_prim_qmpphy_dp_in: endpoint {};
};
};
-
- usb_prim_ssphy: usb3-phy@88e9200 {
- reg = <0 0x088e9200 0 0x200>,
- <0 0x088e9400 0 0x200>,
- <0 0x088e9c00 0 0x218>,
- <0 0x088e9600 0 0x200>,
- <0 0x088e9800 0 0x200>,
- <0 0x088e9a00 0 0x100>;
- #phy-cells = <0>;
- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb3_prim_phy_pipe_clk_src";
- };
-
- usb_prim_dpphy: dp-phy@88ea200 {
- reg = <0 0x088ea200 0 0x200>,
- <0 0x088ea400 0 0x200>,
- <0 0x088eaa00 0 0x200>,
- <0 0x088ea600 0 0x200>,
- <0 0x088ea800 0 0x200>;
- #clock-cells = <1>;
- #phy-cells = <0>;
- };
};
usb_sec_qmpphy: phy@88ee000 {
compatible = "qcom,sc8180x-qmp-usb3-dp-phy";
- reg = <0 0x088ee000 0 0x18c>,
- <0 0x088ed000 0 0x10>,
- <0 0x088ef000 0 0x40>;
- reg-names = "reg-base", "dp_com";
+ reg = <0 0x088ed000 0 0x3000>;
+
clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>,
- <&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_USB3_SEC_CLKREF_CLK>,
- <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>;
+ <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>,
+ <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
clock-names = "aux",
- "ref_clk_src",
"ref",
- "com_aux";
+ "com_aux",
+ "usb3_pipe";
resets = <&gcc GCC_USB3_DP_PHY_SEC_BCR>,
<&gcc GCC_USB3_PHY_SEC_BCR>;
reset-names = "phy", "common";
#clock-cells = <1>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ #phy-cells = <1>;
status = "disabled";
@@ -2612,46 +2586,32 @@
usb_sec_qmpphy_out: endpoint {};
};
+ port@1 {
+ reg = <1>;
+
+ usb_sec_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_sec_dwc3_ss>;
+ };
+ };
+
port@2 {
reg = <2>;
usb_sec_qmpphy_dp_in: endpoint {};
};
};
-
- usb_sec_ssphy: usb3-phy@88e9200 {
- reg = <0 0x088ee200 0 0x200>,
- <0 0x088ee400 0 0x200>,
- <0 0x088eec00 0 0x218>,
- <0 0x088ee600 0 0x200>,
- <0 0x088ee800 0 0x200>,
- <0 0x088eea00 0 0x100>;
- #phy-cells = <0>;
- clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb3_sec_phy_pipe_clk_src";
- };
-
- usb_sec_dpphy: dp-phy@88ef200 {
- reg = <0 0x088ef200 0 0x200>,
- <0 0x088ef400 0 0x200>,
- <0 0x088efa00 0 0x200>,
- <0 0x088ef600 0 0x200>,
- <0 0x088ef800 0 0x200>;
- #clock-cells = <1>;
- #phy-cells = <0>;
- clock-output-names = "qmp_dptx1_phy_pll_link_clk",
- "qmp_dptx1_phy_pll_vco_div_clk";
- };
};
system-cache-controller@9200000 {
compatible = "qcom,sc8180x-llcc";
- reg = <0 0x09200000 0 0x50000>, <0 0x09280000 0 0x50000>,
- <0 0x09300000 0 0x50000>, <0 0x09380000 0 0x50000>,
- <0 0x09600000 0 0x50000>;
+ reg = <0 0x09200000 0 0x58000>, <0 0x09280000 0 0x58000>,
+ <0 0x09300000 0 0x58000>, <0 0x09380000 0 0x58000>,
+ <0 0x09400000 0 0x58000>, <0 0x09480000 0 0x58000>,
+ <0 0x09500000 0 0x58000>, <0 0x09580000 0 0x58000>,
+ <0 0x09600000 0 0x58000>;
reg-names = "llcc0_base", "llcc1_base", "llcc2_base",
- "llcc3_base", "llcc_broadcast_base";
+ "llcc3_base", "llcc4_base", "llcc5_base",
+ "llcc6_base", "llcc7_base", "llcc_broadcast_base";
interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>;
};
@@ -2711,11 +2671,26 @@
iommus = <&apps_smmu 0x140 0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
- phys = <&usb_prim_hsphy>, <&usb_prim_ssphy>;
+ phys = <&usb_prim_hsphy>, <&usb_prim_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
- port {
- usb_prim_role_switch: endpoint {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_prim_dwc3_hs: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_prim_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_prim_qmpphy_usb_ss_in>;
+ };
};
};
};
@@ -2768,11 +2743,26 @@
iommus = <&apps_smmu 0x160 0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
- phys = <&usb_sec_hsphy>, <&usb_sec_ssphy>;
+ phys = <&usb_sec_hsphy>, <&usb_sec_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
- port {
- usb_sec_role_switch: endpoint {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_sec_dwc3_hs: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_sec_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_sec_qmpphy_usb_ss_in>;
+ };
};
};
};
@@ -3086,9 +3076,10 @@
assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
<&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
- assigned-clock-parents = <&usb_prim_dpphy 0>, <&usb_prim_dpphy 1>;
+ assigned-clock-parents = <&usb_prim_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_prim_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
- phys = <&usb_prim_dpphy>;
+ phys = <&usb_prim_qmpphy QMP_USB43DP_DP_PHY>;
phy-names = "dp";
#sound-dai-cells = <0>;
@@ -3163,9 +3154,10 @@
assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK1_CLK_SRC>,
<&dispcc DISP_CC_MDSS_DP_PIXEL2_CLK_SRC>;
- assigned-clock-parents = <&usb_sec_dpphy 0>, <&usb_sec_dpphy 1>;
+ assigned-clock-parents = <&usb_sec_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_sec_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
- phys = <&usb_sec_dpphy>;
+ phys = <&usb_sec_qmpphy QMP_USB43DP_DP_PHY>;
phy-names = "dp";
#sound-dai-cells = <0>;
@@ -3308,21 +3300,27 @@
compatible = "qcom,sc8180x-dispcc";
reg = <0 0x0af00000 0 0x20000>;
clocks = <&rpmhcc RPMH_CXO_CLK>,
- <&sleep_clk>,
- <&usb_prim_dpphy 0>,
- <&usb_prim_dpphy 1>,
- <&usb_sec_dpphy 0>,
- <&usb_sec_dpphy 1>,
+ <&mdss_dsi0_phy 0>,
+ <&mdss_dsi0_phy 1>,
+ <&mdss_dsi1_phy 0>,
+ <&mdss_dsi1_phy 1>,
+ <&usb_prim_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_prim_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>,
<&edp_phy 0>,
- <&edp_phy 1>;
+ <&edp_phy 1>,
+ <&usb_sec_qmpphy QMP_USB43DP_DP_LINK_CLK>,
+ <&usb_sec_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
clock-names = "bi_tcxo",
- "sleep_clk",
+ "dsi0_phy_pll_out_byteclk",
+ "dsi0_phy_pll_out_dsiclk",
+ "dsi1_phy_pll_out_byteclk",
+ "dsi1_phy_pll_out_dsiclk",
"dp_phy_pll_link_clk",
"dp_phy_pll_vco_div_clk",
- "dptx1_phy_pll_link_clk",
- "dptx1_phy_pll_vco_div_clk",
"edp_phy_pll_link_clk",
- "edp_phy_pll_vco_div_clk";
+ "edp_phy_pll_vco_div_clk",
+ "dptx1_phy_pll_link_clk",
+ "dptx1_phy_pll_vco_div_clk";
power-domains = <&rpmhpd SC8180X_MMCX>;
required-opps = <&rpmhpd_opp_low_svs>;
#clock-cells = <1>;
@@ -3368,7 +3366,6 @@
mboxes = <&apss_shared 0>;
#clock-cells = <0>;
- #power-domain-cells = <1>;
};
sram@c3f0000 {
@@ -3771,7 +3768,6 @@
thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 1>;
@@ -3786,7 +3782,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 2>;
@@ -3801,7 +3796,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 3>;
@@ -3816,7 +3810,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 4>;
@@ -3831,7 +3824,6 @@
cpu4-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 7>;
@@ -3846,7 +3838,6 @@
cpu5-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 8>;
@@ -3861,7 +3852,6 @@
cpu6-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 9>;
@@ -3876,7 +3866,6 @@
cpu7-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 10>;
@@ -3891,7 +3880,6 @@
cpu4-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 11>;
@@ -3906,7 +3894,6 @@
cpu5-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 12>;
@@ -3921,7 +3908,6 @@
cpu6-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 13>;
@@ -3936,7 +3922,6 @@
cpu7-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 14>;
@@ -3951,7 +3936,6 @@
aoss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 0>;
@@ -3966,7 +3950,6 @@
cluster0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 5>;
@@ -3981,7 +3964,6 @@
cluster1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 6>;
@@ -3996,7 +3978,6 @@
gpu-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 15>;
@@ -4009,16 +3990,27 @@
trips {
gpu_top_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
aoss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 0>;
@@ -4033,7 +4025,6 @@
wlan-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 1>;
@@ -4048,7 +4039,6 @@
video-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 2>;
@@ -4063,7 +4053,6 @@
mem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 3>;
@@ -4078,7 +4067,6 @@
q6-hvx-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 4>;
@@ -4093,7 +4081,6 @@
camera-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 5>;
@@ -4108,7 +4095,6 @@
compute-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 6>;
@@ -4123,7 +4109,6 @@
mdm-dsp-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 7>;
@@ -4138,7 +4123,6 @@
npu-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 8>;
@@ -4153,7 +4137,6 @@
gpu-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 11>;
@@ -4166,10 +4149,22 @@
trips {
gpu_bottom_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts
index 41215567b3ae..b98b2f7752b5 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts
+++ b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts
@@ -56,7 +56,7 @@
reg = <0>;
pmic_glink_con0_hs: endpoint {
- remote-endpoint = <&usb_0_role_switch>;
+ remote-endpoint = <&usb_0_dwc3_hs>;
};
};
@@ -91,7 +91,7 @@
reg = <0>;
pmic_glink_con1_hs: endpoint {
- remote-endpoint = <&usb_1_role_switch>;
+ remote-endpoint = <&usb_1_dwc3_hs>;
};
};
@@ -675,6 +675,10 @@
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>;
@@ -700,10 +704,6 @@
remote-endpoint = <&pmic_glink_con0_ss>;
};
-&usb_0_role_switch {
- remote-endpoint = <&pmic_glink_con0_hs>;
-};
-
&usb_1 {
status = "okay";
};
@@ -712,6 +712,10 @@
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>;
@@ -737,10 +741,6 @@
remote-endpoint = <&pmic_glink_con1_ss>;
};
-&usb_1_role_switch {
- remote-endpoint = <&pmic_glink_con1_hs>;
-};
-
&xo_board_clk {
clock-frequency = <38400000>;
};
@@ -977,8 +977,7 @@
reset-n-pins {
pins = "gpio99";
function = "gpio";
- output-high;
- 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 e937732abede..b27143f81867 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
+++ b/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
@@ -117,7 +117,7 @@
reg = <0>;
pmic_glink_con0_hs: endpoint {
- remote-endpoint = <&usb_0_role_switch>;
+ remote-endpoint = <&usb_0_dwc3_hs>;
};
};
@@ -152,7 +152,7 @@
reg = <0>;
pmic_glink_con1_hs: endpoint {
- remote-endpoint = <&usb_1_role_switch>;
+ remote-endpoint = <&usb_1_dwc3_hs>;
};
};
@@ -297,9 +297,30 @@
};
thermal-zones {
+ pm8008-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+
+ thermal-sensors = <&pm8008>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
skin-temp-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8280_adc_tm 5>;
trips {
@@ -655,21 +676,101 @@
status = "okay";
- /* FIXME: verify */
touchscreen@10 {
- compatible = "hid-over-i2c";
+ compatible = "elan,ekth5015m", "elan,ekth6915";
reg = <0x10>;
- hid-descr-addr = <0x1>;
interrupts-extended = <&tlmm 175 IRQ_TYPE_LEVEL_LOW>;
- vdd-supply = <&vreg_misc_3p3>;
- vddl-supply = <&vreg_s10b>;
+ reset-gpios = <&tlmm 99 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
+ no-reset-on-power-off;
+
+ vcc33-supply = <&vreg_misc_3p3>;
+ vccio-supply = <&vreg_misc_3p3>;
pinctrl-names = "default";
pinctrl-0 = <&ts0_default>;
};
};
+&i2c11 {
+ clock-frequency = <400000>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c11_default>;
+
+ status = "okay";
+
+ pm8008: pmic@c {
+ compatible = "qcom,pm8008";
+ reg = <0xc>;
+
+ interrupts-extended = <&tlmm 41 IRQ_TYPE_EDGE_RISING>;
+ reset-gpios = <&tlmm 42 GPIO_ACTIVE_LOW>;
+
+ vdd-l1-l2-supply = <&vreg_s11b>;
+ vdd-l3-l4-supply = <&vreg_bob>;
+ vdd-l5-supply = <&vreg_bob>;
+ vdd-l6-supply = <&vreg_bob>;
+ vdd-l7-supply = <&vreg_bob>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pm8008_default>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pm8008 0 0 2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ #thermal-sensor-cells = <0>;
+
+ regulators {
+ vreg_l1q: ldo1 {
+ regulator-name = "vreg_l1q";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l2q: ldo2 {
+ regulator-name = "vreg_l2q";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l3q: ldo3 {
+ regulator-name = "vreg_l3q";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ vreg_l4q: ldo4 {
+ regulator-name = "vreg_l4q";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ vreg_l5q: ldo5 {
+ regulator-name = "vreg_l5q";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l6q: ldo6 {
+ regulator-name = "vreg_l6q";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l7q: ldo7 {
+ regulator-name = "vreg_l7q";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+ };
+ };
+};
+
&i2c21 {
clock-frequency = <400000>;
@@ -1131,6 +1232,10 @@
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>;
@@ -1156,10 +1261,6 @@
remote-endpoint = <&pmic_glink_con0_ss>;
};
-&usb_0_role_switch {
- remote-endpoint = <&pmic_glink_con0_hs>;
-};
-
&usb_1 {
status = "okay";
};
@@ -1168,6 +1269,10 @@
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>;
@@ -1193,10 +1298,6 @@
remote-endpoint = <&pmic_glink_con1_ss>;
};
-&usb_1_role_switch {
- remote-endpoint = <&pmic_glink_con1_hs>;
-};
-
&usb_2 {
status = "okay";
};
@@ -1355,6 +1456,13 @@
bias-disable;
};
+ i2c11_default: i2c11-default-state {
+ pins = "gpio18", "gpio19";
+ function = "qup11";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
i2c21_default: i2c21-default-state {
pins = "gpio81", "gpio82";
function = "qup21";
@@ -1458,6 +1566,22 @@
};
};
+ pm8008_default: pm8008-default-state {
+ int-pins {
+ pins = "gpio41";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ reset-n-pins {
+ pins = "gpio42";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
spkr_1_sd_n_default: spkr-1-sd-n-default-state {
perst-n-pins {
pins = "gpio178";
@@ -1496,8 +1620,8 @@
reset-n-pins {
pins = "gpio99";
function = "gpio";
- output-high;
- drive-strength = <16>;
+ drive-strength = <2>;
+ bias-disable;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi
index 945de77911de..1e3babf2e40d 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi
@@ -14,7 +14,7 @@
thermal-zones {
pm8280_1_thermal: pm8280-1-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pm8280_1_temp_alarm>;
trips {
@@ -34,7 +34,7 @@
pm8280_2_thermal: pm8280-2-thermal {
polling-delay-passive = <100>;
- polling-delay = <0>;
+
thermal-sensors = <&pm8280_2_temp_alarm>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
index 0549ba1fbeea..80a57aa22839 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
@@ -3222,6 +3222,14 @@
usb_0_qmpphy_out: endpoint {};
};
+ port@1 {
+ reg = <1>;
+
+ usb_0_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_0_dwc3_ss>;
+ };
+ };
+
port@2 {
reg = <2>;
@@ -3275,6 +3283,14 @@
usb_1_qmpphy_out: endpoint {};
};
+ port@1 {
+ reg = <1>;
+
+ usb_1_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_ss>;
+ };
+ };
+
port@2 {
reg = <2>;
@@ -3560,8 +3576,23 @@
phys = <&usb_0_hsphy>, <&usb_0_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
- port {
- usb_0_role_switch: endpoint {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_0_dwc3_hs: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_0_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_0_qmpphy_usb_ss_in>;
+ };
};
};
};
@@ -3622,8 +3653,23 @@
phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
- port {
- usb_1_role_switch: endpoint {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_dwc3_hs: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_usb_ss_in>;
+ };
};
};
};
@@ -4623,6 +4669,8 @@
restart@c264000 {
compatible = "qcom,pshold";
reg = <0 0x0c264000 0 0x4>;
+ /* TZ seems to block access */
+ status = "reserved";
};
tsens1: thermal-sensor@c265000 {
@@ -5831,7 +5879,6 @@
thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 1>;
@@ -5846,7 +5893,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 2>;
@@ -5861,7 +5907,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 3>;
@@ -5876,7 +5921,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 4>;
@@ -5891,7 +5935,6 @@
cpu4-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 5>;
@@ -5906,7 +5949,6 @@
cpu5-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 6>;
@@ -5921,7 +5963,6 @@
cpu6-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 7>;
@@ -5936,7 +5977,6 @@
cpu7-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 8>;
@@ -5951,7 +5991,6 @@
cluster0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 9>;
@@ -5965,13 +6004,25 @@
};
gpu-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ polling-delay-passive = <250>;
thermal-sensors = <&tsens2 2>;
+ cooling-maps {
+ map0 {
+ trip = <&gpu_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+
trips {
- gpu-crit {
+ gpu_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <110000>;
hysteresis = <1000>;
type = "critical";
@@ -5981,7 +6032,6 @@
mem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 15>;
diff --git a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts
index 702ab49bbc59..60412281ab27 100644
--- a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts
+++ b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts
@@ -96,6 +96,18 @@
vin-supply = <&vph_pwr>;
};
+
+ /*
+ * this is also used for APC1 CPU power, touching it resets the board
+ */
+ vreg_l10a_1p8: vreg-l10a-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_l10a_1p8";
+ regulator-min-microvolt = <1804000>;
+ regulator-max-microvolt = <1896000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
};
&adsp_pil {
@@ -220,6 +232,7 @@
status = "okay";
vdd-supply = <&vreg_l1b_0p925>;
+ vdda-pll-supply = <&vreg_l10a_1p8>;
vdda-phy-dpdm-supply = <&vreg_l7b_3p125>;
};
@@ -227,6 +240,7 @@
status = "okay";
vdd-supply = <&vreg_l1b_0p925>;
+ vdda-pll-supply = <&vreg_l10a_1p8>;
vdda-phy-dpdm-supply = <&vreg_l7b_3p125>;
};
@@ -464,5 +478,6 @@
&usb3_qmpphy {
vdda-phy-supply = <&vreg_l1b_0p925>;
+ vdda-pll-supply = <&vreg_l10a_1p8>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-lenovo-tbx605f.dts b/arch/arm64/boot/dts/qcom/sdm450-lenovo-tbx605f.dts
new file mode 100644
index 000000000000..175befc02b22
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm450-lenovo-tbx605f.dts
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024, Neil Armstrong <[email protected]>
+ */
+/dts-v1/;
+
+#include "sdm450.dtsi"
+#include "pm8953.dtsi"
+#include "pmi8950.dtsi"
+
+/ {
+ model = "Lenovo Smart Tab M10";
+ compatible = "lenovo,tbx605f", "qcom,sdm450";
+ chassis-type = "tablet";
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ framebuffer@90001000 {
+ compatible = "simple-framebuffer";
+ reg = <0 0x90001000 0 (1200 * 1920 * 3)>;
+
+ width = <1200>;
+ height = <1920>;
+ stride = <(1200 * 3)>;
+ format = "r8g8b8";
+
+ power-domains = <&gcc MDSS_GDSC>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_VSYNC_CLK>,
+ <&gcc GCC_MDSS_MDP_CLK>,
+ <&gcc GCC_MDSS_BYTE0_CLK>,
+ <&gcc GCC_MDSS_PCLK0_CLK>,
+ <&gcc GCC_MDSS_ESC0_CLK>;
+ };
+ };
+
+ reserved-memory {
+ other_ext_region@0 {
+ no-map;
+ reg = <0x00 0x84500000 0x00 0x2300000>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ key-volume-up {
+ label = "volume_up";
+ gpios = <&tlmm 85 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&hsusb_phy {
+ vdd-supply = <&pm8953_l3>;
+ vdda-pll-supply = <&pm8953_l7>;
+ vdda-phy-dpdm-supply = <&pm8953_l13>;
+
+ status = "okay";
+};
+
+&i2c_3 {
+ status = "okay";
+
+ touchscreen@38 {
+ compatible = "edt,edt-ft5506";
+ reg = <0x38>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <65 IRQ_TYPE_EDGE_FALLING>;
+ vcc-supply = <&pm8953_l10>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&ts_int_active &ts_reset_active>;
+
+ reset-gpios = <&tlmm 64 GPIO_ACTIVE_LOW>;
+ touchscreen-size-x = <1200>;
+ touchscreen-size-y = <1920>;
+ };
+};
+
+&pm8953_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&rpm_requests {
+ regulators {
+ compatible = "qcom,rpm-pm8953-regulators";
+
+ vdd_s1-supply = <&vph_pwr>;
+ vdd_s2-supply = <&vph_pwr>;
+ vdd_s3-supply = <&vph_pwr>;
+ vdd_s4-supply = <&vph_pwr>;
+ vdd_s5-supply = <&vph_pwr>;
+ vdd_s6-supply = <&vph_pwr>;
+ vdd_s7-supply = <&vph_pwr>;
+ vdd_l1-supply = <&pm8953_s3>;
+ vdd_l2_l3-supply = <&pm8953_s3>;
+ vdd_l4_l5_l6_l7_l16_l19-supply = <&pm8953_s4>;
+ vdd_l8_l11_l12_l13_l14_l15-supply = <&vph_pwr>;
+ vdd_l9_l10_l17_l18_l22-supply = <&vph_pwr>;
+
+ pm8953_s1: s1 {
+ regulator-min-microvolt = <870000>;
+ regulator-max-microvolt = <1156000>;
+ };
+
+ pm8953_s3: s3 {
+ regulator-min-microvolt = <1224000>;
+ regulator-max-microvolt = <1224000>;
+ };
+
+ pm8953_s4: s4 {
+ regulator-min-microvolt = <1900000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8953_l1: l1 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ pm8953_l2: l2 {
+ regulator-min-microvolt = <975000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8953_l3: l3 {
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <925000>;
+ };
+
+ pm8953_l5: l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8953_l6: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8953_l7: l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1900000>;
+ };
+
+ pm8953_l8: l8 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ pm8953_l9: l9 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8953_l10: l10 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ pm8953_l11: l11 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8953_l12: l12 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8953_l13: l13 {
+ regulator-min-microvolt = <3125000>;
+ regulator-max-microvolt = <3125000>;
+ };
+
+ pm8953_l16: l16 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8953_l17: l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ pm8953_l19: l19 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ pm8953_l22: l22 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ pm8953_l23: l23 {
+ regulator-min-microvolt = <975000>;
+ regulator-max-microvolt = <1225000>;
+ };
+ };
+};
+
+&sdhc_1 {
+ vmmc-supply = <&pm8953_l8>;
+ vqmmc-supply = <&pm8953_l5>;
+
+ status = "okay";
+};
+
+&sdhc_2 {
+ vmmc-supply = <&pm8953_l11>;
+ vqmmc-supply = <&pm8953_l12>;
+
+ cd-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_off>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>, <135 4>;
+
+ ts_int_active: ts-int-active-state {
+ pins = "gpio65";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ ts_reset_active: ts-reset-active-state {
+ pins = "gpio64";
+ function = "gpio";
+ drive-strength = <0x08>;
+ bias-pull-up;
+ };
+};
+
+&usb3 {
+ status = "okay";
+};
+
+&usb3_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&wcnss {
+ vddpx-supply = <&pm8953_l5>;
+
+ status = "okay";
+};
+
+&wcnss_iris {
+ compatible = "qcom,wcn3660b";
+
+ vddxo-supply = <&pm8953_l7>;
+ vddrfa-supply = <&pm8953_l19>;
+ vddpa-supply = <&pm8953_l9>;
+ vdddig-supply = <&pm8953_l5>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-motorola-ali.dts b/arch/arm64/boot/dts/qcom/sdm450-motorola-ali.dts
index e27f3c5d5bba..a288d52fb6d7 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-motorola-ali.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-motorola-ali.dts
@@ -248,5 +248,6 @@
};
&usb3_dwc3 {
+ /delete-property/ usb-role-switch;
dr_mode = "peripheral";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi
index f5921b80ef94..c7e3764a8cf3 100644
--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi
@@ -1302,6 +1302,7 @@
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
+ snps,parkmode-disable-ss-quirk;
phys = <&qusb2phy0>, <&usb3_qmpphy>;
phy-names = "usb2-phy", "usb3-phy";
@@ -2422,7 +2423,6 @@
thermal-zones {
aoss-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 0>;
@@ -2437,7 +2437,6 @@
cpuss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 1>;
@@ -2452,7 +2451,6 @@
cpuss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 2>;
@@ -2467,7 +2465,6 @@
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 3>;
@@ -2488,7 +2485,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 4>;
@@ -2509,7 +2505,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 5>;
@@ -2530,7 +2525,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 6>;
@@ -2557,7 +2551,6 @@
pwr-cluster-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 7>;
@@ -2578,7 +2571,6 @@
gpu-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens 8>;
@@ -2591,20 +2583,32 @@
trips {
gpu_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
};
timer {
compatible = "arm,armv8-timer";
- interrupts = <GIC_PPI 1 0xf08>,
- <GIC_PPI 2 0xf08>,
- <GIC_PPI 3 0xf08>,
- <GIC_PPI 0 0xf08>;
+ interrupts = <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 0 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts b/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts
index e2708c74e95a..2c1172aa97e4 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts
@@ -143,6 +143,10 @@
status = "okay";
};
+&pmi632_vib {
+ status = "okay";
+};
+
&sdhc_1 {
status = "okay";
vmmc-supply = <&pm8953_l8>;
diff --git a/arch/arm64/boot/dts/qcom/sdm632-motorola-ocean.dts b/arch/arm64/boot/dts/qcom/sdm632-motorola-ocean.dts
index c82d6e628d2c..2f55db0c8ce3 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-motorola-ocean.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-motorola-ocean.dts
@@ -287,5 +287,6 @@
};
&usb3_dwc3 {
+ /delete-property/ usb-role-switch;
dr_mode = "peripheral";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 80e81c4233b3..187c6698835d 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -509,6 +509,18 @@
no-map;
};
+ smem@86000000 {
+ compatible = "qcom,smem";
+ reg = <0 0x86000000 0 0x200000>;
+ no-map;
+ hwlocks = <&tcsr_mutex 3>;
+ };
+
+ tz_mem: tz@86200000 {
+ reg = <0 0x86200000 0 0x2d00000>;
+ no-map;
+ };
+
camera_mem: camera-mem@8ab00000 {
reg = <0 0x8ab00000 0 0x500000>;
no-map;
@@ -1139,6 +1151,12 @@
qcom,bcm-voters = <&apps_bcm_voter>;
};
+ tcsr_mutex: hwlock@1f40000 {
+ compatible = "qcom,tcsr-mutex";
+ reg = <0 0x01f40000 0 0x20000>;
+ #hwlock-cells = <1>;
+ };
+
tlmm: pinctrl@3400000 {
compatible = "qcom,sdm670-tlmm";
reg = <0 0x03400000 0 0xc00000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
index 76bfa786612c..2391f842c903 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
@@ -51,9 +51,6 @@
thermal-zones {
xo_thermal: xo-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&pm8998_adc_tm 1>;
trips {
@@ -66,9 +63,6 @@
};
msm_thermal: msm-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&pm8998_adc_tm 2>;
trips {
@@ -81,9 +75,6 @@
};
pa_thermal: pa-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&pm8998_adc_tm 3>;
trips {
@@ -96,9 +87,6 @@
};
quiet_thermal: quiet-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&pm8998_adc_tm 4>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 10de2bd46ffc..54077549b9da 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -15,6 +15,7 @@
#include <dt-bindings/dma/qcom-gpi.h>
#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interconnect/qcom,icc.h>
#include <dt-bindings/interconnect/qcom,osm-l3.h>
#include <dt-bindings/interconnect/qcom,sdm845.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -2666,6 +2667,8 @@
"ref_aux",
"qref";
+ power-domains = <&gcc UFS_PHY_GDSC>;
+
resets = <&ufs_mem_hc 0>;
reset-names = "ufsphy";
@@ -4028,6 +4031,35 @@
#clock-cells = <1>;
#phy-cells = <1>;
+ orientation-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_qmpphy_out: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_ss>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ usb_1_qmpphy_dp_in: endpoint {
+ remote-endpoint = <&dp_out>;
+ };
+ };
+ };
};
usb_2_qmpphy: phy@88eb000 {
@@ -4106,8 +4138,29 @@
iommus = <&apps_smmu 0x740 0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
+ snps,parkmode-disable-ss-quirk;
phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_dwc3_hs: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_usb_ss_in>;
+ };
+ };
+ };
};
};
@@ -4161,6 +4214,7 @@
iommus = <&apps_smmu 0x760 0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
+ snps,parkmode-disable-ss-quirk;
phys = <&usb_2_hsphy>, <&usb_2_qmpphy>;
phy-names = "usb2-phy", "usb3-phy";
};
@@ -4598,7 +4652,9 @@
port@1 {
reg = <1>;
- dp_out: endpoint { };
+ dp_out: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_dp_in>;
+ };
};
};
@@ -5105,6 +5161,78 @@
<GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>;
};
+ anoc_1_tbu: tbu@150c5000 {
+ compatible = "qcom,sdm845-tbu";
+ reg = <0x0 0x150c5000 0x0 0x1000>;
+ interconnects = <&system_noc MASTER_GNOC_SNOC QCOM_ICC_TAG_ACTIVE_ONLY
+ &config_noc SLAVE_IMEM_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_AGGRE_NOC_MMU_TBU1_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0x0 0x400>;
+ };
+
+ anoc_2_tbu: tbu@150c9000 {
+ compatible = "qcom,sdm845-tbu";
+ reg = <0x0 0x150c9000 0x0 0x1000>;
+ interconnects = <&system_noc MASTER_GNOC_SNOC QCOM_ICC_TAG_ACTIVE_ONLY
+ &config_noc SLAVE_IMEM_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_AGGRE_NOC_MMU_TBU2_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0x400 0x400>;
+ };
+
+ mnoc_hf_0_tbu: tbu@150cd000 {
+ compatible = "qcom,sdm845-tbu";
+ reg = <0x0 0x150cd000 0x0 0x1000>;
+ interconnects = <&mmss_noc MASTER_MDP0 QCOM_ICC_TAG_ACTIVE_ONLY
+ &mmss_noc SLAVE_MNOC_HF_MEM_NOC QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0x800 0x400>;
+ };
+
+ mnoc_hf_1_tbu: tbu@150d1000 {
+ compatible = "qcom,sdm845-tbu";
+ reg = <0x0 0x150d1000 0x0 0x1000>;
+ interconnects = <&mmss_noc MASTER_MDP0 QCOM_ICC_TAG_ACTIVE_ONLY
+ &mmss_noc SLAVE_MNOC_HF_MEM_NOC QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_MMNOC_MMU_TBU_HF1_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0xc00 0x400>;
+ };
+
+ mnoc_sf_0_tbu: tbu@150d5000 {
+ compatible = "qcom,sdm845-tbu";
+ reg = <0x0 0x150d5000 0x0 0x1000>;
+ interconnects = <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ACTIVE_ONLY
+ &mmss_noc SLAVE_MNOC_SF_MEM_NOC QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_MMNOC_MMU_TBU_SF_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0x1000 0x400>;
+ };
+
+ compute_dsp_tbu: tbu@150d9000 {
+ compatible = "qcom,sdm845-tbu";
+ reg = <0x0 0x150d9000 0x0 0x1000>;
+ interconnects = <&system_noc MASTER_GNOC_SNOC QCOM_ICC_TAG_ACTIVE_ONLY
+ &config_noc SLAVE_IMEM_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
+ qcom,stream-id-range = <&apps_smmu 0x1400 0x400>;
+ };
+
+ adsp_tbu: tbu@150dd000 {
+ compatible = "qcom,sdm845-tbu";
+ reg = <0x0 0x150dd000 0x0 0x1000>;
+ interconnects = <&system_noc MASTER_GNOC_SNOC QCOM_ICC_TAG_ACTIVE_ONLY
+ &config_noc SLAVE_IMEM_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_AGGRE_NOC_MMU_AUDIO_TBU_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0x1800 0x400>;
+ };
+
+ anoc_1_pcie_tbu: tbu@150e1000 {
+ compatible = "qcom,sdm845-tbu";
+ reg = <0x0 0x150e1000 0x0 0x1000>;
+ clocks = <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>;
+ interconnects = <&system_noc MASTER_GNOC_SNOC QCOM_ICC_TAG_ACTIVE_ONLY
+ &config_noc SLAVE_IMEM_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
+ power-domains = <&gcc HLOS1_VOTE_AGGRE_NOC_MMU_PCIE_TBU_GDSC>;
+ qcom,stream-id-range = <&apps_smmu 0x1c00 0x400>;
+ };
+
lpasscc: clock-controller@17014000 {
compatible = "qcom,sdm845-lpasscc";
reg = <0 0x17014000 0 0x1f004>, <0 0x17300000 0 0x200>;
@@ -5358,7 +5486,6 @@
thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 1>;
@@ -5385,7 +5512,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 2>;
@@ -5412,7 +5538,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 3>;
@@ -5439,7 +5564,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 4>;
@@ -5466,7 +5590,6 @@
cpu4-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 7>;
@@ -5493,7 +5616,6 @@
cpu5-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 8>;
@@ -5520,7 +5642,6 @@
cpu6-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 9>;
@@ -5547,7 +5668,6 @@
cpu7-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 10>;
@@ -5574,7 +5694,6 @@
aoss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 0>;
@@ -5589,7 +5708,6 @@
cluster0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 5>;
@@ -5609,7 +5727,6 @@
cluster1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 6>;
@@ -5629,7 +5746,6 @@
gpu-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 11>;
@@ -5642,16 +5758,27 @@
trips {
gpu_top_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
gpu-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 12>;
@@ -5664,16 +5791,27 @@
trips {
gpu_bottom_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
aoss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 0>;
@@ -5688,7 +5826,6 @@
q6-modem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 1>;
@@ -5703,7 +5840,6 @@
mem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 2>;
@@ -5718,7 +5854,6 @@
wlan-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 3>;
@@ -5733,7 +5868,6 @@
q6-hvx-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 4>;
@@ -5748,7 +5882,6 @@
camera-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 5>;
@@ -5763,7 +5896,6 @@
video-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 6>;
@@ -5778,7 +5910,6 @@
modem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 7>;
diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
index 47dc42f6e936..f18050848cd8 100644
--- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
@@ -370,6 +370,66 @@
&i2c1 {
status = "okay";
clock-frequency = <400000>;
+
+ embedded-controller@70 {
+ compatible = "lenovo,yoga-c630-ec";
+ reg = <0x70>;
+
+ interrupts-extended = <&tlmm 20 IRQ_TYPE_LEVEL_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&ec_int_state>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ connector@0 {
+ compatible = "usb-c-connector";
+ reg = <0>;
+ power-role = "dual";
+ data-role = "host";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ ucsi0_hs_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ ucsi0_ss_in: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ ucsi0_sbu: endpoint {
+ };
+ };
+ };
+ };
+
+ connector@1 {
+ compatible = "usb-c-connector";
+ reg = <1>;
+ power-role = "dual";
+ data-role = "host";
+
+ /*
+ * connected to the onboard USB hub, orientation is
+ * handled by the controller
+ */
+ };
+ };
};
&i2c3 {
@@ -494,6 +554,7 @@
&ipa {
qcom,gsi-loader = "self";
memory-region = <&ipa_fw_mem>;
+ firmware-name = "qcom/sdm850/LENOVO/81JL/ipa_fws.elf";
status = "okay";
};
@@ -694,6 +755,13 @@
bias-disable;
};
+
+ ec_int_state: ec-int-state {
+ pins = "gpio20";
+ function = "gpio";
+
+ bias-disable;
+ };
};
&uart6 {
@@ -741,6 +809,10 @@
dr_mode = "host";
};
+&usb_1_dwc3_hs {
+ remote-endpoint = <&ucsi0_hs_in>;
+};
+
&usb_1_hsphy {
status = "okay";
@@ -761,6 +833,10 @@
vdda-pll-supply = <&vdda_usb1_ss_core>;
};
+&usb_1_qmpphy_out {
+ remote-endpoint = <&ucsi0_ss_in>;
+};
+
&usb_2 {
status = "okay";
};
@@ -834,6 +910,7 @@
vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
qcom,snoc-host-cap-8bit-quirk;
+ qcom,ath10k-calibration-variant = "Lenovo_C630";
};
&crypto {
diff --git a/arch/arm64/boot/dts/qcom/sdx75-idp.dts b/arch/arm64/boot/dts/qcom/sdx75-idp.dts
index f76e72fb2072..fde16308c7e2 100644
--- a/arch/arm64/boot/dts/qcom/sdx75-idp.dts
+++ b/arch/arm64/boot/dts/qcom/sdx75-idp.dts
@@ -41,6 +41,29 @@
vin-supply = <&vph_ext>;
};
+
+ reg_2v952_vcc: regulator-2v952-vcc {
+ compatible = "regulator-gpio";
+ regulator-name = "2v952_vcc";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3600000>;
+ enable-gpios = <&tlmm 102 GPIO_ACTIVE_HIGH>;
+ gpios = <&tlmm 84 GPIO_ACTIVE_HIGH>;
+ states = <1650000 0>, <3600000 1>;
+ startup-delay-us = <5000>;
+ enable-active-high;
+ regulator-boot-on;
+
+ vin-supply = <&vph_ext>;
+ };
+
+ reg_2v95_vdd: regulator-2v95-vdd {
+ compatible = "regulator-fixed";
+ regulator-name = "2v95_vdd";
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ vin-supply = <&reg_2v952_vcc>;
+ };
};
&apps_rsc {
@@ -259,8 +282,30 @@
status = "okay";
};
+&sdhc {
+ cd-gpios = <&tlmm 103 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&reg_2v95_vdd>;
+ vqmmc-supply = <&reg_2v952_vcc>;
+ bus-width = <4>;
+ no-sdio;
+ no-mmc;
+
+ pinctrl-0 = <&sdc1_default &sd_cd>;
+ pinctrl-1 = <&sdc1_sleep &sd_cd>;
+ pinctrl-names = "default", "sleep";
+
+ status = "okay";
+};
+
&tlmm {
gpio-reserved-ranges = <110 6>;
+
+ sd_cd: sd-cd-state {
+ pins = "gpio103";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
};
&uart1 {
diff --git a/arch/arm64/boot/dts/qcom/sdx75.dtsi b/arch/arm64/boot/dts/qcom/sdx75.dtsi
index da1704061d58..9b93f6501d55 100644
--- a/arch/arm64/boot/dts/qcom/sdx75.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdx75.dtsi
@@ -8,9 +8,12 @@
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/clock/qcom,sdx75-gcc.h>
+#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interconnect/qcom,icc.h>
#include <dt-bindings/interconnect/qcom,sdx75.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/mailbox/qcom-ipcc.h>
#include <dt-bindings/power/qcom,rpmhpd.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
@@ -405,7 +408,42 @@
};
};
- smem: qcom,smem {
+ smp2p-modem {
+ compatible = "qcom,smp2p";
+ qcom,smem = <435>, <428>;
+ interrupts-extended = <&ipcc IPCC_CLIENT_MPSS
+ IPCC_MPROC_SIGNAL_SMP2P
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_MPSS
+ IPCC_MPROC_SIGNAL_SMP2P>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <1>;
+
+ smp2p_modem_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ smp2p_modem_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ ipa_smp2p_out: ipa-ap-to-modem {
+ qcom,entry-name = "ipa";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ ipa_smp2p_in: ipa-modem-to-ap {
+ qcom,entry-name = "ipa";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ smem: smem {
compatible = "qcom,smem";
memory-region = <&smem_mem>;
hwlocks = <&tcsr_mutex 3>;
@@ -441,6 +479,37 @@
#power-domain-cells = <1>;
};
+ ipcc: mailbox@408000 {
+ compatible = "qcom,sdx75-ipcc", "qcom,ipcc";
+ reg = <0 0x00408000 0 0x1000>;
+ interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #mbox-cells = <2>;
+ };
+
+ gpi_dma: dma-controller@900000 {
+ compatible = "qcom,sdx75-gpi-dma", "qcom,sm6350-gpi-dma";
+ reg = <0x0 0x00900000 0x0 0x60000>;
+ #dma-cells = <3>;
+ interrupts = <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+ dma-channels = <12>;
+ dma-channel-mask = <0x7f>;
+ iommus = <&apps_smmu 0xf6 0x0>;
+ status = "disabled";
+ };
+
qupv3_id_0: geniqup@9c0000 {
compatible = "qcom,geni-se-qup";
reg = <0x0 0x009c0000 0x0 0x2000>;
@@ -457,6 +526,52 @@
ranges;
status = "disabled";
+ i2c0: i2c@980000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x00980000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_i2c0_data_clk>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ spi0: spi@980000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x00980000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_spi0_data_clk>, <&qup_spi0_cs>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
uart1: serial@984000 {
compatible = "qcom,geni-debug-uart";
reg = <0x0 0x00984000 0x0 0x4000>;
@@ -475,6 +590,229 @@
"sleep";
status = "disabled";
};
+
+ i2c2: i2c@988000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x00988000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_i2c2_data_clk>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ spi2: spi@988000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x00988000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_spi2_data_clk>, <&qup_spi2_cs>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 2 QCOM_GPI_SPI>,
+ <&gpi_dma 1 2 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c3: i2c@98c000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x0098c000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_i2c3_data_clk>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ spi3: spi@98c000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x0098c000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_spi3_data_clk>, <&qup_spi3_cs>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 3 QCOM_GPI_SPI>,
+ <&gpi_dma 1 3 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart4: serial@990000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00990000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&qup_uart4_default>, <&qup_uart4_cts_rts>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ status = "disabled";
+ };
+
+ i2c5: i2c@994000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x00994000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_i2c5_data_clk>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c6: i2c@998000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x00998000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_i2c6_data_clk>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 6 QCOM_GPI_I2C>,
+ <&gpi_dma 1 6 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ spi6: spi@998000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x00998000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_spi6_data_clk>, <&qup_spi6_cs>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 6 QCOM_GPI_SPI>,
+ <&gpi_dma 1 6 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c7: i2c@99c000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x0099c000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_i2c7_data_clk>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 7 QCOM_GPI_I2C>,
+ <&gpi_dma 1 7 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ spi7: spi@99c000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x0099c000 0x0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&qup_spi7_data_clk>, <&qup_spi7_cs>;
+ pinctrl-names = "default";
+ 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
+ &system_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
+ <&system_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config", "qup-memory";
+ dmas = <&gpi_dma 0 7 QCOM_GPI_SPI>,
+ <&gpi_dma 1 7 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
};
usb_hsphy: phy@ff4000 {
@@ -538,6 +876,59 @@
#hwlock-cells = <1>;
};
+ tcsr: syscon@1fc0000 {
+ compatible = "qcom,sdx75-tcsr", "syscon";
+ reg = <0x0 0x01fc0000 0x0 0x30000>;
+ };
+
+ sdhc: mmc@8804000 {
+ compatible = "qcom,sdx75-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0x0 0x08804000 0x0 0x1000>;
+
+ interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq",
+ "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC1_AHB_CLK>,
+ <&gcc GCC_SDCC1_APPS_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface",
+ "core",
+ "xo";
+ iommus = <&apps_smmu 0x00a0 0x0>;
+ qcom,dll-config = <0x0007442c>;
+ qcom,ddr-config = <0x80040868>;
+ power-domains = <&rpmhpd RPMHPD_CX>;
+ operating-points-v2 = <&sdhc1_opp_table>;
+
+ interconnects = <&system_noc MASTER_SDCC_1 &mc_virt SLAVE_EBI1>,
+ <&gem_noc MASTER_APPSS_PROC &system_noc SLAVE_SDCC_1>;
+ interconnect-names = "sdhc-ddr",
+ "cpu-sdhc";
+ bus-width = <4>;
+ dma-coherent;
+
+ /* Forbid SDR104/SDR50 - broken hw! */
+ sdhci-caps-mask = <0x3 0>;
+
+ status = "disabled";
+
+ sdhc1_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
+
usb: usb@a6f8800 {
compatible = "qcom,sdx75-dwc3", "qcom,dwc3";
reg = <0x0 0x0a6f8800 0x0 0x400>;
@@ -627,6 +1018,17 @@
interrupt-controller;
};
+ aoss_qmp: power-controller@c310000 {
+ compatible = "qcom,sdx75-aoss-qmp", "qcom,aoss-qmp";
+ reg = <0 0x0c310000 0 0x1000>;
+ interrupt-parent = <&ipcc>;
+ interrupts-extended = <&ipcc IPCC_CLIENT_AOP IPCC_MPROC_SIGNAL_GLINK_QMP
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_AOP IPCC_MPROC_SIGNAL_GLINK_QMP>;
+
+ #clock-cells = <0>;
+ };
+
spmi_bus: spmi@c400000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0x0 0x0c400000 0x0 0x3000>,
@@ -661,6 +1063,145 @@
#interrupt-cells = <2>;
wakeup-parent = <&pdc>;
+ qup_i2c0_data_clk: qup-i2c0-data-clk-state {
+ /* SDA, SCL */
+ pins = "gpio8", "gpio9";
+ function = "qup_se0";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c2_data_clk: qup-i2c2-data-clk-state {
+ /* SDA, SCL */
+ pins = "gpio14", "gpio15";
+ function = "qup_se2";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c3_data_clk: qup-i2c3-data-clk-state {
+ /* SDA, SCL */
+ pins = "gpio52", "gpio53";
+ function = "qup_se3";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c5_data_clk: qup-i2c5-data-clk-state {
+ /* SDA, SCL */
+ pins = "gpio110", "gpio111";
+ function = "qup_se5";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c6_data_clk: qup-i2c6-data-clk-state {
+ /* SDA, SCL */
+ pins = "gpio112", "gpio113";
+ function = "qup_se6";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c7_data_clk: qup-i2c7-data-clk-state {
+ /* SDA, SCL */
+ pins = "gpio116", "gpio117";
+ function = "qup_se7";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_spi0_cs: qup-spi0-cs-state {
+ pins = "gpio11";
+ function = "qup_se0";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ qup_spi0_data_clk: qup-spi0-data-clk-state {
+ /* MISO, MOSI, CLK */
+ pins = "gpio8", "gpio9", "gpio10";
+ function = "qup_se0";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ qup_spi2_cs: qup-spi2-cs-state {
+ pins = "gpio17";
+ function = "qup_se2";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ qup_spi2_data_clk: qup-spi2-data-clk-state {
+ /* MISO, MOSI, CLK */
+ pins = "gpio14", "gpio15", "gpio16";
+ function = "qup_se2";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ qup_spi3_cs: qup-spi3-cs-state {
+ pins = "gpio55";
+ function = "qup_se3";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ qup_spi3_data_clk: qup-spi3-data-clk-state {
+ /* MISO, MOSI, CLK */
+ pins = "gpio52", "gpio53", "gpio54";
+ function = "qup_se3";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ qup_spi6_cs: qup-spi6-cs-state {
+ pins = "gpio115";
+ function = "qup_se6";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ qup_spi6_data_clk: qup-spi6-data-clk-state {
+ /* MISO, MOSI, CLK */
+ pins = "gpio112", "gpio113", "gpio114";
+ function = "qup_se6";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ qup_spi7_cs: qup-spi7-cs-state {
+ pins = "gpio119";
+ function = "qup_se7";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ qup_spi7_data_clk: qup-spi7-data-clk-state {
+ /* MISO, MOSI, CLK */
+ pins = "gpio116", "gpio117", "gpio118";
+ function = "qup_se7";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ qup_uart4_cts_rts: qup-uart4-cts-rts-state {
+ /* CTS, RTS */
+ pins = "gpio52", "gpio53";
+ function = "qup_se3";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ qup_uart4_default: qup-uart4-default-state {
+ /* TX, RX */
+ pins = "gpio54", "gpio55";
+ function = "qup_se3";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
qupv3_se1_2uart_active: qupv3-se1-2uart-active-state {
tx-pins {
pins = "gpio12";
@@ -683,6 +1224,46 @@
drive-strength = <2>;
bias-pull-down;
};
+
+ sdc1_default: sdc1-default-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+ };
+
+ sdc1_sleep: sdc1-sleep-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
};
apps_smmu: iommu@15000000 {
diff --git a/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts b/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts
index 2c7a12983dae..9153a5a55ed9 100644
--- a/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts
+++ b/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts
@@ -240,6 +240,7 @@
};
&usb_dwc3 {
+ /delete-property/ usb-role-switch;
maximum-speed = "high-speed";
dr_mode = "peripheral";
diff --git a/arch/arm64/boot/dts/qcom/sm4450.dtsi b/arch/arm64/boot/dts/qcom/sm4450.dtsi
index 603c962661cc..9c9919e78fbd 100644
--- a/arch/arm64/boot/dts/qcom/sm4450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm4450.dtsi
@@ -29,6 +29,14 @@
clock-frequency = <32000>;
#clock-cells = <0>;
};
+
+ bi_tcxo_div2: bi-tcxo-div2-clk {
+ #clock-cells = <0>;
+ compatible = "fixed-factor-clock";
+ clocks = <&rpmhcc RPMH_CXO_CLK>;
+ clock-mult = <1>;
+ clock-div = <2>;
+ };
};
cpus {
@@ -39,10 +47,12 @@
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>;
power-domain-names = "psci";
+ qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
L2_0: l2-cache {
@@ -63,10 +73,12 @@
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>;
power-domain-names = "psci";
+ qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
L2_100: l2-cache {
@@ -81,10 +93,12 @@
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>;
power-domain-names = "psci";
+ qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
L2_200: l2-cache {
@@ -99,10 +113,12 @@
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>;
power-domain-names = "psci";
+ qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
L2_300: l2-cache {
@@ -117,10 +133,12 @@
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>;
power-domain-names = "psci";
+ qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
L2_400: l2-cache {
@@ -135,10 +153,12 @@
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>;
power-domain-names = "psci";
+ qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
L2_500: l2-cache {
@@ -153,10 +173,12 @@
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>;
power-domain-names = "psci";
+ qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
L2_600: l2-cache {
@@ -171,10 +193,12 @@
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>;
power-domain-names = "psci";
+ qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
L2_700: l2-cache {
@@ -268,9 +292,14 @@
reg = <0x0 0xa0000000 0x0 0x0>;
};
- pmu {
- compatible = "arm,armv8-pmuv3";
- interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ 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>;
};
psci {
@@ -526,6 +555,19 @@
};
};
+ cpufreq_hw: cpufreq@17d91000 {
+ compatible = "qcom,sm4450-cpufreq-epss", "qcom,cpufreq-epss";
+ reg = <0 0x17d91000 0 0x1000>,
+ <0 0x17d92000 0 0x1000>;
+ reg-names = "freq-domain0", "freq-domain1";
+ clocks = <&bi_tcxo_div2>, <&gcc GCC_GPLL0>;
+ clock-names = "xo", "alternate";
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "dcvsh-irq-0", "dcvsh-irq-1";
+ #freq-domain-cells = <1>;
+ #clock-cells = <1>;
+ };
};
timer {
diff --git a/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts b/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts
index 98eb072fa912..4a30024aa48f 100644
--- a/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts
+++ b/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts
@@ -234,6 +234,7 @@
};
&usb_dwc3 {
+ /delete-property/ usb-role-switch;
maximum-speed = "high-speed";
dr_mode = "peripheral";
};
diff --git a/arch/arm64/boot/dts/qcom/sm6115.dtsi b/arch/arm64/boot/dts/qcom/sm6115.dtsi
index aca0a87092e4..e374733f3b85 100644
--- a/arch/arm64/boot/dts/qcom/sm6115.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6115.dtsi
@@ -1088,8 +1088,11 @@
<&gcc GCC_SDCC1_ICE_CORE_CLK>;
clock-names = "iface", "core", "xo", "ice";
+ resets = <&gcc GCC_SDCC1_BCR>;
+
power-domains = <&rpmpd SM6115_VDDCX>;
operating-points-v2 = <&sdhc1_opp_table>;
+ iommus = <&apps_smmu 0x00c0 0x0>;
interconnects = <&system_noc MASTER_SDCC_1 RPM_ALWAYS_TAG
&bimc SLAVE_EBI_CH0 RPM_ALWAYS_TAG>,
<&bimc MASTER_AMPSS_M0 RPM_ALWAYS_TAG
@@ -1230,6 +1233,8 @@
"ref_aux",
"qref";
+ power-domains = <&gcc GCC_UFS_PHY_GDSC>;
+
resets = <&ufs_mem_hc 0>;
reset-names = "ufsphy";
@@ -1655,6 +1660,7 @@
snps,has-lpm-erratum;
snps,hird-threshold = /bits/ 8 <0x10>;
snps,usb3_lpm_capable;
+ snps,parkmode-disable-ss-quirk;
usb-role-switch;
@@ -3011,8 +3017,6 @@
thermal-zones {
mapss-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 0>;
trips {
@@ -3031,8 +3035,6 @@
};
cdsp-hvx-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 1>;
trips {
@@ -3051,8 +3053,6 @@
};
wlan-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 2>;
trips {
@@ -3071,8 +3071,6 @@
};
camera-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 3>;
trips {
@@ -3091,8 +3089,6 @@
};
video-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 4>;
trips {
@@ -3111,8 +3107,6 @@
};
modem1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 5>;
trips {
@@ -3131,8 +3125,6 @@
};
cpu4-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 6>;
trips {
@@ -3157,8 +3149,6 @@
};
cpu5-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 7>;
trips {
@@ -3183,8 +3173,6 @@
};
cpu6-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 8>;
trips {
@@ -3209,8 +3197,6 @@
};
cpu7-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 9>;
trips {
@@ -3235,8 +3221,6 @@
};
cpu45-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 10>;
trips {
@@ -3261,8 +3245,6 @@
};
cpu67-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 11>;
trips {
@@ -3287,8 +3269,6 @@
};
cpu0123-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 12>;
trips {
@@ -3313,8 +3293,6 @@
};
modem0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 13>;
trips {
@@ -3333,8 +3311,6 @@
};
display-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 14>;
trips {
@@ -3353,8 +3329,8 @@
};
gpu-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ polling-delay-passive = <250>;
+
thermal-sensors = <&tsens0 15>;
cooling-maps {
@@ -3366,13 +3342,13 @@
trips {
gpu_alert0: trip-point0 {
- temperature = <115000>;
- hysteresis = <5000>;
+ temperature = <85000>;
+ hysteresis = <1000>;
type = "passive";
};
trip-point1 {
- temperature = <125000>;
+ temperature = <110000>;
hysteresis = <1000>;
type = "critical";
};
diff --git a/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts b/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts
index 54da053a8042..9d78bb3f7190 100644
--- a/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts
+++ b/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts
@@ -359,6 +359,7 @@
};
&usb_dwc3 {
+ /delete-property/ usb-role-switch;
maximum-speed = "high-speed";
dr_mode = "peripheral";
diff --git a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
index 08046f866f60..dcd05f303b78 100644
--- a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
+++ b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
@@ -90,8 +90,6 @@
thermal-zones {
rf-pa0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm6125_adc_tm 0>;
trips {
@@ -104,8 +102,6 @@
};
quiet-thermal {
- polling-delay-passive = <0>;
- polling-delay = <5000>;
thermal-sensors = <&pm6125_adc_tm 1>;
trips {
@@ -118,8 +114,6 @@
};
xo-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm6125_adc_tm 2>;
trips {
@@ -132,8 +126,6 @@
};
rf-pa1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm6125_adc_tm 3>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts
index a49d3ebb1931..994fb0412fcb 100644
--- a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts
+++ b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts
@@ -84,8 +84,6 @@
thermal-zones {
rf-pa0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm6125_adc_tm 0>;
trips {
@@ -98,8 +96,6 @@
};
quiet-thermal {
- polling-delay-passive = <0>;
- polling-delay = <5000>;
thermal-sensors = <&pm6125_adc_tm 1>;
trips {
@@ -112,8 +108,6 @@
};
xo-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm6125_adc_tm 2>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi
index 98ab08356088..777c380c2fa0 100644
--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi
@@ -1588,10 +1588,10 @@
timer {
compatible = "arm,armv8-timer";
- interrupts = <GIC_PPI 1 0xf08
- GIC_PPI 2 0xf08
- GIC_PPI 3 0xf08
- GIC_PPI 0 0xf08>;
+ interrupts = <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 0 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
clock-frequency = <19200000>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm6350-sony-xperia-lena-pdx213.dts b/arch/arm64/boot/dts/qcom/sm6350-sony-xperia-lena-pdx213.dts
index dddd6e44d280..bf23033a294e 100644
--- a/arch/arm64/boot/dts/qcom/sm6350-sony-xperia-lena-pdx213.dts
+++ b/arch/arm64/boot/dts/qcom/sm6350-sony-xperia-lena-pdx213.dts
@@ -293,7 +293,7 @@
compatible = "samsung,s6sy761";
reg = <0x48>;
interrupt-parent = <&tlmm>;
- interrupts = <22 0x2008>;
+ interrupts = <22 IRQ_TYPE_LEVEL_LOW>;
vdd-supply = <&pm6350_l11>;
avdd-supply = <&touch_en_vreg>;
@@ -375,6 +375,7 @@
};
&usb_1_dwc3 {
+ /delete-property/ usb-role-switch;
maximum-speed = "super-speed";
dr_mode = "peripheral";
};
diff --git a/arch/arm64/boot/dts/qcom/sm6350.dtsi b/arch/arm64/boot/dts/qcom/sm6350.dtsi
index 84ff20a96c83..7986ddb30f6e 100644
--- a/arch/arm64/boot/dts/qcom/sm6350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi
@@ -1197,6 +1197,8 @@
"ref_aux",
"qref";
+ power-domains = <&gcc UFS_PHY_GDSC>;
+
resets = <&ufs_mem_hc 0>;
reset-names = "ufsphy";
@@ -1321,6 +1323,7 @@
compatible = "qcom,fastrpc";
qcom,glink-channels = "fastrpcglink-apps-dsp";
label = "adsp";
+ qcom,non-secure-domain;
#address-cells = <1>;
#size-cells = <0>;
@@ -1580,6 +1583,7 @@
compatible = "qcom,fastrpc";
qcom,glink-channels = "fastrpcglink-apps-dsp";
label = "cdsp";
+ qcom,non-secure-domain;
#address-cells = <1>;
#size-cells = <0>;
@@ -1713,10 +1717,39 @@
<&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
reset-names = "phy", "common";
+ orientation-switch;
+
#clock-cells = <1>;
#phy-cells = <1>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_qmpphy_out: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_ss_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ usb_1_qmpphy_dp_in: endpoint {
+ };
+ };
+ };
};
dc_noc: interconnect@9160000 {
@@ -1890,8 +1923,30 @@
snps,dis_enblslpm_quirk;
snps,has-lpm-erratum;
snps,hird-threshold = /bits/ 8 <0x10>;
+ snps,parkmode-disable-ss-quirk;
phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
+ usb-role-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_dwc3_hs_out: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_dwc3_ss_out: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_usb_ss_in>;
+ };
+ };
+ };
};
};
@@ -2831,9 +2886,6 @@
thermal-zones {
aoss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 0>;
trips {
@@ -2846,9 +2898,6 @@
};
aoss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 0>;
trips {
@@ -2861,9 +2910,6 @@
};
audio-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 2>;
trips {
@@ -2876,9 +2922,6 @@
};
camera-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 5>;
trips {
@@ -2891,9 +2934,6 @@
};
cpu0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 1>;
trips {
@@ -2919,9 +2959,6 @@
};
cpu1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 2>;
trips {
@@ -2947,9 +2984,6 @@
};
cpu2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 3>;
trips {
@@ -2975,9 +3009,6 @@
};
cpu3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 4>;
trips {
@@ -3003,9 +3034,6 @@
};
cpu4-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 5>;
trips {
@@ -3031,9 +3059,6 @@
};
cpu5-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 6>;
trips {
@@ -3059,9 +3084,6 @@
};
cpu6-left-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 9>;
trips {
@@ -3087,9 +3109,6 @@
};
cpu6-right-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 10>;
trips {
@@ -3115,9 +3134,6 @@
};
cpu7-left-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 11>;
trips {
@@ -3143,9 +3159,6 @@
};
cpu7-right-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 12>;
trips {
@@ -3171,9 +3184,6 @@
};
cpuss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 7>;
trips {
@@ -3186,9 +3196,6 @@
};
cpuss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 8>;
trips {
@@ -3201,9 +3208,6 @@
};
cwlan-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 1>;
trips {
@@ -3216,9 +3220,6 @@
};
ddr-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 3>;
trips {
@@ -3231,21 +3232,20 @@
};
gpuss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ polling-delay-passive = <250>;
thermal-sensors = <&tsens0 13>;
trips {
gpuss0_alert0: trip-point0 {
- temperature = <95000>;
+ temperature = <85000>;
hysteresis = <2000>;
type = "passive";
};
gpuss0-crit {
- temperature = <115000>;
- hysteresis = <0>;
+ temperature = <110000>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -3259,21 +3259,20 @@
};
gpuss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
+ polling-delay-passive = <250>;
thermal-sensors = <&tsens0 14>;
trips {
gpuss1_alert0: trip-point0 {
- temperature = <95000>;
+ temperature = <85000>;
hysteresis = <2000>;
type = "passive";
};
gpuss1-crit {
- temperature = <115000>;
- hysteresis = <0>;
+ temperature = <110000>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -3287,9 +3286,6 @@
};
modem-core0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 6>;
trips {
@@ -3302,9 +3298,6 @@
};
modem-core1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 7>;
trips {
@@ -3317,9 +3310,6 @@
};
modem-scl-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 9>;
trips {
@@ -3332,9 +3322,6 @@
};
modem-vec-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 8>;
trips {
@@ -3347,9 +3334,6 @@
};
npu-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 10>;
trips {
@@ -3362,9 +3346,6 @@
};
q6-hvx-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 4>;
trips {
@@ -3377,9 +3358,6 @@
};
video-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 11>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sm6375-sony-xperia-murray-pdx225.dts b/arch/arm64/boot/dts/qcom/sm6375-sony-xperia-murray-pdx225.dts
index cca2c2eb88ad..e04a3b8f81c5 100644
--- a/arch/arm64/boot/dts/qcom/sm6375-sony-xperia-murray-pdx225.dts
+++ b/arch/arm64/boot/dts/qcom/sm6375-sony-xperia-murray-pdx225.dts
@@ -142,7 +142,7 @@
compatible = "samsung,s6sy761";
reg = <0x48>;
interrupt-parent = <&tlmm>;
- interrupts = <22 0x2008>;
+ interrupts = <22 IRQ_TYPE_LEVEL_LOW>;
vdd-supply = <&pm6125_l13>;
avdd-supply = <&touch_avdd>;
diff --git a/arch/arm64/boot/dts/qcom/sm6375.dtsi b/arch/arm64/boot/dts/qcom/sm6375.dtsi
index f40509d91bbd..ddea681b536d 100644
--- a/arch/arm64/boot/dts/qcom/sm6375.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6375.dtsi
@@ -1837,9 +1837,6 @@
thermal-zones {
mapss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 0>;
trips {
@@ -1864,9 +1861,6 @@
};
cpu0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 1>;
trips {
@@ -1891,9 +1885,6 @@
};
cpu1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 2>;
trips {
@@ -1918,9 +1909,6 @@
};
cpu2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 3>;
trips {
@@ -1945,9 +1933,6 @@
};
cpu3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 4>;
trips {
@@ -1972,9 +1957,6 @@
};
cpu4-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 5>;
trips {
@@ -1999,9 +1981,6 @@
};
cpu5-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 6>;
trips {
@@ -2026,9 +2005,6 @@
};
cluster0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 7>;
trips {
@@ -2053,9 +2029,6 @@
};
cluster1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 8>;
trips {
@@ -2080,9 +2053,6 @@
};
cpu6-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 9>;
trips {
@@ -2107,9 +2077,6 @@
};
cpu7-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 10>;
trips {
@@ -2134,9 +2101,6 @@
};
cpu-unk0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 11>;
trips {
@@ -2161,9 +2125,6 @@
};
cpu-unk1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 12>;
trips {
@@ -2188,9 +2149,6 @@
};
gpuss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 13>;
trips {
@@ -2215,9 +2173,6 @@
};
gpuss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens0 14>;
trips {
@@ -2242,9 +2197,6 @@
};
mapss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 0>;
trips {
@@ -2269,9 +2221,6 @@
};
cwlan-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 1>;
trips {
@@ -2296,9 +2245,6 @@
};
audio-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 2>;
trips {
@@ -2323,9 +2269,6 @@
};
ddr-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 3>;
trips {
@@ -2350,9 +2293,6 @@
};
q6hvx-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 4>;
trips {
@@ -2377,9 +2317,6 @@
};
camera-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 5>;
trips {
@@ -2404,9 +2341,6 @@
};
mdm-core0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 6>;
trips {
@@ -2431,9 +2365,6 @@
};
mdm-core1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 7>;
trips {
@@ -2458,9 +2389,6 @@
};
mdm-vec-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 8>;
trips {
@@ -2485,9 +2413,6 @@
};
msm-scl-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 9>;
trips {
@@ -2512,9 +2437,6 @@
};
video-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
-
thermal-sensors = <&tsens1 10>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts b/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts
index bc67e8c1fe4d..2ee2561b57b1 100644
--- a/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts
+++ b/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts
@@ -19,6 +19,7 @@
#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/usb/pd.h>
#include "sm7225.dtsi"
#include "pm6150l.dtsi"
#include "pm6350.dtsi"
@@ -92,10 +93,22 @@
};
};
+ msm_therm_sensor: thermal-sensor-msm {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&pm6150l_adc ADC5_AMUX_THM2_100K_PU>;
+ io-channel-names = "sensor-channel";
+ };
+
+ rear_cam_sensor: thermal-sensor-rear-cam {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&pm6150l_adc ADC5_GPIO2_100K_PU>;
+ io-channel-names = "sensor-channel";
+ };
+
thermal-zones {
chg-skin-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm7250b_adc_tm 0>;
trips {
@@ -108,8 +121,6 @@
};
conn-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm7250b_adc_tm 1>;
trips {
@@ -120,6 +131,119 @@
};
};
};
+
+ pa0-thermal {
+ thermal-sensors = <&pm6150l_adc_tm 1>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ pa1-thermal {
+ thermal-sensors = <&pm6150l_adc_tm 0>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ pm8008-thermal {
+ polling-delay-passive = <100>;
+ thermal-sensors = <&pm8008>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ quiet-thermal {
+ thermal-sensors = <&pm6150l_adc_tm 3>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ rear-cam-thermal {
+ polling-delay-passive = <1000>;
+ polling-delay = <5000>;
+ thermal-sensors = <&rear_cam_sensor>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ rfc-flash-thermal {
+ thermal-sensors = <&pm6150l_adc_tm 2>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ sdm-skin-thermal {
+ polling-delay-passive = <1000>;
+ polling-delay = <5000>;
+ thermal-sensors = <&msm_therm_sensor>;
+
+ trips {
+ trip0 {
+ temperature = <45000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <55000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ xo-thermal {
+ thermal-sensors = <&pmk8350_adc_tm 0>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
};
};
@@ -134,124 +258,145 @@
qcom,pmic-id = "a";
vreg_s1a: smps1 {
+ regulator-name = "vreg_s1a";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1200000>;
};
vreg_s2a: smps2 {
+ regulator-name = "vreg_s2a";
regulator-min-microvolt = <1503000>;
regulator-max-microvolt = <2048000>;
};
vreg_l2a: ldo2 {
+ regulator-name = "vreg_l2a";
regulator-min-microvolt = <1503000>;
regulator-max-microvolt = <1980000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l3a: ldo3 {
+ regulator-name = "vreg_l3a";
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <3300000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l4a: ldo4 {
+ regulator-name = "vreg_l4a";
regulator-min-microvolt = <352000>;
regulator-max-microvolt = <801000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l5a: ldo5 {
+ regulator-name = "vreg_l5a";
regulator-min-microvolt = <1503000>;
regulator-max-microvolt = <1980000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l6a: ldo6 {
+ regulator-name = "vreg_l6a";
regulator-min-microvolt = <1710000>;
regulator-max-microvolt = <3544000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l7a: ldo7 {
+ regulator-name = "vreg_l7a";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <1980000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l8a: ldo8 {
+ regulator-name = "vreg_l8a";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l9a: ldo9 {
+ regulator-name = "vreg_l9a";
regulator-min-microvolt = <1650000>;
regulator-max-microvolt = <3401000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l11a: ldo11 {
+ regulator-name = "vreg_l11a";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <2000000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l12a: ldo12 {
+ regulator-name = "vreg_l12a";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <1980000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l13a: ldo13 {
+ regulator-name = "vreg_l13a";
regulator-min-microvolt = <570000>;
regulator-max-microvolt = <650000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l14a: ldo14 {
+ regulator-name = "vreg_l14a";
regulator-min-microvolt = <1700000>;
regulator-max-microvolt = <1900000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l15a: ldo15 {
+ regulator-name = "vreg_l15a";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1305000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l16a: ldo16 {
+ regulator-name = "vreg_l16a";
regulator-min-microvolt = <830000>;
regulator-max-microvolt = <921000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l18a: ldo18 {
+ regulator-name = "vreg_l18a";
regulator-min-microvolt = <788000>;
regulator-max-microvolt = <1049000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l19a: ldo19 {
+ regulator-name = "vreg_l19a";
regulator-min-microvolt = <1080000>;
regulator-max-microvolt = <1305000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l20a: ldo20 {
+ regulator-name = "vreg_l20a";
regulator-min-microvolt = <530000>;
regulator-max-microvolt = <801000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l21a: ldo21 {
+ regulator-name = "vreg_l21a";
regulator-min-microvolt = <751000>;
regulator-max-microvolt = <825000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l22a: ldo22 {
+ regulator-name = "vreg_l22a";
regulator-min-microvolt = <1080000>;
regulator-max-microvolt = <1305000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
@@ -263,41 +408,48 @@
qcom,pmic-id = "e";
vreg_s8e: smps8 {
+ regulator-name = "vreg_s8e";
regulator-min-microvolt = <313000>;
regulator-max-microvolt = <1395000>;
};
vreg_l1e: ldo1 {
+ regulator-name = "vreg_l1e";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <1980000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l2e: ldo2 {
+ regulator-name = "vreg_l2e";
regulator-min-microvolt = <1170000>;
regulator-max-microvolt = <1305000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l3e: ldo3 {
+ regulator-name = "vreg_l3e";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1299000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l4e: ldo4 {
+ regulator-name = "vreg_l4e";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <3300000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l5e: ldo5 {
+ regulator-name = "vreg_l5e";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <3300000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l6e: ldo6 {
+ regulator-name = "vreg_l6e";
regulator-min-microvolt = <1700000>;
regulator-max-microvolt = <2950000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
@@ -307,18 +459,21 @@
};
vreg_l7e: ldo7 {
+ regulator-name = "vreg_l7e";
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <3544000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l8e: ldo8 {
+ regulator-name = "vreg_l8e";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <2000000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l9e: ldo9 {
+ regulator-name = "vreg_l9e";
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <2960000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
@@ -328,18 +483,21 @@
};
vreg_l10e: ldo10 {
+ regulator-name = "vreg_l10e";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3401000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_l11e: ldo11 {
+ regulator-name = "vreg_l11e";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3401000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
vreg_bob: bob {
+ regulator-name = "vreg_bob";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <5492000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
@@ -407,7 +565,79 @@
};
&i2c10 {
- /* PM8008 PMIC @ 8 and 9 */
+ clock-frequency = <400000>;
+ status = "okay";
+
+ pm8008: pmic@8 {
+ compatible = "qcom,pm8008";
+ reg = <0x8>;
+
+ interrupts-extended = <&tlmm 59 IRQ_TYPE_EDGE_RISING>;
+ reset-gpios = <&tlmm 58 GPIO_ACTIVE_LOW>;
+
+ vdd-l1-l2-supply = <&vreg_s8e>;
+ vdd-l3-l4-supply = <&vreg_bob>;
+ vdd-l5-supply = <&vreg_bob>;
+ vdd-l6-supply = <&vreg_s2a>;
+ vdd-l7-supply = <&vreg_bob>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pm8008_default>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pm8008 0 0 2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ #thermal-sensor-cells = <0>;
+
+ regulators {
+ vreg_l1p: ldo1 {
+ regulator-name = "vreg_l1p";
+ regulator-min-microvolt = <528000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l2p: ldo2 {
+ regulator-name = "vreg_l2p";
+ regulator-min-microvolt = <528000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l3p: ldo3 {
+ regulator-name = "vreg_l3p";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ vreg_l4p: ldo4 {
+ regulator-name = "vreg_l4p";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2904000>;
+ };
+
+ vreg_l5p: ldo5 {
+ regulator-name = "vreg_l5p";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ vreg_l6p: ldo6 {
+ regulator-name = "vreg_l6p";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l7p: ldo7 {
+ regulator-name = "vreg_l7p";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <3140000>;
+ };
+ };
+ };
+
/* PX8618 @ 26 */
/* SMB1395 PMIC @ 34 */
/* awinic,aw8695 @ 5a */
@@ -462,6 +692,91 @@
status = "okay";
};
+&pm6150l_adc {
+ pinctrl-0 = <&pm6150l_adc_default>;
+ pinctrl-names = "default";
+
+ channel@4d {
+ reg = <ADC5_AMUX_THM1_100K_PU>;
+ label = "pa_therm1";
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ };
+
+ channel@4e {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ label = "msm_therm";
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ };
+
+ channel@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ label = "pa_therm0";
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ };
+
+ channel@53 {
+ reg = <ADC5_GPIO2_100K_PU>;
+ label = "rear_cam_therm";
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ };
+
+ channel@54 {
+ reg = <ADC5_GPIO3_100K_PU>;
+ label = "rear_cam_flash_therm";
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ };
+
+ channel@55 {
+ reg = <ADC5_GPIO4_100K_PU>;
+ label = "quiet_therm";
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ };
+};
+
+&pm6150l_adc_tm {
+ status = "okay";
+
+ pa-therm1@0 {
+ reg = <0>;
+ io-channels = <&pm6150l_adc ADC5_AMUX_THM1_100K_PU>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,ratiometric;
+ };
+
+ pa-therm0@1 {
+ reg = <1>;
+ io-channels = <&pm6150l_adc ADC5_AMUX_THM3_100K_PU>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,ratiometric;
+ };
+
+ rear-cam-flash-therm@2 {
+ reg = <2>;
+ io-channels = <&pm6150l_adc ADC5_GPIO3_100K_PU>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,ratiometric;
+ };
+
+ quiet-therm@3 {
+ reg = <3>;
+ io-channels = <&pm6150l_adc ADC5_GPIO4_100K_PU>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,ratiometric;
+ };
+};
+
&pm6150l_flash {
status = "okay";
@@ -484,6 +799,14 @@
};
};
+&pm6150l_gpios {
+ pm6150l_adc_default: adc-default-state {
+ pins = "gpio6", "gpio7", "gpio10";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ bias-high-impedance;
+ };
+};
+
&pm6150l_wled {
qcom,switching-freq = <800>;
qcom,current-limit-microamp = <20000>;
@@ -543,6 +866,64 @@
};
};
+&pm7250b_typec {
+ vdd-pdphy-supply = <&vreg_l3a>;
+
+ status = "okay";
+
+ connector {
+ compatible = "usb-c-connector";
+
+ power-role = "dual";
+ data-role = "dual";
+ self-powered;
+
+ /*
+ * Disable USB Power Delivery for now, seems to need extra work
+ * to support role switching while also letting the battery
+ * charge still - without charger driver
+ */
+ typec-power-opmode = "default";
+ pd-disable;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ pm7250b_hs_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_hs_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ pm7250b_ss_in: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_out>;
+ };
+ };
+ };
+ };
+};
+
+&pm7250b_vbus {
+ regulator-min-microamp = <500000>;
+ regulator-max-microamp = <1500000>;
+ status = "okay";
+};
+
+&pmk8350_adc_tm {
+ status = "okay";
+
+ xo-therm@0 {
+ reg = <0>;
+ io-channels = <&pmk8350_vadc PMK8350_ADC7_AMUX_THM1_100K_PU>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,ratiometric;
+ };
+};
+
&pmk8350_rtc {
status = "okay";
};
@@ -673,6 +1054,22 @@
*/
bias-pull-up;
};
+
+ pm8008_default: pm8008-default-state {
+ int-pins {
+ pins = "gpio59";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ reset-n-pins {
+ pins = "gpio58";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
};
&uart1 {
@@ -726,7 +1123,11 @@
&usb_1_dwc3 {
maximum-speed = "super-speed";
- dr_mode = "peripheral";
+ dr_mode = "otg";
+};
+
+&usb_1_dwc3_hs_out {
+ remote-endpoint = <&pm7250b_hs_in>;
};
&usb_1_hsphy {
@@ -744,6 +1145,10 @@
status = "okay";
};
+&usb_1_qmpphy_out {
+ remote-endpoint = <&pm7250b_ss_in>;
+};
+
&wifi {
vdd-0.8-cx-mx-supply = <&vreg_l4a>;
vdd-1.8-xo-supply = <&vreg_l7a>;
diff --git a/arch/arm64/boot/dts/qcom/sm8150-hdk.dts b/arch/arm64/boot/dts/qcom/sm8150-hdk.dts
index 6cb6f503fdac..bac08f00b303 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8150-hdk.dts
@@ -470,7 +470,6 @@
&mdss_dp_out {
data-lanes = <0 1>;
- remote-endpoint = <&usb_1_qmpphy_dp_in>;
};
&mdss_dsi0 {
@@ -556,7 +555,7 @@
port@0 {
reg = <0>;
- pm8150b_role_switch_in: endpoint {
+ pm8150b_hs_in: endpoint {
remote-endpoint = <&usb_1_dwc3_hs>;
};
};
@@ -676,18 +675,10 @@
orientation-switch;
};
-&usb_1_qmpphy_dp_in {
- remote-endpoint = <&mdss_dp_out>;
-};
-
&usb_1_qmpphy_out {
remote-endpoint = <&pm8150b_typec_mux_in>;
};
-&usb_1_qmpphy_usb_ss_in {
- remote-endpoint = <&usb_1_dwc3_ss>;
-};
-
&usb_2_qmpphy {
status = "okay";
vdda-phy-supply = <&vreg_l3c_1p2>;
@@ -708,11 +699,7 @@
};
&usb_1_dwc3_hs {
- remote-endpoint = <&pm8150b_role_switch_in>;
-};
-
-&usb_1_dwc3_ss {
- remote-endpoint = <&usb_1_qmpphy_usb_ss_in>;
+ remote-endpoint = <&pm8150b_hs_in>;
};
&usb_2_dwc3 {
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index ff22e4346660..3e236adb9397 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -14,6 +14,7 @@
#include <dt-bindings/clock/qcom,dispcc-sm8150.h>
#include <dt-bindings/clock/qcom,gcc-sm8150.h>
#include <dt-bindings/clock/qcom,gpucc-sm8150.h>
+#include <dt-bindings/clock/qcom,videocc-sm8150.h>
#include <dt-bindings/interconnect/qcom,osm-l3.h>
#include <dt-bindings/interconnect/qcom,sm8150.h>
#include <dt-bindings/thermal/thermal.h>
@@ -3507,6 +3508,7 @@
reg = <1>;
usb_1_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_ss>;
};
};
@@ -3514,6 +3516,7 @@
reg = <2>;
usb_1_qmpphy_dp_in: endpoint {
+ remote-endpoint = <&mdss_dp_out>;
};
};
};
@@ -3672,6 +3675,7 @@
reg = <1>;
usb_1_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_usb_ss_in>;
};
};
};
@@ -3735,6 +3739,19 @@
};
};
+ videocc: clock-controller@ab00000 {
+ compatible = "qcom,sm8150-videocc";
+ reg = <0 0x0ab00000 0 0x10000>;
+ clocks = <&gcc GCC_VIDEO_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "bi_tcxo";
+ power-domains = <&rpmhpd SM8150_MMCX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
camnoc_virt: interconnect@ac00000 {
compatible = "qcom,sm8150-camnoc-virt";
reg = <0 0x0ac00000 0 0x1000>;
@@ -3894,6 +3911,7 @@
reg = <1>;
mdss_dp_out: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_dp_in>;
};
};
};
@@ -4577,7 +4595,6 @@
thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 1>;
@@ -4621,7 +4638,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 2>;
@@ -4665,7 +4681,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 3>;
@@ -4709,7 +4724,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 4>;
@@ -4753,7 +4767,6 @@
cpu4-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 7>;
@@ -4797,7 +4810,6 @@
cpu5-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 8>;
@@ -4841,7 +4853,6 @@
cpu6-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 9>;
@@ -4885,7 +4896,6 @@
cpu7-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 10>;
@@ -4929,7 +4939,6 @@
cpu4-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 11>;
@@ -4973,7 +4982,6 @@
cpu5-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 12>;
@@ -5017,7 +5025,6 @@
cpu6-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 13>;
@@ -5061,7 +5068,6 @@
cpu7-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 14>;
@@ -5105,7 +5111,6 @@
aoss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 0>;
@@ -5120,7 +5125,6 @@
cluster0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 5>;
@@ -5140,7 +5144,6 @@
cluster1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 6>;
@@ -5160,7 +5163,6 @@
gpu-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 15>;
@@ -5173,16 +5175,27 @@
trips {
gpu_top_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
aoss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 0>;
@@ -5197,7 +5210,6 @@
wlan-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 1>;
@@ -5212,7 +5224,6 @@
video-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 2>;
@@ -5227,7 +5238,6 @@
mem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 3>;
@@ -5242,7 +5252,6 @@
q6-hvx-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 4>;
@@ -5257,7 +5266,6 @@
camera-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 5>;
@@ -5272,7 +5280,6 @@
compute-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 6>;
@@ -5287,7 +5294,6 @@
modem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 7>;
@@ -5302,7 +5308,6 @@
npu-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 8>;
@@ -5317,7 +5322,6 @@
modem-vec-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 9>;
@@ -5332,7 +5336,6 @@
modem-scl-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 10>;
@@ -5347,7 +5350,6 @@
gpu-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 11>;
@@ -5360,10 +5362,22 @@
trips {
gpu_bottom_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
index 7ef99038cb37..21b2ca1def83 100644
--- a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
@@ -53,8 +53,6 @@
thermal-zones {
camera-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150l_adc_tm 0>;
trips {
@@ -67,8 +65,6 @@
};
conn-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150b_adc_tm 0>;
trips {
@@ -81,8 +77,6 @@
};
mmw-pa1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150_adc_tm 2>;
trips {
@@ -95,8 +89,6 @@
};
mmw-pa2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150l_adc_tm 2>;
trips {
@@ -109,8 +101,6 @@
};
skin-msm-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150l_adc_tm 1>;
trips {
@@ -123,8 +113,6 @@
};
skin-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150_adc_tm 1>;
trips {
@@ -137,8 +125,6 @@
};
xo-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pm8150_adc_tm 0>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
index e07d0311ecb5..f6870d3f2886 100644
--- a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
@@ -520,7 +520,7 @@
compatible = "samsung,s6sy761";
reg = <0x48>;
interrupt-parent = <&tlmm>;
- interrupts = <39 0x2008>;
+ interrupts = <39 IRQ_TYPE_LEVEL_LOW>;
/* It's "vddio" downstream but it works anyway! */
vdd-supply = <&vreg_l1c_1p8>;
avdd-supply = <&vreg_l10c_3p3>;
diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi
index 41f117474872..3596dd328c31 100644
--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi
@@ -659,8 +659,8 @@
port@0 {
reg = <0>;
- pm8150b_role_switch_in: endpoint {
- remote-endpoint = <&usb_1_role_switch_out>;
+ pm8150b_hs_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_hs_out>;
};
};
};
@@ -725,8 +725,8 @@
status = "okay";
};
-&usb_1_role_switch_out {
- remote-endpoint = <&pm8150b_role_switch_in>;
+&usb_1_dwc3_hs_out {
+ remote-endpoint = <&pm8150b_hs_in>;
};
&ufs_mem_hc {
diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index 8ccade628f1f..9d6c97d1fd9d 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -2204,7 +2204,7 @@
status = "disabled";
- pcie@0 {
+ pcieport0: pcie@0 {
device_type = "pci";
reg = <0x0 0x0 0x0 0x0 0x0>;
bus-range = <0x01 0xff>;
@@ -2580,6 +2580,8 @@
resets = <&ufs_mem_hc 0>;
reset-names = "ufsphy";
+ power-domains = <&gcc UFS_PHY_GDSC>;
+
#phy-cells = <0>;
status = "disabled";
@@ -3936,6 +3938,8 @@
#clock-cells = <1>;
#phy-cells = <1>;
+ orientation-switch;
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -3947,6 +3951,10 @@
port@1 {
reg = <1>;
+
+ usb_1_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_ss_out>;
+ };
};
port@2 {
@@ -4225,8 +4233,24 @@
phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
phy-names = "usb2-phy", "usb3-phy";
- port {
- usb_1_role_switch_out: endpoint {};
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_dwc3_hs_out: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_dwc3_ss_out: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_usb_ss_in>;
+ };
+ };
};
};
};
@@ -6275,7 +6299,6 @@
thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 1>;
@@ -6319,7 +6342,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 2>;
@@ -6363,7 +6385,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 3>;
@@ -6407,7 +6428,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 4>;
@@ -6451,7 +6471,6 @@
cpu4-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 7>;
@@ -6495,7 +6514,6 @@
cpu5-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 8>;
@@ -6539,7 +6557,6 @@
cpu6-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 9>;
@@ -6583,7 +6600,6 @@
cpu7-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 10>;
@@ -6627,7 +6643,6 @@
cpu4-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 11>;
@@ -6671,7 +6686,6 @@
cpu5-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 12>;
@@ -6715,7 +6729,6 @@
cpu6-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 13>;
@@ -6759,7 +6772,6 @@
cpu7-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 14>;
@@ -6803,7 +6815,6 @@
aoss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 0>;
@@ -6818,7 +6829,6 @@
cluster0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 5>;
@@ -6838,7 +6848,6 @@
cluster1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 6>;
@@ -6858,7 +6867,6 @@
gpu-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 15>;
@@ -6871,16 +6879,27 @@
trips {
gpu_top_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
aoss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 0>;
@@ -6895,7 +6914,6 @@
wlan-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 1>;
@@ -6910,7 +6928,6 @@
video-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 2>;
@@ -6925,7 +6942,6 @@
mem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 3>;
@@ -6940,7 +6956,6 @@
q6-hvx-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 4>;
@@ -6955,7 +6970,6 @@
camera-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 5>;
@@ -6970,7 +6984,6 @@
compute-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 6>;
@@ -6985,7 +6998,6 @@
npu-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 7>;
@@ -7000,7 +7012,6 @@
gpu-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 8>;
@@ -7013,10 +7024,22 @@
trips {
gpu_bottom_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
index 4c25ab2f5670..895adce59e75 100644
--- a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
@@ -486,17 +486,10 @@
&mdss_dp {
status = "okay";
+};
- ports {
- port@1 {
- reg = <1>;
-
- mdss_dp0_out: endpoint {
- data-lanes = <0 1>;
- remote-endpoint = <&usb_1_qmpphy_dp_in>;
- };
- };
- };
+&mdss_dp_out {
+ data-lanes = <0 1>;
};
&mpss {
@@ -864,10 +857,6 @@
remote-endpoint = <&pmic_glink_hs_in>;
};
-&usb_1_dwc3_ss {
- remote-endpoint = <&usb_1_qmpphy_usb_ss_in>;
-};
-
&usb_1_hsphy {
status = "okay";
@@ -881,22 +870,12 @@
vdda-phy-supply = <&vreg_l6b_1p2>;
vdda-pll-supply = <&vreg_l1b_0p88>;
-
- orientation-switch;
-};
-
-&usb_1_qmpphy_dp_in {
- remote-endpoint = <&mdss_dp0_out>;
};
&usb_1_qmpphy_out {
remote-endpoint = <&pmic_glink_ss_in>;
};
-&usb_1_qmpphy_usb_ss_in {
- remote-endpoint = <&usb_1_dwc3_ss>;
-};
-
&usb_2 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi
index f7c4700f00c3..38ee0850c335 100644
--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi
@@ -301,8 +301,18 @@
reg = <0x0 0x80000000 0x0 0x0>;
};
- 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>;
+ };
+
+ pmu-x1 {
+ compatible = "arm,cortex-x1-pmu";
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
};
@@ -1779,6 +1789,8 @@
"ref_aux",
"qref";
+ power-domains = <&gcc UFS_PHY_GDSC>;
+
resets = <&ufs_mem_hc 0>;
reset-names = "ufsphy";
@@ -2256,6 +2268,8 @@
#clock-cells = <1>;
#phy-cells = <1>;
+ orientation-switch;
+
status = "disabled";
ports {
@@ -2273,6 +2287,7 @@
reg = <1>;
usb_1_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_ss>;
};
};
@@ -2280,6 +2295,7 @@
reg = <2>;
usb_1_qmpphy_dp_in: endpoint {
+ remote-endpoint = <&mdss_dp_out>;
};
};
};
@@ -2405,6 +2421,7 @@
reg = <1>;
usb_1_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_usb_ss_in>;
};
};
};
@@ -2626,6 +2643,14 @@
remote-endpoint = <&dpu_intf0_out>;
};
};
+
+ port@1 {
+ reg = <1>;
+
+ mdss_dp_out: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_dp_in>;
+ };
+ };
};
dp_opp_table: opp-table {
@@ -3665,7 +3690,6 @@
thermal_zones: thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 1>;
@@ -3709,7 +3733,6 @@
cpu1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 2>;
@@ -3753,7 +3776,6 @@
cpu2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 3>;
@@ -3797,7 +3819,6 @@
cpu3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 4>;
@@ -3841,7 +3862,6 @@
cpu4-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 7>;
@@ -3885,7 +3905,6 @@
cpu5-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 8>;
@@ -3929,7 +3948,6 @@
cpu6-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 9>;
@@ -3973,7 +3991,6 @@
cpu7-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 10>;
@@ -4017,7 +4034,6 @@
cpu4-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 11>;
@@ -4061,7 +4077,6 @@
cpu5-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 12>;
@@ -4105,7 +4120,6 @@
cpu6-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 13>;
@@ -4149,7 +4163,6 @@
cpu7-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 14>;
@@ -4193,7 +4206,6 @@
aoss0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 0>;
@@ -4208,7 +4220,6 @@
cluster0-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 5>;
@@ -4228,7 +4239,6 @@
cluster1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens0 6>;
@@ -4248,7 +4258,6 @@
aoss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 0>;
@@ -4263,7 +4272,6 @@
gpu-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 1>;
@@ -4276,16 +4284,27 @@
trips {
gpu_top_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
gpu-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 2>;
@@ -4298,16 +4317,27 @@
trips {
gpu_bottom_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
hysteresis = <1000>;
type = "hot";
};
+
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
};
};
nspss1-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 3>;
@@ -4322,7 +4352,6 @@
nspss2-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 4>;
@@ -4337,7 +4366,6 @@
nspss3-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 5>;
@@ -4352,7 +4380,6 @@
video-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 6>;
@@ -4367,7 +4394,6 @@
mem-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 7>;
@@ -4382,7 +4408,6 @@
modem1-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 8>;
@@ -4397,7 +4422,6 @@
modem2-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 9>;
@@ -4412,7 +4436,6 @@
modem3-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 10>;
@@ -4427,7 +4450,6 @@
modem4-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 11>;
@@ -4442,7 +4464,6 @@
camera-top-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 12>;
@@ -4457,7 +4478,6 @@
cam-bottom-thermal {
polling-delay-passive = <250>;
- polling-delay = <1000>;
thermal-sensors = <&tsens1 13>;
diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
index 3be46b56c723..a754b8fe9167 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
@@ -138,7 +138,7 @@
thermal-zones {
camera-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 2>;
trips {
@@ -152,7 +152,7 @@
rear-tof-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 5>;
trips {
@@ -166,7 +166,7 @@
skin-msm-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 1>;
trips {
@@ -180,7 +180,7 @@
therm1-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 3>;
trips {
@@ -194,7 +194,7 @@
therm2-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 6>;
trips {
@@ -208,7 +208,7 @@
usb-conn-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 7>;
trips {
@@ -222,7 +222,7 @@
wide-rfc-thermal {
polling-delay-passive = <250>;
- polling-delay = <0>;
+
thermal-sensors = <&pmk8350_adc_tm 4>;
trips {
@@ -235,8 +235,6 @@
};
xo-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&pmk8350_adc_tm 0>;
trips {
@@ -674,17 +672,10 @@
&mdss_dp0 {
status = "okay";
+};
- ports {
- port@1 {
- reg = <1>;
-
- mdss_dp0_out: endpoint {
- data-lanes = <0 1>;
- remote-endpoint = <&usb_1_qmpphy_dp_in>;
- };
- };
- };
+&mdss_dp0_out {
+ data-lanes = <0 1>;
};
&pcie0 {
@@ -1114,10 +1105,6 @@
remote-endpoint = <&pmic_glink_hs_in>;
};
-&usb_1_dwc3_ss {
- remote-endpoint = <&usb_1_qmpphy_usb_ss_in>;
-};
-
&usb_1_hsphy {
status = "okay";
@@ -1131,22 +1118,12 @@
vdda-phy-supply = <&vreg_l6b_1p2>;
vdda-pll-supply = <&vreg_l1b_0p91>;
-
- orientation-switch;
-};
-
-&usb_1_qmpphy_dp_in {
- remote-endpoint = <&mdss_dp0_out>;
};
&usb_1_qmpphy_out {
remote-endpoint = <&pmic_glink_ss_in>;
};
-&usb_1_qmpphy_usb_ss_in {
- remote-endpoint = <&usb_1_dwc3_ss>;
-};
-
&vamacro {
pinctrl-0 = <&dmic01_default>, <&dmic23_default>;
pinctrl-names = "default";
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 8b29fcf483a3..17dbb67868ae 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi
@@ -488,7 +488,7 @@
compatible = "samsung,s6sy761";
reg = <0x48>;
interrupt-parent = <&tlmm>;
- interrupts = <21 0x2008>;
+ interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
vdd-supply = <&pm8350c_l2>;
avdd-supply = <&pm8350c_l3>;
diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
index 616461fcbab9..9bafb3b350ff 100644
--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
@@ -754,8 +754,8 @@
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&sleep_clk>,
<&pcie0_phy>,
- <&pcie1_phy>,
- <0>,
+ <&pcie1_phy QMP_PCIE_PIPE_CLK>,
+ <&pcie1_phy QMP_PCIE_PHY_AUX_CLK>,
<&ufs_mem_phy 0>,
<&ufs_mem_phy 1>,
<&ufs_mem_phy 2>,
@@ -1803,6 +1803,12 @@
<0 0 0 3 &intc 0 0 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
<0 0 0 4 &intc 0 0 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+ interconnects = <&pcie_noc MASTER_PCIE_0 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_PCIE_0 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "pcie-mem", "cpu-pcie";
+
clocks = <&gcc GCC_PCIE_0_PIPE_CLK>,
<&gcc GCC_PCIE_0_PIPE_CLK_SRC>,
<&pcie0_phy>,
@@ -1845,8 +1851,35 @@
pinctrl-names = "default";
pinctrl-0 = <&pcie0_default_state>;
+ operating-points-v2 = <&pcie0_opp_table>;
+
status = "disabled";
+ pcie0_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ /* GEN 1 x1 */
+ opp-2500000 {
+ opp-hz = /bits/ 64 <2500000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <250000 1>;
+ };
+
+ /* GEN 2 x1 */
+ opp-5000000 {
+ opp-hz = /bits/ 64 <5000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <500000 1>;
+ };
+
+ /* GEN 3 x1 */
+ opp-8000000 {
+ opp-hz = /bits/ 64 <8000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ opp-peak-kBps = <984500 1>;
+ };
+ };
+
pcie@0 {
device_type = "pci";
reg = <0x0 0x0 0x0 0x0 0x0>;
@@ -1932,6 +1965,12 @@
<0 0 0 3 &intc 0 0 0 438 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
<0 0 0 4 &intc 0 0 0 439 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+ interconnects = <&pcie_noc MASTER_PCIE_1 QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_PCIE_1 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "pcie-mem", "cpu-pcie";
+
clocks = <&gcc GCC_PCIE_1_PIPE_CLK>,
<&gcc GCC_PCIE_1_PIPE_CLK_SRC>,
<&pcie1_phy>,
@@ -1972,8 +2011,56 @@
pinctrl-names = "default";
pinctrl-0 = <&pcie1_default_state>;
+ operating-points-v2 = <&pcie1_opp_table>;
+
status = "disabled";
+ pcie1_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ /* GEN 1 x1 */
+ opp-2500000 {
+ opp-hz = /bits/ 64 <2500000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <250000 1>;
+ };
+
+ /* GEN 1 x2 and GEN 2 x1 */
+ opp-5000000 {
+ opp-hz = /bits/ 64 <5000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <500000 1>;
+ };
+
+ /* GEN 2 x2 */
+ opp-10000000 {
+ opp-hz = /bits/ 64 <10000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <1000000 1>;
+ };
+
+ /* GEN 3 x1 */
+ opp-8000000 {
+ opp-hz = /bits/ 64 <8000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ opp-peak-kBps = <984500 1>;
+ };
+
+ /* GEN 3 x2 and GEN 4 x1 */
+ opp-16000000 {
+ opp-hz = /bits/ 64 <16000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ opp-peak-kBps = <1969000 1>;
+ };
+
+ /* GEN 4 x2 */
+ opp-32000000 {
+ opp-hz = /bits/ 64 <32000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ opp-peak-kBps = <3938000 1>;
+ };
+ };
+
pcie@0 {
device_type = "pci";
reg = <0x0 0x0 0x0 0x0 0x0>;
@@ -2001,7 +2088,7 @@
"pipe";
clock-output-names = "pcie_1_pipe_clk";
- #clock-cells = <0>;
+ #clock-cells = <1>;
#phy-cells = <0>;
@@ -2304,6 +2391,8 @@
#clock-cells = <1>;
#phy-cells = <1>;
+ orientation-switch;
+
status = "disabled";
ports {
@@ -2321,6 +2410,7 @@
reg = <1>;
usb_1_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_ss>;
};
};
@@ -2328,6 +2418,7 @@
reg = <2>;
usb_1_qmpphy_dp_in: endpoint {
+ remote-endpoint = <&mdss_dp0_out>;
};
};
};
@@ -3119,6 +3210,14 @@
remote-endpoint = <&dpu_intf0_out>;
};
};
+
+ port@1 {
+ reg = <1>;
+
+ mdss_dp0_out: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_dp_in>;
+ };
+ };
};
dp_opp_table: opp-table {
@@ -4362,9 +4461,10 @@
compatible = "qcom,sm8450-llcc";
reg = <0 0x19200000 0 0x80000>, <0 0x19600000 0 0x80000>,
<0 0x19300000 0 0x80000>, <0 0x19700000 0 0x80000>,
- <0 0x19a00000 0 0x80000>;
+ <0 0x19a00000 0 0x80000>, <0 0x19c00000 0 0x80000>;
reg-names = "llcc0_base", "llcc1_base", "llcc2_base",
- "llcc3_base", "llcc_broadcast_base";
+ "llcc3_base", "llcc_broadcast_base",
+ "llcc_broadcast_and_base";
interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
};
@@ -4429,6 +4529,8 @@
<&gcc GCC_UFS_PHY_PHY_AUX_CLK>,
<&gcc GCC_UFS_0_CLKREF_EN>;
+ power-domains = <&gcc UFS_PHY_GDSC>;
+
resets = <&ufs_mem_hc 0>;
reset-names = "ufsphy";
@@ -4584,6 +4686,7 @@
reg = <1>;
usb_1_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_usb_ss_in>;
};
};
};
@@ -4610,8 +4713,6 @@
thermal-zones {
aoss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 0>;
trips {
@@ -4630,8 +4731,6 @@
};
cpuss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 1>;
trips {
@@ -4650,8 +4749,6 @@
};
cpuss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 2>;
trips {
@@ -4670,8 +4767,6 @@
};
cpuss3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 3>;
trips {
@@ -4690,8 +4785,6 @@
};
cpuss4-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 4>;
trips {
@@ -4710,8 +4803,6 @@
};
cpu4-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 5>;
trips {
@@ -4736,8 +4827,6 @@
};
cpu4-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 6>;
trips {
@@ -4762,8 +4851,6 @@
};
cpu5-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 7>;
trips {
@@ -4788,8 +4875,6 @@
};
cpu5-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 8>;
trips {
@@ -4814,8 +4899,6 @@
};
cpu6-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 9>;
trips {
@@ -4840,8 +4923,6 @@
};
cpu6-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 10>;
trips {
@@ -4866,8 +4947,6 @@
};
cpu7-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 11>;
trips {
@@ -4892,8 +4971,6 @@
};
cpu7-middle-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 12>;
trips {
@@ -4918,8 +4995,6 @@
};
cpu7-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 13>;
trips {
@@ -4945,7 +5020,7 @@
gpu-top-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens0 14>;
cooling-maps {
@@ -4956,35 +5031,29 @@
};
trips {
- thermal-engine-config {
- temperature = <125000>;
+ gpu_top_alert0: trip-point0 {
+ temperature = <85000>;
hysteresis = <1000>;
type = "passive";
};
- thermal-hal-config {
- temperature = <125000>;
+ trip-point1 {
+ temperature = <90000>;
hysteresis = <1000>;
- type = "passive";
+ type = "hot";
};
- reset-mon-cfg {
- temperature = <115000>;
- hysteresis = <5000>;
- type = "passive";
- };
-
- gpu_top_alert0: trip-point0 {
- temperature = <95000>;
- hysteresis = <5000>;
- type = "passive";
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
gpu-bottom-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens0 15>;
cooling-maps {
@@ -4995,35 +5064,27 @@
};
trips {
- thermal-engine-config {
- temperature = <125000>;
+ gpu_bottom_alert0: trip-point0 {
+ temperature = <85000>;
hysteresis = <1000>;
type = "passive";
};
- thermal-hal-config {
- temperature = <125000>;
+ trip-point1 {
+ temperature = <90000>;
hysteresis = <1000>;
- type = "passive";
- };
-
- reset-mon-cfg {
- temperature = <115000>;
- hysteresis = <5000>;
- type = "passive";
+ type = "hot";
};
- gpu_bottom_alert0: trip-point0 {
- temperature = <95000>;
- hysteresis = <5000>;
- type = "passive";
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
aoss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 0>;
trips {
@@ -5042,8 +5103,6 @@
};
cpu0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 1>;
trips {
@@ -5068,8 +5127,6 @@
};
cpu1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 2>;
trips {
@@ -5094,8 +5151,6 @@
};
cpu2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 3>;
trips {
@@ -5120,8 +5175,6 @@
};
cpu3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 4>;
trips {
@@ -5147,7 +5200,7 @@
cdsp0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens1 5>;
trips {
@@ -5179,7 +5232,7 @@
cdsp1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens1 6>;
trips {
@@ -5211,7 +5264,7 @@
cdsp2-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens1 7>;
trips {
@@ -5242,8 +5295,6 @@
};
video-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 8>;
trips {
@@ -5263,7 +5314,7 @@
mem-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens1 9>;
trips {
@@ -5288,8 +5339,6 @@
};
modem0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 10>;
trips {
@@ -5320,8 +5369,6 @@
};
modem1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 11>;
trips {
@@ -5352,8 +5399,6 @@
};
modem2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 12>;
trips {
@@ -5384,8 +5429,6 @@
};
modem3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 13>;
trips {
@@ -5416,8 +5459,6 @@
};
camera0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 14>;
trips {
@@ -5436,8 +5477,6 @@
};
camera1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 15>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/sm8550-hdk.dts b/arch/arm64/boot/dts/qcom/sm8550-hdk.dts
index 12d60a0ee095..2e12219006c9 100644
--- a/arch/arm64/boot/dts/qcom/sm8550-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8550-hdk.dts
@@ -940,7 +940,6 @@
};
&mdss_dp0_out {
- remote-endpoint = <&usb_dp_qmpphy_dp_in>;
data-lanes = <0 1>;
};
@@ -979,10 +978,6 @@
status = "okay";
};
-&pcie_1_phy_aux_clk {
- clock-frequency = <1000>;
-};
-
&pm8550_gpios {
sdc2_card_det_n: sdc2-card-det-state {
pins = "gpio12";
@@ -1111,6 +1106,7 @@
#sound-dai-cells = <0>;
sound-name-prefix = "SpkrLeft";
+ qcom,port-mapping = <1 2 3 7 10 13>;
};
/* WSA8845, Speaker South */
@@ -1128,6 +1124,7 @@
#sound-dai-cells = <0>;
sound-name-prefix = "SpkrRight";
+ qcom,port-mapping = <4 5 6 7 11 13>;
};
};
@@ -1258,19 +1255,10 @@
status = "okay";
};
-&usb_1_dwc3 {
- dr_mode = "otg";
- usb-role-switch;
-};
-
&usb_1_dwc3_hs {
remote-endpoint = <&pmic_glink_hs_in>;
};
-&usb_1_dwc3_ss {
- remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
-};
-
&usb_1_hsphy {
vdd-supply = <&vreg_l1e_0p88>;
vdda12-supply = <&vreg_l3e_1p2>;
@@ -1284,23 +1272,13 @@
vdda-phy-supply = <&vreg_l3e_1p2>;
vdda-pll-supply = <&vreg_l3f_0p88>;
- orientation-switch;
-
status = "okay";
};
-&usb_dp_qmpphy_dp_in {
- remote-endpoint = <&mdss_dp0_out>;
-};
-
&usb_dp_qmpphy_out {
remote-endpoint = <&pmic_glink_ss_in>;
};
-&usb_dp_qmpphy_usb_ss_in {
- remote-endpoint = <&usb_1_dwc3_ss>;
-};
-
&xo_board {
clock-frequency = <76800000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sm8550-mtp.dts b/arch/arm64/boot/dts/qcom/sm8550-mtp.dts
index 3d4ad5aac70f..ab447fc252f7 100644
--- a/arch/arm64/boot/dts/qcom/sm8550-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8550-mtp.dts
@@ -736,11 +736,6 @@
&mdss_dp0_out {
data-lanes = <0 1>;
- remote-endpoint = <&usb_dp_qmpphy_dp_in>;
-};
-
-&pcie_1_phy_aux_clk {
- clock-frequency = <1000>;
};
&pcie0 {
@@ -847,6 +842,7 @@
sound-name-prefix = "SpkrLeft";
vdd-1p8-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l3g_1p2>;
+ qcom,port-mapping = <1 2 3 7 10 13>;
};
/* WSA8845 */
@@ -860,6 +856,7 @@
sound-name-prefix = "SpkrRight";
vdd-1p8-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l3g_1p2>;
+ qcom,port-mapping = <4 5 6 7 11 13>;
};
};
@@ -951,19 +948,10 @@
status = "okay";
};
-&usb_1_dwc3 {
- dr_mode = "otg";
- usb-role-switch;
-};
-
&usb_1_dwc3_hs {
remote-endpoint = <&pmic_glink_hs_in>;
};
-&usb_1_dwc3_ss {
- remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
-};
-
&usb_1_hsphy {
vdd-supply = <&vreg_l1e_0p88>;
vdda12-supply = <&vreg_l3e_1p2>;
@@ -977,23 +965,13 @@
vdda-phy-supply = <&vreg_l3e_1p2>;
vdda-pll-supply = <&vreg_l3f_0p91>;
- orientation-switch;
-
status = "okay";
};
-&usb_dp_qmpphy_dp_in {
- remote-endpoint = <&mdss_dp0_out>;
-};
-
&usb_dp_qmpphy_out {
remote-endpoint = <&pmic_glink_ss_in>;
};
-&usb_dp_qmpphy_usb_ss_in {
- remote-endpoint = <&usb_1_dwc3_ss>;
-};
-
&xo_board {
clock-frequency = <76800000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sm8550-qrd.dts b/arch/arm64/boot/dts/qcom/sm8550-qrd.dts
index 92f015017418..774bdfcffec3 100644
--- a/arch/arm64/boot/dts/qcom/sm8550-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8550-qrd.dts
@@ -214,6 +214,68 @@
regulator-always-on;
regulator-boot-on;
};
+
+ wcn7850-pmu {
+ compatible = "qcom,wcn7850-pmu";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_en>, <&pmk8550_sleep_clk>;
+
+ wlan-enable-gpios = <&tlmm 80 GPIO_ACTIVE_HIGH>;
+ /*
+ * TODO Add bt-enable-gpios once the Bluetooth driver is
+ * converted to using the power sequencer.
+ */
+
+ vdd-supply = <&vreg_s5g_0p85>;
+ vddio-supply = <&vreg_l15b_1p8>;
+ vddaon-supply = <&vreg_s2g_0p85>;
+ vdddig-supply = <&vreg_s4e_0p95>;
+ vddrfa1p2-supply = <&vreg_s4g_1p25>;
+ vddrfa1p8-supply = <&vreg_s6g_1p86>;
+
+ 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_1p8: ldo7 {
+ regulator-name = "vreg_pmu_rfa_1p8";
+ };
+
+ vreg_pmu_pcie_0p9: ldo8 {
+ regulator-name = "vreg_pmu_pcie_0p9";
+ };
+
+ vreg_pmu_pcie_1p8: ldo9 {
+ regulator-name = "vreg_pmu_pcie_1p8";
+ };
+ };
+ };
};
&apps_rsc {
@@ -720,17 +782,6 @@
status = "okay";
};
-&gcc {
- clocks = <&bi_tcxo_div2>, <&sleep_clk>,
- <&pcie0_phy>,
- <&pcie1_phy>,
- <0>,
- <&ufs_mem_phy 0>,
- <&ufs_mem_phy 1>,
- <&ufs_mem_phy 2>,
- <&usb_dp_qmpphy QMP_USB43DP_USB3_PIPE_CLK>;
-};
-
&gpi_dma1 {
status = "okay";
};
@@ -807,11 +858,6 @@
&mdss_dp0_out {
data-lanes = <0 1>;
- remote-endpoint = <&usb_dp_qmpphy_dp_in>;
-};
-
-&pcie_1_phy_aux_clk {
- status = "disabled";
};
&pcie0 {
@@ -824,6 +870,23 @@
status = "okay";
};
+&pcieport0 {
+ wifi@0 {
+ compatible = "pci17cb,1107";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ 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>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ };
+};
+
&pcie0_phy {
vdda-phy-supply = <&vreg_l1e_0p88>;
vdda-pll-supply = <&vreg_l3e_1p2>;
@@ -907,8 +970,15 @@
status = "okay";
};
-&pcie_1_phy_aux_clk {
- clock-frequency = <1000>;
+&pmk8550_gpios {
+ pmk8550_sleep_clk: sleep-clk-state {
+ pins = "gpio3";
+ function = "func1";
+ input-disable;
+ output-enable;
+ bias-disable;
+ power-source = <0>;
+ };
};
&qupv3_id_0 {
@@ -955,6 +1025,7 @@
sound-name-prefix = "SpkrLeft";
vdd-1p8-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l3g_1p2>;
+ qcom,port-mapping = <1 2 3 7 10 13>;
};
/* WSA8845, Speaker South */
@@ -968,6 +1039,7 @@
sound-name-prefix = "SpkrRight";
vdd-1p8-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l3g_1p2>;
+ qcom,port-mapping = <4 5 6 7 11 13>;
};
};
@@ -1084,6 +1156,13 @@
bias-disable;
output-low;
};
+
+ wlan_en: wlan-en-state {
+ pins = "gpio80";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-down;
+ };
};
&uart7 {
@@ -1135,19 +1214,10 @@
status = "okay";
};
-&usb_1_dwc3 {
- dr_mode = "otg";
- usb-role-switch;
-};
-
&usb_1_dwc3_hs {
remote-endpoint = <&pmic_glink_hs_in>;
};
-&usb_1_dwc3_ss {
- remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
-};
-
&usb_1_hsphy {
vdd-supply = <&vreg_l1e_0p88>;
vdda12-supply = <&vreg_l3e_1p2>;
@@ -1161,23 +1231,13 @@
vdda-phy-supply = <&vreg_l3e_1p2>;
vdda-pll-supply = <&vreg_l3f_0p88>;
- orientation-switch;
-
status = "okay";
};
-&usb_dp_qmpphy_dp_in {
- remote-endpoint = <&mdss_dp0_out>;
-};
-
&usb_dp_qmpphy_out {
remote-endpoint = <&redriver_ss_in>;
};
-&usb_dp_qmpphy_usb_ss_in {
- remote-endpoint = <&usb_1_dwc3_ss>;
-};
-
&xo_board {
clock-frequency = <76800000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sm8550-samsung-q5q.dts b/arch/arm64/boot/dts/qcom/sm8550-samsung-q5q.dts
new file mode 100644
index 000000000000..3d351e90bb39
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8550-samsung-q5q.dts
@@ -0,0 +1,593 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024, Alexandru Marc Serdeliuc <[email protected]>
+ * Copyright (c) 2024, David Wronek <[email protected]>
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include "sm8550.dtsi"
+#include "pm8550.dtsi"
+#include "pm8550vs.dtsi"
+#include "pmk8550.dtsi"
+
+/delete-node/ &adspslpi_mem;
+/delete-node/ &cdsp_mem;
+/delete-node/ &mpss_dsm_mem;
+/delete-node/ &mpss_mem;
+/delete-node/ &rmtfs_mem;
+
+/ {
+ model = "Samsung Galaxy Z Fold5";
+ compatible = "samsung,q5q", "qcom,sm8550";
+ chassis-type = "handset";
+
+ aliases {
+ serial0 = &uart7;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ framebuffer: framebuffer@b8000000 {
+ compatible = "simple-framebuffer";
+ reg = <0x0 0xb8000000 0x0 0x2b00000>;
+ width = <2176>;
+ height = <1812>;
+ stride = <(2176 * 4)>;
+ format = "a8r8g8b8";
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&volume_up_n>;
+ pinctrl-names = "default";
+
+ key-volume-up {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&pm8550_gpios 6 GPIO_ACTIVE_LOW>;
+ debounce-interval = <15>;
+ linux,can-disable;
+ wakeup-source;
+ };
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ reserved-memory {
+ adspslpi_mem: adspslpi@9ea00000 {
+ reg = <0x0 0x9ea00000 0x0 0x59b4000>;
+ no-map;
+ };
+
+ cdsp_mem: cdsp-region@9c900000 {
+ reg = <0 0x9c900000 0 0x2000000>;
+ no-map;
+ };
+
+ mpss_dsm_mem: mpss-dsm@d4d00000 {
+ reg = <0x0 0xd4d00000 0x0 0x3300000>;
+ no-map;
+ };
+
+ mpss_mem: mpss@8b400000 {
+ reg = <0x0 0x8b400000 0x0 0xfc00000>;
+ no-map;
+ };
+
+ rmtfs_mem: rmtfs-region@d4a80000 {
+ reg = <0x0 0xd4a80000 0x0 0x280000>;
+ no-map;
+ };
+
+ /*
+ * The bootloader will only keep display hardware enabled
+ * if this memory region is named exactly 'splash_region'
+ */
+ splash_region@b8000000 {
+ reg = <0x0 0xb8000000 0x0 0x2b00000>;
+ no-map;
+ };
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8550-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vreg_bob1: bob1 {
+ regulator-name = "vreg_bob1";
+ regulator-min-microvolt = <3296000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob2: bob2 {
+ regulator-name = "vreg_bob2";
+ regulator-min-microvolt = <2720000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1b_1p8: ldo1 {
+ regulator-name = "vreg_l1b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2b_3p0: ldo2 {
+ regulator-name = "vreg_l2b_3p0";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5b_3p1: ldo5 {
+ regulator-name = "vreg_l5b_3p1";
+ regulator-min-microvolt = <3104000>;
+ regulator-max-microvolt = <3104000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6b_1p8: ldo6 {
+ regulator-name = "vreg_l6b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7b_1p8: ldo7 {
+ regulator-name = "vreg_l7b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8b_1p8: ldo8 {
+ regulator-name = "vreg_l8b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9b_2p9: ldo9 {
+ regulator-name = "vreg_l9b_2p9";
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11b_1p2: ldo11 {
+ regulator-name = "vreg_l11b_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1504000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12b_1p8: ldo12 {
+ regulator-name = "vreg_l12b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13b_3p0: ldo13 {
+ regulator-name = "vreg_l13b_3p0";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14b_3p2: ldo14 {
+ regulator-name = "vreg_l14b_3p2";
+ regulator-min-microvolt = <3200000>;
+ regulator-max-microvolt = <3200000>;
+ 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>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
+ };
+
+ vreg_l16b_2p8: ldo16 {
+ regulator-name = "vreg_l16b_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ 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,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vreg_l3c_0p91: ldo3 {
+ regulator-name = "vreg_l3c_0p9";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-2 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "d";
+
+ vreg_l1d_0p88: ldo1 {
+ regulator-name = "vreg_l1d_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-3 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "e";
+
+ vreg_s4e_0p9: smps4 {
+ regulator-name = "vreg_s4e_0p9";
+ regulator-min-microvolt = <904000>;
+ regulator-max-microvolt = <984000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s5e_1p1: smps5 {
+ regulator-name = "vreg_s5e_1p1";
+ regulator-min-microvolt = <1080000>;
+ regulator-max-microvolt = <1120000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1e_0p88: ldo1 {
+ regulator-name = "vreg_l1e_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2e_0p9: ldo2 {
+ regulator-name = "vreg_l2e_0p9";
+ regulator-min-microvolt = <904000>;
+ regulator-max-microvolt = <970000>;
+ 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,pm8550ve-rpmh-regulators";
+ qcom,pmic-id = "f";
+
+ vreg_s4f_0p5: smps4 {
+ regulator-name = "vreg_s4f_0p5";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <700000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1f_0p9: ldo1 {
+ regulator-name = "vreg_l1f_0p9";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2f_0p88: ldo2 {
+ regulator-name = "vreg_l2f_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3f_0p91: ldo3 {
+ regulator-name = "vreg_l3f_0p91";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-5 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+ qcom,pmic-id = "g";
+
+ vreg_s1g_1p2: smps1 {
+ regulator-name = "vreg_s1g_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s2g_0p8: smps2 {
+ regulator-name = "vreg_s2g_0p8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s3g_0p7: smps3 {
+ regulator-name = "vreg_s3g_0p7";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1004000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s4g_1p3: smps4 {
+ regulator-name = "vreg_s4g_1p3";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1352000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s5g_0p8: smps5 {
+ regulator-name = "vreg_s5g_0p8";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1004000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s6g_1p8: smps6 {
+ regulator-name = "vreg_s6g_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1g_1p2: ldo1 {
+ regulator-name = "vreg_l1g_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2g_1p2: ldo2 {
+ regulator-name = "vreg_l2g_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3g_1p2: ldo3 {
+ regulator-name = "vreg_l3g_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-6 {
+ compatible = "qcom,pm8010-rpmh-regulators";
+ qcom,pmic-id = "m";
+
+ vreg_l1m_1p056: ldo1 {
+ regulator-name = "vreg_l1m_1p056";
+ regulator-min-microvolt = <1056000>;
+ regulator-max-microvolt = <1056000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2m_1p056: ldo2 {
+ regulator-name = "vreg_l2m_1p056";
+ regulator-min-microvolt = <1056000>;
+ regulator-max-microvolt = <1056000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3m_2p8: ldo3 {
+ regulator-name = "vreg_l3m_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4m_2p8: ldo4 {
+ regulator-name = "vreg_l4m_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5m_1p8: ldo5 {
+ regulator-name = "vreg_l5m_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6m_1p8: ldo6 {
+ regulator-name = "vreg_l6m_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7m_2p9: ldo7 {
+ regulator-name = "vreg_l7m_2p9";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2904000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-7 {
+ compatible = "qcom,pm8010-rpmh-regulators";
+ qcom,pmic-id = "n";
+
+ vreg_l1n_1p1: ldo1 {
+ regulator-name = "vreg_l1n_1p1";
+ regulator-min-microvolt = <1104000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2n_1p1: ldo2 {
+ regulator-name = "vreg_l2n_1p1";
+ regulator-min-microvolt = <1104000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3n_2p8: ldo3 {
+ regulator-name = "vreg_l3n_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4n_2p8: ldo4 {
+ regulator-name = "vreg_l4n_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5n_1p8: ldo5 {
+ regulator-name = "vreg_l5n_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6n_3p3: ldo6 {
+ regulator-name = "vreg_l6n_3p3";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7n_2p96: ldo7 {
+ regulator-name = "vreg_l7n_2p96";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&dispcc {
+ status = "disabled";
+};
+
+&i2c_master_hub_0 {
+ status = "okay";
+};
+
+&pcie0 {
+ wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>;
+ perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&pcie0_default_state>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pcie0_phy {
+ vdda-phy-supply = <&vreg_l1e_0p88>;
+ vdda-pll-supply = <&vreg_l3e_1p2>;
+ status = "okay";
+};
+
+&pm8550_gpios {
+ volume_up_n: volume-up-n-state {
+ pins = "gpio6";
+ function = "normal";
+ power-source = <1>;
+ bias-pull-up;
+ input-enable;
+ };
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ status = "okay";
+ linux,code = <KEY_VOLUMEDOWN>;
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&remoteproc_adsp {
+ firmware-name = "qcom/sm8550/adsp.mdt",
+ "qcom/sm8550/adsp_dtb.mdt";
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/sm8550/cdsp.mdt",
+ "qcom/sm8550/cdsp_dtb.mdt";
+ status = "okay";
+};
+
+&remoteproc_mpss {
+ firmware-name = "qcom/sm8550/modem.mdt",
+ "qcom/sm8550/modem_dtb.mdt";
+ status = "okay";
+};
+
+&sleep_clk {
+ clock-frequency = <32000>;
+};
+
+&tlmm {
+ gpio-reserved-ranges = <36 4>, <50 2>;
+};
+
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 210 GPIO_ACTIVE_LOW>;
+ vcc-supply = <&vreg_l17b_2p5>;
+ vcc-max-microamp = <1300000>;
+ vccq-supply = <&vreg_l1g_1p2>;
+ vccq-max-microamp = <1200000>;
+ vdd-hba-supply = <&vreg_l3g_1p2>;
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vreg_l1d_0p88>;
+ vdda-pll-supply = <&vreg_l3e_1p2>;
+ status = "okay";
+};
+
+&xo_board {
+ clock-frequency = <76800000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8550-sony-xperia-yodo-pdx234.dts b/arch/arm64/boot/dts/qcom/sm8550-sony-xperia-yodo-pdx234.dts
index 85e0d3d66e16..85d487ef80a0 100644
--- a/arch/arm64/boot/dts/qcom/sm8550-sony-xperia-yodo-pdx234.dts
+++ b/arch/arm64/boot/dts/qcom/sm8550-sony-xperia-yodo-pdx234.dts
@@ -737,19 +737,10 @@
status = "okay";
};
-&usb_1_dwc3 {
- dr_mode = "otg";
- usb-role-switch;
-};
-
&usb_1_dwc3_hs {
remote-endpoint = <&pmic_glink_hs_in>;
};
-&usb_1_dwc3_ss {
- remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
-};
-
&usb_1_hsphy {
vdd-supply = <&pm8550vs_2_l1>;
vdda12-supply = <&pm8550vs_2_l3>;
@@ -761,7 +752,6 @@
&usb_dp_qmpphy {
vdda-phy-supply = <&pm8550vs_2_l3>;
vdda-pll-supply = <&pm8550ve_l3>;
- orientation-switch;
status = "okay";
};
@@ -770,10 +760,6 @@
remote-endpoint = <&pmic_glink_ss_in>;
};
-&usb_dp_qmpphy_usb_ss_in {
- remote-endpoint = <&usb_1_dwc3_ss>;
-};
-
&xo_board {
clock-frequency = <76800000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi
index bc5aeb05ffc3..4c9820adcf52 100644
--- a/arch/arm64/boot/dts/qcom/sm8550.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi
@@ -58,11 +58,6 @@
clock-mult = <1>;
clock-div = <2>;
};
-
- pcie_1_phy_aux_clk: pcie-1-phy-aux-clk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- };
};
cpus {
@@ -357,8 +352,23 @@
reg = <0 0xa0000000 0 0>;
};
- pmu {
- compatible = "arm,armv8-pmuv3";
+ pmu-a510 {
+ compatible = "arm,cortex-a510-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ pmu-a710 {
+ compatible = "arm,cortex-a710-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ pmu-a715 {
+ compatible = "arm,cortex-a715-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ pmu-x3 {
+ compatible = "arm,cortex-x3-pmu";
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
};
@@ -776,8 +786,8 @@
#power-domain-cells = <1>;
clocks = <&bi_tcxo_div2>, <&sleep_clk>,
<&pcie0_phy>,
- <&pcie1_phy>,
- <&pcie_1_phy_aux_clk>,
+ <&pcie1_phy QMP_PCIE_PIPE_CLK>,
+ <&pcie1_phy QMP_PCIE_PHY_AUX_CLK>,
<&ufs_mem_phy 0>,
<&ufs_mem_phy 1>,
<&ufs_mem_phy 2>,
@@ -1774,7 +1784,7 @@
status = "disabled";
- pcie@0 {
+ pcieport0: pcie@0 {
device_type = "pci";
reg = <0x0 0x0 0x0 0x0 0x0>;
bus-range = <0x01 0xff>;
@@ -1928,7 +1938,7 @@
power-domains = <&gcc PCIE_1_PHY_GDSC>;
- #clock-cells = <0>;
+ #clock-cells = <1>;
clock-output-names = "pcie1_pipe_clk";
#phy-cells = <0>;
@@ -2910,6 +2920,7 @@
port@1 {
reg = <1>;
mdss_dp0_out: endpoint {
+ remote-endpoint = <&usb_dp_qmpphy_dp_in>;
};
};
};
@@ -3169,6 +3180,8 @@
#clock-cells = <1>;
#phy-cells = <1>;
+ orientation-switch;
+
status = "disabled";
ports {
@@ -3186,6 +3199,7 @@
reg = <1>;
usb_dp_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_ss>;
};
};
@@ -3193,6 +3207,7 @@
reg = <2>;
usb_dp_qmpphy_dp_in: endpoint {
+ remote-endpoint = <&mdss_dp0_out>;
};
};
};
@@ -3264,6 +3279,7 @@
snps,has-lpm-erratum;
tx-fifo-resize;
dma-coherent;
+ usb-role-switch;
ports {
#address-cells = <1>;
@@ -3280,6 +3296,7 @@
reg = <1>;
usb_1_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
};
};
};
@@ -4295,12 +4312,14 @@
<0 0x25200000 0 0x200000>,
<0 0x25400000 0 0x200000>,
<0 0x25600000 0 0x200000>,
- <0 0x25800000 0 0x200000>;
+ <0 0x25800000 0 0x200000>,
+ <0 0x25a00000 0 0x200000>;
reg-names = "llcc0_base",
"llcc1_base",
"llcc2_base",
"llcc3_base",
- "llcc_broadcast_base";
+ "llcc_broadcast_base",
+ "llcc_broadcast_and_base";
interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
};
@@ -4571,8 +4590,6 @@
thermal-zones {
aoss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 0>;
trips {
@@ -4591,8 +4608,6 @@
};
cpuss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 1>;
trips {
@@ -4611,8 +4626,6 @@
};
cpuss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 2>;
trips {
@@ -4631,8 +4644,6 @@
};
cpuss2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 3>;
trips {
@@ -4651,8 +4662,6 @@
};
cpuss3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 4>;
trips {
@@ -4671,8 +4680,6 @@
};
cpu3-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 5>;
trips {
@@ -4697,8 +4704,6 @@
};
cpu3-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 6>;
trips {
@@ -4723,8 +4728,6 @@
};
cpu4-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 7>;
trips {
@@ -4749,8 +4752,6 @@
};
cpu4-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 8>;
trips {
@@ -4775,8 +4776,6 @@
};
cpu5-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 9>;
trips {
@@ -4801,8 +4800,6 @@
};
cpu5-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 10>;
trips {
@@ -4827,8 +4824,6 @@
};
cpu6-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 11>;
trips {
@@ -4853,8 +4848,6 @@
};
cpu6-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 12>;
trips {
@@ -4879,8 +4872,6 @@
};
cpu7-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 13>;
trips {
@@ -4905,8 +4896,6 @@
};
cpu7-middle-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 14>;
trips {
@@ -4931,8 +4920,6 @@
};
cpu7-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 15>;
trips {
@@ -4957,8 +4944,6 @@
};
aoss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 0>;
trips {
@@ -4977,8 +4962,6 @@
};
cpu0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 1>;
trips {
@@ -5003,8 +4986,6 @@
};
cpu1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 2>;
trips {
@@ -5029,8 +5010,6 @@
};
cpu2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 3>;
trips {
@@ -5056,7 +5035,7 @@
cdsp0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 4>;
trips {
@@ -5088,7 +5067,7 @@
cdsp1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 5>;
trips {
@@ -5120,7 +5099,7 @@
cdsp2-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 6>;
trips {
@@ -5152,7 +5131,7 @@
cdsp3-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 7>;
trips {
@@ -5183,8 +5162,6 @@
};
video-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 8>;
trips {
@@ -5204,7 +5181,7 @@
mem-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens1 9>;
trips {
@@ -5229,8 +5206,6 @@
};
modem0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 10>;
trips {
@@ -5261,8 +5236,6 @@
};
modem1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 11>;
trips {
@@ -5293,8 +5266,6 @@
};
modem2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 12>;
trips {
@@ -5325,8 +5296,6 @@
};
modem3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 13>;
trips {
@@ -5357,8 +5326,6 @@
};
camera0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 14>;
trips {
@@ -5377,8 +5344,6 @@
};
camera1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 15>;
trips {
@@ -5397,8 +5362,6 @@
};
aoss2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 0>;
trips {
@@ -5418,312 +5381,264 @@
gpuss-0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 1>;
cooling-maps {
map0 {
- trip = <&gpu0_junction_config>;
+ trip = <&gpu0_alert0>;
cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
trips {
- thermal-engine-config {
- temperature = <125000>;
+ gpu0_alert0: trip-point0 {
+ temperature = <85000>;
hysteresis = <1000>;
type = "passive";
};
- thermal-hal-config {
- temperature = <125000>;
+ trip-point1 {
+ temperature = <90000>;
hysteresis = <1000>;
- type = "passive";
- };
-
- reset-mon-config {
- temperature = <115000>;
- hysteresis = <5000>;
- type = "passive";
+ type = "hot";
};
- gpu0_junction_config: junction-config {
- temperature = <95000>;
- hysteresis = <5000>;
- type = "passive";
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
gpuss-1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 2>;
cooling-maps {
map0 {
- trip = <&gpu1_junction_config>;
+ trip = <&gpu1_alert0>;
cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
trips {
- thermal-engine-config {
- temperature = <125000>;
+ gpu1_alert0: trip-point0 {
+ temperature = <85000>;
hysteresis = <1000>;
type = "passive";
};
- thermal-hal-config {
- temperature = <125000>;
+ trip-point1 {
+ temperature = <90000>;
hysteresis = <1000>;
- type = "passive";
+ type = "hot";
};
- reset-mon-config {
- temperature = <115000>;
- hysteresis = <5000>;
- type = "passive";
- };
-
- gpu1_junction_config: junction-config {
- temperature = <95000>;
- hysteresis = <5000>;
- type = "passive";
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
gpuss-2-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 3>;
cooling-maps {
map0 {
- trip = <&gpu2_junction_config>;
+ trip = <&gpu2_alert0>;
cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
trips {
- thermal-engine-config {
- temperature = <125000>;
+ gpu2_alert0: trip-point0 {
+ temperature = <85000>;
hysteresis = <1000>;
type = "passive";
};
- thermal-hal-config {
- temperature = <125000>;
+ trip-point1 {
+ temperature = <90000>;
hysteresis = <1000>;
- type = "passive";
+ type = "hot";
};
- reset-mon-config {
- temperature = <115000>;
- hysteresis = <5000>;
- type = "passive";
- };
-
- gpu2_junction_config: junction-config {
- temperature = <95000>;
- hysteresis = <5000>;
- type = "passive";
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
gpuss-3-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 4>;
cooling-maps {
map0 {
- trip = <&gpu3_junction_config>;
+ trip = <&gpu3_alert0>;
cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
trips {
- thermal-engine-config {
- temperature = <125000>;
+ gpu3_alert0: trip-point0 {
+ temperature = <85000>;
hysteresis = <1000>;
type = "passive";
};
- thermal-hal-config {
- temperature = <125000>;
+ trip-point1 {
+ temperature = <90000>;
hysteresis = <1000>;
- type = "passive";
- };
-
- reset-mon-config {
- temperature = <115000>;
- hysteresis = <5000>;
- type = "passive";
+ type = "hot";
};
- gpu3_junction_config: junction-config {
- temperature = <95000>;
- hysteresis = <5000>;
- type = "passive";
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
gpuss-4-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 5>;
cooling-maps {
map0 {
- trip = <&gpu4_junction_config>;
+ trip = <&gpu4_alert0>;
cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
trips {
- thermal-engine-config {
- temperature = <125000>;
+ gpu4_alert0: trip-point0 {
+ temperature = <85000>;
hysteresis = <1000>;
type = "passive";
};
- thermal-hal-config {
- temperature = <125000>;
+ trip-point1 {
+ temperature = <90000>;
hysteresis = <1000>;
- type = "passive";
- };
-
- reset-mon-config {
- temperature = <115000>;
- hysteresis = <5000>;
- type = "passive";
+ type = "hot";
};
- gpu4_junction_config: junction-config {
- temperature = <95000>;
- hysteresis = <5000>;
- type = "passive";
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
gpuss-5-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 6>;
cooling-maps {
map0 {
- trip = <&gpu5_junction_config>;
+ trip = <&gpu5_alert0>;
cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
trips {
- thermal-engine-config {
- temperature = <125000>;
+ gpu5_alert0: trip-point0 {
+ temperature = <85000>;
hysteresis = <1000>;
type = "passive";
};
- thermal-hal-config {
- temperature = <125000>;
+ trip-point1 {
+ temperature = <90000>;
hysteresis = <1000>;
- type = "passive";
+ type = "hot";
};
- reset-mon-config {
- temperature = <115000>;
- hysteresis = <5000>;
- type = "passive";
- };
-
- gpu5_junction_config: junction-config {
- temperature = <95000>;
- hysteresis = <5000>;
- type = "passive";
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
gpuss-6-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 7>;
cooling-maps {
map0 {
- trip = <&gpu6_junction_config>;
+ trip = <&gpu6_alert0>;
cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
trips {
- thermal-engine-config {
- temperature = <125000>;
+ gpu6_alert0: trip-point0 {
+ temperature = <85000>;
hysteresis = <1000>;
type = "passive";
};
- thermal-hal-config {
- temperature = <125000>;
+ trip-point1 {
+ temperature = <90000>;
hysteresis = <1000>;
- type = "passive";
+ type = "hot";
};
- reset-mon-config {
- temperature = <115000>;
- hysteresis = <5000>;
- type = "passive";
- };
-
- gpu6_junction_config: junction-config {
- temperature = <95000>;
- hysteresis = <5000>;
- type = "passive";
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
gpuss-7-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 8>;
cooling-maps {
map0 {
- trip = <&gpu7_junction_config>;
+ trip = <&gpu7_alert0>;
cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
trips {
- thermal-engine-config {
- temperature = <125000>;
+ gpu7_alert0: trip-point0 {
+ temperature = <85000>;
hysteresis = <1000>;
type = "passive";
};
- thermal-hal-config {
- temperature = <125000>;
+ trip-point1 {
+ temperature = <90000>;
hysteresis = <1000>;
- type = "passive";
+ type = "hot";
};
- reset-mon-config {
- temperature = <115000>;
- hysteresis = <5000>;
- type = "passive";
- };
-
- gpu7_junction_config: junction-config {
- temperature = <95000>;
- hysteresis = <5000>;
- type = "passive";
+ trip-point2 {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm8650-hdk-display-card.dtso b/arch/arm64/boot/dts/qcom/sm8650-hdk-display-card.dtso
new file mode 100644
index 000000000000..cb102535838d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8650-hdk-display-card.dtso
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+/*
+ * Display Card kit overlay
+ * This requires S5702 Switch 7 to be turned to OFF to route DSI0 to the display panel
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/dts-v1/;
+/plugin/;
+
+/* Disable HDMI bridge related nodes (mutually exclusive with the display card) */
+
+&i2c6 {
+ status = "disabled";
+};
+
+&lt9611_1v2 {
+ status = "disabled";
+};
+
+&lt9611_3v3 {
+ status = "disabled";
+};
+
+&vreg_bob_3v3 {
+ status = "disabled";
+};
+
+&lt9611_codec {
+ status = "disabled";
+};
+
+&mdss_dsi0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "visionox,vtdr6130";
+ reg = <0>;
+
+ reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>;
+
+ vddio-supply = <&vreg_l12b_1p8>;
+ vci-supply = <&vreg_l13b_3p0>;
+ vdd-supply = <&vreg_l11b_1p2>;
+
+ pinctrl-0 = <&disp0_reset_n_active>, <&mdp_vsync>;
+ pinctrl-1 = <&disp0_reset_n_suspend>, <&mdp_vsync>;
+ pinctrl-names = "default", "sleep";
+
+ port {
+ panel0_in: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ reg = <1>;
+
+ mdss_dsi0_out: endpoint {
+ remote-endpoint = <&panel0_in>;
+ };
+ };
+ };
+};
+
+&spi4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "okay";
+
+ touchscreen@0 {
+ compatible = "goodix,gt9916";
+ reg = <0>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <162 IRQ_TYPE_LEVEL_LOW>;
+
+ reset-gpios = <&tlmm 161 GPIO_ACTIVE_LOW>;
+
+ avdd-supply = <&vreg_l14b_3p2>;
+
+ spi-max-frequency = <1000000>;
+
+ touchscreen-size-x = <1080>;
+ touchscreen-size-y = <2400>;
+
+ pinctrl-0 = <&ts_irq>, <&ts_reset>;
+ pinctrl-names = "default";
+ };
+};
+
+&tlmm {
+ disp0_reset_n_active: disp0-reset-n-active-state {
+ pins = "gpio133";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ disp0_reset_n_suspend: disp0-reset-n-suspend-state {
+ pins = "gpio133";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ mdp_vsync: mdp-vsync-state {
+ pins = "gpio86";
+ function = "mdp_vsync";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ ts_irq: ts-irq-state {
+ pins = "gpio161";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ output-disable;
+ };
+
+ ts_reset: ts-reset-state {
+ pins = "gpio162";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8650-hdk.dts b/arch/arm64/boot/dts/qcom/sm8650-hdk.dts
new file mode 100644
index 000000000000..591e6ab9bf5b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8650-hdk.dts
@@ -0,0 +1,1355 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include "sm8650.dtsi"
+#include "pm8010.dtsi"
+#include "pm8550.dtsi"
+#include "pm8550b.dtsi"
+#define PMK8550VE_SID 8
+#include "pm8550ve.dtsi"
+#include "pm8550vs.dtsi"
+#include "pmk8550.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SM8650 HDK";
+ compatible = "qcom,sm8650-hdk", "qcom,sm8650";
+ chassis-type = "embedded";
+
+ aliases {
+ serial0 = &uart15;
+ serial1 = &uart14;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ hdmi-out {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_connector_out: endpoint {
+ remote-endpoint = <&lt9611_out>;
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&volume_up_n>;
+ pinctrl-names = "default";
+
+ key-volume-up {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&pm8550_gpios 6 GPIO_ACTIVE_LOW>;
+ debounce-interval = <15>;
+ linux,can-disable;
+ wakeup-source;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ function = LED_FUNCTION_BLUETOOTH;
+ color = <LED_COLOR_ID_BLUE>;
+ gpios = <&pm8550_gpios 11 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "bluetooth-power";
+ default-state = "off";
+ };
+
+ led-1 {
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&pm8550b_gpios 9 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ panic-indicator;
+ };
+
+ led-2 {
+ function = LED_FUNCTION_WLAN;
+ color = <LED_COLOR_ID_ORANGE>;
+ gpios = <&pm8550b_gpios 10 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "phy0tx";
+ default-state = "off";
+ };
+ };
+
+ pmic-glink {
+ compatible = "qcom,sm8650-pmic-glink",
+ "qcom,sm8550-pmic-glink",
+ "qcom,pmic-glink";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ orientation-gpios = <&tlmm 29 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_ss_in: endpoint {
+ remote-endpoint = <&usb_dp_qmpphy_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ pmic_glink_sbu: endpoint {
+ remote-endpoint = <&wcd_usbss_sbu_mux>;
+ };
+ };
+ };
+ };
+ };
+
+ lt9611_1v2: regulator-lt9611-1v2 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "LT9611_1V2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+
+ vin-supply = <&vph_pwr>;
+ gpio = <&tlmm 79 GPIO_ACTIVE_HIGH>;
+
+ enable-active-high;
+ };
+
+ lt9611_3v3: regulator-lt9611-3v3 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "LT9611_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ vin-supply = <&vreg_bob_3v3>;
+ gpio = <&tlmm 78 GPIO_ACTIVE_HIGH>;
+
+ enable-active-high;
+ };
+
+ sound {
+ compatible = "qcom,sm8650-sndcard", "qcom,sm8450-sndcard";
+ model = "SM8650-HDK";
+ audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT",
+ "SpkrRight IN", "WSA_SPK2 OUT",
+ "IN1_HPHL", "HPHL_OUT",
+ "IN2_HPHR", "HPHR_OUT",
+ "AMIC1", "MIC BIAS1",
+ "AMIC2", "MIC BIAS2",
+ "AMIC5", "MIC BIAS4",
+ "TX SWR_INPUT0", "ADC1_OUTPUT",
+ "TX SWR_INPUT1", "ADC2_OUTPUT",
+ "TX SWR_INPUT3", "ADC4_OUTPUT";
+
+ wcd-playback-dai-link {
+ link-name = "WCD Playback";
+
+ cpu {
+ sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>;
+ };
+
+ codec {
+ sound-dai = <&wcd939x 0>, <&swr1 0>, <&lpass_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 = <&wcd939x 1>, <&swr2 0>, <&lpass_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 = <&north_spkr>, <&south_spkr>, <&swr0 0>, <&lpass_wsamacro 0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+ };
+
+ 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_bob_3v3: regulator-vreg-bob-3v3 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_BOB_3P3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ vin-supply = <&vph_pwr>;
+ };
+
+ wcd939x: audio-codec {
+ compatible = "qcom,wcd9395-codec", "qcom,wcd9390-codec";
+
+ pinctrl-0 = <&wcd_default>;
+ pinctrl-names = "default";
+
+ qcom,micbias1-microvolt = <1800000>;
+ qcom,micbias2-microvolt = <1800000>;
+ qcom,micbias3-microvolt = <1800000>;
+ qcom,micbias4-microvolt = <1800000>;
+ qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000 500000 500000 500000>;
+ qcom,mbhc-headset-vthreshold-microvolt = <1700000>;
+ qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
+ qcom,rx-device = <&wcd_rx>;
+ qcom,tx-device = <&wcd_tx>;
+
+ reset-gpios = <&tlmm 107 GPIO_ACTIVE_LOW>;
+
+ vdd-buck-supply = <&vreg_l15b_1p8>;
+ vdd-rxtx-supply = <&vreg_l15b_1p8>;
+ vdd-io-supply = <&vreg_l15b_1p8>;
+ vdd-mic-bias-supply = <&vreg_bob1>;
+
+ #sound-dai-cells = <1>;
+ };
+
+ wcn7850-pmu {
+ compatible = "qcom,wcn7850-pmu";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_en>;
+
+ wlan-enable-gpios = <&tlmm 16 GPIO_ACTIVE_HIGH>;
+ /*
+ * TODO Add bt-enable-gpios once the Bluetooth driver is
+ * converted to using the power sequencer.
+ */
+
+ vdd-supply = <&vreg_s4i_0p85>;
+ vddio-supply = <&vreg_l15b_1p8>;
+ vddio1p2-supply = <&vreg_l3c_1p2>;
+ vddaon-supply = <&vreg_s2c_0p8>;
+ vdddig-supply = <&vreg_s3c_0p9>;
+ vddrfa1p2-supply = <&vreg_s1c_1p2>;
+ vddrfa1p8-supply = <&vreg_s6c_1p8>;
+
+ clocks = <&rpmhcc RPMH_RF_CLK1>;
+
+ 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_1p8: ldo7 {
+ regulator-name = "vreg_pmu_rfa_1p8";
+ };
+
+ vreg_pmu_pcie_0p9: ldo8 {
+ regulator-name = "vreg_pmu_pcie_0p9";
+ };
+
+ vreg_pmu_pcie_1p8: ldo9 {
+ regulator-name = "vreg_pmu_pcie_1p8";
+ };
+ };
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8550-rpmh-regulators";
+
+ vdd-bob1-supply = <&vph_pwr>;
+ vdd-bob2-supply = <&vph_pwr>;
+ vdd-l2-l13-l14-supply = <&vreg_bob1>;
+ vdd-l3-supply = <&vreg_s1c_1p2>;
+ vdd-l5-l16-supply = <&vreg_bob1>;
+ vdd-l6-l7-supply = <&vreg_bob1>;
+ vdd-l8-l9-supply = <&vreg_bob1>;
+ vdd-l11-supply = <&vreg_s1c_1p2>;
+ vdd-l12-supply = <&vreg_s6c_1p8>;
+ vdd-l15-supply = <&vreg_s6c_1p8>;
+ vdd-l17-supply = <&vreg_bob2>;
+
+ qcom,pmic-id = "b";
+
+ vreg_bob1: bob1 {
+ regulator-name = "vreg_bob1";
+ regulator-min-microvolt = <3296000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob2: bob2 {
+ regulator-name = "vreg_bob2";
+ regulator-min-microvolt = <2720000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2b_3p0: ldo2 {
+ regulator-name = "vreg_l2b_3p0";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5b_3p1: ldo5 {
+ regulator-name = "vreg_l5b_3p1";
+ regulator-min-microvolt = <3104000>;
+ regulator-max-microvolt = <3104000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6b_1p8: ldo6 {
+ regulator-name = "vreg_l6b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7b_1p8: ldo7 {
+ regulator-name = "vreg_l7b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8b_1p8: ldo8 {
+ regulator-name = "vreg_l8b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9b_2p9: ldo9 {
+ regulator-name = "vreg_l9b_2p9";
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11b_1p2: ldo11 {
+ regulator-name = "vreg_l11b_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1504000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12b_1p8: ldo12 {
+ regulator-name = "vreg_l12b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13b_3p0: ldo13 {
+ regulator-name = "vreg_l13b_3p0";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14b_3p2: ldo14 {
+ regulator-name = "vreg_l14b_3p2";
+ regulator-min-microvolt = <3200000>;
+ regulator-max-microvolt = <3200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ 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>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l16b_2p8: ldo16 {
+ regulator-name = "vreg_l16b_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ 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>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+
+ vdd-l1-supply = <&vreg_s1c_1p2>;
+ vdd-l2-supply = <&vreg_s1c_1p2>;
+ vdd-l3-supply = <&vreg_s1c_1p2>;
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+
+ qcom,pmic-id = "c";
+
+ vreg_s1c_1p2: smps1 {
+ regulator-name = "vreg_s1c_1p2";
+ regulator-min-microvolt = <1256000>;
+ regulator-max-microvolt = <1348000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s2c_0p8: smps2 {
+ regulator-name = "vreg_s2c_0p8";
+ regulator-min-microvolt = <852000>;
+ regulator-max-microvolt = <1036000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s3c_0p9: smps3 {
+ regulator-name = "vreg_s3c_0p9";
+ regulator-min-microvolt = <976000>;
+ regulator-max-microvolt = <1064000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s4c_1p2: smps4 {
+ regulator-name = "vreg_s4c_1p2";
+ regulator-min-microvolt = <1224000>;
+ regulator-max-microvolt = <1280000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s5c_0p7: smps5 {
+ regulator-name = "vreg_s5c_0p7";
+ regulator-min-microvolt = <752000>;
+ regulator-max-microvolt = <900000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s6c_1p8: smps6 {
+ regulator-name = "vreg_s6c_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>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3c_1p2: ldo3 {
+ regulator-name = "vreg_l3c_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-2 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+
+ vdd-l1-supply = <&vreg_s3c_0p9>;
+
+ qcom,pmic-id = "d";
+
+ vreg_l1d_0p88: ldo1 {
+ regulator-name = "vreg_l1d_0p88";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-3 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+
+ vdd-l3-supply = <&vreg_s3c_0p9>;
+
+ qcom,pmic-id = "e";
+
+ vreg_l3e_0p9: ldo3 {
+ regulator-name = "vreg_l3e_0p9";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-4 {
+ compatible = "qcom,pm8550vs-rpmh-regulators";
+
+ vdd-l1-supply = <&vreg_s3c_0p9>;
+ vdd-l3-supply = <&vreg_s3c_0p9>;
+
+ qcom,pmic-id = "g";
+
+ vreg_l1g_0p91: ldo1 {
+ regulator-name = "vreg_l1g_0p91";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3g_0p91: ldo3 {
+ regulator-name = "vreg_l3g_0p91";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-5 {
+ compatible = "qcom,pm8550ve-rpmh-regulators";
+
+ vdd-l1-supply = <&vreg_s3c_0p9>;
+ vdd-l2-supply = <&vreg_s3c_0p9>;
+ vdd-l3-supply = <&vreg_s1c_1p2>;
+ vdd-s4-supply = <&vph_pwr>;
+
+ qcom,pmic-id = "i";
+
+ vreg_s4i_0p85: smps4 {
+ regulator-name = "vreg_s4i_0p85";
+ regulator-min-microvolt = <852000>;
+ regulator-max-microvolt = <1004000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1i_0p88: ldo1 {
+ regulator-name = "vreg_l1i_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2i_0p88: ldo2 {
+ regulator-name = "vreg_l2i_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3i_1p2: ldo3 {
+ regulator-name = "vreg_l3i_0p91";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-6 {
+ compatible = "qcom,pm8010-rpmh-regulators";
+ qcom,pmic-id = "m";
+
+ vdd-l1-l2-supply = <&vreg_s1c_1p2>;
+ vdd-l3-l4-supply = <&vreg_bob2>;
+ vdd-l5-supply = <&vreg_s6c_1p8>;
+ vdd-l6-supply = <&vreg_bob1>;
+ vdd-l7-supply = <&vreg_bob1>;
+
+ vreg_l1m_1p1: ldo1 {
+ regulator-name = "vreg_l1m_1p1";
+ regulator-min-microvolt = <1104000>;
+ regulator-max-microvolt = <1104000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2m_1p056: ldo2 {
+ regulator-name = "vreg_l2m_1p056";
+ regulator-min-microvolt = <1056000>;
+ regulator-max-microvolt = <1056000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3m_2p8: ldo3 {
+ regulator-name = "vreg_l3m_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4m_2p8: ldo4 {
+ regulator-name = "vreg_l4m_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5m_1p8: ldo5 {
+ regulator-name = "vreg_l5m_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6m_2p8: ldo6 {
+ regulator-name = "vreg_l6m_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7m_2p96: ldo7 {
+ regulator-name = "vreg_l7m_2p96";
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-7 {
+ compatible = "qcom,pm8010-rpmh-regulators";
+ qcom,pmic-id = "n";
+
+ vdd-l1-l2-supply = <&vreg_s1c_1p2>;
+ vdd-l3-l4-supply = <&vreg_s6c_1p8>;
+ vdd-l5-supply = <&vreg_bob2>;
+ vdd-l6-supply = <&vreg_bob2>;
+ vdd-l7-supply = <&vreg_bob1>;
+
+ vreg_l1n_1p1: ldo1 {
+ regulator-name = "vreg_l1n_1p1";
+ regulator-min-microvolt = <1104000>;
+ regulator-max-microvolt = <1104000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2n_1p056: ldo2 {
+ regulator-name = "vreg_l2n_1p056";
+ regulator-min-microvolt = <1056000>;
+ regulator-max-microvolt = <1056000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3n_1p8: ldo3 {
+ regulator-name = "vreg_l3n_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4n_1p8: ldo4 {
+ regulator-name = "vreg_l4n_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5n_2p8: ldo5 {
+ regulator-name = "vreg_l5n_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6n_2p8: ldo6 {
+ regulator-name = "vreg_l6n_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7n_3p3: ldo7 {
+ regulator-name = "vreg_l7n_3p3";
+ regulator-min-microvolt = <3304000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&dispcc {
+ status = "okay";
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+
+ wcd_usbss: typec-mux@e {
+ compatible = "qcom,wcd9395-usbss", "qcom,wcd9390-usbss";
+ reg = <0xe>;
+
+ vdd-supply = <&vreg_l15b_1p8>;
+ reset-gpios = <&tlmm 152 GPIO_ACTIVE_HIGH>;
+
+ mode-switch;
+ orientation-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ wcd_usbss_sbu_mux: endpoint {
+ remote-endpoint = <&pmic_glink_sbu>;
+ };
+ };
+ };
+ };
+};
+
+&i2c6 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ lt9611_codec: hdmi-bridge@2b {
+ compatible = "lontium,lt9611uxc";
+ reg = <0x2b>;
+
+ interrupts-extended = <&tlmm 85 IRQ_TYPE_EDGE_FALLING>;
+
+ reset-gpios = <&tlmm 28 GPIO_ACTIVE_HIGH>;
+
+ vdd-supply = <&lt9611_1v2>;
+ vcc-supply = <&lt9611_3v3>;
+
+ pinctrl-0 = <&lt9611_irq_pin>, <&lt9611_rst_pin>;
+ pinctrl-names = "default";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ lt9611_a: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ lt9611_out: endpoint {
+ remote-endpoint = <&hdmi_connector_out>;
+ };
+ };
+ };
+ };
+};
+
+&ipa {
+ qcom,gsi-loader = "self";
+ memory-region = <&ipa_fw_mem>;
+ firmware-name = "qcom/sm8650/ipa_fws.mbn";
+ status = "okay";
+};
+
+&gpu {
+ status = "okay";
+
+ zap-shader {
+ firmware-name = "qcom/sm8650/gen70900_zap.mbn";
+ };
+};
+
+&lpass_tlmm {
+ spkr_1_sd_n_active: spkr-1-sd-n-active-state {
+ pins = "gpio21";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+};
+
+&mdss {
+ status = "okay";
+};
+
+&mdss_dsi0 {
+ vdda-supply = <&vreg_l3i_1p2>;
+
+ status = "okay";
+};
+
+&mdss_dsi0_out {
+ remote-endpoint = <&lt9611_a>;
+ data-lanes = <0 1 2 3>;
+};
+
+&mdss_dsi0_phy {
+ vdds-supply = <&vreg_l1i_0p88>;
+
+ status = "okay";
+};
+
+&mdss_dp0 {
+ status = "okay";
+};
+
+&mdss_dp0_out {
+ data-lanes = <0 1>;
+};
+
+&pcie0 {
+ wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>;
+ perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&pcie0_default_state>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&pcieport0 {
+ wifi@0 {
+ compatible = "pci17cb,1107";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ 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>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ };
+};
+
+&pcie0_phy {
+ vdda-phy-supply = <&vreg_l1i_0p88>;
+ vdda-pll-supply = <&vreg_l3i_1p2>;
+
+ status = "okay";
+};
+
+&pcie1 {
+ wake-gpios = <&tlmm 99 GPIO_ACTIVE_HIGH>;
+ perst-gpios = <&tlmm 97 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&pcie1_default_state>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&pcie1_phy {
+ vdda-phy-supply = <&vreg_l3e_0p9>;
+ vdda-pll-supply = <&vreg_l3i_1p2>;
+ vdda-qref-supply = <&vreg_l1i_0p88>;
+
+ status = "okay";
+};
+
+&pm8550_gpios {
+ sdc2_card_det_n: sdc2-card-det-state {
+ pins = "gpio12";
+ function = "normal";
+ bias-pull-up;
+ input-enable;
+ output-disable;
+ power-source = <1>; /* 1.8 V */
+ };
+
+ volume_up_n: volume-up-n-state {
+ pins = "gpio6";
+ function = "normal";
+ bias-pull-up;
+ input-enable;
+ power-source = <1>;
+ };
+};
+
+/* The RGB signals are routed to 3 separate LEDs on the HDK8650 */
+&pm8550_pwm {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "okay";
+
+ led@1 {
+ reg = <1>;
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ };
+
+ led@2 {
+ reg = <2>;
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ };
+
+ led@3 {
+ reg = <3>;
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "off";
+ };
+};
+
+&pm8550b_eusb2_repeater {
+ vdd18-supply = <&vreg_l15b_1p8>;
+ vdd3-supply = <&vreg_l5b_3p1>;
+};
+
+&pmk8550_rtc {
+ status = "okay";
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+
+ status = "okay";
+};
+
+&qup_i2c3_data_clk {
+ /* Use internal I2C pull-up */
+ bias-pull-up = <2200>;
+};
+
+&qupv3_id_0 {
+ iommus = <&apps_smmu 0xa3 0x3>;
+
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&remoteproc_adsp {
+ firmware-name = "qcom/sm8650/adsp.mbn",
+ "qcom/sm8650/adsp_dtb.mbn";
+
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/sm8650/cdsp.mbn",
+ "qcom/sm8650/cdsp_dtb.mbn";
+
+ status = "okay";
+};
+
+&remoteproc_mpss {
+ firmware-name = "qcom/sm8650/modem.mbn",
+ "qcom/sm8650/modem_dtb.mbn";
+
+ status = "okay";
+};
+
+&sdhc_2 {
+ cd-gpios = <&pm8550_gpios 12 GPIO_ACTIVE_HIGH>;
+
+ vmmc-supply = <&vreg_l9b_2p9>;
+ vqmmc-supply = <&vreg_l8b_1p8>;
+ bus-width = <4>;
+ no-sdio;
+ no-mmc;
+
+ pinctrl-0 = <&sdc2_default>, <&sdc2_card_det_n>;
+ pinctrl-1 = <&sdc2_sleep>, <&sdc2_card_det_n>;
+ pinctrl-names = "default", "sleep";
+
+ status = "okay";
+};
+
+&sleep_clk {
+ clock-frequency = <32000>;
+};
+
+&swr0 {
+ status = "okay";
+
+ /* WSA8845, Speaker North */
+ north_spkr: speaker@0,0 {
+ compatible = "sdw20217020400";
+ reg = <0 0>;
+ pinctrl-0 = <&spkr_1_sd_n_active>;
+ pinctrl-names = "default";
+ powerdown-gpios = <&lpass_tlmm 21 GPIO_ACTIVE_LOW>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "SpkrLeft";
+ vdd-1p8-supply = <&vreg_l15b_1p8>;
+ vdd-io-supply = <&vreg_l3c_1p2>;
+
+ /*
+ * WSA8845 Port 1 (DAC) <=> SWR0 Port 1 (SPKR_L)
+ * WSA8845 Port 2 (COMP) <=> SWR0 Port 2 (SPKR_L_COMP)
+ * WSA8845 Port 3 (BOOST) <=> SWR0 Port 3 (SPKR_L_BOOST)
+ * WSA8845 Port 4 (PBR) <=> SWR0 Port 7 (PBR)
+ * WSA8845 Port 5 (VISENSE) <=> SWR0 Port 10 (SPKR_L_VI)
+ * WSA8845 Port 6 (CPS) <=> SWR0 Port 13 (CPS)
+ */
+ qcom,port-mapping = <1 2 3 7 10 13>;
+ };
+
+ /* WSA8845, Speaker South */
+ south_spkr: speaker@0,1 {
+ compatible = "sdw20217020400";
+ reg = <0 1>;
+ pinctrl-0 = <&spkr_2_sd_n_active>;
+ pinctrl-names = "default";
+ powerdown-gpios = <&tlmm 77 GPIO_ACTIVE_LOW>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "SpkrRight";
+ vdd-1p8-supply = <&vreg_l15b_1p8>;
+ vdd-io-supply = <&vreg_l3c_1p2>;
+
+ /*
+ * WSA8845 Port 1 (DAC) <=> SWR0 Port 4 (SPKR_R)
+ * WSA8845 Port 2 (COMP) <=> SWR0 Port 5 (SPKR_R_COMP)
+ * WSA8845 Port 3 (BOOST) <=> SWR0 Port 6 (SPKR_R_BOOST)
+ * WSA8845 Port 4 (PBR) <=> SWR0 Port 7 (PBR)
+ * WSA8845 Port 5 (VISENSE) <=> SWR0 Port 11 (SPKR_R_VI)
+ * WSA8845 Port 6 (CPS) <=> SWR0 Port 13 (CPS)
+ */
+ qcom,port-mapping = <4 5 6 7 11 13>;
+ };
+};
+
+&swr1 {
+ status = "okay";
+
+ /* WCD9395 RX */
+ wcd_rx: codec@0,4 {
+ compatible = "sdw20217010e00";
+ reg = <0 4>;
+
+ /*
+ * WCD9395 RX Port 1 (HPH_L/R) <=> SWR1 Port 1 (HPH_L/R)
+ * WCD9395 RX Port 2 (CLSH) <=> SWR1 Port 2 (CLSH)
+ * WCD9395 RX Port 3 (COMP_L/R) <=> SWR1 Port 3 (COMP_L/R)
+ * WCD9395 RX Port 4 (LO) <=> SWR1 Port 4 (LO)
+ * WCD9395 RX Port 5 (DSD_L/R) <=> SWR1 Port 5 (DSD_L/R)
+ * WCD9395 RX Port 6 (HIFI_PCM_L/R) <=> SWR1 Port 9 (HIFI_PCM_L/R)
+ */
+ qcom,rx-port-mapping = <1 2 3 4 5 9>;
+ };
+};
+
+&swr2 {
+ status = "okay";
+
+ /* WCD9395 TX */
+ wcd_tx: codec@0,3 {
+ compatible = "sdw20217010e00";
+ reg = <0 3>;
+
+ /*
+ * WCD9395 TX Port 1 (ADC1,2,3,4) <=> SWR2 Port 2 (TX SWR_INPUT 0,1,2,3)
+ * WCD9395 TX Port 2 (ADC3,4 & DMIC0,1) <=> SWR2 Port 2 (TX SWR_INPUT 0,1,2,3)
+ * WCD9395 TX Port 3 (DMIC0,1,2,3 & MBHC) <=> SWR2 Port 3 (TX SWR_INPUT 4,5,6,7)
+ * WCD9395 TX Port 4 (DMIC4,5,6,7) <=> SWR2 Port 4 (TX SWR_INPUT 8,9,10,11)
+ */
+ qcom,tx-port-mapping = <2 2 3 4>;
+ };
+};
+
+&tlmm {
+ /* Reserved I/Os for NFC */
+ gpio-reserved-ranges = <32 8>, <74 1>;
+
+ bt_default: bt-default-state {
+ bt-en-pins {
+ pins = "gpio17";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ sw-ctrl-pins {
+ pins = "gpio18";
+ function = "gpio";
+ bias-pull-down;
+ };
+ };
+
+ lt9611_irq_pin: lt9611-irq-state {
+ pins = "gpio85";
+ function = "gpio";
+ bias-disable;
+ };
+
+ lt9611_rst_pin: lt9611-rst-state {
+ pins = "gpio28";
+ function = "gpio";
+ output-high;
+ };
+
+ spkr_2_sd_n_active: spkr-2-sd-n-active-state {
+ pins = "gpio77";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+
+ wcd_default: wcd-reset-n-active-state {
+ pins = "gpio107";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+
+ wlan_en: wlan-en-state {
+ pins = "gpio16";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-down;
+ };
+};
+
+&uart14 {
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,wcn7850-bt";
+
+ vddio-supply = <&vreg_l3c_1p2>;
+ vddaon-supply = <&vreg_l15b_1p8>;
+ vdddig-supply = <&vreg_s3c_0p9>;
+ vddrfa0p8-supply = <&vreg_s3c_0p9>;
+ vddrfa1p2-supply = <&vreg_s1c_1p2>;
+ vddrfa1p9-supply = <&vreg_s6c_1p8>;
+
+ max-speed = <3200000>;
+
+ enable-gpios = <&tlmm 17 GPIO_ACTIVE_HIGH>;
+ swctrl-gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&bt_default>;
+ pinctrl-names = "default";
+ };
+};
+
+&uart15 {
+ status = "okay";
+};
+
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 210 GPIO_ACTIVE_LOW>;
+
+ vcc-supply = <&vreg_l17b_2p5>;
+ vcc-max-microamp = <1300000>;
+ vccq-supply = <&vreg_l1c_1p2>;
+ vccq-max-microamp = <1200000>;
+
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vreg_l1d_0p88>;
+ vdda-pll-supply = <&vreg_l3i_1p2>;
+
+ status = "okay";
+};
+
+/*
+ * DPAUX -> WCD9395 -> USB_SBU -> USB-C
+ * eUSB2 DP/DM -> PM85550HS -> eUSB2 DP/DM -> WCD9395 -> USB-C
+ * USB SS -> USB-C
+ */
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "otg";
+ usb-role-switch;
+};
+
+&usb_1_dwc3_hs {
+ remote-endpoint = <&pmic_glink_hs_in>;
+};
+
+&usb_1_hsphy {
+ vdd-supply = <&vreg_l1i_0p88>;
+ vdda12-supply = <&vreg_l3i_1p2>;
+
+ phys = <&pm8550b_eusb2_repeater>;
+
+ status = "okay";
+};
+
+&usb_dp_qmpphy {
+ vdda-phy-supply = <&vreg_l3i_1p2>;
+ vdda-pll-supply = <&vreg_l3g_0p91>;
+
+ status = "okay";
+};
+
+&usb_dp_qmpphy_out {
+ remote-endpoint = <&pmic_glink_ss_in>;
+};
+
+&xo_board {
+ clock-frequency = <76800000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8650-mtp.dts b/arch/arm64/boot/dts/qcom/sm8650-mtp.dts
index d04ceaa73c2b..c63822f5b127 100644
--- a/arch/arm64/boot/dts/qcom/sm8650-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8650-mtp.dts
@@ -59,7 +59,7 @@
reg = <1>;
pmic_glink_ss_in: endpoint {
- remote-endpoint = <&usb_1_dwc3_ss>;
+ remote-endpoint = <&usb_dp_qmpphy_out>;
};
};
};
@@ -641,10 +641,6 @@
status = "okay";
};
-&pcie_1_phy_aux_clk {
- clock-frequency = <1000>;
-};
-
&pcie0 {
wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>;
perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
@@ -755,6 +751,16 @@
sound-name-prefix = "SpkrLeft";
vdd-1p8-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l3c_1p2>;
+
+ /*
+ * WSA8845 Port 1 (DAC) <=> SWR0 Port 1 (SPKR_L)
+ * WSA8845 Port 2 (COMP) <=> SWR0 Port 2 (SPKR_L_COMP)
+ * WSA8845 Port 3 (BOOST) <=> SWR0 Port 3 (SPKR_L_BOOST)
+ * WSA8845 Port 4 (PBR) <=> SWR0 Port 7 (PBR)
+ * WSA8845 Port 5 (VISENSE) <=> SWR0 Port 10 (SPKR_L_VI)
+ * WSA8845 Port 6 (CPS) <=> SWR0 Port 13 (CPS)
+ */
+ qcom,port-mapping = <1 2 3 7 10 13>;
};
/* WSA8845, Speaker Right */
@@ -768,6 +774,16 @@
sound-name-prefix = "SpkrRight";
vdd-1p8-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l3c_1p2>;
+
+ /*
+ * WSA8845 Port 1 (DAC) <=> SWR0 Port 4 (SPKR_R)
+ * WSA8845 Port 2 (COMP) <=> SWR0 Port 5 (SPKR_R_COMP)
+ * WSA8845 Port 3 (BOOST) <=> SWR0 Port 6 (SPKR_R_BOOST)
+ * WSA8845 Port 4 (PBR) <=> SWR0 Port 7 (PBR)
+ * WSA8845 Port 5 (VISENSE) <=> SWR0 Port 11 (SPKR_R_VI)
+ * WSA8845 Port 6 (CPS) <=> SWR0 Port 13 (CPS)
+ */
+ qcom,port-mapping = <4 5 6 7 11 13>;
};
};
@@ -853,10 +869,6 @@
remote-endpoint = <&pmic_glink_hs_in>;
};
-&usb_1_dwc3_ss {
- remote-endpoint = <&pmic_glink_ss_in>;
-};
-
&usb_1_hsphy {
vdd-supply = <&vreg_l1i_0p88>;
vdda12-supply = <&vreg_l3i_1p2>;
@@ -873,6 +885,10 @@
status = "okay";
};
+&usb_dp_qmpphy_out {
+ remote-endpoint = <&pmic_glink_ss_in>;
+};
+
&xo_board {
clock-frequency = <76800000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sm8650-qrd.dts b/arch/arm64/boot/dts/qcom/sm8650-qrd.dts
index 4e94f7fe4d2d..b0d7927b708f 100644
--- a/arch/arm64/boot/dts/qcom/sm8650-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8650-qrd.dts
@@ -203,6 +203,71 @@
};
};
};
+
+ wcn7850-pmu {
+ compatible = "qcom,wcn7850-pmu";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_en>;
+
+ wlan-enable-gpios = <&tlmm 16 GPIO_ACTIVE_HIGH>;
+ /*
+ * TODO Add bt-enable-gpios once the Bluetooth driver is
+ * converted to using the power sequencer.
+ */
+
+ vdd-supply = <&vreg_s4i_0p85>;
+ vddio-supply = <&vreg_l15b_1p8>;
+ vddio1p2-supply = <&vreg_l3c_1p2>;
+ vddaon-supply = <&vreg_s2c_0p8>;
+ vdddig-supply = <&vreg_s3c_0p9>;
+ vddrfa1p2-supply = <&vreg_s1c_1p2>;
+ vddrfa1p8-supply = <&vreg_s6c_1p8>;
+
+ clocks = <&rpmhcc RPMH_RF_CLK1>;
+
+ 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_1p8: ldo7 {
+ regulator-name = "vreg_pmu_rfa_1p8";
+ };
+
+ vreg_pmu_pcie_0p9: ldo8 {
+ regulator-name = "vreg_pmu_pcie_0p9";
+ };
+
+ vreg_pmu_pcie_1p8: ldo9 {
+ regulator-name = "vreg_pmu_pcie_1p8";
+ };
+ };
+ };
};
&apps_rsc {
@@ -832,11 +897,6 @@
&mdss_dp0_out {
data-lanes = <0 1>;
- remote-endpoint = <&usb_dp_qmpphy_dp_in>;
-};
-
-&pcie_1_phy_aux_clk {
- clock-frequency = <1000>;
};
&pcie0 {
@@ -849,6 +909,23 @@
status = "okay";
};
+&pcieport0 {
+ wifi@0 {
+ compatible = "pci17cb,1107";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ 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>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ };
+};
+
&pcie0_phy {
vdda-phy-supply = <&vreg_l1i_0p88>;
vdda-pll-supply = <&vreg_l3i_1p2>;
@@ -1012,6 +1089,16 @@
sound-name-prefix = "SpkrLeft";
vdd-1p8-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l3c_1p2>;
+
+ /*
+ * WSA8845 Port 1 (DAC) <=> SWR0 Port 1 (SPKR_L)
+ * WSA8845 Port 2 (COMP) <=> SWR0 Port 2 (SPKR_L_COMP)
+ * WSA8845 Port 3 (BOOST) <=> SWR0 Port 3 (SPKR_L_BOOST)
+ * WSA8845 Port 4 (PBR) <=> SWR0 Port 7 (PBR)
+ * WSA8845 Port 5 (VISENSE) <=> SWR0 Port 10 (SPKR_L_VI)
+ * WSA8845 Port 6 (CPS) <=> SWR0 Port 13 (CPS)
+ */
+ qcom,port-mapping = <1 2 3 7 10 13>;
};
/* WSA8845, Speaker Right */
@@ -1025,6 +1112,16 @@
sound-name-prefix = "SpkrRight";
vdd-1p8-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l3c_1p2>;
+
+ /*
+ * WSA8845 Port 1 (DAC) <=> SWR0 Port 4 (SPKR_R)
+ * WSA8845 Port 2 (COMP) <=> SWR0 Port 5 (SPKR_R_COMP)
+ * WSA8845 Port 3 (BOOST) <=> SWR0 Port 6 (SPKR_R_BOOST)
+ * WSA8845 Port 4 (PBR) <=> SWR0 Port 7 (PBR)
+ * WSA8845 Port 5 (VISENSE) <=> SWR0 Port 11 (SPKR_R_VI)
+ * WSA8845 Port 6 (CPS) <=> SWR0 Port 13 (CPS)
+ */
+ qcom,port-mapping = <4 5 6 7 11 13>;
};
};
@@ -1143,6 +1240,13 @@
bias-disable;
output-low;
};
+
+ wlan_en: wlan-en-state {
+ pins = "gpio16";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-down;
+ };
};
&uart14 {
@@ -1211,10 +1315,6 @@
remote-endpoint = <&pmic_glink_hs_in>;
};
-&usb_1_dwc3_ss {
- remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
-};
-
&usb_1_hsphy {
vdd-supply = <&vreg_l1i_0p88>;
vdda12-supply = <&vreg_l3i_1p2>;
@@ -1228,23 +1328,13 @@
vdda-phy-supply = <&vreg_l3i_1p2>;
vdda-pll-supply = <&vreg_l3g_0p91>;
- orientation-switch;
-
status = "okay";
};
-&usb_dp_qmpphy_dp_in {
- remote-endpoint = <&mdss_dp0_out>;
-};
-
&usb_dp_qmpphy_out {
remote-endpoint = <&redriver_ss_in>;
};
-&usb_dp_qmpphy_usb_ss_in {
- remote-endpoint = <&usb_1_dwc3_ss>;
-};
-
&xo_board {
clock-frequency = <76800000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
index 62a6e77730bc..9d9bbb9aca64 100644
--- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
@@ -4,10 +4,12 @@
*/
#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/clock/qcom,sm8650-camcc.h>
#include <dt-bindings/clock/qcom,sm8650-dispcc.h>
#include <dt-bindings/clock/qcom,sm8650-gcc.h>
#include <dt-bindings/clock/qcom,sm8650-gpucc.h>
#include <dt-bindings/clock/qcom,sm8650-tcsr.h>
+#include <dt-bindings/clock/qcom,sm8650-videocc.h>
#include <dt-bindings/dma/qcom-gpi.h>
#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
@@ -60,11 +62,6 @@
clock-mult = <1>;
clock-div = <2>;
};
-
- pcie_1_phy_aux_clk: pcie-1-phy-aux-clk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- };
};
cpus {
@@ -371,6 +368,7 @@
firmware {
scm: scm {
compatible = "qcom,scm-sm8650", "qcom,scm";
+ qcom,dload-mode = <&tcsr 0x19000>;
interconnects = <&aggre2_noc MASTER_CRYPTO QCOM_ICC_TAG_ALWAYS
&mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
};
@@ -394,8 +392,18 @@
reg = <0 0xa0000000 0 0>;
};
- pmu {
- compatible = "arm,armv8-pmuv3";
+ pmu-a520 {
+ compatible = "arm,cortex-a520-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ pmu-a720 {
+ compatible = "arm,cortex-a720-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ pmu-x4 {
+ compatible = "arm,cortex-x4-pmu";
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
};
@@ -758,8 +766,8 @@
<&bi_tcxo_ao_div2>,
<&sleep_clk>,
<&pcie0_phy>,
- <&pcie1_phy>,
- <&pcie_1_phy_aux_clk>,
+ <&pcie1_phy QMP_PCIE_PIPE_CLK>,
+ <&pcie1_phy QMP_PCIE_PHY_AUX_CLK>,
<&ufs_mem_phy 0>,
<&ufs_mem_phy 1>,
<&ufs_mem_phy 2>,
@@ -2208,7 +2216,7 @@
reg = <0 0x010c3000 0 0x1000>;
};
- pcie0: pci@1c00000 {
+ pcie0: pcie@1c00000 {
device_type = "pci";
compatible = "qcom,pcie-sm8650", "qcom,pcie-sm8550";
reg = <0 0x01c00000 0 0x3000>,
@@ -2294,7 +2302,7 @@
status = "disabled";
- pcie@0 {
+ pcieport0: pcie@0 {
device_type = "pci";
reg = <0x0 0x0 0x0 0x0 0x0>;
bus-range = <0x01 0xff>;
@@ -2336,7 +2344,7 @@
status = "disabled";
};
- pcie1: pci@1c08000 {
+ pcie1: pcie@1c08000 {
device_type = "pci";
compatible = "qcom,pcie-sm8650", "qcom,pcie-sm8550";
reg = <0 0x01c08000 0 0x3000>,
@@ -2467,7 +2475,7 @@
power-domains = <&gcc PCIE_1_PHY_GDSC>;
- #clock-cells = <0>;
+ #clock-cells = <1>;
clock-output-names = "pcie1_pipe_clk";
#phy-cells = <0>;
@@ -2626,6 +2634,7 @@
operating-points-v2 = <&gpu_opp_table>;
qcom,gmu = <&gmu>;
+ #cooling-cells = <2>;
status = "disabled";
@@ -3309,6 +3318,30 @@
};
};
+ videocc: clock-controller@aaf0000 {
+ compatible = "qcom,sm8650-videocc";
+ reg = <0 0x0aaf0000 0 0x10000>;
+ clocks = <&bi_tcxo_div2>,
+ <&gcc GCC_VIDEO_AHB_CLK>;
+ power-domains = <&rpmhpd RPMHPD_MMCX>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ camcc: clock-controller@ade0000 {
+ compatible = "qcom,sm8650-camcc";
+ reg = <0 0x0ade0000 0 0x20000>;
+ clocks = <&gcc GCC_CAMERA_AHB_CLK>,
+ <&bi_tcxo_div2>,
+ <&bi_tcxo_ao_div2>,
+ <&sleep_clk>;
+ power-domains = <&rpmhpd RPMHPD_MMCX>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
mdss: display-subsystem@ae00000 {
compatible = "qcom,sm8650-mdss";
reg = <0 0x0ae00000 0 0x1000>;
@@ -3675,6 +3708,7 @@
reg = <1>;
mdss_dp0_out: endpoint {
+ remote-endpoint = <&usb_dp_qmpphy_dp_in>;
};
};
};
@@ -3750,6 +3784,8 @@
#clock-cells = <1>;
#phy-cells = <1>;
+ orientation-switch;
+
status = "disabled";
ports {
@@ -3767,6 +3803,7 @@
reg = <1>;
usb_dp_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_ss>;
};
};
@@ -3774,6 +3811,7 @@
reg = <2>;
usb_dp_qmpphy_dp_in: endpoint {
+ remote-endpoint = <&mdss_dp0_out>;
};
};
};
@@ -3864,6 +3902,7 @@
reg = <1>;
usb_1_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
};
};
};
@@ -4982,12 +5021,14 @@
<0 0x25400000 0 0x200000>,
<0 0x25200000 0 0x200000>,
<0 0x25600000 0 0x200000>,
- <0 0x25800000 0 0x200000>;
+ <0 0x25800000 0 0x200000>,
+ <0 0x25a00000 0 0x200000>;
reg-names = "llcc0_base",
"llcc1_base",
"llcc2_base",
"llcc3_base",
- "llcc_broadcast_base";
+ "llcc_broadcast_base",
+ "llcc_broadcast_and_base";
interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
};
@@ -5328,8 +5369,6 @@
thermal-zones {
aoss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 0>;
trips {
@@ -5348,8 +5387,6 @@
};
cpuss0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 1>;
trips {
@@ -5368,8 +5405,6 @@
};
cpuss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 2>;
trips {
@@ -5388,8 +5423,6 @@
};
cpuss2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 3>;
trips {
@@ -5408,8 +5441,6 @@
};
cpuss3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 4>;
trips {
@@ -5428,8 +5459,6 @@
};
cpu2-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 5>;
trips {
@@ -5454,8 +5483,6 @@
};
cpu2-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 6>;
trips {
@@ -5480,8 +5507,6 @@
};
cpu3-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 7>;
trips {
@@ -5506,8 +5531,6 @@
};
cpu3-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 8>;
trips {
@@ -5532,8 +5555,6 @@
};
cpu4-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 9>;
trips {
@@ -5558,8 +5579,6 @@
};
cpu4-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 10>;
trips {
@@ -5584,8 +5603,6 @@
};
cpu5-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 11>;
trips {
@@ -5610,8 +5627,6 @@
};
cpu5-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 12>;
trips {
@@ -5636,8 +5651,6 @@
};
cpu6-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 13>;
trips {
@@ -5662,8 +5675,6 @@
};
cpu6-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens0 14>;
trips {
@@ -5688,8 +5699,6 @@
};
aoss1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 0>;
trips {
@@ -5708,8 +5717,6 @@
};
cpu7-top-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 1>;
trips {
@@ -5734,8 +5741,6 @@
};
cpu7-middle-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 2>;
trips {
@@ -5760,8 +5765,6 @@
};
cpu7-bottom-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 3>;
trips {
@@ -5786,8 +5789,6 @@
};
cpu0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 4>;
trips {
@@ -5812,8 +5813,6 @@
};
cpu1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 5>;
trips {
@@ -5839,7 +5838,7 @@
nsphvx0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 6>;
trips {
@@ -5859,7 +5858,7 @@
nsphvx1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 7>;
trips {
@@ -5879,7 +5878,7 @@
nsphmx0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 8>;
trips {
@@ -5899,7 +5898,7 @@
nsphmx1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 9>;
trips {
@@ -5919,7 +5918,7 @@
nsphmx2-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 10>;
trips {
@@ -5939,7 +5938,7 @@
nsphmx3-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 11>;
trips {
@@ -5959,7 +5958,7 @@
video-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens1 12>;
trips {
@@ -5979,7 +5978,7 @@
ddr-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens1 13>;
trips {
@@ -5998,8 +5997,6 @@
};
camera0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 14>;
trips {
@@ -6018,8 +6015,6 @@
};
camera1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens1 15>;
trips {
@@ -6038,8 +6033,6 @@
};
aoss2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 0>;
trips {
@@ -6059,19 +6052,32 @@
gpuss0-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 1>;
+ cooling-maps {
+ map0 {
+ trip = <&gpu0_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+
trips {
- trip-point0 {
+ gpu0_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
- gpuss0-critical {
+ trip-point2 {
temperature = <110000>;
- hysteresis = <0>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -6079,19 +6085,32 @@
gpuss1-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 2>;
+ cooling-maps {
+ map0 {
+ trip = <&gpu1_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+
trips {
- trip-point0 {
+ gpu1_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
- gpuss1-critical {
+ trip-point2 {
temperature = <110000>;
- hysteresis = <0>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -6099,19 +6118,32 @@
gpuss2-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 3>;
+ cooling-maps {
+ map0 {
+ trip = <&gpu2_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+
trips {
- trip-point0 {
+ gpu2_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
- gpuss2-critical {
+ trip-point2 {
temperature = <110000>;
- hysteresis = <0>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -6119,19 +6151,32 @@
gpuss3-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 4>;
+ cooling-maps {
+ map0 {
+ trip = <&gpu3_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+
trips {
- trip-point0 {
+ gpu3_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
- gpuss3-critical {
+ trip-point2 {
temperature = <110000>;
- hysteresis = <0>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -6139,19 +6184,32 @@
gpuss4-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 5>;
+ cooling-maps {
+ map0 {
+ trip = <&gpu4_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+
trips {
- trip-point0 {
+ gpu4_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
- gpuss4-critical {
+ trip-point2 {
temperature = <110000>;
- hysteresis = <0>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -6159,19 +6217,32 @@
gpuss5-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 6>;
+ cooling-maps {
+ map0 {
+ trip = <&gpu5_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+
trips {
- trip-point0 {
+ gpu5_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
- gpuss5-critical {
+ trip-point2 {
temperature = <110000>;
- hysteresis = <0>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -6179,19 +6250,32 @@
gpuss6-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 7>;
+ cooling-maps {
+ map0 {
+ trip = <&gpu6_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+
trips {
- trip-point0 {
+ gpu6_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
- gpuss6-critical {
+ trip-point2 {
temperature = <110000>;
- hysteresis = <0>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -6199,27 +6283,38 @@
gpuss7-thermal {
polling-delay-passive = <10>;
- polling-delay = <0>;
+
thermal-sensors = <&tsens2 8>;
+ cooling-maps {
+ map0 {
+ trip = <&gpu7_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+
trips {
- trip-point0 {
+ gpu7_alert0: trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
temperature = <90000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "hot";
};
- gpuss7-critical {
+ trip-point2 {
temperature = <110000>;
- hysteresis = <0>;
+ hysteresis = <1000>;
type = "critical";
};
};
};
modem0-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 9>;
trips {
@@ -6238,8 +6333,6 @@
};
modem1-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 10>;
trips {
@@ -6258,8 +6351,6 @@
};
modem2-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 11>;
trips {
@@ -6278,8 +6369,6 @@
};
modem3-thermal {
- polling-delay-passive = <0>;
- polling-delay = <0>;
thermal-sensors = <&tsens2 12>;
trips {
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts b/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts
new file mode 100644
index 000000000000..7fb980fcb307
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts
@@ -0,0 +1,616 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2024, Xilin Wu <[email protected]>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+#include "x1e80100.dtsi"
+#include "x1e80100-pmics.dtsi"
+
+/ {
+ model = "ASUS Vivobook S 15";
+ compatible = "asus,vivobook-s15", "qcom,x1e80100";
+ chassis-type = "laptop";
+
+ 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>;
+
+ /* Left-side port, closer to the screen */
+ 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 port, farther from the screen */
+ 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;
+ };
+ };
+
+ 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";
+
+ 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_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";
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8550-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vdd-bob1-supply = <&vph_pwr>;
+ vdd-bob2-supply = <&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 = <3100000>;
+ 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>;
+ };
+ };
+
+ 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>;
+ vdd-s4-supply = <&vph_pwr>;
+
+ vreg_s4c_1p8: smps4 {
+ regulator-name = "vreg_s4c_1p8";
+ regulator-min-microvolt = <1856000>;
+ regulator-max-microvolt = <2000000>;
+ 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 = <&vph_pwr>;
+
+ vreg_l1d_0p8: ldo1 {
+ regulator-name = "vreg_l1d_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2d_0p9: ldo2 {
+ regulator-name = "vreg_l2d_0p9";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <920000>;
+ 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 = <920000>;
+ 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 = <&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 = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ };
+
+ 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 = <&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_0p8: ldo1 {
+ regulator-name = "vreg_l1j_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2j_1p2: ldo2 {
+ regulator-name = "vreg_l2j_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3j_0p8: ldo3 {
+ regulator-name = "vreg_l3j_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ touchpad@15 {
+ compatible = "hid-over-i2c";
+ reg = <0x15>;
+
+ hid-descr-addr = <0x1>;
+ interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-0 = <&tpad_default>;
+ pinctrl-names = "default";
+
+ wakeup-source;
+ };
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ /* PS8830 USB4 Retimer? @ 0x8 */
+};
+
+&i2c3 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ /* PS8830 USB4 Retimer? @ 0x8 */
+};
+
+&i2c5 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ keyboard@3a {
+ compatible = "hid-over-i2c";
+ reg = <0x3a>;
+
+ hid-descr-addr = <0x1>;
+ interrupts-extended = <&tlmm 67 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-0 = <&kybd_default>;
+ pinctrl-names = "default";
+
+ wakeup-source;
+ };
+
+ /* EC? @ 0x5b, 0x76 */
+};
+
+&i2c7 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ /* PS8830 USB4 Retimer? @ 0x8 */
+};
+
+&mdss {
+ status = "okay";
+};
+
+&mdss_dp3 {
+ compatible = "qcom,x1e80100-dp";
+ /delete-property/ #sound-dai-cells;
+
+ status = "okay";
+
+ aux-bus {
+ panel {
+ compatible = "edp-panel";
+ power-supply = <&vreg_edp_3p3>;
+
+ 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 {
+ status = "okay";
+};
+
+&pcie4_phy {
+ vdda-phy-supply = <&vreg_l3j_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/ASUSTeK/vivobook-s15/qcadsp8380.mbn",
+ "qcom/x1e80100/ASUSTeK/vivobook-s15/adsp_dtbs.elf";
+
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/x1e80100/ASUSTeK/vivobook-s15/qccdsp8380.mbn",
+ "qcom/x1e80100/ASUSTeK/vivobook-s15/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>;
+};
+
+&smb2360_2 {
+ status = "disabled";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <34 2>, /* Unused */
+ <44 4>, /* SPI (TPM) */
+ <238 1>; /* UFS Reset */
+
+ edp_reg_en: edp-reg-en-state {
+ pins = "gpio70";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ kybd_default: kybd-default-state {
+ pins = "gpio67";
+ function = "gpio";
+ bias-disable;
+ };
+
+ nvme_reg_en: nvme-reg-en-state {
+ pins = "gpio18";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ pcie6a_default: pcie2a-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-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio154";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ tpad_default: tpad-default-state {
+ pins = "gpio3";
+ function = "gpio";
+ bias-disable;
+ };
+};
+
+&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_0p8>;
+
+ orientation-switch;
+
+ 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>;
+
+ orientation-switch;
+
+ 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-crd.dts b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
index c5c2895b37c7..6152bcd0bc1f 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
+++ b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
@@ -49,6 +49,113 @@
stdout-path = "serial0:115200n8";
};
+ pmic-glink {
+ compatible = "qcom,x1e80100-pmic-glink",
+ "qcom,sm8550-pmic-glink",
+ "qcom,pmic-glink";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ orientation-gpios = <&tlmm 121 GPIO_ACTIVE_HIGH>,
+ <&tlmm 123 GPIO_ACTIVE_HIGH>,
+ <&tlmm 125 GPIO_ACTIVE_HIGH>;
+
+ /* Left-side rear 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 front 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>;
+ };
+ };
+ };
+ };
+
+ /* Right-side port */
+ connector@2 {
+ compatible = "usb-c-connector";
+ reg = <2>;
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ pmic_glink_ss2_hs_in: endpoint {
+ remote-endpoint = <&usb_1_ss2_dwc3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ pmic_glink_ss2_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss2_qmpphy_out>;
+ };
+ };
+ };
+ };
+ };
+
+ reserved-memory {
+ linux,cma {
+ compatible = "shared-dma-pool";
+ size = <0x0 0x8000000>;
+ reusable;
+ linux,cma-default;
+ };
+ };
+
sound {
compatible = "qcom,x1e80100-sndcard";
model = "X1E80100-CRD";
@@ -93,7 +200,7 @@
};
codec {
- sound-dai = <&wcd938x 1>, <&swr2 0>, <&lpass_txmacro 0>;
+ sound-dai = <&wcd938x 1>, <&swr2 1>, <&lpass_txmacro 0>;
};
platform {
@@ -164,6 +271,20 @@
regulator-always-on;
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-names = "default";
+ pinctrl-0 = <&nvme_reg_en>;
+ };
};
&apps_rsc {
@@ -646,11 +767,19 @@
};
&pcie6a {
+ perst-gpios = <&tlmm 152 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 154 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_nvme>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie6a_default>;
+
status = "okay";
};
&pcie6a_phy {
- vdda-phy-supply = <&vreg_l3j_0p8>;
+ vdda-phy-supply = <&vreg_l1d_0p8>;
vdda-pll-supply = <&vreg_l2j_1p2>;
status = "okay";
@@ -744,7 +873,7 @@
wcd_tx: codec@0,3 {
compatible = "sdw20217010d00";
reg = <0 3>;
- qcom,tx-port-mapping = <1 1 2 3>;
+ qcom,tx-port-mapping = <2 2 3 4>;
};
};
@@ -795,6 +924,36 @@
bias-disable;
};
+ nvme_reg_en: nvme-reg-en-state {
+ pins = "gpio18";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ pcie6a_default: pcie2a-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-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio154";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
tpad_default: tpad-default-state {
pins = "gpio3";
function = "gpio";
@@ -831,8 +990,8 @@
};
&usb_1_ss0_hsphy {
- vdd-supply = <&vreg_l2e_0p8>;
- vdda12-supply = <&vreg_l3e_1p2>;
+ vdd-supply = <&vreg_l3j_0p8>;
+ vdda12-supply = <&vreg_l2j_1p2>;
phys = <&smb2360_0_eusb2_repeater>;
@@ -840,6 +999,9 @@
};
&usb_1_ss0_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l1j_0p8>;
+
status = "okay";
};
@@ -849,12 +1011,19 @@
&usb_1_ss0_dwc3 {
dr_mode = "host";
- usb-role-switch;
+};
+
+&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_l2e_0p8>;
- vdda12-supply = <&vreg_l3e_1p2>;
+ vdd-supply = <&vreg_l3j_0p8>;
+ vdda12-supply = <&vreg_l2j_1p2>;
phys = <&smb2360_1_eusb2_repeater>;
@@ -862,6 +1031,9 @@
};
&usb_1_ss1_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l2d_0p9>;
+
status = "okay";
};
@@ -871,12 +1043,19 @@
&usb_1_ss1_dwc3 {
dr_mode = "host";
- usb-role-switch;
+};
+
+&usb_1_ss1_dwc3_hs {
+ remote-endpoint = <&pmic_glink_ss1_hs_in>;
+};
+
+&usb_1_ss1_qmpphy_out {
+ remote-endpoint = <&pmic_glink_ss1_ss_in>;
};
&usb_1_ss2_hsphy {
- vdd-supply = <&vreg_l2e_0p8>;
- vdda12-supply = <&vreg_l3e_1p2>;
+ vdd-supply = <&vreg_l3j_0p8>;
+ vdda12-supply = <&vreg_l2j_1p2>;
phys = <&smb2360_2_eusb2_repeater>;
@@ -884,6 +1063,9 @@
};
&usb_1_ss2_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l2d_0p9>;
+
status = "okay";
};
@@ -893,5 +1075,12 @@
&usb_1_ss2_dwc3 {
dr_mode = "host";
- usb-role-switch;
+};
+
+&usb_1_ss2_dwc3_hs {
+ remote-endpoint = <&pmic_glink_ss2_hs_in>;
+};
+
+&usb_1_ss2_qmpphy_out {
+ remote-endpoint = <&pmic_glink_ss2_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
new file mode 100644
index 000000000000..fbff558f5b07
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts
@@ -0,0 +1,929 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+#include "x1e80100.dtsi"
+#include "x1e80100-pmics.dtsi"
+
+/ {
+ model = "Lenovo Yoga Slim 7x";
+ compatible = "lenovo,yoga-slim7x", "qcom,x1e80100";
+
+ pmic-glink {
+ compatible = "qcom,x1e80100-pmic-glink",
+ "qcom,sm8550-pmic-glink",
+ "qcom,pmic-glink";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ orientation-gpios = <&tlmm 121 GPIO_ACTIVE_HIGH>,
+ <&tlmm 123 GPIO_ACTIVE_HIGH>,
+ <&tlmm 125 GPIO_ACTIVE_HIGH>;
+
+ /* Left-side rear 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 front 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>;
+ };
+ };
+ };
+ };
+
+ /* Right-side port */
+ connector@2 {
+ compatible = "usb-c-connector";
+ reg = <2>;
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ pmic_glink_ss2_hs_in: endpoint {
+ remote-endpoint = <&usb_1_ss2_dwc3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ pmic_glink_ss2_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss2_qmpphy_out>;
+ };
+ };
+ };
+ };
+ };
+
+ reserved-memory {
+ linux,cma {
+ compatible = "shared-dma-pool";
+ size = <0x0 0x8000000>;
+ reusable;
+ linux,cma-default;
+ };
+ };
+
+ sound {
+ compatible = "qcom,x1e80100-sndcard";
+ model = "X1E80100-LENOVO-Yoga-Slim7x";
+ audio-routing = "WooferLeft IN", "WSA WSA_SPK1 OUT",
+ "TweeterLeft IN", "WSA WSA_SPK2 OUT",
+ "WooferRight IN", "WSA2 WSA_SPK2 OUT",
+ "TweeterRight IN", "WSA2 WSA_SPK2 OUT";
+
+ wsa-dai-link {
+ link-name = "WSA Playback";
+
+ cpu {
+ sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>;
+ };
+
+ codec {
+ sound-dai = <&left_woofer>, <&left_tweeter>,
+ <&swr0 0>, <&lpass_wsamacro 0>,
+ <&right_woofer>, <&right_tweeter>,
+ <&swr3 0>, <&lpass_wsa2macro 0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+
+ va-dai-link {
+ link-name = "VA Capture";
+
+ cpu {
+ sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>;
+ };
+
+ codec {
+ sound-dai = <&lpass_vamacro 0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+ };
+
+ 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";
+
+ 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_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";
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8550-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vdd-bob1-supply = <&vph_pwr>;
+ vdd-bob2-supply = <&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_l1b_1p8: ldo1 {
+ regulator-name = "vreg_l1b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2b_3p0: ldo2 {
+ regulator-name = "vreg_l2b_3p0";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3100000>;
+ 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_l12b_1p2: ldo12 {
+ regulator-name = "vreg_l12b_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ 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>;
+ };
+
+ };
+
+ 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>;
+ vdd-s4-supply = <&vph_pwr>;
+
+ 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 = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3c_0p8: ldo3 {
+ regulator-name = "vreg_l3c_0p8";
+ regulator-min-microvolt = <880000>;
+ 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 = <&vph_pwr>;
+
+ vreg_l1d_0p8: ldo1 {
+ regulator-name = "vreg_l1d_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2d_0p9: ldo2 {
+ regulator-name = "vreg_l2d_0p9";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <920000>;
+ 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 = <920000>;
+ 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 = <&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>;
+ };
+
+ vreg_l1f_1p0: ldo1 {
+ regulator-name = "vreg_l1f_1p0";
+ regulator-min-microvolt = <1024000>;
+ regulator-max-microvolt = <1024000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2f_1p0: ldo2 {
+ regulator-name = "vreg_l2f_1p0";
+ regulator-min-microvolt = <1024000>;
+ regulator-max-microvolt = <1024000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3f_1p0: ldo3 {
+ regulator-name = "vreg_l3f_1p0";
+ regulator-min-microvolt = <1024000>;
+ regulator-max-microvolt = <1024000>;
+ 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 = <&vph_pwr>;
+ vdd-s2-supply = <&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 = <920000>;
+ 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 = <&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_0p8: ldo1 {
+ regulator-name = "vreg_l1j_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2j_1p2: ldo2 {
+ regulator-name = "vreg_l2j_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3j_0p8: ldo3 {
+ regulator-name = "vreg_l3j_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&gpu {
+ status = "okay";
+
+ zap-shader {
+ firmware-name = "qcom/x1e80100/LENOVO/83ED/qcdxkmsuc8380.mbn";
+ };
+};
+
+&i2c0 {
+ 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;
+ };
+
+ keyboard@3a {
+ compatible = "hid-over-i2c";
+ reg = <0x3a>;
+
+ hid-descr-addr = <0x1>;
+ interrupts-extended = <&tlmm 67 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-0 = <&kybd_default>;
+ pinctrl-names = "default";
+
+ wakeup-source;
+ };
+};
+
+&i2c8 {
+ clock-frequency = <400000>;
+
+ status = "okay";
+
+ touchscreen@14 {
+ compatible = "hid-over-i2c";
+ reg = <0x14>;
+
+ hid-descr-addr = <0x1>;
+ interrupts-extended = <&tlmm 51 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-0 = <&ts0_default>;
+ pinctrl-names = "default";
+ };
+};
+
+&lpass_tlmm {
+ spkr_01_sd_n_active: spkr-01-sd-n-active-state {
+ pins = "gpio12";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+
+ spkr_23_sd_n_active: spkr-23-sd-n-active-state {
+ pins = "gpio13";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+};
+
+&lpass_vamacro {
+ pinctrl-0 = <&dmic01_default>, <&dmic23_default>;
+ pinctrl-names = "default";
+
+ vdd-micb-supply = <&vreg_l1b_1p8>;
+ qcom,dmic-sample-rate = <4800000>;
+};
+
+&mdss {
+ status = "okay";
+};
+
+&mdss_dp3 {
+ compatible = "qcom,x1e80100-dp";
+ /delete-property/ #sound-dai-cells;
+
+ status = "okay";
+
+ aux-bus {
+ panel {
+ compatible = "edp-panel";
+ power-supply = <&vreg_edp_3p3>;
+
+ 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 {
+ status = "okay";
+};
+
+&pcie4_phy {
+ vdda-phy-supply = <&vreg_l3j_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/LENOVO/83ED/qcadsp8380.mbn",
+ "qcom/x1e80100/LENOVO/83ED/adsp_dtbs.elf";
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/x1e80100/LENOVO/83ED/qccdsp8380.mbn",
+ "qcom/x1e80100/LENOVO/83ED/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>;
+};
+
+&smb2360_2_eusb2_repeater {
+ vdd18-supply = <&vreg_l3d_1p8>;
+ vdd3-supply = <&vreg_l8b_3p0>;
+};
+
+&swr0 {
+ status = "okay";
+
+ pinctrl-0 = <&wsa_swr_active>, <&spkr_01_sd_n_active>;
+ pinctrl-names = "default";
+
+ /* WSA8845, Left Woofer */
+ left_woofer: speaker@0,0 {
+ compatible = "sdw20217020400";
+ reg = <0 0>;
+ reset-gpios = <&lpass_tlmm 12 GPIO_ACTIVE_LOW>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "WooferLeft";
+ vdd-1p8-supply = <&vreg_l15b_1p8>;
+ vdd-io-supply = <&vreg_l12b_1p2>;
+ qcom,port-mapping = <1 2 3 7 10 13>;
+ };
+
+ /* WSA8845, Left Tweeter */
+ left_tweeter: speaker@0,1 {
+ compatible = "sdw20217020400";
+ reg = <0 1>;
+ reset-gpios = <&lpass_tlmm 12 GPIO_ACTIVE_LOW>;
+ #sound-dai-cells = <0>;
+ 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>;
+ };
+};
+
+
+&swr3 {
+ status = "okay";
+
+ pinctrl-0 = <&wsa2_swr_active>, <&spkr_23_sd_n_active>;
+ pinctrl-names = "default";
+
+ /* WSA8845, Right Woofer */
+ right_woofer: speaker@0,0 {
+ compatible = "sdw20217020400";
+ reg = <0 0>;
+ reset-gpios = <&lpass_tlmm 13 GPIO_ACTIVE_LOW>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "WooferRight";
+ vdd-1p8-supply = <&vreg_l15b_1p8>;
+ vdd-io-supply = <&vreg_l12b_1p2>;
+ qcom,port-mapping = <1 2 3 7 10 13>;
+ };
+
+ /* WSA8845, Right Tweeter */
+ right_tweeter: speaker@0,1 {
+ compatible = "sdw20217020400";
+ reg = <0 1>;
+ reset-gpios = <&lpass_tlmm 13 GPIO_ACTIVE_LOW>;
+ #sound-dai-cells = <0>;
+ 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>;
+ };
+};
+
+&tlmm {
+ gpio-reserved-ranges = <34 2>, /* Unused */
+ <44 4>, /* SPI (TPM) */
+ <238 1>; /* UFS Reset */
+
+ edp_reg_en: edp-reg-en-state {
+ pins = "gpio70";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ kybd_default: kybd-default-state {
+ pins = "gpio67";
+ function = "gpio";
+ bias-disable;
+ };
+
+ nvme_reg_en: nvme-reg-en-state {
+ pins = "gpio18";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ pcie6a_default: pcie2a-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-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio154";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ tpad_default: tpad-default-state {
+ pins = "gpio3";
+ function = "gpio";
+ bias-disable;
+ };
+
+ ts0_default: ts0-default-state {
+ int-n-pins {
+ pins = "gpio51";
+ function = "gpio";
+ bias-disable;
+ };
+
+ reset-n-pins {
+ pins = "gpio48";
+ function = "gpio";
+ output-high;
+ drive-strength = <16>;
+ };
+ };
+
+};
+
+&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_0p8>;
+
+ orientation-switch;
+
+ 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>;
+
+ orientation-switch;
+
+ 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>;
+};
+
+&usb_1_ss2_hsphy {
+ vdd-supply = <&vreg_l3j_0p8>;
+ vdda12-supply = <&vreg_l2j_1p2>;
+
+ phys = <&smb2360_2_eusb2_repeater>;
+
+ status = "okay";
+};
+
+&usb_1_ss2_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l2d_0p9>;
+
+ status = "okay";
+};
+
+&usb_1_ss2 {
+ status = "okay";
+};
+
+&usb_1_ss2_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_1_ss2_dwc3_hs {
+ remote-endpoint = <&pmic_glink_ss2_hs_in>;
+};
+
+&usb_1_ss2_qmpphy_out {
+ remote-endpoint = <&pmic_glink_ss2_ss_in>;
+};
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi b/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi
index 04301f772fbd..e34e70922cd3 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi
@@ -3,10 +3,477 @@
* Copyright (c) 2024, Linaro Limited
*/
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
/ {
+ thermal-zones {
+ pm8550-thermal {
+ polling-delay-passive = <100>;
+
+ thermal-sensors = <&pm8550_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+
+ pm8550ve-2-thermal {
+ polling-delay-passive = <100>;
+
+ thermal-sensors = <&pm8550ve_2_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+
+ pmc8380-3-thermal {
+ polling-delay-passive = <100>;
+
+ thermal-sensors = <&pmc8380_3_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+
+ pmc8380-4-thermal {
+ polling-delay-passive = <100>;
+
+ thermal-sensors = <&pmc8380_4_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+
+ pmc8380-5-thermal {
+ polling-delay-passive = <100>;
+
+ thermal-sensors = <&pmc8380_5_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+
+ pmc8380-6-thermal {
+ polling-delay-passive = <100>;
+
+ thermal-sensors = <&pmc8380_6_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+
+ pm8550ve-8-thermal {
+ polling-delay-passive = <100>;
+
+ thermal-sensors = <&pm8550ve_8_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+
+ pm8550ve-9-thermal {
+ polling-delay-passive = <100>;
+
+ thermal-sensors = <&pm8550ve_9_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+
+ pm8010-thermal {
+ polling-delay-passive = <100>;
+
+ thermal-sensors = <&pm8010_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+ };
+ };
+ };
+};
+
+&spmi_bus0 {
+ /* PMK8380 */
+ pmk8550: pmic@0 {
+ compatible = "qcom,pm8550", "qcom,spmi-pmic";
+ reg = <0x0 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmk8550_pon: pon@1300 {
+ compatible = "qcom,pmk8350-pon";
+ reg = <0x1300>, <0x800>;
+ reg-names = "hlos", "pbs";
+
+ pon_pwrkey: pwrkey {
+ compatible = "qcom,pmk8350-pwrkey";
+ interrupts = <0x0 0x13 0x7 IRQ_TYPE_EDGE_BOTH>;
+ linux,code = <KEY_POWER>;
+ };
+
+ pon_resin: resin {
+ compatible = "qcom,pmk8350-resin";
+ interrupts = <0x0 0x13 0x6 IRQ_TYPE_EDGE_BOTH>;
+ status = "disabled";
+ };
+ };
+
+ pmk8550_rtc: rtc@6100 {
+ compatible = "qcom,pmk8350-rtc";
+ reg = <0x6100>, <0x6200>;
+ reg-names = "rtc", "alarm";
+ interrupts = <0x0 0x62 0x1 IRQ_TYPE_EDGE_RISING>;
+ /* Not yet sure what blocks access */
+ status = "reserved";
+ };
+
+ pmk8550_sdam_2: nvram@7100 {
+ compatible = "qcom,spmi-sdam";
+ reg = <0x7100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x7100 0x100>;
+
+ reboot_reason: reboot-reason@48 {
+ reg = <0x48 0x1>;
+ bits = <1 7>;
+ };
+ };
+
+ pmk8550_gpios: gpio@8800 {
+ compatible = "qcom,pmk8550-gpio", "qcom,spmi-gpio";
+ reg = <0xb800>;
+ gpio-controller;
+ gpio-ranges = <&pmk8550_gpios 0 0 6>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ /* PMC8380C */
+ pm8550: pmic@1 {
+ compatible = "qcom,pm8550", "qcom,spmi-pmic";
+ reg = <0x1 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8550_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0x1 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ pm8550_gpios: gpio@8800 {
+ compatible = "qcom,pm8550-gpio", "qcom,spmi-gpio";
+ reg = <0x8800>;
+ gpio-controller;
+ gpio-ranges = <&pm8550_gpios 0 0 12>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pm8550_flash: led-controller@ee00 {
+ compatible = "qcom,pm8550-flash-led", "qcom,spmi-flash-led";
+ reg = <0xee00>;
+ status = "disabled";
+ };
+
+ pm8550_pwm: pwm {
+ compatible = "qcom,pm8550-pwm", "qcom,pm8350c-pwm";
+ #pwm-cells = <2>;
+
+ status = "disabled";
+ };
+ };
+
+ /* PMC8380VE */
+ pm8550ve_2: pmic@2 {
+ compatible = "qcom,pm8550", "qcom,spmi-pmic";
+ reg = <0x2 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8550ve_2_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0x2 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ pm8550ve_2_gpios: gpio@8800 {
+ compatible = "qcom,pm8550ve-gpio", "qcom,spmi-gpio";
+ reg = <0x8800>;
+ gpio-controller;
+ gpio-ranges = <&pm8550ve_2_gpios 0 0 8>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ /* PMC8380 is actually not a PM8550 series rebrand */
+ pmc8380_3: pmic@3 {
+ compatible = "qcom,pmc8380", "qcom,spmi-pmic";
+ reg = <0x3 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmc8380_3_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0x3 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ pmc8380_3_gpios: gpio@8800 {
+ compatible = "qcom,pmc8380-gpio", "qcom,spmi-gpio";
+ reg = <0x8800>;
+ gpio-controller;
+ gpio-ranges = <&pmc8380_3_gpios 0 0 10>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pmc8380_4: pmic@4 {
+ compatible = "qcom,pmc8380", "qcom,spmi-pmic";
+ reg = <0x4 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmc8380_4_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0x4 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ pmc8380_4_gpios: gpio@8800 {
+ compatible = "qcom,pmc8380-gpio", "qcom,spmi-gpio";
+ reg = <0x8800>;
+ gpio-controller;
+ gpio-ranges = <&pmc8380_4_gpios 0 0 10>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pmc8380_5: pmic@5 {
+ compatible = "qcom,pmc8380", "qcom,spmi-pmic";
+ reg = <0x5 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmc8380_5_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0x5 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ pmc8380_5_gpios: gpio@8800 {
+ compatible = "qcom,pmc8380-gpio", "qcom,spmi-gpio";
+ reg = <0x8800>;
+ gpio-controller;
+ gpio-ranges = <&pmc8380_5_gpios 0 0 10>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pmc8380_6: pmic@6 {
+ compatible = "qcom,pmc8380", "qcom,spmi-pmic";
+ reg = <0x6 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmc8380_6_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0x6 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ pmc8380_6_gpios: gpio@8800 {
+ compatible = "qcom,pmc8380-gpio", "qcom,spmi-gpio";
+ reg = <0x8800>;
+ gpio-controller;
+ gpio-ranges = <&pmc8380_6_gpios 0 0 10>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ /* PMC8380VE */
+ pm8550ve_8: pmic@8 {
+ compatible = "qcom,pm8550", "qcom,spmi-pmic";
+ reg = <0x8 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8550ve_8_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0x8 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ pm8550ve_8_gpios: gpio@8800 {
+ compatible = "qcom,pm8550ve-gpio", "qcom,spmi-gpio";
+ reg = <0x8800>;
+ gpio-controller;
+ gpio-ranges = <&pm8550ve_8_gpios 0 0 8>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ /* PMC8380VE */
+ pm8550ve_9: pmic@9 {
+ compatible = "qcom,pm8550", "qcom,spmi-pmic";
+ reg = <0x9 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8550ve_9_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0x9 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ pm8550ve_9_gpios: gpio@8800 {
+ compatible = "qcom,pm8550ve-gpio", "qcom,spmi-gpio";
+ reg = <0x8800>;
+ gpio-controller;
+ gpio-ranges = <&pm8550ve_9_gpios 0 0 8>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pm8010: pmic@c {
+ compatible = "qcom,pm8010", "qcom,spmi-pmic";
+ reg = <0xc SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8010_temp_alarm: temp-alarm@2400 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0x2400>;
+ interrupts = <0xc 0x24 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+ };
};
&spmi_bus1 {
@@ -48,4 +515,19 @@
#phy-cells = <0>;
};
};
+
+ smb2360_3: pmic@c {
+ compatible = "qcom,smb2360", "qcom,spmi-pmic";
+ reg = <0xc SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+
+ smb2360_3_eusb2_repeater: phy@fd00 {
+ compatible = "qcom,smb2360-eusb2-repeater";
+ reg = <0xfd00>;
+ #phy-cells = <0>;
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
index 2061fbe7b75a..72a4f4138616 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
+++ b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
@@ -19,10 +19,200 @@
serial0 = &uart21;
};
+ wcd938x: audio-codec {
+ compatible = "qcom,wcd9385-codec";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wcd_default>;
+
+ qcom,micbias1-microvolt = <1800000>;
+ qcom,micbias2-microvolt = <1800000>;
+ qcom,micbias3-microvolt = <1800000>;
+ qcom,micbias4-microvolt = <1800000>;
+ qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000 500000 500000 500000>;
+ qcom,mbhc-headset-vthreshold-microvolt = <1700000>;
+ qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
+ qcom,rx-device = <&wcd_rx>;
+ qcom,tx-device = <&wcd_tx>;
+
+ reset-gpios = <&tlmm 191 GPIO_ACTIVE_LOW>;
+
+ vdd-buck-supply = <&vreg_l15b_1p8>;
+ vdd-rxtx-supply = <&vreg_l15b_1p8>;
+ vdd-io-supply = <&vreg_l15b_1p8>;
+ vdd-mic-bias-supply = <&vreg_bob1>;
+
+ #sound-dai-cells = <1>;
+ };
+
chosen {
stdout-path = "serial0:115200n8";
};
+ pmic-glink {
+ compatible = "qcom,x1e80100-pmic-glink",
+ "qcom,sm8550-pmic-glink",
+ "qcom,pmic-glink";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ orientation-gpios = <&tlmm 121 GPIO_ACTIVE_HIGH>,
+ <&tlmm 123 GPIO_ACTIVE_HIGH>,
+ <&tlmm 125 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_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>;
+ };
+ };
+ };
+ };
+
+ 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>;
+ };
+ };
+ };
+ };
+
+ connector@2 {
+ compatible = "usb-c-connector";
+ reg = <2>;
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ pmic_glink_ss2_hs_in: endpoint {
+ remote-endpoint = <&usb_1_ss2_dwc3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ pmic_glink_ss2_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss2_qmpphy_out>;
+ };
+ };
+ };
+ };
+ };
+
+ reserved-memory {
+ linux,cma {
+ compatible = "shared-dma-pool";
+ size = <0x0 0x8000000>;
+ reusable;
+ linux,cma-default;
+ };
+ };
+
+ sound {
+ compatible = "qcom,x1e80100-sndcard";
+ model = "X1E80100-QCP";
+ audio-routing = "SpkrLeft IN", "WSA WSA_SPK1 OUT",
+ "SpkrRight IN", "WSA WSA_SPK2 OUT",
+ "IN1_HPHL", "HPHL_OUT",
+ "IN2_HPHR", "HPHR_OUT",
+ "AMIC2", "MIC BIAS2",
+ "TX SWR_INPUT1", "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>, <&lpass_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 1>, <&lpass_txmacro 0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+
+ wsa-dai-link {
+ link-name = "WSA Playback";
+
+ cpu {
+ sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>;
+ };
+
+ codec {
+ sound-dai = <&left_spkr>, <&right_spkr>,
+ <&swr0 0>, <&lpass_wsamacro 0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+ };
+
vph_pwr: vph-pwr-regulator {
compatible = "regulator-fixed";
@@ -50,6 +240,20 @@
regulator-always-on;
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-names = "default";
+ pinctrl-0 = <&nvme_reg_en>;
+ };
};
&apps_rsc {
@@ -402,6 +606,16 @@
};
};
+&lpass_tlmm {
+ spkr_01_sd_n_active: spkr-01-sd-n-active-state {
+ pins = "gpio12";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+};
+
&mdss {
status = "okay";
};
@@ -457,11 +671,19 @@
};
&pcie6a {
+ perst-gpios = <&tlmm 152 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 154 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_nvme>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie6a_default>;
+
status = "okay";
};
&pcie6a_phy {
- vdda-phy-supply = <&vreg_l3j_0p8>;
+ vdda-phy-supply = <&vreg_l1d_0p8>;
vdda-pll-supply = <&vreg_l2j_1p2>;
status = "okay";
@@ -493,6 +715,10 @@
status = "okay";
};
+&smb2360_3 {
+ status = "okay";
+};
+
&smb2360_0_eusb2_repeater {
vdd18-supply = <&vreg_l3d_1p8>;
vdd3-supply = <&vreg_l2b_3p0>;
@@ -508,6 +734,57 @@
vdd3-supply = <&vreg_l8b_3p0>;
};
+&swr0 {
+ pinctrl-0 = <&wsa_swr_active>, <&spkr_01_sd_n_active>;
+ pinctrl-names = "default";
+
+ status = "okay";
+
+ /* WSA8845, Left Speaker */
+ left_spkr: speaker@0,0 {
+ compatible = "sdw20217020400";
+ reg = <0 0>;
+ #sound-dai-cells = <0>;
+ reset-gpios = <&lpass_tlmm 12 GPIO_ACTIVE_LOW>;
+ sound-name-prefix = "SpkrLeft";
+ vdd-1p8-supply = <&vreg_l15b_1p8>;
+ vdd-io-supply = <&vreg_l12b_1p2>;
+ };
+
+ /* WSA8845, Right Speaker */
+ right_spkr: speaker@0,1 {
+ compatible = "sdw20217020400";
+ reg = <0 1>;
+ #sound-dai-cells = <0>;
+ reset-gpios = <&lpass_tlmm 12 GPIO_ACTIVE_LOW>;
+ sound-name-prefix = "SpkrRight";
+ vdd-1p8-supply = <&vreg_l15b_1p8>;
+ vdd-io-supply = <&vreg_l12b_1p2>;
+ };
+};
+
+&swr1 {
+ status = "okay";
+
+ /* WCD9385 RX */
+ wcd_rx: codec@0,4 {
+ compatible = "sdw20217010d00";
+ reg = <0 4>;
+ qcom,rx-port-mapping = <1 2 3 4 5>;
+ };
+};
+
+&swr2 {
+ status = "okay";
+
+ /* WCD9385 TX */
+ wcd_tx: codec@0,3 {
+ compatible = "sdw20217010d00";
+ reg = <0 3>;
+ qcom,tx-port-mapping = <2 2 3 4>;
+ };
+};
+
&tlmm {
gpio-reserved-ranges = <33 3>, /* Unused */
<44 4>, /* SPI (TPM) */
@@ -519,6 +796,44 @@
drive-strength = <16>;
bias-disable;
};
+
+ nvme_reg_en: nvme-reg-en-state {
+ pins = "gpio18";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ pcie6a_default: pcie2a-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-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio154";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ wcd_default: wcd-reset-n-active-state {
+ pins = "gpio191";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
};
&uart21 {
@@ -527,8 +842,8 @@
};
&usb_1_ss0_hsphy {
- vdd-supply = <&vreg_l2e_0p8>;
- vdda12-supply = <&vreg_l3e_1p2>;
+ vdd-supply = <&vreg_l3j_0p8>;
+ vdda12-supply = <&vreg_l2j_1p2>;
phys = <&smb2360_0_eusb2_repeater>;
@@ -536,6 +851,9 @@
};
&usb_1_ss0_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l1j_0p8>;
+
status = "okay";
};
@@ -545,12 +863,19 @@
&usb_1_ss0_dwc3 {
dr_mode = "host";
- usb-role-switch;
+};
+
+&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_l2e_0p8>;
- vdda12-supply = <&vreg_l3e_1p2>;
+ vdd-supply = <&vreg_l3j_0p8>;
+ vdda12-supply = <&vreg_l2j_1p2>;
phys = <&smb2360_1_eusb2_repeater>;
@@ -558,6 +883,9 @@
};
&usb_1_ss1_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l2d_0p9>;
+
status = "okay";
};
@@ -567,12 +895,19 @@
&usb_1_ss1_dwc3 {
dr_mode = "host";
- usb-role-switch;
+};
+
+&usb_1_ss1_dwc3_hs {
+ remote-endpoint = <&pmic_glink_ss1_hs_in>;
+};
+
+&usb_1_ss1_qmpphy_out {
+ remote-endpoint = <&pmic_glink_ss1_ss_in>;
};
&usb_1_ss2_hsphy {
- vdd-supply = <&vreg_l2e_0p8>;
- vdda12-supply = <&vreg_l3e_1p2>;
+ vdd-supply = <&vreg_l3j_0p8>;
+ vdda12-supply = <&vreg_l2j_1p2>;
phys = <&smb2360_2_eusb2_repeater>;
@@ -580,6 +915,9 @@
};
&usb_1_ss2_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l2d_0p9>;
+
status = "okay";
};
@@ -589,5 +927,12 @@
&usb_1_ss2_dwc3 {
dr_mode = "host";
- usb-role-switch;
+};
+
+&usb_1_ss2_dwc3_hs {
+ remote-endpoint = <&pmic_glink_ss2_hs_in>;
+};
+
+&usb_1_ss2_qmpphy_out {
+ remote-endpoint = <&pmic_glink_ss2_ss_in>;
};
diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
index 5f90a0b3c016..7bca5fcd7d52 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/clock/qcom,x1e80100-dispcc.h>
#include <dt-bindings/clock/qcom,x1e80100-gcc.h>
+#include <dt-bindings/clock/qcom,x1e80100-gpucc.h>
#include <dt-bindings/clock/qcom,x1e80100-tcsr.h>
#include <dt-bindings/dma/qcom-gpi.h>
#include <dt-bindings/interconnect/qcom,icc.h>
@@ -2505,6 +2506,66 @@
};
};
+ tsens0: thermal-sensor@c271000 {
+ compatible = "qcom,x1e80100-tsens", "qcom,tsens-v2";
+ reg = <0 0x0c271000 0 0x1000>,
+ <0 0x0c222000 0 0x1000>;
+
+ interrupts-extended = <&pdc 26 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 641 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uplow",
+ "critical";
+
+ #qcom,sensors = <16>;
+
+ #thermal-sensor-cells = <1>;
+ };
+
+ tsens1: thermal-sensor@c272000 {
+ compatible = "qcom,x1e80100-tsens", "qcom,tsens-v2";
+ reg = <0 0x0c272000 0 0x1000>,
+ <0 0x0c223000 0 0x1000>;
+
+ interrupts-extended = <&pdc 27 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 642 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uplow",
+ "critical";
+
+ #qcom,sensors = <16>;
+
+ #thermal-sensor-cells = <1>;
+ };
+
+ tsens2: thermal-sensor@c273000 {
+ compatible = "qcom,x1e80100-tsens", "qcom,tsens-v2";
+ reg = <0 0x0c273000 0 0x1000>,
+ <0 0x0c224000 0 0x1000>;
+
+ interrupts-extended = <&pdc 28 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 643 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uplow",
+ "critical";
+
+ #qcom,sensors = <16>;
+
+ #thermal-sensor-cells = <1>;
+ };
+
+ tsens3: thermal-sensor@c274000 {
+ compatible = "qcom,x1e80100-tsens", "qcom,tsens-v2";
+ reg = <0 0x0c274000 0 0x1000>,
+ <0 0x0c225000 0 0x1000>;
+
+ interrupts-extended = <&pdc 29 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 770 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uplow",
+ "critical";
+
+ #qcom,sensors = <16>;
+
+ #thermal-sensor-cells = <1>;
+ };
+
usb_1_ss0_hsphy: phy@fd3000 {
compatible = "qcom,x1e80100-snps-eusb2-phy",
"qcom,sm8550-snps-eusb2-phy";
@@ -2543,6 +2604,34 @@
#phy-cells = <1>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_ss0_qmpphy_out: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_ss0_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss0_dwc3_ss>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ usb_1_ss0_qmpphy_dp_in: endpoint {
+ remote-endpoint = <&mdss_dp0_out>;
+ };
+ };
+ };
};
usb_1_ss1_hsphy: phy@fd9000 {
@@ -2583,6 +2672,34 @@
#phy-cells = <1>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_ss1_qmpphy_out: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_ss1_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss1_dwc3_ss>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ usb_1_ss1_qmpphy_dp_in: endpoint {
+ remote-endpoint = <&mdss_dp1_out>;
+ };
+ };
+ };
};
usb_1_ss2_hsphy: phy@fde000 {
@@ -2623,6 +2740,34 @@
#phy-cells = <1>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_ss2_qmpphy_out: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_ss2_qmpphy_usb_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss2_dwc3_ss>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ usb_1_ss2_qmpphy_dp_in: endpoint {
+ remote-endpoint = <&mdss_dp2_out>;
+ };
+ };
+ };
};
cnoc_main: interconnect@1500000 {
@@ -2737,15 +2882,17 @@
device_type = "pci";
compatible = "qcom,pcie-x1e80100";
reg = <0 0x01bf8000 0 0x3000>,
- <0 0x70000000 0 0xf1d>,
- <0 0x70000f20 0 0xa8>,
+ <0 0x70000000 0 0xf20>,
+ <0 0x70000f40 0 0xa8>,
<0 0x70001000 0 0x1000>,
- <0 0x70100000 0 0x100000>;
+ <0 0x70100000 0 0x100000>,
+ <0 0x01bfb000 0 0x1000>;
reg-names = "parf",
"dbi",
"elbi",
"atu",
- "config";
+ "config",
+ "mhi";
#address-cells = <3>;
#size-cells = <2>;
ranges = <0x01000000 0 0x00000000 0 0x70200000 0 0x100000>,
@@ -2985,6 +3132,200 @@
#reset-cells = <1>;
};
+ gpu: gpu@3d00000 {
+ compatible = "qcom,adreno-43050c01", "qcom,adreno";
+ reg = <0x0 0x03d00000 0x0 0x40000>,
+ <0x0 0x03d9e000 0x0 0x1000>,
+ <0x0 0x03d61000 0x0 0x800>;
+
+ reg-names = "kgsl_3d0_reg_memory",
+ "cx_mem",
+ "cx_dbgc";
+
+ interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
+
+ iommus = <&adreno_smmu 0 0x0>,
+ <&adreno_smmu 1 0x0>;
+
+ operating-points-v2 = <&gpu_opp_table>;
+
+ qcom,gmu = <&gmu>;
+ #cooling-cells = <2>;
+
+ interconnects = <&gem_noc MASTER_GFX3D 0 &mc_virt SLAVE_EBI1 0>;
+ interconnect-names = "gfx-mem";
+
+ zap-shader {
+ memory-region = <&gpu_microcode_mem>;
+ firmware-name = "qcom/gen70500_zap.mbn";
+ };
+
+ gpu_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-1100000000 {
+ opp-hz = /bits/ 64 <1100000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
+ opp-peak-kBps = <16500000>;
+ };
+
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_TURBO>;
+ opp-peak-kBps = <14398438>;
+ };
+
+ opp-925000000 {
+ opp-hz = /bits/ 64 <925000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
+ opp-peak-kBps = <14398438>;
+ };
+
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_NOM>;
+ opp-peak-kBps = <12449219>;
+ };
+
+ opp-744000000 {
+ opp-hz = /bits/ 64 <744000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_SVS_L2>;
+ opp-peak-kBps = <10687500>;
+ };
+
+ opp-687000000 {
+ opp-hz = /bits/ 64 <687000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
+ opp-peak-kBps = <8171875>;
+ };
+
+ opp-550000000 {
+ opp-hz = /bits/ 64 <550000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
+ opp-peak-kBps = <6074219>;
+ };
+
+ opp-390000000 {
+ opp-hz = /bits/ 64 <390000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
+ opp-peak-kBps = <3000000>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS_D1>;
+ opp-peak-kBps = <2136719>;
+ };
+ };
+ };
+
+ gmu: gmu@3d6a000 {
+ compatible = "qcom,adreno-gmu-x185.1", "qcom,adreno-gmu";
+ reg = <0x0 0x03d6a000 0x0 0x35000>,
+ <0x0 0x03d50000 0x0 0x10000>,
+ <0x0 0x0b280000 0x0 0x10000>;
+ reg-names = "gmu", "rscc", "gmu_pdc";
+
+ interrupts = <GIC_SPI 304 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hfi", "gmu";
+
+ clocks = <&gpucc GPU_CC_AHB_CLK>,
+ <&gpucc GPU_CC_CX_GMU_CLK>,
+ <&gpucc GPU_CC_CXO_CLK>,
+ <&gcc GCC_DDRSS_GPU_AXI_CLK>,
+ <&gcc GCC_GPU_MEMNOC_GFX_CLK>,
+ <&gpucc GPU_CC_HUB_CX_INT_CLK>,
+ <&gpucc GPU_CC_DEMET_CLK>;
+ clock-names = "ahb",
+ "gmu",
+ "cxo",
+ "axi",
+ "memnoc",
+ "hub",
+ "demet";
+
+ power-domains = <&gpucc GPU_CX_GDSC>,
+ <&gpucc GPU_GX_GDSC>;
+ power-domain-names = "cx",
+ "gx";
+
+ iommus = <&adreno_smmu 5 0x0>;
+
+ qcom,qmp = <&aoss_qmp>;
+
+ operating-points-v2 = <&gmu_opp_table>;
+
+ gmu_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-550000000 {
+ opp-hz = /bits/ 64 <550000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
+ };
+
+ opp-220000000 {
+ opp-hz = /bits/ 64 <220000000>;
+ opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
+ };
+ };
+ };
+
+ gpucc: clock-controller@3d90000 {
+ compatible = "qcom,x1e80100-gpucc";
+ reg = <0 0x03d90000 0 0xa000>;
+ clocks = <&bi_tcxo_div2>,
+ <&gcc GCC_GPU_GPLL0_CPH_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_DIV_CPH_CLK_SRC>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ adreno_smmu: iommu@3da0000 {
+ compatible = "qcom,x1e80100-smmu-500", "qcom,adreno-smmu",
+ "qcom,smmu-500", "arm,mmu-500";
+ reg = <0x0 0x03da0000 0x0 0x40000>;
+ #iommu-cells = <2>;
+ #global-interrupts = <1>;
+ interrupts = <GIC_SPI 673 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 678 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 679 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 680 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 681 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 682 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 683 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 684 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 685 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 686 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 687 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 688 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 476 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 574 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 575 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 576 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 577 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 660 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 662 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 665 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 666 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 667 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 669 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 670 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 700 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>,
+ <&gcc GCC_GPU_MEMNOC_GFX_CLK>,
+ <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>,
+ <&gpucc GPU_CC_AHB_CLK>;
+ clock-names = "hlos",
+ "bus",
+ "iface",
+ "ahb";
+ power-domains = <&gpucc GPU_CX_GDSC>;
+ dma-coherent;
+ };
+
gem_noc: interconnect@26400000 {
compatible = "qcom,x1e80100-gem-noc";
reg = <0 0x26400000 0 0x311200>;
@@ -3445,8 +3786,23 @@
dma-coherent;
- port {
- usb_1_ss2_role_switch: endpoint {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_ss2_dwc3_hs: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_ss2_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_1_ss2_qmpphy_usb_ss_in>;
+ };
};
};
};
@@ -3514,8 +3870,15 @@
phy-names = "usb2-phy";
maximum-speed = "high-speed";
- port {
- usb_2_role_switch: endpoint {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_2_dwc3_hs: endpoint {
+ };
};
};
};
@@ -3590,8 +3953,23 @@
dma-coherent;
- port {
- usb_1_ss0_role_switch: endpoint {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_ss0_dwc3_hs: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_ss0_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_1_ss0_qmpphy_usb_ss_in>;
+ };
};
};
};
@@ -3673,8 +4051,23 @@
dma-coherent;
- port {
- usb_1_ss1_role_switch: endpoint {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_1_ss1_dwc3_hs: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_1_ss1_dwc3_ss: endpoint {
+ remote-endpoint = <&usb_1_ss1_qmpphy_usb_ss_in>;
+ };
};
};
};
@@ -3860,6 +4253,7 @@
reg = <1>;
mdss_dp0_out: endpoint {
+ remote-endpoint = <&usb_1_ss0_qmpphy_dp_in>;
};
};
};
@@ -3942,6 +4336,7 @@
reg = <1>;
mdss_dp1_out: endpoint {
+ remote-endpoint = <&usb_1_ss1_qmpphy_dp_in>;
};
};
};
@@ -4021,6 +4416,10 @@
port@1 {
reg = <1>;
+
+ mdss_dp2_out: endpoint {
+ remote-endpoint = <&usb_1_ss2_qmpphy_dp_in>;
+ };
};
};
@@ -5155,6 +5554,129 @@
};
};
+ pmu@24091000 {
+ compatible = "qcom,x1e80100-llcc-bwmon", "qcom,sc7280-llcc-bwmon";
+ reg = <0 0x24091000 0 0x1000>;
+
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+
+ interconnects = <&mc_virt MASTER_LLCC QCOM_ICC_TAG_ACTIVE_ONLY
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>;
+
+ operating-points-v2 = <&llcc_bwmon_opp_table>;
+
+ llcc_bwmon_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-0 {
+ opp-peak-kBps = <800000>;
+ };
+
+ opp-1 {
+ opp-peak-kBps = <2188000>;
+ };
+
+ opp-2 {
+ opp-peak-kBps = <3072000>;
+ };
+
+ opp-3 {
+ opp-peak-kBps = <6220800>;
+ };
+
+ opp-4 {
+ opp-peak-kBps = <6835200>;
+ };
+
+ opp-5 {
+ opp-peak-kBps = <8371200>;
+ };
+
+ opp-6 {
+ opp-peak-kBps = <10944000>;
+ };
+
+ opp-7 {
+ opp-peak-kBps = <12748800>;
+ };
+
+ opp-8 {
+ opp-peak-kBps = <14745600>;
+ };
+
+ opp-9 {
+ opp-peak-kBps = <16896000>;
+ };
+ };
+ };
+
+ /* cluster0 */
+ pmu@240b3400 {
+ compatible = "qcom,x1e80100-cpu-bwmon", "qcom,sdm845-bwmon";
+ reg = <0 0x240b3400 0 0x600>;
+
+ interrupts = <GIC_SPI 581 IRQ_TYPE_LEVEL_HIGH>;
+
+ interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+ &gem_noc SLAVE_LLCC QCOM_ICC_TAG_ACTIVE_ONLY>;
+
+ operating-points-v2 = <&cpu_bwmon_opp_table>;
+
+ cpu_bwmon_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-0 {
+ opp-peak-kBps = <4800000>;
+ };
+
+ opp-1 {
+ opp-peak-kBps = <7464000>;
+ };
+
+ opp-2 {
+ opp-peak-kBps = <9600000>;
+ };
+
+ opp-3 {
+ opp-peak-kBps = <12896000>;
+ };
+
+ opp-4 {
+ opp-peak-kBps = <14928000>;
+ };
+
+ opp-5 {
+ opp-peak-kBps = <17064000>;
+ };
+ };
+ };
+
+ /* cluster2 */
+ pmu@240b5400 {
+ compatible = "qcom,x1e80100-cpu-bwmon", "qcom,sdm845-bwmon";
+ reg = <0 0x240b5400 0 0x600>;
+
+ interrupts = <GIC_SPI 581 IRQ_TYPE_LEVEL_HIGH>;
+
+ interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+ &gem_noc SLAVE_LLCC QCOM_ICC_TAG_ACTIVE_ONLY>;
+
+ operating-points-v2 = <&cpu_bwmon_opp_table>;
+ };
+
+ /* cluster1 */
+ pmu@240b6400 {
+ compatible = "qcom,x1e80100-cpu-bwmon", "qcom,sdm845-bwmon";
+ reg = <0 0x240b6400 0 0x600>;
+
+ interrupts = <GIC_SPI 581 IRQ_TYPE_LEVEL_HIGH>;
+
+ interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+ &gem_noc SLAVE_LLCC QCOM_ICC_TAG_ACTIVE_ONLY>;
+
+ operating-points-v2 = <&cpu_bwmon_opp_table>;
+ };
+
system-cache-controller@25000000 {
compatible = "qcom,x1e80100-llcc";
reg = <0 0x25000000 0 0x200000>,
@@ -5224,6 +5746,55 @@
label = "lpass";
qcom,remote-pid = <2>;
+ fastrpc {
+ compatible = "qcom,fastrpc";
+ qcom,glink-channels = "fastrpcglink-apps-dsp";
+ label = "adsp";
+ qcom,non-secure-domain;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compute-cb@3 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <3>;
+ iommus = <&apps_smmu 0x1003 0x80>,
+ <&apps_smmu 0x1063 0x0>;
+ dma-coherent;
+ };
+
+ compute-cb@4 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <4>;
+ iommus = <&apps_smmu 0x1004 0x80>,
+ <&apps_smmu 0x1064 0x0>;
+ dma-coherent;
+ };
+
+ compute-cb@5 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <5>;
+ iommus = <&apps_smmu 0x1005 0x80>,
+ <&apps_smmu 0x1065 0x0>;
+ dma-coherent;
+ };
+
+ compute-cb@6 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <6>;
+ iommus = <&apps_smmu 0x1006 0x80>,
+ <&apps_smmu 0x1066 0x0>;
+ dma-coherent;
+ };
+
+ compute-cb@7 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <7>;
+ iommus = <&apps_smmu 0x1007 0x80>,
+ <&apps_smmu 0x1067 0x0>;
+ dma-coherent;
+ };
+ };
+
gpr {
compatible = "qcom,gpr";
qcom,glink-channels = "adsp_apps";
@@ -5313,6 +5884,101 @@
label = "cdsp";
qcom,remote-pid = <5>;
+
+ fastrpc {
+ compatible = "qcom,fastrpc";
+ qcom,glink-channels = "fastrpcglink-apps-dsp";
+ label = "cdsp";
+ qcom,non-secure-domain;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compute-cb@1 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <1>;
+ iommus = <&apps_smmu 0x0c01 0x20>;
+ dma-coherent;
+ };
+
+ compute-cb@2 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <2>;
+ iommus = <&apps_smmu 0x0c02 0x20>;
+ dma-coherent;
+ };
+
+ compute-cb@3 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <3>;
+ iommus = <&apps_smmu 0x0c03 0x20>;
+ dma-coherent;
+ };
+
+ compute-cb@4 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <4>;
+ iommus = <&apps_smmu 0x0c04 0x20>;
+ dma-coherent;
+ };
+
+ compute-cb@5 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <5>;
+ iommus = <&apps_smmu 0x0c05 0x20>;
+ dma-coherent;
+ };
+
+ compute-cb@6 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <6>;
+ iommus = <&apps_smmu 0x0c06 0x20>;
+ dma-coherent;
+ };
+
+ compute-cb@7 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <7>;
+ iommus = <&apps_smmu 0x0c07 0x20>;
+ dma-coherent;
+ };
+
+ compute-cb@8 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <8>;
+ iommus = <&apps_smmu 0x0c08 0x20>;
+ dma-coherent;
+ };
+
+ /* note: compute-cb@9 is secure */
+
+ compute-cb@10 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <10>;
+ iommus = <&apps_smmu 0x0c0c 0x20>;
+ dma-coherent;
+ };
+
+ compute-cb@11 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <11>;
+ iommus = <&apps_smmu 0x0c0d 0x20>;
+ dma-coherent;
+ };
+
+ compute-cb@12 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <12>;
+ iommus = <&apps_smmu 0x0c0e 0x20>;
+ dma-coherent;
+ };
+
+ compute-cb@13 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <13>;
+ iommus = <&apps_smmu 0x0c0f 0x20>;
+ dma-coherent;
+ };
+ };
};
};
};
@@ -5325,4 +5991,1158 @@
<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
};
+
+ thermal-zones {
+ aoss0-thermal {
+ thermal-sensors = <&tsens0 0>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ aoss0-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu0-0-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens0 1>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu0-0-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens0 2>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu0-1-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens0 3>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu0-1-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens0 4>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu0-2-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens0 5>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu0-2-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens0 6>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu0-3-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens0 7>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu0-3-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens0 8>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpuss0-top-thermal {
+ thermal-sensors = <&tsens0 9>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ cpuss2-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpuss0-btm-thermal {
+ thermal-sensors = <&tsens0 10>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ cpuss2-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ mem-thermal {
+ thermal-sensors = <&tsens0 11>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ mem-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ video-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens0 12>;
+
+ trips {
+ trip-point0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ aoss1-thermal {
+ thermal-sensors = <&tsens1 0>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ aoss0-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu1-0-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens1 1>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu1-0-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens1 2>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu1-1-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens1 3>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu1-1-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens1 4>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu1-2-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens1 5>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu1-2-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens1 6>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu1-3-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens1 7>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu1-3-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens1 8>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpuss1-top-thermal {
+ thermal-sensors = <&tsens1 9>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ cpuss2-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpuss1-btm-thermal {
+ thermal-sensors = <&tsens1 10>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ cpuss2-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ aoss2-thermal {
+ thermal-sensors = <&tsens2 0>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ aoss0-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu2-0-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens2 1>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu2-0-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens2 2>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu2-1-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens2 3>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu2-1-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens2 4>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu2-2-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens2 5>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu2-2-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens2 6>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu2-3-top-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens2 7>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu2-3-btm-thermal {
+ polling-delay-passive = <250>;
+
+ thermal-sensors = <&tsens2 8>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu-critical {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpuss2-top-thermal {
+ thermal-sensors = <&tsens2 9>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ cpuss2-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpuss2-btm-thermal {
+ thermal-sensors = <&tsens2 10>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ cpuss2-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ aoss3-thermal {
+ thermal-sensors = <&tsens3 0>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ aoss0-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ nsp0-thermal {
+ thermal-sensors = <&tsens3 1>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ nsp0-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ nsp1-thermal {
+ thermal-sensors = <&tsens3 2>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ nsp1-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ nsp2-thermal {
+ thermal-sensors = <&tsens3 3>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ nsp2-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ nsp3-thermal {
+ thermal-sensors = <&tsens3 4>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ nsp3-critical {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpuss-0-thermal {
+ polling-delay-passive = <10>;
+
+ thermal-sensors = <&tsens3 5>;
+
+ trips {
+ trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <90000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+
+ trip-point2 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpuss-1-thermal {
+ polling-delay-passive = <10>;
+
+ thermal-sensors = <&tsens3 6>;
+
+ trips {
+ trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <90000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+
+ trip-point2 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpuss-2-thermal {
+ polling-delay-passive = <10>;
+
+ thermal-sensors = <&tsens3 7>;
+
+ trips {
+ trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <90000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+
+ trip-point2 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpuss-3-thermal {
+ polling-delay-passive = <10>;
+
+ thermal-sensors = <&tsens3 8>;
+
+ trips {
+ trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <90000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+
+ trip-point2 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpuss-4-thermal {
+ polling-delay-passive = <10>;
+
+ thermal-sensors = <&tsens3 9>;
+
+ trips {
+ trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <90000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+
+ trip-point2 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpuss-5-thermal {
+ polling-delay-passive = <10>;
+
+ thermal-sensors = <&tsens3 10>;
+
+ trips {
+ trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <90000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+
+ trip-point2 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpuss-6-thermal {
+ polling-delay-passive = <10>;
+
+ thermal-sensors = <&tsens3 11>;
+
+ trips {
+ trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <90000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+
+ trip-point2 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpuss-7-thermal {
+ polling-delay-passive = <10>;
+
+ thermal-sensors = <&tsens3 12>;
+
+ trips {
+ trip-point0 {
+ temperature = <85000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ trip-point1 {
+ temperature = <90000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+
+ trip-point2 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ camera0-thermal {
+ thermal-sensors = <&tsens3 13>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ camera0-critical {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ camera1-thermal {
+ thermal-sensors = <&tsens3 14>;
+
+ trips {
+ trip-point0 {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ camera0-critical {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/renesas/condor-common.dtsi b/arch/arm64/boot/dts/renesas/condor-common.dtsi
index 7c34d14dcd7e..8b7c0c34eadc 100644
--- a/arch/arm64/boot/dts/renesas/condor-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/condor-common.dtsi
@@ -227,6 +227,12 @@
};
};
};
+
+ eeprom@50 {
+ compatible = "rohm,br24t01", "atmel,24c01";
+ reg = <0x50>;
+ pagesize = <8>;
+ };
};
&i2c1 {
diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
index a8a44fe5e83b..1dbf9d56c68d 100644
--- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
@@ -2853,6 +2853,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clocks - can be overridden by the board */
diff --git a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi
index 4fff511e994c..10f22c52e79e 100644
--- a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi
@@ -2704,6 +2704,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clocks - can be overridden by the board */
diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
index 1ef43d78c3a5..3e2af50ce7c6 100644
--- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
@@ -1990,6 +1990,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clocks - can be overridden by the board */
diff --git a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi
index be55ae83944c..1eeb4c7b4c4b 100644
--- a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi
@@ -2985,6 +2985,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clocks - can be overridden by the board */
diff --git a/arch/arm64/boot/dts/renesas/r8a77951.dtsi b/arch/arm64/boot/dts/renesas/r8a77951.dtsi
index bea4edd17d53..96f3b5fe7e92 100644
--- a/arch/arm64/boot/dts/renesas/r8a77951.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77951.dtsi
@@ -3473,6 +3473,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clocks - can be overridden by the board */
diff --git a/arch/arm64/boot/dts/renesas/r8a77960.dtsi b/arch/arm64/boot/dts/renesas/r8a77960.dtsi
index 7846fea8e40d..1122c470b72f 100644
--- a/arch/arm64/boot/dts/renesas/r8a77960.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77960.dtsi
@@ -3068,6 +3068,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clocks - can be overridden by the board */
diff --git a/arch/arm64/boot/dts/renesas/r8a77961.dtsi b/arch/arm64/boot/dts/renesas/r8a77961.dtsi
index 58f9286a5ab5..bf1130af7de3 100644
--- a/arch/arm64/boot/dts/renesas/r8a77961.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77961.dtsi
@@ -2889,6 +2889,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clocks - can be overridden by the board */
diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
index 692940662d38..f02d1547b881 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
@@ -2877,6 +2877,7 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
/* External USB clocks - can be overridden by the board */
diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi
index d2d3cecc76d5..64fb95b1c89a 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi
@@ -1223,5 +1223,6 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
index 68d1f1d53b3a..1d326552e2fa 100644
--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
@@ -14,11 +14,3 @@
model = "Renesas Condor board based on r8a77980";
compatible = "renesas,condor", "renesas,r8a77980";
};
-
-&i2c0 {
- eeprom@50 {
- compatible = "rohm,br24t01", "atmel,24c01";
- reg = <0x50>;
- pagesize = <8>;
- };
-};
diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi
index c0ba110c74d6..0c2b157036e7 100644
--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi
@@ -1630,5 +1630,6 @@
IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
index 37063e3f4e1b..233af3081e84 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -2157,5 +2157,6 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
index 89990dd8ebf7..5f0828a4675b 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
@@ -1476,5 +1476,6 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
index cfa70b441e32..d76347001cc1 100644
--- a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
@@ -2919,6 +2919,9 @@
interrupts-extended = <&gic GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
- <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>,
+ <&gic GIC_PPI 12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys",
+ "hyp-virt";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
index 477f3114d2fd..4ed8d4c37906 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
@@ -15,6 +15,12 @@
compatible = "renesas,spider-cpu", "renesas,r8a779f0";
aliases {
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ i2c5 = &i2c5;
serial0 = &hscif0;
serial1 = &scif0;
};
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
index 72cf30341fc4..9629adb47d99 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
@@ -1324,7 +1324,10 @@
interrupts-extended = <&gic GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
- <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>,
+ <&gic GIC_PPI 12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys",
+ "hyp-virt";
};
ufs30_clk: ufs30-clk {
diff --git a/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts b/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts
index bc65a7b4d999..fa910b85859e 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts
+++ b/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts
@@ -14,6 +14,12 @@
compatible = "renesas,s4sk", "renesas,r8a779f4", "renesas,r8a779f0";
aliases {
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ i2c5 = &i2c5;
serial0 = &hscif0;
serial1 = &hscif1;
ethernet0 = &rswitch;
diff --git a/arch/arm64/boot/dts/renesas/r8a779g0-white-hawk-ard-audio-da7212.dtso b/arch/arm64/boot/dts/renesas/r8a779g0-white-hawk-ard-audio-da7212.dtso
index e6f53377ecd9..e6cf304c77ee 100644
--- a/arch/arm64/boot/dts/renesas/r8a779g0-white-hawk-ard-audio-da7212.dtso
+++ b/arch/arm64/boot/dts/renesas/r8a779g0-white-hawk-ard-audio-da7212.dtso
@@ -155,11 +155,7 @@
pinctrl-0 = <&sound_clk_pins>, <&sound_pins>;
pinctrl-names = "default";
- /* Single DAI */
- #sound-dai-cells = <0>;
-
/* audio_clkout */
- #clock-cells = <0>;
clock-frequency = <5644800>; /* 44.1kHz groups [(C) clock] */
// clock-frequency = <6144000>; /* 48 kHz groups [(C) clock] */
diff --git a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
index 9bc542bc6169..53d1d4d8197a 100644
--- a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
@@ -815,8 +815,6 @@
phy-mode = "rgmii";
rx-internal-delay-ps = <0>;
tx-internal-delay-ps = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
status = "disabled";
};
@@ -862,8 +860,6 @@
phy-mode = "rgmii";
rx-internal-delay-ps = <0>;
tx-internal-delay-ps = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
status = "disabled";
};
@@ -909,8 +905,6 @@
phy-mode = "rgmii";
rx-internal-delay-ps = <0>;
tx-internal-delay-ps = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
status = "disabled";
};
@@ -1724,18 +1718,6 @@
};
rcar_sound: sound@ec5a0000 {
- /*
- * #sound-dai-cells is required
- *
- * Single DAI : #sound-dai-cells = <0>; <&rcar_sound>;
- * Multi DAI : #sound-dai-cells = <1>; <&rcar_sound N>;
- */
- /*
- * #clock-cells is required
- *
- * clkout : #clock-cells = <0>; <&rcar_sound>;
- * audio_clkout0/1/2/3 : #clock-cells = <1>; <&rcar_sound N>;
- */
compatible = "renesas,rcar_sound-r8a779g0", "renesas,rcar_sound-gen4";
reg = <0 0xec5a0000 0 0x020>,
<0 0xec540000 0 0x1000>,
@@ -1745,6 +1727,11 @@
clocks = <&cpg CPG_MOD 2926>, <&cpg CPG_MOD 2927>, <&audio_clkin>;
clock-names = "ssiu.0", "ssi.0", "clkin";
+ /* #clock-cells is fixed */
+ #clock-cells = <0>;
+ /* #sound-dai-cells is fixed */
+ #sound-dai-cells = <0>;
+
power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
resets = <&cpg 2926>, <&cpg 2927>;
reset-names = "ssiu.0", "ssi.0";
@@ -2359,6 +2346,9 @@
interrupts-extended = <&gic GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
- <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>,
+ <&gic GIC_PPI 12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys",
+ "hyp-virt";
};
};
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 cfbe8c8680cd..2b9a19bb1c5d 100644
--- a/arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts
+++ b/arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts
@@ -17,6 +17,10 @@
compatible = "renesas,gray-hawk-single", "renesas,r8a779h0";
aliases {
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
serial0 = &hscif0;
serial1 = &hscif2;
ethernet0 = &avb0;
diff --git a/arch/arm64/boot/dts/renesas/r8a779h0.dtsi b/arch/arm64/boot/dts/renesas/r8a779h0.dtsi
index 6d791024cabe..a03ab2b6a859 100644
--- a/arch/arm64/boot/dts/renesas/r8a779h0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779h0.dtsi
@@ -14,9 +14,15 @@
#address-cells = <2>;
#size-cells = <2>;
+ /* External Audio clock - to be overridden by boards that provide it */
+ audio_clkin: audio_clkin {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
cluster0_opp: opp-table-0 {
compatible = "operating-points-v2";
- opp-shared;
opp-500000000 {
opp-hz = /bits/ 64 <500000000>;
@@ -939,6 +945,454 @@
status = "disabled";
};
+ vin00: video@e6ef0000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6ef0000 0 0x1000>;
+ interrupts = <GIC_SPI 529 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 730>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 730>;
+ renesas,id = <0>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin00isp0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&isp0vin00>;
+ };
+ };
+ };
+ };
+
+ vin01: video@e6ef1000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6ef1000 0 0x1000>;
+ interrupts = <GIC_SPI 530 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 731>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 731>;
+ renesas,id = <1>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin01isp0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&isp0vin01>;
+ };
+ };
+ };
+ };
+
+ vin02: video@e6ef2000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6ef2000 0 0x1000>;
+ interrupts = <GIC_SPI 531 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 800>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 800>;
+ renesas,id = <2>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin02isp0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&isp0vin02>;
+ };
+ };
+ };
+ };
+
+ vin03: video@e6ef3000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6ef3000 0 0x1000>;
+ interrupts = <GIC_SPI 532 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 801>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 801>;
+ renesas,id = <3>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin03isp0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&isp0vin03>;
+ };
+ };
+ };
+ };
+
+ vin04: video@e6ef4000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6ef4000 0 0x1000>;
+ interrupts = <GIC_SPI 533 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 802>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 802>;
+ renesas,id = <4>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin04isp0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&isp0vin04>;
+ };
+ };
+ };
+ };
+
+ vin05: video@e6ef5000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6ef5000 0 0x1000>;
+ interrupts = <GIC_SPI 534 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 803>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 803>;
+ renesas,id = <5>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin05isp0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&isp0vin05>;
+ };
+ };
+ };
+ };
+
+ vin06: video@e6ef6000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6ef6000 0 0x1000>;
+ interrupts = <GIC_SPI 535 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 804>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 804>;
+ renesas,id = <6>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin06isp0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&isp0vin06>;
+ };
+ };
+ };
+ };
+
+ vin07: video@e6ef7000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6ef7000 0 0x1000>;
+ interrupts = <GIC_SPI 536 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 805>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 805>;
+ renesas,id = <7>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin07isp0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&isp0vin07>;
+ };
+ };
+ };
+ };
+
+ vin08: video@e6ef8000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6ef8000 0 0x1000>;
+ interrupts = <GIC_SPI 537 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 806>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 806>;
+ renesas,id = <8>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin08isp1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&isp1vin08>;
+ };
+ };
+ };
+ };
+
+ vin09: video@e6ef9000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6ef9000 0 0x1000>;
+ interrupts = <GIC_SPI 538 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 807>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 807>;
+ renesas,id = <9>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin09isp1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&isp1vin09>;
+ };
+ };
+ };
+ };
+
+ vin10: video@e6efa000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6efa000 0 0x1000>;
+ interrupts = <GIC_SPI 539 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 808>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 808>;
+ renesas,id = <10>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin10isp1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&isp1vin10>;
+ };
+ };
+ };
+ };
+
+ vin11: video@e6efb000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6efb000 0 0x1000>;
+ interrupts = <GIC_SPI 540 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 809>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 809>;
+ renesas,id = <11>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin11isp1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&isp1vin11>;
+ };
+ };
+ };
+ };
+
+ vin12: video@e6efc000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6efc000 0 0x1000>;
+ interrupts = <GIC_SPI 541 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 810>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 810>;
+ renesas,id = <12>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin12isp1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&isp1vin12>;
+ };
+ };
+ };
+ };
+
+ vin13: video@e6efd000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6efd000 0 0x1000>;
+ interrupts = <GIC_SPI 542 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 811>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 811>;
+ renesas,id = <13>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin13isp1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&isp1vin13>;
+ };
+ };
+ };
+ };
+
+ vin14: video@e6efe000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6efe000 0 0x1000>;
+ interrupts = <GIC_SPI 543 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 812>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 812>;
+ renesas,id = <14>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin14isp1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&isp1vin14>;
+ };
+ };
+ };
+ };
+
+ vin15: video@e6eff000 {
+ compatible = "renesas,vin-r8a779h0";
+ reg = <0 0xe6eff000 0 0x1000>;
+ interrupts = <GIC_SPI 544 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 813>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 813>;
+ renesas,id = <15>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <2>;
+
+ vin15isp1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&isp1vin15>;
+ };
+ };
+ };
+ };
+
dmac1: dma-controller@e7350000 {
compatible = "renesas,dmac-r8a779h0",
"renesas,rcar-gen4-dmac";
@@ -1011,6 +1465,67 @@
<&ipmmu_ds0 22>, <&ipmmu_ds0 23>;
};
+ rcar_sound: sound@ec400000 {
+ compatible = "renesas,rcar_sound-r8a779h0", "renesas,rcar_sound-gen4";
+ reg = <0 0xec400000 0 0x40000>,
+ <0 0xec540000 0 0x1000>,
+ <0 0xec541000 0 0x050>,
+ <0 0xec5a0000 0 0x020>;
+ reg-names = "sdmc", "ssiu", "ssi", "adg";
+ clocks = <&cpg CPG_MOD 2926>, <&cpg CPG_MOD 2927>, <&audio_clkin>;
+ clock-names = "ssiu.0", "ssi.0", "clkin";
+ /* #clock-cells is fixed */
+ #clock-cells = <0>;
+ /* #sound-dai-cells is fixed */
+ #sound-dai-cells = <0>;
+
+ power-domains = <&sysc R8A779H0_PD_ALWAYS_ON>;
+ resets = <&cpg 2926>, <&cpg 2927>;
+ reset-names = "ssiu.0", "ssi.0";
+ status = "disabled";
+
+ rcar_sound,ssiu {
+ ssiu00: ssiu-0 {
+ dmas = <&dmac1 0x6e>, <&dmac1 0x6f>;
+ dma-names = "tx", "rx";
+ };
+ ssiu01: ssiu-1 {
+ dmas = <&dmac1 0x6c>, <&dmac1 0x6d>;
+ dma-names = "tx", "rx";
+ };
+ ssiu02: ssiu-2 {
+ dmas = <&dmac1 0x6a>, <&dmac1 0x6b>;
+ dma-names = "tx", "rx";
+ };
+ ssiu03: ssiu-3 {
+ dmas = <&dmac1 0x68>, <&dmac1 0x69>;
+ dma-names = "tx", "rx";
+ };
+ ssiu04: ssiu-4 {
+ dmas = <&dmac1 0x66>, <&dmac1 0x67>;
+ dma-names = "tx", "rx";
+ };
+ ssiu05: ssiu-5 {
+ dmas = <&dmac1 0x64>, <&dmac1 0x65>;
+ dma-names = "tx", "rx";
+ };
+ ssiu06: ssiu-6 {
+ dmas = <&dmac1 0x62>, <&dmac1 0x63>;
+ dma-names = "tx", "rx";
+ };
+ ssiu07: ssiu-7 {
+ dmas = <&dmac1 0x60>, <&dmac1 0x61>;
+ dma-names = "tx", "rx";
+ };
+ };
+
+ rcar_sound,ssi {
+ ssi0: ssi-0 {
+ interrupts = <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+ };
+
mmc0: mmc@ee140000 {
compatible = "renesas,sdhi-r8a779h0",
"renesas,rcar-gen4-sdhi";
@@ -1152,6 +1667,224 @@
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
+ csi40: csi2@fe500000 {
+ compatible = "renesas,r8a779h0-csi2";
+ reg = <0 0xfe500000 0 0x40000>;
+ interrupts = <GIC_SPI 499 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 331>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 331>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+
+ port@1 {
+ reg = <1>;
+ csi40isp0: endpoint {
+ remote-endpoint = <&isp0csi40>;
+ };
+ };
+ };
+ };
+
+ csi41: csi2@fe540000 {
+ compatible = "renesas,r8a779h0-csi2";
+ reg = <0 0xfe540000 0 0x40000>;
+ interrupts = <GIC_SPI 500 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 400>;
+ power-domains = <&sysc R8A779H0_PD_C4>;
+ resets = <&cpg 400>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+
+ port@1 {
+ reg = <1>;
+ csi41isp1: endpoint {
+ remote-endpoint = <&isp1csi41>;
+ };
+ };
+ };
+ };
+
+ isp0: isp@fed00000 {
+ compatible = "renesas,r8a779h0-isp";
+ reg = <0 0xfed00000 0 0x10000>;
+ interrupts = <GIC_SPI 473 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&cpg CPG_MOD 612>;
+ power-domains = <&sysc R8A779H0_PD_A3ISP0>;
+ resets = <&cpg 612>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <0>;
+
+ isp0csi40: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&csi40isp0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ isp0vin00: endpoint {
+ remote-endpoint = <&vin00isp0>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ isp0vin01: endpoint {
+ remote-endpoint = <&vin01isp0>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ isp0vin02: endpoint {
+ remote-endpoint = <&vin02isp0>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+ isp0vin03: endpoint {
+ remote-endpoint = <&vin03isp0>;
+ };
+ };
+
+ port@5 {
+ reg = <5>;
+ isp0vin04: endpoint {
+ remote-endpoint = <&vin04isp0>;
+ };
+ };
+
+ port@6 {
+ reg = <6>;
+ isp0vin05: endpoint {
+ remote-endpoint = <&vin05isp0>;
+ };
+ };
+
+ port@7 {
+ reg = <7>;
+ isp0vin06: endpoint {
+ remote-endpoint = <&vin06isp0>;
+ };
+ };
+
+ port@8 {
+ reg = <8>;
+ isp0vin07: endpoint {
+ remote-endpoint = <&vin07isp0>;
+ };
+ };
+ };
+ };
+
+ isp1: isp@fed20000 {
+ compatible = "renesas,r8a779h0-isp";
+ reg = <0 0xfed20000 0 0x10000>;
+ interrupts = <GIC_SPI 474 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&cpg CPG_MOD 613>;
+ power-domains = <&sysc R8A779H0_PD_A3ISP0>;
+ resets = <&cpg 613>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <0>;
+
+ isp1csi41: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&csi41isp1>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ isp1vin08: endpoint {
+ remote-endpoint = <&vin08isp1>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ isp1vin09: endpoint {
+ remote-endpoint = <&vin09isp1>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ isp1vin10: endpoint {
+ remote-endpoint = <&vin10isp1>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+ isp1vin11: endpoint {
+ remote-endpoint = <&vin11isp1>;
+ };
+ };
+
+ port@5 {
+ reg = <5>;
+ isp1vin12: endpoint {
+ remote-endpoint = <&vin12isp1>;
+ };
+ };
+
+ port@6 {
+ reg = <6>;
+ isp1vin13: endpoint {
+ remote-endpoint = <&vin13isp1>;
+ };
+ };
+
+ port@7 {
+ reg = <7>;
+ isp1vin14: endpoint {
+ remote-endpoint = <&vin14isp1>;
+ };
+ };
+
+ port@8 {
+ reg = <8>;
+ isp1vin15: endpoint {
+ remote-endpoint = <&vin15isp1>;
+ };
+ };
+ };
+ };
+
prr: chipid@fff00044 {
compatible = "renesas,prr";
reg = <0 0xfff00044 0 4>;
@@ -1195,5 +1928,7 @@
<&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys",
+ "hyp-virt";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r9a07g043.dtsi b/arch/arm64/boot/dts/renesas/r9a07g043.dtsi
index 6212ee550f33..2eccab9c8962 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g043.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g043.dtsi
@@ -646,7 +646,7 @@
sdhi0: mmc@11c00000 {
compatible = "renesas,sdhi-r9a07g043",
- "renesas,rcar-gen3-sdhi";
+ "renesas,rzg2l-sdhi";
reg = <0x0 0x11c00000 0 0x10000>;
interrupts = <SOC_PERIPHERAL_IRQ(104) IRQ_TYPE_LEVEL_HIGH>,
<SOC_PERIPHERAL_IRQ(105) IRQ_TYPE_LEVEL_HIGH>;
@@ -662,7 +662,7 @@
sdhi1: mmc@11c10000 {
compatible = "renesas,sdhi-r9a07g043",
- "renesas,rcar-gen3-sdhi";
+ "renesas,rzg2l-sdhi";
reg = <0x0 0x11c10000 0 0x10000>;
interrupts = <SOC_PERIPHERAL_IRQ(106) IRQ_TYPE_LEVEL_HIGH>,
<SOC_PERIPHERAL_IRQ(107) IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi b/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi
index 165bfcfef3bc..18ef297db933 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi
@@ -50,7 +50,10 @@
interrupts-extended = <&gic GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
- <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>,
+ <&gic GIC_PPI 12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys",
+ "hyp-virt";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
index 88634ae43287..d3838e5820fc 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
@@ -1050,7 +1050,7 @@
sdhi0: mmc@11c00000 {
compatible = "renesas,sdhi-r9a07g044",
- "renesas,rcar-gen3-sdhi";
+ "renesas,rzg2l-sdhi";
reg = <0x0 0x11c00000 0 0x10000>;
interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
@@ -1066,7 +1066,7 @@
sdhi1: mmc@11c10000 {
compatible = "renesas,sdhi-r9a07g044",
- "renesas,rcar-gen3-sdhi";
+ "renesas,rzg2l-sdhi";
reg = <0x0 0x11c10000 0 0x10000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
@@ -1334,6 +1334,9 @@
interrupts-extended = <&gic GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
- <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>,
+ <&gic GIC_PPI 12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys",
+ "hyp-virt";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi
index e89bfe4085f5..1de2e5f0917d 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi
@@ -1058,7 +1058,7 @@
sdhi0: mmc@11c00000 {
compatible = "renesas,sdhi-r9a07g054",
- "renesas,rcar-gen3-sdhi";
+ "renesas,rzg2l-sdhi";
reg = <0x0 0x11c00000 0 0x10000>;
interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
@@ -1074,7 +1074,7 @@
sdhi1: mmc@11c10000 {
compatible = "renesas,sdhi-r9a07g054",
- "renesas,rcar-gen3-sdhi";
+ "renesas,rzg2l-sdhi";
reg = <0x0 0x11c10000 0 0x10000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
@@ -1342,6 +1342,9 @@
interrupts-extended = <&gic GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
- <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>,
+ <&gic GIC_PPI 12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys",
+ "hyp-virt";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
index f5f3f4f4c8d6..0d5c47a65e46 100644
--- a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
@@ -182,7 +182,7 @@
};
sdhi0: mmc@11c00000 {
- compatible = "renesas,sdhi-r9a08g045", "renesas,rcar-gen3-sdhi";
+ compatible = "renesas,sdhi-r9a08g045", "renesas,rzg2l-sdhi";
reg = <0x0 0x11c00000 0 0x10000>;
interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
@@ -197,7 +197,7 @@
};
sdhi1: mmc@11c10000 {
- compatible = "renesas,sdhi-r9a08g045", "renesas,rcar-gen3-sdhi";
+ compatible = "renesas,sdhi-r9a08g045", "renesas,rzg2l-sdhi";
reg = <0x0 0x11c10000 0 0x10000>;
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
@@ -212,7 +212,7 @@
};
sdhi2: mmc@11c20000 {
- compatible = "renesas,sdhi-r9a08g045", "renesas,rcar-gen3-sdhi";
+ compatible = "renesas,sdhi-r9a08g045", "renesas,rzg2l-sdhi";
reg = <0x0 0x11c20000 0 0x10000>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
@@ -294,6 +294,9 @@
interrupts-extended = <&gic GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
- <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>,
+ <&gic GIC_PPI 12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys",
+ "hyp-virt";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r9a09g011.dtsi b/arch/arm64/boot/dts/renesas/r9a09g011.dtsi
index 50ed66d42a24..9a4cbef704c1 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g011.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g011.dtsi
@@ -71,7 +71,7 @@
sdhi0: mmc@85000000 {
compatible = "renesas,sdhi-r9a09g011",
- "renesas,rcar-gen3-sdhi";
+ "renesas,rzg2l-sdhi";
reg = <0x0 0x85000000 0 0x2000>;
interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
@@ -87,7 +87,7 @@
sdhi1: mmc@85010000 {
compatible = "renesas,sdhi-r9a09g011",
- "renesas,rcar-gen3-sdhi";
+ "renesas,rzg2l-sdhi";
reg = <0x0 0x85010000 0 0x2000>;
interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>;
@@ -103,7 +103,7 @@
emmc: mmc@85020000 {
compatible = "renesas,sdhi-r9a09g011",
- "renesas,rcar-gen3-sdhi";
+ "renesas,rzg2l-sdhi";
reg = <0x0 0x85020000 0 0x2000>;
interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
@@ -372,5 +372,6 @@
<&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
<&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys";
};
};
diff --git a/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi b/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi
index b7a3e6caa386..b34855956ae0 100644
--- a/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi
@@ -54,14 +54,6 @@
};
};
- usb0_vbus_otg: regulator-usb0-vbus-otg {
- compatible = "regulator-fixed";
-
- regulator-name = "USB0_VBUS_OTG";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- };
-
vccq_sdhi1: regulator-vccq-sdhi1 {
compatible = "regulator-gpio";
regulator-name = "SDHI1 VccQ";
@@ -139,6 +131,9 @@
&phyrst {
status = "okay";
+ usb0_vbus_otg: regulator-vbus {
+ regulator-name = "vbus";
+ };
};
&scif0 {
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 8ac17370ff36..80496fb3d476 100644
--- a/arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi
@@ -13,6 +13,12 @@
/ {
aliases {
ethernet0 = &avb0;
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ i2c5 = &i2c5;
serial0 = &hscif0;
};
@@ -142,18 +148,23 @@
&avb0 {
pinctrl-0 = <&avb0_pins>;
pinctrl-names = "default";
- phy-handle = <&phy0>;
+ phy-handle = <&avb0_phy>;
tx-internal-delay-ps = <2000>;
status = "okay";
- phy0: ethernet-phy@0 {
- compatible = "ethernet-phy-id0022.1622",
- "ethernet-phy-ieee802.3-c22";
- rxc-skew-ps = <1500>;
- reg = <0>;
- interrupt-parent = <&gpio7>;
- interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
- reset-gpios = <&gpio7 10 GPIO_ACTIVE_LOW>;
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ avb0_phy: ethernet-phy@0 {
+ compatible = "ethernet-phy-id0022.1622",
+ "ethernet-phy-ieee802.3-c22";
+ rxc-skew-ps = <1500>;
+ reg = <0>;
+ interrupt-parent = <&gpio7>;
+ interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&gpio7 10 GPIO_ACTIVE_LOW>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/renesas/white-hawk-ethernet.dtsi b/arch/arm64/boot/dts/renesas/white-hawk-ethernet.dtsi
index a218fda337cf..595ec4ff4cdd 100644
--- a/arch/arm64/boot/dts/renesas/white-hawk-ethernet.dtsi
+++ b/arch/arm64/boot/dts/renesas/white-hawk-ethernet.dtsi
@@ -6,6 +6,57 @@
* Copyright (C) 2022 Glider bv
*/
+/ {
+ aliases {
+ ethernet1 = &avb1;
+ ethernet2 = &avb2;
+ };
+};
+
+&avb1 {
+ pinctrl-0 = <&avb1_pins>;
+ pinctrl-names = "default";
+ phy-handle = <&avb1_phy>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reset-gpios = <&gpio6 1 GPIO_ACTIVE_LOW>;
+ reset-post-delay-us = <4000>;
+
+ avb1_phy: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <0>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+};
+
+&avb2 {
+ pinctrl-0 = <&avb2_pins>;
+ pinctrl-names = "default";
+ phy-handle = <&avb2_phy>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reset-gpios = <&gpio5 5 GPIO_ACTIVE_LOW>;
+ reset-post-delay-us = <4000>;
+
+ avb2_phy: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <0>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+};
+
&i2c0 {
eeprom@53 {
compatible = "rohm,br24g01", "atmel,24c01";
@@ -14,3 +65,55 @@
pagesize = <8>;
};
};
+
+&pfc {
+ avb1_pins: avb1 {
+ mux {
+ groups = "avb1_link", "avb1_mdio", "avb1_rgmii",
+ "avb1_txcrefclk";
+ function = "avb1";
+ };
+
+ mdio {
+ groups = "avb1_mdio";
+ drive-strength = <24>;
+ bias-disable;
+ };
+
+ rgmii {
+ groups = "avb1_rgmii";
+ drive-strength = <24>;
+ bias-disable;
+ };
+
+ link {
+ groups = "avb1_link";
+ bias-disable;
+ };
+ };
+
+ avb2_pins: avb2 {
+ mux {
+ groups = "avb2_link", "avb2_mdio", "avb2_rgmii",
+ "avb2_txcrefclk";
+ function = "avb2";
+ };
+
+ mdio {
+ groups = "avb2_mdio";
+ drive-strength = <24>;
+ bias-disable;
+ };
+
+ rgmii {
+ groups = "avb2_rgmii";
+ drive-strength = <24>;
+ bias-disable;
+ };
+
+ link {
+ groups = "avb2_link";
+ bias-disable;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index f42fa62b4064..fda1b980eb4b 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -7,6 +7,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-ringneck-haikou.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-evb.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-roc-cc.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-rock-pi-s.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-rock-s0.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3318-a95x-z2.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-anbernic-rg351m.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-anbernic-rg351v.dtb
@@ -27,6 +28,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-cc.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-pc.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-geekbox.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-lba3368.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-lion-haikou.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-orion-r68-meta.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-px5-evb.dtb
@@ -79,6 +81,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353ps.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353v.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353vs.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg503.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-orangepi-3b-v1.1.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-orangepi-3b-v2.1.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.1.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.2.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinetab2-v0.1.dtb
@@ -90,6 +94,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-powkiddy-x55.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-a.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-b.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-radxa-cm3-io.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-radxa-zero-3e.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-radxa-zero-3w.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-roc-pc.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-rock-3c.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-blade.dtb
@@ -110,6 +116,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-qnap-ts433.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-radxa-e25.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-roc-pc.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3a.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3b.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5-io-expander.dtbo
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-armsom-sige7.dtb
@@ -118,12 +125,16 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6a-io.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6a-wifi.dtbo
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6b-io.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-v10.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-friendlyelec-cm3588-nas.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-jaguar.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nanopc-t6.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-ok3588-c.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-orangepi-5-plus.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-quartzpro64.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5-itx.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5b.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5b-pcie-ep.dtbo
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5b-pcie-srns.dtbo
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-tiger-haikou.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-toybrick-x0.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-turing-rk1.dtb
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 b47fe02c33fb..62d18ca769a1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts
@@ -5,6 +5,8 @@
*/
/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
#include "rk3308.dtsi"
/ {
@@ -15,6 +17,7 @@
ethernet0 = &gmac;
mmc0 = &emmc;
mmc1 = &sdmmc;
+ mmc2 = &sdio;
};
chosen {
@@ -24,17 +27,21 @@
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
- pinctrl-0 = <&green_led_gio>, <&heartbeat_led_gpio>;
+ pinctrl-0 = <&green_led>, <&heartbeat_led>;
green-led {
+ color = <LED_COLOR_ID_GREEN>;
default-state = "on";
+ function = LED_FUNCTION_POWER;
gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
label = "rockpis:green:power";
linux,default-trigger = "default-on";
};
blue-led {
+ color = <LED_COLOR_ID_BLUE>;
default-state = "on";
+ function = LED_FUNCTION_HEARTBEAT;
gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
label = "rockpis:blue:user";
linux,default-trigger = "heartbeat";
@@ -126,21 +133,37 @@
};
&emmc {
- bus-width = <4>;
cap-mmc-highspeed;
- mmc-hs200-1_8v;
+ cap-sd-highspeed;
+ no-sdio;
non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd>;
vmmc-supply = <&vcc_io>;
status = "okay";
};
&gmac {
clock_in_out = "output";
+ phy-handle = <&rtl8201f>;
phy-supply = <&vcc_io>;
- snps,reset-gpio = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
- snps,reset-active-low;
- snps,reset-delays-us = <0 50000 50000>;
status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtl8201f: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac_rst>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
+ };
+ };
};
&gpio0 {
@@ -209,16 +232,46 @@
status = "okay";
};
+&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>;
+ bluetooth {
+ 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_down>;
+ };
+
+ 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 {
- green_led_gio: green-led-gpio {
+ green_led: green-led {
rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
};
- heartbeat_led_gpio: heartbeat-led-gpio {
+ heartbeat_led: heartbeat-led {
rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
@@ -256,15 +309,31 @@
cap-sd-highspeed;
cap-sdio-irq;
keep-power-in-suspend;
- max-frequency = <1000000>;
+ max-frequency = <100000000>;
mmc-pwrseq = <&sdio_pwrseq>;
+ no-mmc;
+ no-sd;
non-removable;
- sd-uhs-sdr104;
+ sd-uhs-sdr50;
+ vmmc-supply = <&vcc_io>;
+ vqmmc-supply = <&vcc_1v8>;
status = "okay";
+
+ rtl8723ds: wifi@1 {
+ reg = <1>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA0 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host-wake";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_host_wake>;
+ };
};
&sdmmc {
+ cap-mmc-highspeed;
cap-sd-highspeed;
+ disable-wp;
+ vmmc-supply = <&vcc_io>;
status = "okay";
};
@@ -283,16 +352,22 @@
};
&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer>;
status = "okay";
};
&uart4 {
+ uart-has-rtscts;
status = "okay";
bluetooth {
- compatible = "realtek,rtl8723bs-bt";
- device-wake-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>;
+ compatible = "realtek,rtl8723ds-bt";
+ device-wake-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>;
+ enable-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>;
host-wake-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_reg_on &bt_wake_host &host_wake_bt>;
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3308-rock-s0.dts b/arch/arm64/boot/dts/rockchip/rk3308-rock-s0.dts
new file mode 100644
index 000000000000..bd6419a5c20a
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-s0.dts
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include "rk3308.dtsi"
+
+/ {
+ model = "Radxa ROCK S0";
+ compatible = "radxa,rock-s0", "rockchip,rk3308";
+
+ aliases {
+ ethernet0 = &gmac;
+ mmc0 = &emmc;
+ mmc1 = &sdmmc;
+ mmc2 = &sdio;
+ };
+
+ chosen {
+ stdout-path = "serial0:1500000n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwr_led>;
+
+ led-green {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "on";
+ function = LED_FUNCTION_HEARTBEAT;
+ gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
+ 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 = <&vcc5v0_sys>;
+ };
+
+ 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 = <&vcc5v0_sys>;
+ };
+
+ 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 = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_sys: regulator-5v0-vcc-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ 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 = <&vcc5v0_sys>;
+ 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-names = "default";
+ pinctrl-0 = <&wifi_reg_on>;
+ reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_core>;
+};
+
+&emmc {
+ cap-mmc-highspeed;
+ no-sd;
+ no-sdio;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_pwren>;
+ vmmc-supply = <&vcc_io>;
+ status = "okay";
+};
+
+&gmac {
+ clock_in_out = "output";
+ phy-handle = <&rtl8201f>;
+ phy-supply = <&vcc_io>;
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtl8201f: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac_rst>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&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>;
+
+ bluetooth {
+ 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_down>;
+ };
+
+ 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 {
+ pwr_led: pwr-led {
+ rockchip,pins = <0 RK_PB6 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";
+};
+
+&sdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ keep-power-in-suspend;
+ max-frequency = <50000000>;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ no-mmc;
+ no-sd;
+ non-removable;
+ vmmc-supply = <&vcc_io>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+
+ brcmf: wifi@1 {
+ compatible = "brcm,bcm43430a1-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";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer>;
+ status = "okay";
+};
+
+&uart4 {
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm43430a1-bt";
+ 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>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_reg_on &bt_wake_host &host_wake_bt>;
+ vbat-supply = <&vcc_io>;
+ vddio-supply = <&vcc_1v8>;
+ };
+};
+
+&usb_host_ehci {
+ status = "okay";
+};
+
+&usb_host_ohci {
+ status = "okay";
+};
+
+&usb20_otg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi
index 962ea893999b..31c25de2d689 100644
--- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi
@@ -173,6 +173,11 @@
compatible = "rockchip,rk3308-grf", "syscon", "simple-mfd";
reg = <0x0 0xff000000 0x0 0x08000>;
+ io_domains: io-domains {
+ compatible = "rockchip,rk3308-io-voltage-domain";
+ status = "disabled";
+ };
+
reboot-mode {
compatible = "syscon-reboot-mode";
offset = <0x500>;
@@ -556,6 +561,30 @@
status = "disabled";
};
+ otp: efuse@ff210000 {
+ compatible = "rockchip,rk3308-otp";
+ reg = <0x0 0xff210000 0x0 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&cru SCLK_OTP_USR>, <&cru PCLK_OTP_NS>,
+ <&cru PCLK_OTP_PHY>;
+ clock-names = "otp", "apb_pclk", "phy";
+ resets = <&cru SRST_OTP_PHY>;
+ reset-names = "phy";
+
+ cpu_id: id@7 {
+ reg = <0x07 0x10>;
+ };
+
+ cpu_leakage: cpu-leakage@17 {
+ reg = <0x17 0x1>;
+ };
+
+ logic_leakage: logic-leakage@18 {
+ reg = <0x18 0x1>;
+ };
+ };
+
dmac0: dma-controller@ff2c0000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0x0 0xff2c0000 0x0 0x4000>;
@@ -811,7 +840,7 @@
clocks = <&cru SCLK_I2S2_8CH_TX_OUT>,
<&cru SCLK_I2S2_8CH_RX_OUT>,
<&cru PCLK_ACODEC>;
- reset-names = "codec-reset";
+ reset-names = "codec";
resets = <&cru SRST_ACODEC_P>;
#sound-dai-cells = <0>;
status = "disabled";
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 f09d60bbe6c4..a608a219543e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts
@@ -241,8 +241,8 @@
rk805: pmic@18 {
compatible = "rockchip,rk805";
reg = <0x18>;
- interrupt-parent = <&gpio2>;
- interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
#clock-cells = <1>;
clock-output-names = "xin32k", "rk805-clkout2";
gpio-controller;
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
index 229fe9da9c2d..90fef766f3ae 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
@@ -154,6 +154,8 @@
};
&hdmi {
+ avdd-0v9-supply = <&vdd_10>;
+ avdd-1v8-supply = <&vcc_18>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 07dcc949b899..b01efd6d042c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -850,8 +850,8 @@
<0>, <24000000>,
<24000000>, <24000000>,
<15000000>, <15000000>,
- <100000000>, <100000000>,
- <100000000>, <100000000>,
+ <300000000>, <100000000>,
+ <400000000>, <100000000>,
<50000000>, <100000000>,
<100000000>, <100000000>,
<50000000>, <50000000>,
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lba3368.dts b/arch/arm64/boot/dts/rockchip/rk3368-lba3368.dts
new file mode 100644
index 000000000000..e0cc4da7f392
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3368-lba3368.dts
@@ -0,0 +1,659 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/clock/rockchip,rk808.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/sound/rt5640.h>
+#include "rk3368.dtsi"
+
+/ {
+ model = "Neardi LBA3368";
+ compatible = "neardi,lba3368", "rockchip,rk3368";
+
+ aliases {
+ ethernet0 = &gmac;
+ mmc0 = &emmc;
+ mmc1 = &sdmmc;
+ mmc2 = &sdio0;
+ rtc0 = &hym8563;
+ rtc1 = &rk808;
+ };
+
+ chosen {
+ stdout-path = "serial1:115200n8";
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x40000000>;
+ };
+
+ adc-key {
+ compatible = "adc-keys";
+ io-channels = <&saradc 1>;
+ io-channel-names = "buttons";
+ poll-interval = <100>;
+ keyup-threshold-microvolt = <1800000>;
+
+ button-recovery {
+ label = "Recovery";
+ linux,code = <KEY_VENDOR>;
+ press-threshold-microvolt = <0>;
+ };
+ };
+
+ analog-sound {
+ compatible = "audio-graph-card";
+ dais = <&i2s_8ch_p0>;
+ hp-det-gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;
+ label = "alc5640";
+ routing = "Mic Jack", "MICBIAS1",
+ "IN1P", "Mic Jack",
+ "Headphone Jack", "HPOL",
+ "Headphone Jack", "HPOR",
+ "Speakers", "SPORP",
+ "Speakers", "SPORN",
+ "Speakers", "SPOLP",
+ "Speakers", "SPOLN";
+ widgets = "Microphone", "Mic Jack",
+ "Headphone", "Headphone Jack",
+ "Speaker", "Speakers";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_det>;
+ };
+
+ dc_12v: dc-12v-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "dc_12v";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ext_gmac: gmac-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <50000000>;
+ clock-output-names = "ext_gmac";
+ #clock-cells = <0>;
+ };
+
+ hub_avdd: hub-avdd-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "hub_avdd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_io>;
+ regulator-always-on;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ power-led {
+ gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_POWER;
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "on";
+ pinctrl-names = "default";
+ pinctrl-0 = <&power_led>;
+ };
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rk808 RK808_CLKOUT1>;
+ clock-names = "ext_clock";
+ reset-gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_reg_on>;
+ };
+
+ vcc_host: vcc-host-regulator {
+ compatible = "regulator-fixed";
+ gpio = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vcc_host";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_sys>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&host_vbus_drv>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ vcc_lan: vcc-lan-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_lan";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_io>;
+ regulator-always-on;
+ };
+
+ vcc_otg: vcc-otg-regulator {
+ compatible = "regulator-fixed";
+ gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vcc_otg";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_sys>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&otg_vbus_drv>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ vcc_sys: vcc-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sys";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&dc_12v>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vdd10_usb: vdd10-usb-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd10_usb";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ vin-supply = <&vdd_10>;
+ regulator-always-on;
+ };
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_b2 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_b3 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&emmc {
+ bus-width = <8>;
+ vmmc-supply = <&vcc_io>;
+ vqmmc-supply = <&vcc_18>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
+ cap-mmc-highspeed;
+ non-removable;
+ no-sd;
+ no-sdio;
+ mmc-hs200-1_8v;
+ status = "okay";
+};
+
+&gmac {
+ clock_in_out = "input";
+ phy-handle = <&phy>;
+ phy-mode = "rmii";
+ phy-supply = <&vcc_lan>;
+ assigned-clocks = <&cru SCLK_MAC>;
+ assigned-clock-parents = <&ext_gmac>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rmii_pins>;
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ max-speed = <100>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <1000000>;
+ reset-gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&phy_rst>;
+ };
+ };
+};
+
+&io_domains {
+ audio-supply = <&vcca1v8_codec>;
+ dvp-supply = <&vcc_18>;
+ flash0-supply = <&vcc_18>;
+ gpio1830-supply = <&vcc_io>;
+ gpio30-supply = <&vcc_io>;
+ sdcard-supply = <&vccio_sd>;
+ wifi-supply = <&vdd1v8_wl>;
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ rk808: pmic@1b {
+ compatible = "rockchip,rk808";
+ reg = <0x1b>;
+ interrupts-extended = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>;
+ clock-output-names = "rk808-clkout1", "xin32k_wifi_bt";
+ vcc1-supply = <&vcc_sys>;
+ vcc2-supply = <&vcc_sys>;
+ vcc3-supply = <&vcc_sys>;
+ vcc4-supply = <&vcc_sys>;
+ vcc6-supply = <&vcc_sys>;
+ vcc7-supply = <&vcc_sys>;
+ vcc8-supply = <&vcc_io>;
+ vcc9-supply = <&vcc_sys>;
+ vcc10-supply = <&vcc_sys>;
+ vcc11-supply = <&vcc_sys>;
+ vcc12-supply = <&vcc_io>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int &pmic_sleep>;
+ system-power-controller;
+ wakeup-source;
+ #clock-cells = <1>;
+
+ regulators {
+ vdd_cpu: DCDC_REG1 {
+ regulator-name = "vdd_cpu";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_log: DCDC_REG2 {
+ regulator-name = "vdd_log";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-ramp-delay = <6001>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-suspend-microvolt = <1000000>;
+ regulator-on-in-suspend;
+ };
+ };
+
+ 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-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcca1v8_codec: LDO_REG1 {
+ regulator-name = "vcca1v8_codec";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca3v0_codec: LDO_REG2 {
+ regulator-name = "vcca3v0_codec";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ 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-suspend-microvolt = <1000000>;
+ regulator-on-in-suspend;
+ };
+ };
+
+ vdd1v8_wl: LDO_REG4 {
+ regulator-name = "vdd1v8_wl";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ 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;
+ };
+ };
+
+ vdd10_lcd: LDO_REG6 {
+ regulator-name = "vdd10_lcd";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_18: LDO_REG7 {
+ regulator-name = "vcc_18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-suspend-microvolt = <1800000>;
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc18_lcd: LDO_REG8 {
+ regulator-name = "vcc18_lcd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_tp: SWITCH_REG1 {
+ regulator-name = "vcc_tp";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_sd: SWITCH_REG2 {
+ regulator-name = "vcc_sd";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&i2c1 {
+ status = "okay";
+
+ codec@1c {
+ compatible = "realtek,rt5640";
+ reg = <0x1c>;
+ clocks = <&cru SCLK_I2S_8CH_OUT>;
+ clock-names = "mclk";
+ realtek,dmic1-data-pin = <RT5640_DMIC1_DATA_PIN_IN1P>;
+ realtek,dmic2-data-pin = <RT5640_DMIC2_DATA_PIN_IN1N>;
+ realtek,in1-differential;
+ #sound-dai-cells = <0>;
+
+ port {
+ rt5640_p0_0: endpoint {
+ remote-endpoint = <&i2s_8ch_p0_0>;
+ };
+ };
+ };
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ clock-output-names = "xin32k";
+ #clock-cells = <0>;
+ };
+};
+
+&i2s_8ch {
+ status = "okay";
+
+ i2s_8ch_p0: port {
+ i2s_8ch_p0_0: endpoint {
+ dai-format = "i2s";
+ mclk-fs = <256>;
+ remote-endpoint = <&rt5640_p0_0>;
+ };
+ };
+};
+
+&pinctrl {
+ bluetooth {
+ bt_host_wake: bt-host-wake {
+ rockchip,pins = <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_reg_on: bt-reg-on {
+ rockchip,pins = <3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ bt_wake: bt-wake {
+ rockchip,pins = <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ power_led: power-led {
+ rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ phy {
+ phy_rst: phy-rst {
+ rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int: pmic-int {
+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ pmic_sleep: pmic-sleep {
+ rockchip,pins = <0 RK_PA0 2 &pcfg_pull_none>;
+ };
+ };
+
+ sdio-pwrseq {
+ wifi_reg_on: wifi-reg-on {
+ rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sound {
+ hp_det: hp-det {
+ rockchip,pins = <0 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb {
+ host_vbus_drv: host-vbus-drv {
+ rockchip,pins = <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ otg_vbus_drv: otg-vbus-drv {
+ rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wifi {
+ wifi_host_wake: wifi-host-wake {
+ rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ pmu-supply = <&vcc_io>;
+ vop-supply = <&vcc_io>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_18>;
+ status = "okay";
+};
+
+&sdio0 {
+ bus-width = <4>;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ vmmc-supply = <&vcc_io>;
+ vqmmc-supply = <&vdd1v8_wl>;
+ assigned-clocks = <&cru SCLK_SDIO0>;
+ assigned-clock-parents = <&cru PLL_CPLL>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ no-sd;
+ no-mmc;
+ non-removable;
+ sd-uhs-sdr104;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ wifi@1 {
+ compatible = "brcm,bcm43455-fmac", "brcm,bcm4329-fmac";
+ reg = <1>;
+ interrupts-extended = <&gpio3 RK_PA6 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host-wake";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_host_wake>;
+ };
+};
+
+&sdmmc {
+ bus-width = <4>;
+ vmmc-supply = <&vcc_sd>;
+ vqmmc-supply = <&vccio_sd>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4 &sdmmc_cd>;
+ cap-sd-highspeed;
+ disable-wp;
+ no-mmc;
+ no-sdio;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ status = "okay";
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <0>;
+ rockchip,hw-tshut-polarity = <1>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4345c5";
+ interrupts-extended = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>;
+ interrupt-names = "host-wakeup";
+ clocks = <&rk808 RK808_CLKOUT1>;
+ clock-names = "lpo";
+ device-wakeup-gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&gpio3 RK_PA2 GPIO_ACTIVE_HIGH>;
+ max-speed = <15000000>;
+ vbat-supply = <&vcc_io>;
+ vddio-supply = <&vdd1v8_wl>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_host_wake &bt_wake &bt_reg_on>;
+ };
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_xfer>;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart4_xfer>;
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ hub@1 {
+ compatible = "usb5e3,610";
+ reg = <1>;
+ vdd-supply = <&hub_avdd>;
+ };
+};
+
+&usb_otg {
+ vbus-supply = <&vcc_otg>;
+ vusb_a-supply = <&vcc_io>;
+ vusb_d-supply = <&vdd10_usb>;
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
index 734f87db4d11..73618df7a889 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -793,6 +793,7 @@
dma-names = "tx";
pinctrl-names = "default";
pinctrl-0 = <&spdif_tx>;
+ #sound-dai-cells = <0>;
status = "disabled";
};
@@ -804,6 +805,7 @@
clocks = <&cru SCLK_I2S_2CH>, <&cru HCLK_I2S_2CH>;
dmas = <&dmac_bus 6>, <&dmac_bus 7>;
dma-names = "tx", "rx";
+ #sound-dai-cells = <0>;
status = "disabled";
};
@@ -817,6 +819,7 @@
dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&i2s_8ch_bus>;
+ #sound-dai-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
index 789fd0dcc88b..3cd63d1e8f15 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
@@ -450,7 +450,7 @@ ap_i2c_audio: &i2c8 {
dlg,btn-cfg = <50>;
dlg,mic-det-thr = <500>;
dlg,jack-ins-deb = <20>;
- dlg,jack-det-rate = "32ms_64ms";
+ dlg,jack-det-rate = "32_64";
dlg,jack-rem-deb = <1>;
dlg,a-d-btn-thr = <0xa>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index e5709c7ee06a..ef754ea30a94 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -12,6 +12,7 @@
/dts-v1/;
#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-opp.dtsi"
@@ -69,6 +70,34 @@
};
};
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&red_led_pin &green_led_pin &blue_led_pin>;
+
+ led_red: led-0 {
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>;
+ };
+
+ led_green: led-1 {
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&gpio4 RK_PD5 GPIO_ACTIVE_HIGH>;
+ };
+
+ led_blue: led-2 {
+ color = <LED_COLOR_ID_BLUE>;
+ gpios = <&gpio4 RK_PD6 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ multi-led {
+ compatible = "leds-group-multicolor";
+ color = <LED_COLOR_ID_RGB>;
+ function = LED_FUNCTION_INDICATOR;
+ leds = <&led_red>, <&led_green>, <&led_blue>;
+ };
+
vcc_sys: vcc-sys-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
@@ -152,6 +181,12 @@
gpio = <&gpio3 RK_PA1 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
};
+
+ vibrator {
+ compatible = "gpio-vibrator";
+ enable-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>;
+ vcc-supply = <&vcc3v3_sys>;
+ };
};
&cpu_alert0 {
@@ -407,6 +442,21 @@
};
};
+&i2c4 {
+ i2c-scl-rising-time-ns = <600>;
+ i2c-scl-falling-time-ns = <20>;
+ status = "okay";
+
+ /* Accelerometer/gyroscope */
+ mpu6500@68 {
+ compatible = "invensense,mpu6500";
+ reg = <0x68>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <RK_PC6 IRQ_TYPE_LEVEL_LOW>;
+ vddio-supply = <&vcc_1v8>;
+ };
+};
+
&cluster0_opp {
opp04 {
status = "disabled";
@@ -481,6 +531,20 @@
};
};
+ leds {
+ red_led_pin: red-led-pin {
+ rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ green_led_pin: green-led-pin {
+ rockchip,pins = <4 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ blue_led_pin: blue-led-pin {
+ rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
pmic {
pmic_int_l: pmic-int-l {
rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
@@ -565,6 +629,16 @@
status = "okay";
};
+&spi1 {
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+ };
+};
+
&tsadc {
rockchip,hw-tshut-mode = <1>;
rockchip,hw-tshut-polarity = <1>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro.dtsi
deleted file mode 100644
index bb5ebf6608b9..000000000000
--- a/arch/arm64/boot/dts/rockchip/rk3399pro.dtsi
+++ /dev/null
@@ -1,22 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-// Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd.
-
-#include "rk3399.dtsi"
-
-/ {
- compatible = "rockchip,rk3399pro";
-};
-
-/* Default to enabled since AP talk to NPU part over pcie */
-&pcie_phy {
- status = "okay";
-};
-
-/* Default to enabled since AP talk to NPU part over pcie */
-&pcie0 {
- ep-gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>;
- num-lanes = <4>;
- pinctrl-names = "default";
- pinctrl-0 = <&pcie_clkreqn_cpm>;
- status = "okay";
-};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts
new file mode 100644
index 000000000000..074e93bd4b85
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v1.1.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include "rk3566-orangepi-3b.dtsi"
+
+/ {
+ model = "Xunlong Orange Pi 3B v1.1";
+ compatible = "xunlong,orangepi-3b-v1.1", "xunlong,orangepi-3b", "rockchip,rk3566";
+};
+
+&pmu_io_domains {
+ vccio5-supply = <&vcc_3v3>;
+};
+
+&gmac1 {
+ phy-handle = <&rgmii_phy1>;
+ status = "okay";
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v2.1.dts b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v2.1.dts
new file mode 100644
index 000000000000..d894bff41e61
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b-v2.1.dts
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include "rk3566-orangepi-3b.dtsi"
+
+/ {
+ model = "Xunlong Orange Pi 3B v2.1";
+ compatible = "xunlong,orangepi-3b-v2.1", "xunlong,orangepi-3b", "rockchip,rk3566";
+
+ vccio_phy1: regulator-1v8-vccio-phy {
+ compatible = "regulator-fixed";
+ regulator-name = "vccio_phy1";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1800000>;
+ regulator-min-microvolt = <1800000>;
+ };
+};
+
+&pmu_io_domains {
+ vccio5-supply = <&vccio_phy1>;
+};
+
+&gmac1 {
+ phy-handle = <&rgmii_phy1>;
+ status = "okay";
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&sdmmc1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ brcmf: wifi@1 {
+ compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac";
+ reg = <1>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PD6 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host-wake";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_wake_host_h>;
+ };
+};
+
+&uart1 {
+ bluetooth {
+ compatible = "brcm,bcm4345c5";
+ clocks = <&rk809 1>;
+ clock-names = "lpo";
+ interrupt-parent = <&gpio2>;
+ interrupts = <RK_PC0 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host-wakeup";
+ device-wakeup-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_reg_on_h &bt_wake_host_h &host_wake_bt_h>;
+ vbat-supply = <&vcc_3v3>;
+ vddio-supply = <&vcc_1v8>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi
new file mode 100644
index 000000000000..d539570f531e
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtsi
@@ -0,0 +1,678 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
+#include "rk3566.dtsi"
+
+/ {
+ model = "Xunlong Orange Pi 3B";
+ compatible = "xunlong,orangepi-3b", "rockchip,rk3566";
+
+ aliases {
+ ethernet0 = &gmac1;
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc0;
+ mmc2 = &sdmmc1;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&work_led>;
+
+ led-0 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "on";
+ function = LED_FUNCTION_HEARTBEAT;
+ gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ vcc3v3_pcie30: regulator-3v3-vcc-pcie30 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie20_pwren>;
+ regulator-name = "vcc3v3_pcie30";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ vcc3v3_sys: regulator-3v3-vcc-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-5v0-vcc-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc5v0_usb_host: regulator-5v0-vcc-usb-host {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio0 RK_PA6 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 = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_usb_otg: regulator-5v0-vcc-usb-otg {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_otg_pwren_h>;
+ regulator-name = "vcc5v0_usb_otg";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rk809 1>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_reg_on_h>;
+ post-power-on-delay-ms = <200>;
+ power-off-delay-us = <5000000>;
+ reset-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_LOW>;
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "Analog RK809";
+ simple-audio-card,mclk-fs = <256>;
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_8ch>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&rk809>;
+ };
+ };
+};
+
+&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>;
+ clock_in_out = "input";
+ phy-mode = "rgmii-id";
+ phy-supply = <&vcc_3v3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1m0_miim
+ &gmac1m0_tx_bus2
+ &gmac1m0_rx_bus2
+ &gmac1m0_rgmii_clk
+ &gmac1m0_rgmii_bus
+ &gmac1m0_clkinout>;
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu>;
+ status = "okay";
+};
+
+&hdmi {
+ avdd-0v9-supply = <&vdda0v9_image>;
+ avdd-1v8-supply = <&vcca1v8_image>;
+ status = "okay";
+};
+
+&hdmi_in {
+ hdmi_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi>;
+ };
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdmi_sound {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ rk809: pmic@20 {
+ compatible = "rockchip,rk809";
+ reg = <0x20>;
+ assigned-clocks = <&cru I2S1_MCLKOUT_TX>;
+ assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>;
+ #clock-cells = <1>;
+ clocks = <&cru I2S1_MCLKOUT_TX>;
+ clock-names = "mclk";
+ clock-output-names = "rk809-clkout1", "rk809-clkout2";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int_l>, <&i2s1m0_mclk>;
+ #sound-dai-cells = <0>;
+ system-power-controller;
+ wakeup-source;
+
+ 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>;
+
+ 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-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;
+ };
+ };
+
+ 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 = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda_0v9: LDO_REG2 {
+ regulator-name = "vdda_0v9";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda0v9_pmu: LDO_REG3 {
+ regulator-name = "vdda0v9_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <900000>;
+ };
+ };
+
+ vccio_acodec: LDO_REG4 {
+ regulator-name = "vccio_acodec";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd: LDO_REG5 {
+ regulator-name = "vccio_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ 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;
+ };
+ };
+ };
+ };
+
+ vdd_cpu: regulator@40 {
+ compatible = "silergy,syr827";
+ reg = <0x40>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <830000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc3v3_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2s0_8ch {
+ status = "okay";
+};
+
+&i2s1_8ch {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s1m0_sclktx
+ &i2s1m0_lrcktx
+ &i2s1m0_sdi0
+ &i2s1m0_sdo0>;
+ rockchip,trcm-sync-tx-only;
+ status = "okay";
+};
+
+&pcie2x1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie20_pins>;
+ reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie30>;
+ status = "okay";
+};
+
+&pinctrl {
+ bluetooth {
+ bt_reg_on_h: bt-reg-on-h {
+ rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_wake_host_h: bt-wake-host-h {
+ rockchip,pins = <2 RK_PC0 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+
+ host_wake_bt_h: host-wake-bt-h {
+ rockchip,pins = <2 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ work_led: work-led {
+ rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie {
+ pcie20_pins: pcie20-pins {
+ rockchip,pins =
+ <1 RK_PB0 4 &pcfg_pull_none>,
+ <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>,
+ <1 RK_PB1 4 &pcfg_pull_none>;
+ };
+
+ pcie20_pwren: pcie20-pwren {
+ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ usb {
+ usb_host_pwren_h: usb-host-pwren-h {
+ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ usb_otg_pwren_h: usb-otg-pwren-h {
+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wifi {
+ wifi_reg_on_h: wifi-reg-on-h {
+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wifi_wake_host_h: wifi-wake-host-h {
+ rockchip,pins = <0 RK_PD6 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ pmuio1-supply = <&vcc3v3_pmu>;
+ pmuio2-supply = <&vcc3v3_pmu>;
+ vccio1-supply = <&vccio_acodec>;
+ vccio2-supply = <&vcc_1v8>;
+ vccio3-supply = <&vccio_sd>;
+ vccio4-supply = <&vcc_1v8>;
+ vccio6-supply = <&vcc_3v3>;
+ vccio7-supply = <&vcc_3v3>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcca_1v8>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ max-frequency = <200000000>;
+ mmc-hs200-1_8v;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdmmc0 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ disable-wp;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>;
+ vmmc-supply = <&vcc3v3_sd>;
+ vqmmc-supply = <&vccio_sd>;
+ status = "okay";
+};
+
+&sdmmc1 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ no-mmc;
+ no-sd;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_clk &sdmmc1_cmd>;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sfc {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <104000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <1>;
+ };
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <1>;
+ rockchip,hw-tshut-polarity = <0>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn &uart1m0_rtsn>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
+
+&usb_host1_xhci {
+ status = "okay";
+};
+
+&usb2phy0 {
+ status = "okay";
+};
+
+&usb2phy0_host {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&usb2phy0_otg {
+ phy-supply = <&vcc5v0_usb_otg>;
+ status = "okay";
+};
+
+&usb2phy1 {
+ status = "okay";
+};
+
+&usb2phy1_host {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&usb2phy1_otg {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&vop {
+ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
index d899087bf0b5..ae2536c65a83 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
@@ -674,6 +674,7 @@
};
&uart1 {
+ dma-names = "tx", "rx";
pinctrl-0 = <&uart1m0_ctsn>, <&uart1m0_rtsn>, <&uart1m0_xfer>;
pinctrl-names = "default";
uart-has-rtscts;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
index 0b191d8462ad..37a1303d9a34 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
@@ -738,6 +738,7 @@
};
&uart1 {
+ dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn &uart1m0_rtsn>;
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts
index 26322a358d91..13e599a85eb8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts
@@ -289,7 +289,7 @@
regulator-name = "vdd_gpu";
regulator-always-on;
regulator-boot-on;
- regulator-min-microvolt = <900000>;
+ regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
regulator-ramp-delay = <6001>;
@@ -652,6 +652,7 @@
};
&uart1 {
+ dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn &uart1m0_rtsn>;
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi
new file mode 100644
index 000000000000..9cc7aa3298d0
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi
@@ -0,0 +1,531 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
+#include "rk3566.dtsi"
+
+/ {
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "d";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&user_led2>;
+
+ led-green {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "on";
+ function = LED_FUNCTION_HEARTBEAT;
+ gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ 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_1v8_p>;
+ };
+
+ vcca_1v8: regulator-1v8-vcca {
+ compatible = "regulator-fixed";
+ regulator-name = "vcca_1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_1v8_p>;
+ };
+
+ vcca1v8_image: regulator-1v8-vcca-image {
+ compatible = "regulator-fixed";
+ regulator-name = "vcca1v8_image";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_1v8_p>;
+ };
+
+ vcc_3v3: regulator-3v3-vcc {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ vcc_sys: regulator-5v0-vcc-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+};
+
+&combphy1 {
+ status = "okay";
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&gpio0 {
+ gpio-line-names =
+ /* GPIO0_A0 - A7 */
+ "", "", "", "", "", "", "", "",
+ /* GPIO0_B0 - B7 */
+ "", "", "", "", "", "", "", "",
+ /* GPIO0_C0 - C7 */
+ "", "", "", "", "", "", "", "",
+ /* GPIO0_D0 - D7 */
+ "pin-10 [GPIO0_D0]", "pin-08 [GPIO0_D1]", "",
+ "", "", "", "", "";
+};
+
+&gpio1 {
+ gpio-line-names =
+ /* GPIO1_A0 - A7 */
+ "pin-03 [GPIO1_A0]", "pin-05 [GPIO1_A1]", "",
+ "", "pin-37 [GPIO1_A4]", "",
+ "", "",
+ /* GPIO1_B0 - B7 */
+ "", "", "", "", "", "", "", "",
+ /* GPIO1_C0 - C7 */
+ "", "", "", "", "", "", "", "",
+ /* GPIO1_D0 - D7 */
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio2 {
+ gpio-line-names =
+ /* GPIO2_A0 - A7 */
+ "", "", "", "", "", "", "", "",
+ /* GPIO2_B0 - B7 */
+ "", "", "", "", "", "", "", "",
+ /* GPIO2_C0 - C7 */
+ "", "", "", "", "", "", "", "",
+ /* GPIO2_D0 - D7 */
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio3 {
+ gpio-line-names =
+ /* GPIO3_A0 - A7 */
+ "", "pin-11 [GPIO3_A1]", "pin-13 [GPIO3_A2]",
+ "pin-12 [GPIO3_A3]", "pin-35 [GPIO3_A4]", "pin-40 [GPIO3_A5]",
+ "pin-38 [GPIO3_A6]", "pin-36 [GPIO3_A7]",
+ /* GPIO3_B0 - B7 */
+ "pin-15 [GPIO3_B0]", "pin-16 [GPIO3_B1]", "pin-18 [GPIO3_B2]",
+ "pin-29 [GPIO3_B3]", "pin-31 [GPIO3_B4]", "",
+ "", "",
+ /* GPIO3_C0 - C7 */
+ "", "pin-22 [GPIO3_C1]", "pin-32 [GPIO3_C2]",
+ "pin-33 [GPIO3_C3]", "pin-07 [GPIO3_C4]", "",
+ "", "",
+ /* GPIO3_D0 - D7 */
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio4 {
+ gpio-line-names =
+ /* GPIO4_A0 - A7 */
+ "", "", "", "", "", "", "", "",
+ /* GPIO4_B0 - B7 */
+ "", "", "pin-27 [GPIO4_B2]",
+ "pin-28 [GPIO4_B3]", "", "", "", "",
+ /* GPIO4_C0 - C7 */
+ "", "", "pin-23 [GPIO4_C2]",
+ "pin-19 [GPIO4_C3]", "", "pin-21 [GPIO4_C5]",
+ "pin-24 [GPIO4_C6]", "",
+ /* GPIO4_D0 - D7 */
+ "", "", "", "", "", "", "", "";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu_npu>;
+ status = "okay";
+};
+
+&hdmi {
+ avdd-0v9-supply = <&vdda_0v9>;
+ avdd-1v8-supply = <&vcca1v8_image>;
+ status = "okay";
+};
+
+&hdmi_in {
+ hdmi_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi>;
+ };
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdmi_sound {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ rk817: pmic@20 {
+ compatible = "rockchip,rk817";
+ reg = <0x20>;
+ #clock-cells = <1>;
+ clock-output-names = "rk817-clkout1", "rk817-clkout2";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>;
+ 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_sys>;
+ vcc6-supply = <&vcc_sys>;
+ vcc7-supply = <&vcc_sys>;
+ vcc8-supply = <&vcc_sys>;
+ vcc9-supply = <&vcc5v_midu>;
+
+ 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;
+ regulator-suspend-microvolt = <900000>;
+ };
+ };
+
+ vdd_gpu_npu: DCDC_REG2 {
+ regulator-name = "vdd_gpu_npu";
+ 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;
+ };
+ };
+
+ 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;
+ };
+ };
+
+ vcc3v3_sys: DCDC_REG4 {
+ regulator-name = "vcc3v3_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcca1v8_pmu: LDO_REG1 {
+ 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>;
+ };
+ };
+
+ vdda_0v9: LDO_REG2 {
+ regulator-name = "vdda_0v9";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda0v9_pmu: LDO_REG3 {
+ regulator-name = "vdda0v9_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <900000>;
+ };
+ };
+
+ vccio_acodec: LDO_REG4 {
+ regulator-name = "vccio_acodec";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd: LDO_REG5 {
+ regulator-name = "vccio_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ 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>;
+ };
+ };
+
+ vcc_1v8_p: LDO_REG7 {
+ regulator-name = "vcc_1v8_p";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc1v8_dvp: LDO_REG8 {
+ regulator-name = "vcc1v8_dvp";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc2v8_dvp: LDO_REG9 {
+ regulator-name = "vcc2v8_dvp";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc5v_midu: BOOST {
+ regulator-name = "vcc5v_midu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vbus: OTG_SWITCH {
+ regulator-name = "vbus";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+
+ vdd_cpu: regulator@40 {
+ compatible = "rockchip,rk8600";
+ reg = <0x40>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1390000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2s0_8ch {
+ status = "okay";
+};
+
+&pinctrl {
+ leds {
+ user_led2: user-led2 {
+ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ pmuio1-supply = <&vcc3v3_pmu>;
+ pmuio2-supply = <&vcca1v8_pmu>;
+ vccio1-supply = <&vccio_acodec>;
+ vccio2-supply = <&vcc_1v8>;
+ vccio3-supply = <&vccio_sd>;
+ vccio4-supply = <&vcc_1v8>;
+ vccio5-supply = <&vcc_3v3>;
+ vccio6-supply = <&vcc_3v3>;
+ vccio7-supply = <&vcc_3v3>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcca_1v8>;
+ status = "okay";
+};
+
+&sdmmc0 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ disable-wp;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>;
+ vmmc-supply = <&vcc3v3_sys>;
+ vqmmc-supply = <&vccio_sd>;
+ status = "okay";
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <1>;
+ rockchip,hw-tshut-polarity = <0>;
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usb_host1_xhci {
+ status = "okay";
+};
+
+&usb2phy0 {
+ status = "okay";
+};
+
+&usb2phy0_host {
+ status = "okay";
+};
+
+&usb2phy0_otg {
+ status = "okay";
+};
+
+&vop {
+ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3e.dts b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3e.dts
new file mode 100644
index 000000000000..4a830eb09f0b
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3e.dts
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include "rk3566-radxa-zero-3.dtsi"
+
+/ {
+ model = "Radxa ZERO 3E";
+ compatible = "radxa,zero-3e", "rockchip,rk3566";
+
+ aliases {
+ ethernet0 = &gmac1;
+ mmc0 = &sdmmc0;
+ };
+};
+
+&gmac1 {
+ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>;
+ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru CLK_MAC1_2TOP>;
+ clock_in_out = "input";
+ phy-handle = <&rgmii_phy1>;
+ phy-mode = "rgmii-id";
+ phy-supply = <&vcc_3v3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1m1_miim
+ &gmac1m1_tx_bus2
+ &gmac1m1_rx_bus2
+ &gmac1m1_rgmii_clk
+ &gmac1m1_rgmii_bus
+ &gmac1m1_clkinout>;
+ status = "okay";
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1_rstn>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pinctrl {
+ gmac1 {
+ gmac1_rstn: gmac1-rstn {
+ rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3w.dts b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3w.dts
new file mode 100644
index 000000000000..f92475c59deb
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3w.dts
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include "rk3566-radxa-zero-3.dtsi"
+
+/ {
+ model = "Radxa ZERO 3W";
+ compatible = "radxa,zero-3w", "rockchip,rk3566";
+
+ aliases {
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc0;
+ mmc2 = &sdmmc1;
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rk817 1>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_reg_on_h>;
+ post-power-on-delay-ms = <100>;
+ power-off-delay-us = <5000000>;
+ reset-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pinctrl {
+ bluetooth {
+ bt_reg_on_h: bt-reg-on-h {
+ rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_wake_host_h: bt-wake-host-h {
+ rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ host_wake_bt_h: host-wake-bt-h {
+ rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wifi {
+ wifi_reg_on_h: wifi-reg-on-h {
+ rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wifi_wake_host_h: wifi-wake-host-h {
+ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&sdhci {
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ max-frequency = <200000000>;
+ mmc-hs200-1_8v;
+ no-sd;
+ no-sdio;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdmmc1 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ no-mmc;
+ no-sd;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_clk &sdmmc1_cmd>;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn &uart1m0_rtsn>;
+ uart-has-rtscts;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts b/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts
index 63eea27293fe..67e7801bd489 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts
@@ -269,7 +269,7 @@
vcc9-supply = <&vcc3v3_sys>;
codec {
- mic-in-differential;
+ rockchip,mic-in-differential;
};
regulators {
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts b/arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts
index b242409d378c..f2cc086e5001 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts
@@ -633,7 +633,7 @@
flash@0 {
compatible = "jedec,spi-nor";
reg = <0x0>;
- spi-max-frequency = <120000000>;
+ spi-max-frequency = <104000000>;
spi-rx-bus-width = <4>;
spi-tx-bus-width = <1>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
index dd4e9c1893c6..e42c474ef4ad 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
@@ -614,6 +614,7 @@
};
&uart1 {
+ dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn &uart1m0_rtsn>;
uart-has-rtscts;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
index 19f8fc369b13..8c3ab07d3807 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
@@ -475,7 +475,7 @@
};
codec {
- mic-in-differential;
+ rockchip,mic-in-differential;
};
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts
index 58ab7e9971db..b5e67990dd0f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts
@@ -11,6 +11,10 @@
};
};
+&pmu_io_domains {
+ vccio3-supply = <&vccio_sd>;
+};
+
&sdmmc0 {
bus-width = <4>;
cap-mmc-highspeed;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi
index 89e84e3a9262..25c49bdbadbc 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi
@@ -39,9 +39,9 @@
};
};
- dc_12v: dc-12v-regulator {
+ vcc12v_dcin: vcc12v-dcin-regulator {
compatible = "regulator-fixed";
- regulator-name = "dc_12v";
+ regulator-name = "vcc12v_dcin";
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <12000000>;
@@ -65,7 +65,7 @@
regulator-boot-on;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
- vin-supply = <&dc_12v>;
+ vin-supply = <&vcc12v_dcin>;
};
vcc5v0_sys: vcc5v0-sys-regulator {
@@ -75,16 +75,7 @@
regulator-boot-on;
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
- vin-supply = <&dc_12v>;
- };
-
- vcc5v0_usb_host: vcc5v0-usb-host-regulator {
- compatible = "regulator-fixed";
- regulator-name = "vcc5v0_usb_host";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc12v_dcin>;
};
vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
@@ -94,8 +85,9 @@
pinctrl-names = "default";
pinctrl-0 = <&vcc5v0_usb_otg_en>;
regulator-name = "vcc5v0_usb_otg";
- regulator-always-on;
- regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
};
};
@@ -123,6 +115,10 @@
cpu-supply = <&vdd_cpu>;
};
+&display_subsystem {
+ status = "disabled";
+};
+
&gpu {
mali-supply = <&vdd_gpu>;
status = "okay";
@@ -405,8 +401,8 @@
&pmu_io_domains {
pmuio1-supply = <&vcc3v3_pmu>;
pmuio2-supply = <&vcc3v3_pmu>;
- vccio1-supply = <&vccio_acodec>;
- vccio3-supply = <&vccio_sd>;
+ vccio1-supply = <&vcc_3v3>;
+ vccio2-supply = <&vcc_1v8>;
vccio4-supply = <&vcc_1v8>;
vccio5-supply = <&vcc_3v3>;
vccio6-supply = <&vcc_1v8>;
@@ -429,28 +425,12 @@
status = "okay";
};
-&usb_host0_ehci {
- status = "okay";
-};
-
-&usb_host0_ohci {
- status = "okay";
-};
-
&usb_host0_xhci {
dr_mode = "host";
extcon = <&usb2phy0>;
status = "okay";
};
-&usb_host1_ehci {
- status = "okay";
-};
-
-&usb_host1_ohci {
- status = "okay";
-};
-
&usb_host1_xhci {
status = "okay";
};
@@ -460,7 +440,7 @@
};
&usb2phy0_host {
- phy-supply = <&vcc5v0_usb_host>;
+ phy-supply = <&vcc5v0_sys>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts
index e1fe5e442689..ce2a5e1ccefc 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts
@@ -39,7 +39,7 @@
&gmac0_rx_bus2
&gmac0_rgmii_clk
&gmac0_rgmii_bus>;
- snps,reset-gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>;
+ snps,reset-gpio = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
/* Reset time is 15ms, 50ms for rtl8211f */
snps,reset-delays-us = <0 15000 50000>;
@@ -61,7 +61,7 @@
&gmac1m1_rx_bus2
&gmac1m1_rgmii_clk
&gmac1m1_rgmii_bus>;
- snps,reset-gpio = <&gpio0 RK_PB1 GPIO_ACTIVE_LOW>;
+ snps,reset-gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
/* Reset time is 15ms, 50ms for rtl8211f */
snps,reset-delays-us = <0 15000 50000>;
@@ -71,18 +71,18 @@
};
&mdio0 {
- rgmii_phy0: ethernet-phy@0 {
+ rgmii_phy0: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
- reg = <0>;
+ reg = <0x1>;
pinctrl-0 = <&eth_phy0_reset_pin>;
pinctrl-names = "default";
};
};
&mdio1 {
- rgmii_phy1: ethernet-phy@0 {
+ rgmii_phy1: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
- reg = <0>;
+ reg = <0x1>;
pinctrl-0 = <&eth_phy1_reset_pin>;
pinctrl-names = "default";
};
@@ -102,6 +102,10 @@
};
};
+&pmu_io_domains {
+ vccio3-supply = <&vcc_3v3>;
+};
+
&sdhci {
bus-width = <8>;
max-frequency = <200000000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
index ebdedea15ad1..59f1403b4fa5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
@@ -531,10 +531,6 @@
};
};
};
-
- codec {
- mic-in-differential;
- };
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts b/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts
new file mode 100644
index 000000000000..3d0c1ccfaa79
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3b.dts
@@ -0,0 +1,781 @@
+// 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/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
+#include "rk3568.dtsi"
+
+/ {
+ model = "Radxa ROCK 3B";
+ compatible = "radxa,rock-3b", "rockchip,rk3568";
+
+ aliases {
+ ethernet0 = &gmac0;
+ ethernet1 = &gmac1;
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc0;
+ mmc2 = &sdmmc2;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
+ ir-receiver {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpio0 RK_PC2 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm3_ir>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led>;
+
+ led-0 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "on";
+ function = LED_FUNCTION_HEARTBEAT;
+ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ /* pi6c pcie clock generator */
+ vcc3v3_pi6c_03: regulator-3v3-vcc-pi6c-03 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_pwren_h>;
+ regulator-name = "vcc3v3_pi6c_03";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <10000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc3v3_sys: regulator-3v3-vcc-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>;
+ };
+
+ vcc3v3_sys2: regulator-3v3-vcc-sys2 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_sys2";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_sys: regulator-5v0-vcc-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc5v0_usb_host: regulator-5v0-vcc-usb-host {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio0 RK_PA6 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 = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_usb_otg: regulator-5v0-vcc-usb-otg {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_otg_pwren_h>;
+ regulator-name = "vcc5v0_usb_otg";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rk809 1>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_reg_on_h>;
+ post-power-on-delay-ms = <100>;
+ power-off-delay-us = <5000000>;
+ reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_LOW>;
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "Analog RK809";
+ simple-audio-card,mclk-fs = <256>;
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_8ch>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&rk809>;
+ };
+ };
+};
+
+&combphy0 {
+ status = "okay";
+};
+
+&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>;
+};
+
+&gmac0 {
+ assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>;
+ assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>, <&cru CLK_MAC0_2TOP>;
+ clock_in_out = "input";
+ phy-handle = <&rgmii_phy0>;
+ phy-mode = "rgmii-id";
+ phy-supply = <&vcc_3v3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac0_miim
+ &gmac0_tx_bus2
+ &gmac0_rx_bus2
+ &gmac0_rgmii_clk
+ &gmac0_rgmii_bus
+ &gmac0_clkinout>;
+ status = "okay";
+};
+
+&gmac1 {
+ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>;
+ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru CLK_MAC1_2TOP>;
+ clock_in_out = "input";
+ phy-handle = <&rgmii_phy1>;
+ phy-mode = "rgmii-id";
+ phy-supply = <&vcc_3v3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1m1_miim
+ &gmac1m1_tx_bus2
+ &gmac1m1_rx_bus2
+ &gmac1m1_rgmii_clk
+ &gmac1m1_rgmii_bus
+ &gmac1m1_clkinout>;
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu>;
+ status = "okay";
+};
+
+&hdmi {
+ avdd-0v9-supply = <&vdda0v9_image>;
+ avdd-1v8-supply = <&vcca1v8_image>;
+ status = "okay";
+};
+
+&hdmi_in {
+ hdmi_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi>;
+ };
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdmi_sound {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ vdd_cpu: regulator@1c {
+ compatible = "tcs,tcs4525";
+ reg = <0x1c>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ rk809: pmic@20 {
+ compatible = "rockchip,rk809";
+ reg = <0x20>;
+ assigned-clocks = <&cru I2S1_MCLKOUT_TX>;
+ assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>;
+ #clock-cells = <1>;
+ clocks = <&cru I2S1_MCLKOUT_TX>;
+ clock-names = "mclk";
+ clock-output-names = "rk809-clkout1", "rk809-clkout2";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int_l>, <&i2s1m0_mclk>;
+ #sound-dai-cells = <0>;
+ system-power-controller;
+ wakeup-source;
+
+ 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>;
+
+ 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-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;
+ };
+ };
+
+ 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 = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda_0v9: LDO_REG2 {
+ regulator-name = "vdda_0v9";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda0v9_pmu: LDO_REG3 {
+ regulator-name = "vdda0v9_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <900000>;
+ };
+ };
+
+ vccio_acodec: LDO_REG4 {
+ regulator-name = "vccio_acodec";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd: LDO_REG5 {
+ regulator-name = "vccio_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ 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;
+ };
+ };
+ };
+ };
+};
+
+&i2c5 {
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <0>;
+ clock-output-names = "rtcic_32kout";
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtcic_int_l>;
+ wakeup-source;
+ };
+};
+
+&i2s0_8ch {
+ status = "okay";
+};
+
+&i2s1_8ch {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s1m0_sclktx
+ &i2s1m0_lrcktx
+ &i2s1m0_sdi0
+ &i2s1m0_sdo0>;
+ rockchip,trcm-sync-tx-only;
+ status = "okay";
+};
+
+&mdio0 {
+ rgmii_phy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pcie2x1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie20m1_pins>;
+ reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_sys2>;
+ status = "okay";
+};
+
+&pcie30phy {
+ status = "okay";
+};
+
+&pcie3x2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie30x2m1_pins>;
+ reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&pinctrl {
+ bluetooth {
+ bt_reg_on_h: bt-reg-on-h {
+ rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_wake_host_h: bt-wake-host-h {
+ rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ host_wake_bt_h: host-wake-bt-h {
+ rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ ir-receiver {
+ pwm3_ir: pwm3-ir {
+ rockchip,pins = <0 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ led: led {
+ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie {
+ pcie_pwren_h: pcie-pwren-h {
+ rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie20 {
+ pcie20m1_pins: pcie20m1-pins {
+ rockchip,pins =
+ <2 RK_PD0 4 &pcfg_pull_none>,
+ <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>,
+ <2 RK_PD1 4 &pcfg_pull_none>;
+ };
+ };
+
+ pcie30x2 {
+ pcie30x2m1_pins: pcie30x2m1-pins {
+ rockchip,pins =
+ <2 RK_PD4 4 &pcfg_pull_none>,
+ <2 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>,
+ <2 RK_PD5 4 &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ rtc {
+ rtcic_int_l: rtcic-int-l {
+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ usb {
+ usb_host_pwren_h: usb-host-pwren-h {
+ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ usb_otg_pwren_h: usb-otg-pwren-h {
+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wifi {
+ wifi_reg_on_h: wifi-reg-on-h {
+ rockchip,pins = <3 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wifi_wake_host_h: wifi-wake-host-h {
+ rockchip,pins = <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ pmuio1-supply = <&vcc3v3_pmu>;
+ pmuio2-supply = <&vcc3v3_pmu>;
+ vccio1-supply = <&vccio_acodec>;
+ vccio2-supply = <&vcc_1v8>;
+ vccio3-supply = <&vccio_sd>;
+ vccio4-supply = <&vcc_1v8>;
+ vccio5-supply = <&vcc_3v3>;
+ vccio6-supply = <&vcc_1v8>;
+ vccio7-supply = <&vcc_3v3>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcca_1v8>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ max-frequency = <200000000>;
+ mmc-hs200-1_8v;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdmmc0 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ disable-wp;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>;
+ vmmc-supply = <&vcc3v3_sd>;
+ vqmmc-supply = <&vccio_sd>;
+ status = "okay";
+};
+
+&sdmmc2 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc2m0_bus4 &sdmmc2m0_clk &sdmmc2m0_cmd>;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc3v3_sys2>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "disabled";
+};
+
+&sfc {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <104000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <1>;
+ };
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <1>;
+ rockchip,hw-tshut-polarity = <0>;
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart8m0_xfer &uart8m0_ctsn &uart8m0_rtsn>;
+ uart-has-rtscts;
+ status = "disabled";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ extcon = <&usb2phy0>;
+ status = "okay";
+};
+
+&usb_host1_xhci {
+ status = "okay";
+};
+
+&usb2phy0 {
+ status = "okay";
+};
+
+&usb2phy0_host {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&usb2phy0_otg {
+ phy-supply = <&vcc5v0_usb_otg>;
+ status = "okay";
+};
+
+&usb2phy1 {
+ status = "okay";
+};
+
+&usb2phy1_otg {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&vop {
+ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index d8543b5557ee..4690be841a1c 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -195,32 +195,32 @@
opp-200000000 {
opp-hz = /bits/ 64 <200000000>;
- opp-microvolt = <825000>;
+ opp-microvolt = <850000 850000 1000000>;
};
opp-300000000 {
opp-hz = /bits/ 64 <300000000>;
- opp-microvolt = <825000>;
+ opp-microvolt = <850000 850000 1000000>;
};
opp-400000000 {
opp-hz = /bits/ 64 <400000000>;
- opp-microvolt = <825000>;
+ opp-microvolt = <850000 850000 1000000>;
};
opp-600000000 {
opp-hz = /bits/ 64 <600000000>;
- opp-microvolt = <825000>;
+ opp-microvolt = <900000 900000 1000000>;
};
opp-700000000 {
opp-hz = /bits/ 64 <700000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <950000 950000 1000000>;
};
opp-800000000 {
opp-hz = /bits/ 64 <800000000>;
- opp-microvolt = <1000000>;
+ opp-microvolt = <1000000 1000000 1000000>;
};
};
@@ -790,6 +790,7 @@
clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
clock-names = "aclk", "iface";
#iommu-cells = <0>;
+ power-domains = <&power RK3568_PD_VO>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
index 98c622b27647..c667704ba985 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
@@ -673,6 +673,10 @@
};
};
+&tsadc {
+ status = "okay";
+};
+
&u2phy0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi
index 30db12c4fc82..30db12c4fc82 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
new file mode 100644
index 000000000000..b6e4df180f0b
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
@@ -0,0 +1,2799 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ */
+
+#include <dt-bindings/clock/rockchip,rk3588-cru.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/rk3588-power.h>
+#include <dt-bindings/reset/rockchip,rk3588-cru.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/ata/ahci.h>
+#include <dt-bindings/thermal/thermal.h>
+
+/ {
+ compatible = "rockchip,rk3588";
+
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ gpio0 = &gpio0;
+ gpio1 = &gpio1;
+ gpio2 = &gpio2;
+ gpio3 = &gpio3;
+ gpio4 = &gpio4;
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ i2c5 = &i2c5;
+ i2c6 = &i2c6;
+ i2c7 = &i2c7;
+ i2c8 = &i2c8;
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ serial5 = &uart5;
+ serial6 = &uart6;
+ serial7 = &uart7;
+ serial8 = &uart8;
+ serial9 = &uart9;
+ spi0 = &spi0;
+ spi1 = &spi1;
+ spi2 = &spi2;
+ spi3 = &spi3;
+ spi4 = &spi4;
+ };
+
+ 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>;
+ };
+ };
+ cluster2 {
+ core0 {
+ cpu = <&cpu_b2>;
+ };
+ core1 {
+ cpu = <&cpu_b3>;
+ };
+ };
+ };
+
+ cpu_l0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <530>;
+ clocks = <&scmi_clk SCMI_CLK_CPUL>;
+ assigned-clocks = <&scmi_clk SCMI_CLK_CPUL>;
+ assigned-clock-rates = <816000000>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ i-cache-size = <32768>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache_l0>;
+ dynamic-power-coefficient = <228>;
+ #cooling-cells = <2>;
+ };
+
+ cpu_l1: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x100>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <530>;
+ clocks = <&scmi_clk SCMI_CLK_CPUL>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ i-cache-size = <32768>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache_l1>;
+ dynamic-power-coefficient = <228>;
+ #cooling-cells = <2>;
+ };
+
+ cpu_l2: cpu@200 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x200>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <530>;
+ clocks = <&scmi_clk SCMI_CLK_CPUL>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ i-cache-size = <32768>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache_l2>;
+ dynamic-power-coefficient = <228>;
+ #cooling-cells = <2>;
+ };
+
+ cpu_l3: cpu@300 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x300>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <530>;
+ clocks = <&scmi_clk SCMI_CLK_CPUL>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ i-cache-size = <32768>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <128>;
+ d-cache-size = <32768>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_cache_l3>;
+ dynamic-power-coefficient = <228>;
+ #cooling-cells = <2>;
+ };
+
+ cpu_b0: cpu@400 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a76";
+ reg = <0x400>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ clocks = <&scmi_clk SCMI_CLK_CPUB01>;
+ assigned-clocks = <&scmi_clk SCMI_CLK_CPUB01>;
+ assigned-clock-rates = <816000000>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ i-cache-size = <65536>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <65536>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&l2_cache_b0>;
+ dynamic-power-coefficient = <416>;
+ #cooling-cells = <2>;
+ };
+
+ cpu_b1: cpu@500 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a76";
+ reg = <0x500>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ clocks = <&scmi_clk SCMI_CLK_CPUB01>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ i-cache-size = <65536>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <65536>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&l2_cache_b1>;
+ dynamic-power-coefficient = <416>;
+ #cooling-cells = <2>;
+ };
+
+ cpu_b2: cpu@600 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a76";
+ reg = <0x600>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ clocks = <&scmi_clk SCMI_CLK_CPUB23>;
+ assigned-clocks = <&scmi_clk SCMI_CLK_CPUB23>;
+ assigned-clock-rates = <816000000>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ i-cache-size = <65536>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <65536>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&l2_cache_b2>;
+ dynamic-power-coefficient = <416>;
+ #cooling-cells = <2>;
+ };
+
+ cpu_b3: cpu@700 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a76";
+ reg = <0x700>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ clocks = <&scmi_clk SCMI_CLK_CPUB23>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ i-cache-size = <65536>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <65536>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&l2_cache_b3>;
+ dynamic-power-coefficient = <416>;
+ #cooling-cells = <2>;
+ };
+
+ idle-states {
+ entry-method = "psci";
+ CPU_SLEEP: cpu-sleep {
+ compatible = "arm,idle-state";
+ local-timer-stop;
+ arm,psci-suspend-param = <0x0010000>;
+ entry-latency-us = <100>;
+ exit-latency-us = <120>;
+ min-residency-us = <1000>;
+ };
+ };
+
+ l2_cache_l0: l2-cache-l0 {
+ compatible = "cache";
+ cache-size = <131072>;
+ cache-line-size = <64>;
+ cache-sets = <512>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l1: l2-cache-l1 {
+ compatible = "cache";
+ cache-size = <131072>;
+ cache-line-size = <64>;
+ cache-sets = <512>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l2: l2-cache-l2 {
+ compatible = "cache";
+ cache-size = <131072>;
+ cache-line-size = <64>;
+ cache-sets = <512>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l3: l2-cache-l3 {
+ compatible = "cache";
+ cache-size = <131072>;
+ cache-line-size = <64>;
+ cache-sets = <512>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_b0: l2-cache-b0 {
+ compatible = "cache";
+ cache-size = <524288>;
+ cache-line-size = <64>;
+ cache-sets = <1024>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_b1: l2-cache-b1 {
+ compatible = "cache";
+ cache-size = <524288>;
+ cache-line-size = <64>;
+ cache-sets = <1024>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_b2: l2-cache-b2 {
+ compatible = "cache";
+ cache-size = <524288>;
+ cache-line-size = <64>;
+ cache-sets = <1024>;
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_b3: l2-cache-b3 {
+ compatible = "cache";
+ cache-size = <524288>;
+ cache-line-size = <64>;
+ cache-sets = <1024>;
+ cache-level = <2>;
+ 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;
+ };
+ };
+
+ display_subsystem: display-subsystem {
+ compatible = "rockchip,display-subsystem";
+ ports = <&vop_out>;
+ };
+
+ firmware {
+ optee: optee {
+ compatible = "linaro,optee-tz";
+ method = "smc";
+ };
+
+ 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>;
+ };
+
+ scmi_reset: protocol@16 {
+ reg = <0x16>;
+ #reset-cells = <1>;
+ };
+ };
+ };
+
+ pmu-a55 {
+ compatible = "arm,cortex-a55-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition0>;
+ };
+
+ pmu-a76 {
+ compatible = "arm,cortex-a76-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition1>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ spll: clock-0 {
+ compatible = "fixed-clock";
+ clock-frequency = <702000000>;
+ clock-output-names = "spll";
+ #clock-cells = <0>;
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_PPI 12 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "sec-phys", "phys", "virt", "hyp-phys", "hyp-virt";
+ };
+
+ xin24m: clock-1 {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "xin24m";
+ #clock-cells = <0>;
+ };
+
+ xin32k: clock-2 {
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ clock-output-names = "xin32k";
+ #clock-cells = <0>;
+ };
+
+ pmu_sram: sram@10f000 {
+ compatible = "mmio-sram";
+ reg = <0x0 0x0010f000 0x0 0x100>;
+ ranges = <0 0x0 0x0010f000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ scmi_shmem: sram@0 {
+ compatible = "arm,scmi-shmem";
+ reg = <0x0 0x100>;
+ };
+ };
+
+ gpu: gpu@fb000000 {
+ compatible = "rockchip,rk3588-mali", "arm,mali-valhall-csf";
+ reg = <0x0 0xfb000000 0x0 0x200000>;
+ #cooling-cells = <2>;
+ assigned-clocks = <&scmi_clk SCMI_CLK_GPU>;
+ assigned-clock-rates = <200000000>;
+ clocks = <&cru CLK_GPU>, <&cru CLK_GPU_COREGROUP>,
+ <&cru CLK_GPU_STACKS>;
+ clock-names = "core", "coregroup", "stacks";
+ dynamic-power-coefficient = <2982>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "job", "mmu", "gpu";
+ power-domains = <&power RK3588_PD_GPU>;
+ status = "disabled";
+ };
+
+ usb_host0_xhci: usb@fc000000 {
+ compatible = "rockchip,rk3588-dwc3", "snps,dwc3";
+ reg = <0x0 0xfc000000 0x0 0x400000>;
+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru REF_CLK_USB3OTG0>, <&cru SUSPEND_CLK_USB3OTG0>,
+ <&cru ACLK_USB3OTG0>;
+ clock-names = "ref_clk", "suspend_clk", "bus_clk";
+ dr_mode = "otg";
+ phys = <&u2phy0_otg>, <&usbdp_phy0 PHY_TYPE_USB3>;
+ phy-names = "usb2-phy", "usb3-phy";
+ phy_type = "utmi_wide";
+ power-domains = <&power RK3588_PD_USB>;
+ resets = <&cru SRST_A_USB3OTG0>;
+ snps,dis_enblslpm_quirk;
+ snps,dis-u1-entry-quirk;
+ snps,dis-u2-entry-quirk;
+ snps,dis-u2-freeclk-exists-quirk;
+ snps,dis-del-phy-power-chg-quirk;
+ snps,dis-tx-ipgap-linecheck-quirk;
+ status = "disabled";
+ };
+
+ usb_host0_ehci: usb@fc800000 {
+ compatible = "rockchip,rk3588-ehci", "generic-ehci";
+ reg = <0x0 0xfc800000 0x0 0x40000>;
+ interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST_ARB0>, <&cru ACLK_USB>, <&u2phy2>;
+ phys = <&u2phy2_host>;
+ phy-names = "usb";
+ power-domains = <&power RK3588_PD_USB>;
+ status = "disabled";
+ };
+
+ usb_host0_ohci: usb@fc840000 {
+ compatible = "rockchip,rk3588-ohci", "generic-ohci";
+ reg = <0x0 0xfc840000 0x0 0x40000>;
+ interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST_ARB0>, <&cru ACLK_USB>, <&u2phy2>;
+ phys = <&u2phy2_host>;
+ phy-names = "usb";
+ power-domains = <&power RK3588_PD_USB>;
+ status = "disabled";
+ };
+
+ usb_host1_ehci: usb@fc880000 {
+ compatible = "rockchip,rk3588-ehci", "generic-ehci";
+ reg = <0x0 0xfc880000 0x0 0x40000>;
+ interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST_ARB1>, <&cru ACLK_USB>, <&u2phy3>;
+ phys = <&u2phy3_host>;
+ phy-names = "usb";
+ power-domains = <&power RK3588_PD_USB>;
+ status = "disabled";
+ };
+
+ usb_host1_ohci: usb@fc8c0000 {
+ compatible = "rockchip,rk3588-ohci", "generic-ohci";
+ reg = <0x0 0xfc8c0000 0x0 0x40000>;
+ interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST_ARB1>, <&cru ACLK_USB>, <&u2phy3>;
+ phys = <&u2phy3_host>;
+ phy-names = "usb";
+ power-domains = <&power RK3588_PD_USB>;
+ status = "disabled";
+ };
+
+ usb_host2_xhci: usb@fcd00000 {
+ compatible = "rockchip,rk3588-dwc3", "snps,dwc3";
+ reg = <0x0 0xfcd00000 0x0 0x400000>;
+ interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru REF_CLK_USB3OTG2>, <&cru SUSPEND_CLK_USB3OTG2>,
+ <&cru ACLK_USB3OTG2>, <&cru CLK_UTMI_OTG2>,
+ <&cru CLK_PIPEPHY2_PIPE_U3_G>;
+ clock-names = "ref_clk", "suspend_clk", "bus_clk", "utmi", "pipe";
+ dr_mode = "host";
+ phys = <&combphy2_psu PHY_TYPE_USB3>;
+ phy-names = "usb3-phy";
+ phy_type = "utmi_wide";
+ resets = <&cru SRST_A_USB3OTG2>;
+ snps,dis_enblslpm_quirk;
+ snps,dis-u2-freeclk-exists-quirk;
+ snps,dis-del-phy-power-chg-quirk;
+ snps,dis-tx-ipgap-linecheck-quirk;
+ snps,dis_rxdet_inp3_quirk;
+ status = "disabled";
+ };
+
+ mmu600_pcie: iommu@fc900000 {
+ compatible = "arm,smmu-v3";
+ reg = <0x0 0xfc900000 0x0 0x200000>;
+ interrupts = <GIC_SPI 369 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 367 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
+ #iommu-cells = <1>;
+ status = "disabled";
+ };
+
+ mmu600_php: iommu@fcb00000 {
+ compatible = "arm,smmu-v3";
+ reg = <0x0 0xfcb00000 0x0 0x200000>;
+ interrupts = <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
+ #iommu-cells = <1>;
+ status = "disabled";
+ };
+
+ pmu1grf: syscon@fd58a000 {
+ compatible = "rockchip,rk3588-pmugrf", "syscon", "simple-mfd";
+ reg = <0x0 0xfd58a000 0x0 0x10000>;
+ };
+
+ sys_grf: syscon@fd58c000 {
+ compatible = "rockchip,rk3588-sys-grf", "syscon";
+ reg = <0x0 0xfd58c000 0x0 0x1000>;
+ };
+
+ vop_grf: syscon@fd5a4000 {
+ compatible = "rockchip,rk3588-vop-grf", "syscon";
+ reg = <0x0 0xfd5a4000 0x0 0x2000>;
+ };
+
+ vo0_grf: syscon@fd5a6000 {
+ compatible = "rockchip,rk3588-vo-grf", "syscon";
+ reg = <0x0 0xfd5a6000 0x0 0x2000>;
+ clocks = <&cru PCLK_VO0GRF>;
+ };
+
+ vo1_grf: syscon@fd5a8000 {
+ compatible = "rockchip,rk3588-vo-grf", "syscon";
+ reg = <0x0 0xfd5a8000 0x0 0x100>;
+ clocks = <&cru PCLK_VO1GRF>;
+ };
+
+ usb_grf: syscon@fd5ac000 {
+ compatible = "rockchip,rk3588-usb-grf", "syscon";
+ reg = <0x0 0xfd5ac000 0x0 0x4000>;
+ };
+
+ php_grf: syscon@fd5b0000 {
+ compatible = "rockchip,rk3588-php-grf", "syscon";
+ reg = <0x0 0xfd5b0000 0x0 0x1000>;
+ };
+
+ pipe_phy0_grf: syscon@fd5bc000 {
+ compatible = "rockchip,rk3588-pipe-phy-grf", "syscon";
+ reg = <0x0 0xfd5bc000 0x0 0x100>;
+ };
+
+ pipe_phy2_grf: syscon@fd5c4000 {
+ compatible = "rockchip,rk3588-pipe-phy-grf", "syscon";
+ reg = <0x0 0xfd5c4000 0x0 0x100>;
+ };
+
+ usbdpphy0_grf: syscon@fd5c8000 {
+ compatible = "rockchip,rk3588-usbdpphy-grf", "syscon";
+ reg = <0x0 0xfd5c8000 0x0 0x4000>;
+ };
+
+ usb2phy0_grf: syscon@fd5d0000 {
+ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
+ reg = <0x0 0xfd5d0000 0x0 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ u2phy0: usb2phy@0 {
+ compatible = "rockchip,rk3588-usb2phy";
+ reg = <0x0 0x10>;
+ #clock-cells = <0>;
+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
+ clock-names = "phyclk";
+ clock-output-names = "usb480m_phy0";
+ interrupts = <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH 0>;
+ resets = <&cru SRST_OTGPHY_U3_0>, <&cru SRST_P_USB2PHY_U3_0_GRF0>;
+ reset-names = "phy", "apb";
+ status = "disabled";
+
+ u2phy0_otg: otg-port {
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ };
+ };
+
+ usb2phy2_grf: syscon@fd5d8000 {
+ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
+ reg = <0x0 0xfd5d8000 0x0 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ u2phy2: usb2phy@8000 {
+ compatible = "rockchip,rk3588-usb2phy";
+ reg = <0x8000 0x10>;
+ #clock-cells = <0>;
+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
+ clock-names = "phyclk";
+ clock-output-names = "usb480m_phy2";
+ interrupts = <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH 0>;
+ resets = <&cru SRST_OTGPHY_U2_0>, <&cru SRST_P_USB2PHY_U2_0_GRF0>;
+ reset-names = "phy", "apb";
+ status = "disabled";
+
+ u2phy2_host: host-port {
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ };
+ };
+
+ usb2phy3_grf: syscon@fd5dc000 {
+ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
+ reg = <0x0 0xfd5dc000 0x0 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ u2phy3: usb2phy@c000 {
+ compatible = "rockchip,rk3588-usb2phy";
+ reg = <0xc000 0x10>;
+ #clock-cells = <0>;
+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
+ clock-names = "phyclk";
+ clock-output-names = "usb480m_phy3";
+ interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH 0>;
+ resets = <&cru SRST_OTGPHY_U2_1>, <&cru SRST_P_USB2PHY_U2_1_GRF0>;
+ reset-names = "phy", "apb";
+ status = "disabled";
+
+ u2phy3_host: host-port {
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ };
+ };
+
+ hdptxphy0_grf: syscon@fd5e0000 {
+ compatible = "rockchip,rk3588-hdptxphy-grf", "syscon";
+ reg = <0x0 0xfd5e0000 0x0 0x100>;
+ };
+
+ ioc: syscon@fd5f0000 {
+ compatible = "rockchip,rk3588-ioc", "syscon";
+ reg = <0x0 0xfd5f0000 0x0 0x10000>;
+ };
+
+ system_sram1: sram@fd600000 {
+ compatible = "mmio-sram";
+ reg = <0x0 0xfd600000 0x0 0x100000>;
+ ranges = <0x0 0x0 0xfd600000 0x100000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ cru: clock-controller@fd7c0000 {
+ compatible = "rockchip,rk3588-cru";
+ reg = <0x0 0xfd7c0000 0x0 0x5c000>;
+ assigned-clocks =
+ <&cru PLL_PPLL>, <&cru PLL_AUPLL>,
+ <&cru PLL_NPLL>, <&cru PLL_GPLL>,
+ <&cru ACLK_CENTER_ROOT>,
+ <&cru HCLK_CENTER_ROOT>, <&cru ACLK_CENTER_LOW_ROOT>,
+ <&cru ACLK_TOP_ROOT>, <&cru PCLK_TOP_ROOT>,
+ <&cru ACLK_LOW_TOP_ROOT>, <&cru PCLK_PMU0_ROOT>,
+ <&cru HCLK_PMU_CM0_ROOT>, <&cru ACLK_VOP>,
+ <&cru ACLK_BUS_ROOT>, <&cru CLK_150M_SRC>,
+ <&cru CLK_GPU>;
+ assigned-clock-rates =
+ <1100000000>, <786432000>,
+ <850000000>, <1188000000>,
+ <702000000>,
+ <400000000>, <500000000>,
+ <800000000>, <100000000>,
+ <400000000>, <100000000>,
+ <200000000>, <500000000>,
+ <375000000>, <150000000>,
+ <200000000>;
+ rockchip,grf = <&php_grf>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ i2c0: i2c@fd880000 {
+ compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0xfd880000 0x0 0x1000>;
+ interrupts = <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru CLK_I2C0>, <&cru PCLK_I2C0>;
+ clock-names = "i2c", "pclk";
+ pinctrl-0 = <&i2c0m0_xfer>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ uart0: serial@fd890000 {
+ compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xfd890000 0x0 0x100>;
+ interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac0 6>, <&dmac0 7>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&uart0m1_xfer>;
+ pinctrl-names = "default";
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ pwm0: pwm@fd8b0000 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfd8b0000 0x0 0x10>;
+ clocks = <&cru CLK_PMU1PWM>, <&cru PCLK_PMU1PWM>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm0m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm1: pwm@fd8b0010 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfd8b0010 0x0 0x10>;
+ clocks = <&cru CLK_PMU1PWM>, <&cru PCLK_PMU1PWM>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm1m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm2: pwm@fd8b0020 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfd8b0020 0x0 0x10>;
+ clocks = <&cru CLK_PMU1PWM>, <&cru PCLK_PMU1PWM>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm2m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm3: pwm@fd8b0030 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfd8b0030 0x0 0x10>;
+ clocks = <&cru CLK_PMU1PWM>, <&cru PCLK_PMU1PWM>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm3m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pmu: power-management@fd8d8000 {
+ compatible = "rockchip,rk3588-pmu", "syscon", "simple-mfd";
+ reg = <0x0 0xfd8d8000 0x0 0x400>;
+
+ power: power-controller {
+ compatible = "rockchip,rk3588-power-controller";
+ #address-cells = <1>;
+ #power-domain-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ /* These power domains are grouped by VD_NPU */
+ power-domain@RK3588_PD_NPU {
+ reg = <RK3588_PD_NPU>;
+ #power-domain-cells = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@RK3588_PD_NPUTOP {
+ reg = <RK3588_PD_NPUTOP>;
+ clocks = <&cru HCLK_NPU_ROOT>,
+ <&cru PCLK_NPU_ROOT>,
+ <&cru CLK_NPU_DSU0>,
+ <&cru HCLK_NPU_CM0_ROOT>;
+ pm_qos = <&qos_npu0_mwr>,
+ <&qos_npu0_mro>,
+ <&qos_mcu_npu>;
+ #power-domain-cells = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@RK3588_PD_NPU1 {
+ reg = <RK3588_PD_NPU1>;
+ clocks = <&cru HCLK_NPU_ROOT>,
+ <&cru PCLK_NPU_ROOT>,
+ <&cru CLK_NPU_DSU0>;
+ pm_qos = <&qos_npu1>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_NPU2 {
+ reg = <RK3588_PD_NPU2>;
+ clocks = <&cru HCLK_NPU_ROOT>,
+ <&cru PCLK_NPU_ROOT>,
+ <&cru CLK_NPU_DSU0>;
+ pm_qos = <&qos_npu2>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+ /* These power domains are grouped by VD_GPU */
+ power-domain@RK3588_PD_GPU {
+ reg = <RK3588_PD_GPU>;
+ clocks = <&cru CLK_GPU>,
+ <&cru CLK_GPU_COREGROUP>,
+ <&cru CLK_GPU_STACKS>;
+ pm_qos = <&qos_gpu_m0>,
+ <&qos_gpu_m1>,
+ <&qos_gpu_m2>,
+ <&qos_gpu_m3>;
+ #power-domain-cells = <0>;
+ };
+ /* These power domains are grouped by VD_VCODEC */
+ power-domain@RK3588_PD_VCODEC {
+ reg = <RK3588_PD_VCODEC>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <0>;
+
+ power-domain@RK3588_PD_RKVDEC0 {
+ reg = <RK3588_PD_RKVDEC0>;
+ clocks = <&cru HCLK_RKVDEC0>,
+ <&cru HCLK_VDPU_ROOT>,
+ <&cru ACLK_VDPU_ROOT>,
+ <&cru ACLK_RKVDEC0>,
+ <&cru ACLK_RKVDEC_CCU>;
+ pm_qos = <&qos_rkvdec0>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_RKVDEC1 {
+ reg = <RK3588_PD_RKVDEC1>;
+ clocks = <&cru HCLK_RKVDEC1>,
+ <&cru HCLK_VDPU_ROOT>,
+ <&cru ACLK_VDPU_ROOT>,
+ <&cru ACLK_RKVDEC1>;
+ pm_qos = <&qos_rkvdec1>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_VENC0 {
+ reg = <RK3588_PD_VENC0>;
+ clocks = <&cru HCLK_RKVENC0>,
+ <&cru ACLK_RKVENC0>;
+ pm_qos = <&qos_rkvenc0_m0ro>,
+ <&qos_rkvenc0_m1ro>,
+ <&qos_rkvenc0_m2wo>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <0>;
+
+ power-domain@RK3588_PD_VENC1 {
+ reg = <RK3588_PD_VENC1>;
+ clocks = <&cru HCLK_RKVENC1>,
+ <&cru HCLK_RKVENC0>,
+ <&cru ACLK_RKVENC0>,
+ <&cru ACLK_RKVENC1>;
+ pm_qos = <&qos_rkvenc1_m0ro>,
+ <&qos_rkvenc1_m1ro>,
+ <&qos_rkvenc1_m2wo>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+ /* These power domains are grouped by VD_LOGIC */
+ power-domain@RK3588_PD_VDPU {
+ reg = <RK3588_PD_VDPU>;
+ clocks = <&cru HCLK_VDPU_ROOT>,
+ <&cru ACLK_VDPU_LOW_ROOT>,
+ <&cru ACLK_VDPU_ROOT>,
+ <&cru ACLK_JPEG_DECODER_ROOT>,
+ <&cru ACLK_IEP2P0>,
+ <&cru HCLK_IEP2P0>,
+ <&cru ACLK_JPEG_ENCODER0>,
+ <&cru HCLK_JPEG_ENCODER0>,
+ <&cru ACLK_JPEG_ENCODER1>,
+ <&cru HCLK_JPEG_ENCODER1>,
+ <&cru ACLK_JPEG_ENCODER2>,
+ <&cru HCLK_JPEG_ENCODER2>,
+ <&cru ACLK_JPEG_ENCODER3>,
+ <&cru HCLK_JPEG_ENCODER3>,
+ <&cru ACLK_JPEG_DECODER>,
+ <&cru HCLK_JPEG_DECODER>,
+ <&cru ACLK_RGA2>,
+ <&cru HCLK_RGA2>;
+ pm_qos = <&qos_iep>,
+ <&qos_jpeg_dec>,
+ <&qos_jpeg_enc0>,
+ <&qos_jpeg_enc1>,
+ <&qos_jpeg_enc2>,
+ <&qos_jpeg_enc3>,
+ <&qos_rga2_mro>,
+ <&qos_rga2_mwo>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <0>;
+
+
+ power-domain@RK3588_PD_AV1 {
+ reg = <RK3588_PD_AV1>;
+ clocks = <&cru PCLK_AV1>,
+ <&cru ACLK_AV1>,
+ <&cru HCLK_VDPU_ROOT>;
+ pm_qos = <&qos_av1>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_RKVDEC0 {
+ reg = <RK3588_PD_RKVDEC0>;
+ clocks = <&cru HCLK_RKVDEC0>,
+ <&cru HCLK_VDPU_ROOT>,
+ <&cru ACLK_VDPU_ROOT>,
+ <&cru ACLK_RKVDEC0>;
+ pm_qos = <&qos_rkvdec0>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_RKVDEC1 {
+ reg = <RK3588_PD_RKVDEC1>;
+ clocks = <&cru HCLK_RKVDEC1>,
+ <&cru HCLK_VDPU_ROOT>,
+ <&cru ACLK_VDPU_ROOT>;
+ pm_qos = <&qos_rkvdec1>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_RGA30 {
+ reg = <RK3588_PD_RGA30>;
+ clocks = <&cru ACLK_RGA3_0>,
+ <&cru HCLK_RGA3_0>;
+ pm_qos = <&qos_rga3_0>;
+ #power-domain-cells = <0>;
+ };
+ };
+ power-domain@RK3588_PD_VOP {
+ reg = <RK3588_PD_VOP>;
+ clocks = <&cru PCLK_VOP_ROOT>,
+ <&cru HCLK_VOP_ROOT>,
+ <&cru ACLK_VOP>;
+ pm_qos = <&qos_vop_m0>,
+ <&qos_vop_m1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <0>;
+
+ power-domain@RK3588_PD_VO0 {
+ reg = <RK3588_PD_VO0>;
+ clocks = <&cru PCLK_VO0_ROOT>,
+ <&cru PCLK_VO0_S_ROOT>,
+ <&cru HCLK_VO0_S_ROOT>,
+ <&cru ACLK_VO0_ROOT>,
+ <&cru HCLK_HDCP0>,
+ <&cru ACLK_HDCP0>,
+ <&cru HCLK_VOP_ROOT>;
+ pm_qos = <&qos_hdcp0>;
+ #power-domain-cells = <0>;
+ };
+ };
+ power-domain@RK3588_PD_VO1 {
+ reg = <RK3588_PD_VO1>;
+ clocks = <&cru PCLK_VO1_ROOT>,
+ <&cru PCLK_VO1_S_ROOT>,
+ <&cru HCLK_VO1_S_ROOT>,
+ <&cru HCLK_HDCP1>,
+ <&cru ACLK_HDCP1>,
+ <&cru ACLK_HDMIRX_ROOT>,
+ <&cru HCLK_VO1USB_TOP_ROOT>;
+ pm_qos = <&qos_hdcp1>,
+ <&qos_hdmirx>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_VI {
+ reg = <RK3588_PD_VI>;
+ clocks = <&cru HCLK_VI_ROOT>,
+ <&cru PCLK_VI_ROOT>,
+ <&cru HCLK_ISP0>,
+ <&cru ACLK_ISP0>,
+ <&cru HCLK_VICAP>,
+ <&cru ACLK_VICAP>;
+ pm_qos = <&qos_isp0_mro>,
+ <&qos_isp0_mwo>,
+ <&qos_vicap_m0>,
+ <&qos_vicap_m1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <0>;
+
+ power-domain@RK3588_PD_ISP1 {
+ reg = <RK3588_PD_ISP1>;
+ clocks = <&cru HCLK_ISP1>,
+ <&cru ACLK_ISP1>,
+ <&cru HCLK_VI_ROOT>,
+ <&cru PCLK_VI_ROOT>;
+ pm_qos = <&qos_isp1_mwo>,
+ <&qos_isp1_mro>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_FEC {
+ reg = <RK3588_PD_FEC>;
+ clocks = <&cru HCLK_FISHEYE0>,
+ <&cru ACLK_FISHEYE0>,
+ <&cru HCLK_FISHEYE1>,
+ <&cru ACLK_FISHEYE1>,
+ <&cru PCLK_VI_ROOT>;
+ pm_qos = <&qos_fisheye0>,
+ <&qos_fisheye1>;
+ #power-domain-cells = <0>;
+ };
+ };
+ power-domain@RK3588_PD_RGA31 {
+ reg = <RK3588_PD_RGA31>;
+ clocks = <&cru HCLK_RGA3_1>,
+ <&cru ACLK_RGA3_1>;
+ pm_qos = <&qos_rga3_1>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_USB {
+ reg = <RK3588_PD_USB>;
+ clocks = <&cru PCLK_PHP_ROOT>,
+ <&cru ACLK_USB_ROOT>,
+ <&cru ACLK_USB>,
+ <&cru HCLK_USB_ROOT>,
+ <&cru HCLK_HOST0>,
+ <&cru HCLK_HOST_ARB0>,
+ <&cru HCLK_HOST1>,
+ <&cru HCLK_HOST_ARB1>;
+ pm_qos = <&qos_usb3_0>,
+ <&qos_usb3_1>,
+ <&qos_usb2host_0>,
+ <&qos_usb2host_1>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_GMAC {
+ reg = <RK3588_PD_GMAC>;
+ clocks = <&cru PCLK_PHP_ROOT>,
+ <&cru ACLK_PCIE_ROOT>,
+ <&cru ACLK_PHP_ROOT>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_PCIE {
+ reg = <RK3588_PD_PCIE>;
+ clocks = <&cru PCLK_PHP_ROOT>,
+ <&cru ACLK_PCIE_ROOT>,
+ <&cru ACLK_PHP_ROOT>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_SDIO {
+ reg = <RK3588_PD_SDIO>;
+ clocks = <&cru HCLK_SDIO>,
+ <&cru HCLK_NVM_ROOT>;
+ pm_qos = <&qos_sdio>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_AUDIO {
+ reg = <RK3588_PD_AUDIO>;
+ clocks = <&cru HCLK_AUDIO_ROOT>,
+ <&cru PCLK_AUDIO_ROOT>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3588_PD_SDMMC {
+ reg = <RK3588_PD_SDMMC>;
+ pm_qos = <&qos_sdmmc>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+
+ av1d: video-codec@fdc70000 {
+ compatible = "rockchip,rk3588-av1-vpu";
+ reg = <0x0 0xfdc70000 0x0 0x800>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "vdpu";
+ assigned-clocks = <&cru ACLK_AV1>, <&cru PCLK_AV1>;
+ assigned-clock-rates = <400000000>, <400000000>;
+ clocks = <&cru ACLK_AV1>, <&cru PCLK_AV1>;
+ clock-names = "aclk", "hclk";
+ power-domains = <&power RK3588_PD_AV1>;
+ resets = <&cru SRST_A_AV1>, <&cru SRST_P_AV1>, <&cru SRST_A_AV1_BIU>, <&cru SRST_P_AV1_BIU>;
+ };
+
+ vop: vop@fdd90000 {
+ compatible = "rockchip,rk3588-vop";
+ reg = <0x0 0xfdd90000 0x0 0x4200>, <0x0 0xfdd95000 0x0 0x1000>;
+ reg-names = "vop", "gamma-lut";
+ interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_VOP>,
+ <&cru HCLK_VOP>,
+ <&cru DCLK_VOP0>,
+ <&cru DCLK_VOP1>,
+ <&cru DCLK_VOP2>,
+ <&cru DCLK_VOP3>,
+ <&cru PCLK_VOP_ROOT>;
+ clock-names = "aclk",
+ "hclk",
+ "dclk_vp0",
+ "dclk_vp1",
+ "dclk_vp2",
+ "dclk_vp3",
+ "pclk_vop";
+ iommus = <&vop_mmu>;
+ power-domains = <&power RK3588_PD_VOP>;
+ rockchip,grf = <&sys_grf>;
+ rockchip,vop-grf = <&vop_grf>;
+ rockchip,vo1-grf = <&vo1_grf>;
+ rockchip,pmu = <&pmu>;
+ status = "disabled";
+
+ vop_out: ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vp0: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ vp1: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ vp2: port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ vp3: port@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+ };
+ };
+
+ vop_mmu: iommu@fdd97e00 {
+ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu";
+ reg = <0x0 0xfdd97e00 0x0 0x100>, <0x0 0xfdd97f00 0x0 0x100>;
+ interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
+ clock-names = "aclk", "iface";
+ #iommu-cells = <0>;
+ power-domains = <&power RK3588_PD_VOP>;
+ status = "disabled";
+ };
+
+ i2s4_8ch: i2s@fddc0000 {
+ compatible = "rockchip,rk3588-i2s-tdm";
+ reg = <0x0 0xfddc0000 0x0 0x1000>;
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S4_8CH_TX>, <&cru MCLK_I2S4_8CH_TX>, <&cru HCLK_I2S4_8CH>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ assigned-clocks = <&cru CLK_I2S4_8CH_TX_SRC>;
+ assigned-clock-parents = <&cru PLL_AUPLL>;
+ dmas = <&dmac2 0>;
+ dma-names = "tx";
+ power-domains = <&power RK3588_PD_VO0>;
+ resets = <&cru SRST_M_I2S4_8CH_TX>;
+ reset-names = "tx-m";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2s5_8ch: i2s@fddf0000 {
+ compatible = "rockchip,rk3588-i2s-tdm";
+ reg = <0x0 0xfddf0000 0x0 0x1000>;
+ interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S5_8CH_TX>, <&cru MCLK_I2S5_8CH_TX>, <&cru HCLK_I2S5_8CH>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ assigned-clocks = <&cru CLK_I2S5_8CH_TX_SRC>;
+ assigned-clock-parents = <&cru PLL_AUPLL>;
+ dmas = <&dmac2 2>;
+ dma-names = "tx";
+ power-domains = <&power RK3588_PD_VO1>;
+ resets = <&cru SRST_M_I2S5_8CH_TX>;
+ reset-names = "tx-m";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2s9_8ch: i2s@fddfc000 {
+ compatible = "rockchip,rk3588-i2s-tdm";
+ reg = <0x0 0xfddfc000 0x0 0x1000>;
+ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S9_8CH_RX>, <&cru MCLK_I2S9_8CH_RX>, <&cru HCLK_I2S9_8CH>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ assigned-clocks = <&cru CLK_I2S9_8CH_RX_SRC>;
+ assigned-clock-parents = <&cru PLL_AUPLL>;
+ dmas = <&dmac2 23>;
+ dma-names = "rx";
+ power-domains = <&power RK3588_PD_VO1>;
+ resets = <&cru SRST_M_I2S9_8CH_RX>;
+ reset-names = "rx-m";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ qos_gpu_m0: qos@fdf35000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf35000 0x0 0x20>;
+ };
+
+ qos_gpu_m1: qos@fdf35200 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf35200 0x0 0x20>;
+ };
+
+ qos_gpu_m2: qos@fdf35400 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf35400 0x0 0x20>;
+ };
+
+ qos_gpu_m3: qos@fdf35600 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf35600 0x0 0x20>;
+ };
+
+ qos_rga3_1: qos@fdf36000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf36000 0x0 0x20>;
+ };
+
+ qos_sdio: qos@fdf39000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf39000 0x0 0x20>;
+ };
+
+ qos_sdmmc: qos@fdf3d800 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf3d800 0x0 0x20>;
+ };
+
+ qos_usb3_1: qos@fdf3e000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf3e000 0x0 0x20>;
+ };
+
+ qos_usb3_0: qos@fdf3e200 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf3e200 0x0 0x20>;
+ };
+
+ qos_usb2host_0: qos@fdf3e400 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf3e400 0x0 0x20>;
+ };
+
+ qos_usb2host_1: qos@fdf3e600 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf3e600 0x0 0x20>;
+ };
+
+ qos_fisheye0: qos@fdf40000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf40000 0x0 0x20>;
+ };
+
+ qos_fisheye1: qos@fdf40200 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf40200 0x0 0x20>;
+ };
+
+ qos_isp0_mro: qos@fdf40400 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf40400 0x0 0x20>;
+ };
+
+ qos_isp0_mwo: qos@fdf40500 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf40500 0x0 0x20>;
+ };
+
+ qos_vicap_m0: qos@fdf40600 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf40600 0x0 0x20>;
+ };
+
+ qos_vicap_m1: qos@fdf40800 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf40800 0x0 0x20>;
+ };
+
+ qos_isp1_mwo: qos@fdf41000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf41000 0x0 0x20>;
+ };
+
+ qos_isp1_mro: qos@fdf41100 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf41100 0x0 0x20>;
+ };
+
+ qos_rkvenc0_m0ro: qos@fdf60000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf60000 0x0 0x20>;
+ };
+
+ qos_rkvenc0_m1ro: qos@fdf60200 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf60200 0x0 0x20>;
+ };
+
+ qos_rkvenc0_m2wo: qos@fdf60400 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf60400 0x0 0x20>;
+ };
+
+ qos_rkvenc1_m0ro: qos@fdf61000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf61000 0x0 0x20>;
+ };
+
+ qos_rkvenc1_m1ro: qos@fdf61200 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf61200 0x0 0x20>;
+ };
+
+ qos_rkvenc1_m2wo: qos@fdf61400 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf61400 0x0 0x20>;
+ };
+
+ qos_rkvdec0: qos@fdf62000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf62000 0x0 0x20>;
+ };
+
+ qos_rkvdec1: qos@fdf63000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf63000 0x0 0x20>;
+ };
+
+ qos_av1: qos@fdf64000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf64000 0x0 0x20>;
+ };
+
+ qos_iep: qos@fdf66000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf66000 0x0 0x20>;
+ };
+
+ qos_jpeg_dec: qos@fdf66200 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf66200 0x0 0x20>;
+ };
+
+ qos_jpeg_enc0: qos@fdf66400 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf66400 0x0 0x20>;
+ };
+
+ qos_jpeg_enc1: qos@fdf66600 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf66600 0x0 0x20>;
+ };
+
+ qos_jpeg_enc2: qos@fdf66800 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf66800 0x0 0x20>;
+ };
+
+ qos_jpeg_enc3: qos@fdf66a00 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf66a00 0x0 0x20>;
+ };
+
+ qos_rga2_mro: qos@fdf66c00 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf66c00 0x0 0x20>;
+ };
+
+ qos_rga2_mwo: qos@fdf66e00 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf66e00 0x0 0x20>;
+ };
+
+ qos_rga3_0: qos@fdf67000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf67000 0x0 0x20>;
+ };
+
+ qos_vdpu: qos@fdf67200 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf67200 0x0 0x20>;
+ };
+
+ qos_npu1: qos@fdf70000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf70000 0x0 0x20>;
+ };
+
+ qos_npu2: qos@fdf71000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf71000 0x0 0x20>;
+ };
+
+ qos_npu0_mwr: qos@fdf72000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf72000 0x0 0x20>;
+ };
+
+ qos_npu0_mro: qos@fdf72200 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf72200 0x0 0x20>;
+ };
+
+ qos_mcu_npu: qos@fdf72400 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf72400 0x0 0x20>;
+ };
+
+ qos_hdcp0: qos@fdf80000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf80000 0x0 0x20>;
+ };
+
+ qos_hdcp1: qos@fdf81000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf81000 0x0 0x20>;
+ };
+
+ qos_hdmirx: qos@fdf81200 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf81200 0x0 0x20>;
+ };
+
+ qos_vop_m0: qos@fdf82000 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf82000 0x0 0x20>;
+ };
+
+ qos_vop_m1: qos@fdf82200 {
+ compatible = "rockchip,rk3588-qos", "syscon";
+ reg = <0x0 0xfdf82200 0x0 0x20>;
+ };
+
+ dfi: dfi@fe060000 {
+ reg = <0x00 0xfe060000 0x00 0x10000>;
+ compatible = "rockchip,rk3588-dfi";
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH 0>;
+ rockchip,pmu = <&pmu1grf>;
+ };
+
+ pcie2x1l1: pcie@fe180000 {
+ compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
+ bus-range = <0x30 0x3f>;
+ clocks = <&cru ACLK_PCIE_1L1_MSTR>, <&cru ACLK_PCIE_1L1_SLV>,
+ <&cru ACLK_PCIE_1L1_DBI>, <&cru PCLK_PCIE_1L1>,
+ <&cru CLK_PCIE_AUX3>, <&cru CLK_PCIE1L1_PIPE>;
+ clock-names = "aclk_mst", "aclk_slv",
+ "aclk_dbi", "pclk",
+ "aux", "pipe";
+ device_type = "pci";
+ interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "sys", "pmc", "msg", "legacy", "err";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie2x1l1_intc 0>,
+ <0 0 0 2 &pcie2x1l1_intc 1>,
+ <0 0 0 3 &pcie2x1l1_intc 2>,
+ <0 0 0 4 &pcie2x1l1_intc 3>;
+ linux,pci-domain = <3>;
+ max-link-speed = <2>;
+ msi-map = <0x3000 &its0 0x3000 0x1000>;
+ num-lanes = <1>;
+ phys = <&combphy2_psu PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy";
+ power-domains = <&power RK3588_PD_PCIE>;
+ ranges = <0x01000000 0x0 0xf3100000 0x0 0xf3100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf3200000 0x0 0xf3200000 0x0 0x00e00000>,
+ <0x03000000 0x0 0x40000000 0x9 0xc0000000 0x0 0x40000000>;
+ reg = <0xa 0x40c00000 0x0 0x00400000>,
+ <0x0 0xfe180000 0x0 0x00010000>,
+ <0x0 0xf3000000 0x0 0x00100000>;
+ reg-names = "dbi", "apb", "config";
+ resets = <&cru SRST_PCIE3_POWER_UP>, <&cru SRST_P_PCIE3>;
+ reset-names = "pwr", "pipe";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ status = "disabled";
+
+ pcie2x1l1_intc: legacy-interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 245 IRQ_TYPE_EDGE_RISING 0>;
+ };
+ };
+
+ pcie2x1l2: pcie@fe190000 {
+ compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
+ bus-range = <0x40 0x4f>;
+ clocks = <&cru ACLK_PCIE_1L2_MSTR>, <&cru ACLK_PCIE_1L2_SLV>,
+ <&cru ACLK_PCIE_1L2_DBI>, <&cru PCLK_PCIE_1L2>,
+ <&cru CLK_PCIE_AUX4>, <&cru CLK_PCIE1L2_PIPE>;
+ clock-names = "aclk_mst", "aclk_slv",
+ "aclk_dbi", "pclk",
+ "aux", "pipe";
+ device_type = "pci";
+ interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "sys", "pmc", "msg", "legacy", "err";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie2x1l2_intc 0>,
+ <0 0 0 2 &pcie2x1l2_intc 1>,
+ <0 0 0 3 &pcie2x1l2_intc 2>,
+ <0 0 0 4 &pcie2x1l2_intc 3>;
+ linux,pci-domain = <4>;
+ max-link-speed = <2>;
+ msi-map = <0x4000 &its0 0x4000 0x1000>;
+ num-lanes = <1>;
+ phys = <&combphy0_ps PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy";
+ power-domains = <&power RK3588_PD_PCIE>;
+ ranges = <0x01000000 0x0 0xf4100000 0x0 0xf4100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf4200000 0x0 0xf4200000 0x0 0x00e00000>,
+ <0x03000000 0x0 0x40000000 0xa 0x00000000 0x0 0x40000000>;
+ reg = <0xa 0x41000000 0x0 0x00400000>,
+ <0x0 0xfe190000 0x0 0x00010000>,
+ <0x0 0xf4000000 0x0 0x00100000>;
+ reg-names = "dbi", "apb", "config";
+ resets = <&cru SRST_PCIE4_POWER_UP>, <&cru SRST_P_PCIE4>;
+ reset-names = "pwr", "pipe";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ status = "disabled";
+
+ pcie2x1l2_intc: legacy-interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 250 IRQ_TYPE_EDGE_RISING 0>;
+ };
+ };
+
+ gmac1: ethernet@fe1c0000 {
+ compatible = "rockchip,rk3588-gmac", "snps,dwmac-4.20a";
+ reg = <0x0 0xfe1c0000 0x0 0x10000>;
+ interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "macirq", "eth_wake_irq";
+ clocks = <&cru CLK_GMAC_125M>, <&cru CLK_GMAC_50M>,
+ <&cru PCLK_GMAC1>, <&cru ACLK_GMAC1>,
+ <&cru CLK_GMAC1_PTP_REF>;
+ clock-names = "stmmaceth", "clk_mac_ref",
+ "pclk_mac", "aclk_mac",
+ "ptp_ref";
+ power-domains = <&power RK3588_PD_GMAC>;
+ resets = <&cru SRST_A_GMAC1>;
+ reset-names = "stmmaceth";
+ rockchip,grf = <&sys_grf>;
+ rockchip,php-grf = <&php_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,wr_osr_lmt = <4>;
+ snps,rd_osr_lmt = <8>;
+ };
+
+ gmac1_mtl_rx_setup: rx-queues-config {
+ snps,rx-queues-to-use = <2>;
+ queue0 {};
+ queue1 {};
+ };
+
+ gmac1_mtl_tx_setup: tx-queues-config {
+ snps,tx-queues-to-use = <2>;
+ queue0 {};
+ queue1 {};
+ };
+ };
+
+ sata0: sata@fe210000 {
+ compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci";
+ reg = <0 0xfe210000 0 0x1000>;
+ interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_SATA0>, <&cru CLK_PMALIVE0>,
+ <&cru CLK_RXOOB0>, <&cru CLK_PIPEPHY0_REF>,
+ <&cru CLK_PIPEPHY0_PIPE_ASIC_G>;
+ clock-names = "sata", "pmalive", "rxoob", "ref", "asic";
+ ports-implemented = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ sata-port@0 {
+ reg = <0>;
+ hba-port-cap = <HBA_PORT_FBSCP>;
+ phys = <&combphy0_ps PHY_TYPE_SATA>;
+ phy-names = "sata-phy";
+ snps,rx-ts-max = <32>;
+ snps,tx-ts-max = <32>;
+ };
+ };
+
+ sata2: sata@fe230000 {
+ compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci";
+ reg = <0 0xfe230000 0 0x1000>;
+ interrupts = <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_SATA2>, <&cru CLK_PMALIVE2>,
+ <&cru CLK_RXOOB2>, <&cru CLK_PIPEPHY2_REF>,
+ <&cru CLK_PIPEPHY2_PIPE_ASIC_G>;
+ clock-names = "sata", "pmalive", "rxoob", "ref", "asic";
+ ports-implemented = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ sata-port@0 {
+ reg = <0>;
+ hba-port-cap = <HBA_PORT_FBSCP>;
+ phys = <&combphy2_psu PHY_TYPE_SATA>;
+ phy-names = "sata-phy";
+ snps,rx-ts-max = <32>;
+ snps,tx-ts-max = <32>;
+ };
+ };
+
+ sfc: spi@fe2b0000 {
+ compatible = "rockchip,sfc";
+ reg = <0x0 0xfe2b0000 0x0 0x4000>;
+ interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>;
+ clock-names = "clk_sfc", "hclk_sfc";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ sdmmc: mmc@fe2c0000 {
+ compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
+ reg = <0x0 0xfe2c0000 0x0 0x4000>;
+ interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&scmi_clk SCMI_HCLK_SD>, <&scmi_clk SCMI_CCLK_SD>,
+ <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ fifo-depth = <0x100>;
+ max-frequency = <200000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>;
+ power-domains = <&power RK3588_PD_SDMMC>;
+ status = "disabled";
+ };
+
+ sdio: mmc@fe2d0000 {
+ compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
+ reg = <0x00 0xfe2d0000 0x00 0x4000>;
+ interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru HCLK_SDIO>, <&cru CCLK_SRC_SDIO>,
+ <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ fifo-depth = <0x100>;
+ max-frequency = <200000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdiom1_pins>;
+ power-domains = <&power RK3588_PD_SDIO>;
+ status = "disabled";
+ };
+
+ sdhci: mmc@fe2e0000 {
+ compatible = "rockchip,rk3588-dwcmshc";
+ reg = <0x0 0xfe2e0000 0x0 0x10000>;
+ interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH 0>;
+ assigned-clocks = <&cru BCLK_EMMC>, <&cru TMCLK_EMMC>, <&cru CCLK_EMMC>;
+ assigned-clock-rates = <200000000>, <24000000>, <200000000>;
+ clocks = <&cru CCLK_EMMC>, <&cru HCLK_EMMC>,
+ <&cru ACLK_EMMC>, <&cru BCLK_EMMC>,
+ <&cru TMCLK_EMMC>;
+ clock-names = "core", "bus", "axi", "block", "timer";
+ max-frequency = <200000000>;
+ pinctrl-0 = <&emmc_rstnout>, <&emmc_bus8>, <&emmc_clk>,
+ <&emmc_cmd>, <&emmc_data_strobe>;
+ pinctrl-names = "default";
+ 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";
+ status = "disabled";
+ };
+
+ i2s0_8ch: i2s@fe470000 {
+ compatible = "rockchip,rk3588-i2s-tdm";
+ reg = <0x0 0xfe470000 0x0 0x1000>;
+ interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S0_8CH_TX>, <&cru MCLK_I2S0_8CH_RX>, <&cru HCLK_I2S0_8CH>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ assigned-clocks = <&cru CLK_I2S0_8CH_TX_SRC>, <&cru CLK_I2S0_8CH_RX_SRC>;
+ assigned-clock-parents = <&cru PLL_AUPLL>, <&cru PLL_AUPLL>;
+ dmas = <&dmac0 0>, <&dmac0 1>;
+ dma-names = "tx", "rx";
+ power-domains = <&power RK3588_PD_AUDIO>;
+ resets = <&cru SRST_M_I2S0_8CH_TX>, <&cru SRST_M_I2S0_8CH_RX>;
+ reset-names = "tx-m", "rx-m";
+ rockchip,trcm-sync-tx-only;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_lrck
+ &i2s0_sclk
+ &i2s0_sdi0
+ &i2s0_sdi1
+ &i2s0_sdi2
+ &i2s0_sdi3
+ &i2s0_sdo0
+ &i2s0_sdo1
+ &i2s0_sdo2
+ &i2s0_sdo3>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2s1_8ch: i2s@fe480000 {
+ compatible = "rockchip,rk3588-i2s-tdm";
+ reg = <0x0 0xfe480000 0x0 0x1000>;
+ interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S1_8CH_TX>, <&cru MCLK_I2S1_8CH_RX>, <&cru HCLK_I2S1_8CH>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ dmas = <&dmac0 2>, <&dmac0 3>;
+ dma-names = "tx", "rx";
+ resets = <&cru SRST_M_I2S1_8CH_TX>, <&cru SRST_M_I2S1_8CH_RX>;
+ reset-names = "tx-m", "rx-m";
+ rockchip,trcm-sync-tx-only;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s1m0_lrck
+ &i2s1m0_sclk
+ &i2s1m0_sdi0
+ &i2s1m0_sdi1
+ &i2s1m0_sdi2
+ &i2s1m0_sdi3
+ &i2s1m0_sdo0
+ &i2s1m0_sdo1
+ &i2s1m0_sdo2
+ &i2s1m0_sdo3>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2s2_2ch: i2s@fe490000 {
+ compatible = "rockchip,rk3588-i2s", "rockchip,rk3066-i2s";
+ reg = <0x0 0xfe490000 0x0 0x1000>;
+ interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S2_2CH>, <&cru HCLK_I2S2_2CH>;
+ clock-names = "i2s_clk", "i2s_hclk";
+ assigned-clocks = <&cru CLK_I2S2_2CH_SRC>;
+ assigned-clock-parents = <&cru PLL_AUPLL>;
+ dmas = <&dmac1 0>, <&dmac1 1>;
+ dma-names = "tx", "rx";
+ power-domains = <&power RK3588_PD_AUDIO>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s2m1_lrck
+ &i2s2m1_sclk
+ &i2s2m1_sdi
+ &i2s2m1_sdo>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2s3_2ch: i2s@fe4a0000 {
+ compatible = "rockchip,rk3588-i2s", "rockchip,rk3066-i2s";
+ reg = <0x0 0xfe4a0000 0x0 0x1000>;
+ interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S3_2CH>, <&cru HCLK_I2S3_2CH>;
+ clock-names = "i2s_clk", "i2s_hclk";
+ assigned-clocks = <&cru CLK_I2S3_2CH_SRC>;
+ assigned-clock-parents = <&cru PLL_AUPLL>;
+ dmas = <&dmac1 2>, <&dmac1 3>;
+ dma-names = "tx", "rx";
+ power-domains = <&power RK3588_PD_AUDIO>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s3_lrck
+ &i2s3_sclk
+ &i2s3_sdi
+ &i2s3_sdo>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@fe600000 {
+ compatible = "arm,gic-v3";
+ reg = <0x0 0xfe600000 0 0x10000>, /* GICD */
+ <0x0 0xfe680000 0 0x100000>; /* GICR */
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-controller;
+ mbi-alias = <0x0 0xfe610000>;
+ mbi-ranges = <424 56>;
+ msi-controller;
+ ranges;
+ #address-cells = <2>;
+ #interrupt-cells = <4>;
+ #size-cells = <2>;
+
+ its0: msi-controller@fe640000 {
+ compatible = "arm,gic-v3-its";
+ reg = <0x0 0xfe640000 0x0 0x20000>;
+ msi-controller;
+ #msi-cells = <1>;
+ };
+
+ its1: msi-controller@fe660000 {
+ compatible = "arm,gic-v3-its";
+ reg = <0x0 0xfe660000 0x0 0x20000>;
+ msi-controller;
+ #msi-cells = <1>;
+ };
+
+ ppi-partitions {
+ ppi_partition0: interrupt-partition-0 {
+ affinity = <&cpu_l0 &cpu_l1 &cpu_l2 &cpu_l3>;
+ };
+
+ ppi_partition1: interrupt-partition-1 {
+ affinity = <&cpu_b0 &cpu_b1 &cpu_b2 &cpu_b3>;
+ };
+ };
+ };
+
+ dmac0: dma-controller@fea10000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x0 0xfea10000 0x0 0x4000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH 0>;
+ arm,pl330-periph-burst;
+ clocks = <&cru ACLK_DMAC0>;
+ clock-names = "apb_pclk";
+ #dma-cells = <1>;
+ };
+
+ dmac1: dma-controller@fea30000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x0 0xfea30000 0x0 0x4000>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH 0>;
+ arm,pl330-periph-burst;
+ clocks = <&cru ACLK_DMAC1>;
+ clock-names = "apb_pclk";
+ #dma-cells = <1>;
+ };
+
+ i2c1: i2c@fea90000 {
+ compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0xfea90000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C1>, <&cru PCLK_I2C1>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH 0>;
+ pinctrl-0 = <&i2c1m0_xfer>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@feaa0000 {
+ compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0xfeaa0000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C2>, <&cru PCLK_I2C2>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH 0>;
+ pinctrl-0 = <&i2c2m0_xfer>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@feab0000 {
+ compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0xfeab0000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C3>, <&cru PCLK_I2C3>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH 0>;
+ pinctrl-0 = <&i2c3m0_xfer>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@feac0000 {
+ compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0xfeac0000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C4>, <&cru PCLK_I2C4>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH 0>;
+ pinctrl-0 = <&i2c4m0_xfer>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c5: i2c@fead0000 {
+ compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0xfead0000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C5>, <&cru PCLK_I2C5>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH 0>;
+ pinctrl-0 = <&i2c5m0_xfer>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ timer0: timer@feae0000 {
+ compatible = "rockchip,rk3588-timer", "rockchip,rk3288-timer";
+ reg = <0x0 0xfeae0000 0x0 0x20>;
+ interrupts = <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru PCLK_BUSTIMER0>, <&cru CLK_BUSTIMER0>;
+ clock-names = "pclk", "timer";
+ };
+
+ wdt: watchdog@feaf0000 {
+ compatible = "rockchip,rk3588-wdt", "snps,dw-wdt";
+ reg = <0x0 0xfeaf0000 0x0 0x100>;
+ clocks = <&cru TCLK_WDT0>, <&cru PCLK_WDT0>;
+ clock-names = "tclk", "pclk";
+ interrupts = <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH 0>;
+ };
+
+ spi0: spi@feb00000 {
+ compatible = "rockchip,rk3588-spi", "rockchip,rk3066-spi";
+ reg = <0x0 0xfeb00000 0x0 0x1000>;
+ interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru CLK_SPI0>, <&cru PCLK_SPI0>;
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac0 14>, <&dmac0 15>;
+ dma-names = "tx", "rx";
+ num-cs = <2>;
+ pinctrl-0 = <&spi0m0_cs0 &spi0m0_cs1 &spi0m0_pins>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi1: spi@feb10000 {
+ compatible = "rockchip,rk3588-spi", "rockchip,rk3066-spi";
+ reg = <0x0 0xfeb10000 0x0 0x1000>;
+ interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru CLK_SPI1>, <&cru PCLK_SPI1>;
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac0 16>, <&dmac0 17>;
+ dma-names = "tx", "rx";
+ num-cs = <2>;
+ pinctrl-0 = <&spi1m1_cs0 &spi1m1_cs1 &spi1m1_pins>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi2: spi@feb20000 {
+ compatible = "rockchip,rk3588-spi", "rockchip,rk3066-spi";
+ reg = <0x0 0xfeb20000 0x0 0x1000>;
+ interrupts = <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru CLK_SPI2>, <&cru PCLK_SPI2>;
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac1 15>, <&dmac1 16>;
+ dma-names = "tx", "rx";
+ num-cs = <2>;
+ pinctrl-0 = <&spi2m2_cs0 &spi2m2_cs1 &spi2m2_pins>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi3: spi@feb30000 {
+ compatible = "rockchip,rk3588-spi", "rockchip,rk3066-spi";
+ reg = <0x0 0xfeb30000 0x0 0x1000>;
+ interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru CLK_SPI3>, <&cru PCLK_SPI3>;
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac1 17>, <&dmac1 18>;
+ dma-names = "tx", "rx";
+ num-cs = <2>;
+ pinctrl-0 = <&spi3m1_cs0 &spi3m1_cs1 &spi3m1_pins>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ uart1: serial@feb40000 {
+ compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xfeb40000 0x0 0x100>;
+ interrupts = <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac0 8>, <&dmac0 9>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&uart1m1_xfer>;
+ pinctrl-names = "default";
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart2: serial@feb50000 {
+ compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xfeb50000 0x0 0x100>;
+ interrupts = <GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac0 10>, <&dmac0 11>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&uart2m1_xfer>;
+ pinctrl-names = "default";
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart3: serial@feb60000 {
+ compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xfeb60000 0x0 0x100>;
+ interrupts = <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac0 12>, <&dmac0 13>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&uart3m1_xfer>;
+ pinctrl-names = "default";
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart4: serial@feb70000 {
+ compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xfeb70000 0x0 0x100>;
+ interrupts = <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac1 9>, <&dmac1 10>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&uart4m1_xfer>;
+ pinctrl-names = "default";
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart5: serial@feb80000 {
+ compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xfeb80000 0x0 0x100>;
+ interrupts = <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac1 11>, <&dmac1 12>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&uart5m1_xfer>;
+ pinctrl-names = "default";
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart6: serial@feb90000 {
+ compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xfeb90000 0x0 0x100>;
+ interrupts = <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_UART6>, <&cru PCLK_UART6>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac1 13>, <&dmac1 14>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&uart6m1_xfer>;
+ pinctrl-names = "default";
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart7: serial@feba0000 {
+ compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xfeba0000 0x0 0x100>;
+ interrupts = <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_UART7>, <&cru PCLK_UART7>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac2 7>, <&dmac2 8>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&uart7m1_xfer>;
+ pinctrl-names = "default";
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart8: serial@febb0000 {
+ compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xfebb0000 0x0 0x100>;
+ interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_UART8>, <&cru PCLK_UART8>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac2 9>, <&dmac2 10>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&uart8m1_xfer>;
+ pinctrl-names = "default";
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart9: serial@febc0000 {
+ compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xfebc0000 0x0 0x100>;
+ interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru SCLK_UART9>, <&cru PCLK_UART9>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac2 11>, <&dmac2 12>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&uart9m1_xfer>;
+ pinctrl-names = "default";
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ pwm4: pwm@febd0000 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebd0000 0x0 0x10>;
+ clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm4m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm5: pwm@febd0010 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebd0010 0x0 0x10>;
+ clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm5m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm6: pwm@febd0020 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebd0020 0x0 0x10>;
+ clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm6m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm7: pwm@febd0030 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebd0030 0x0 0x10>;
+ clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm7m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm8: pwm@febe0000 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebe0000 0x0 0x10>;
+ clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm8m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm9: pwm@febe0010 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebe0010 0x0 0x10>;
+ clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm9m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm10: pwm@febe0020 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebe0020 0x0 0x10>;
+ clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm10m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm11: pwm@febe0030 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebe0030 0x0 0x10>;
+ clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm11m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm12: pwm@febf0000 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebf0000 0x0 0x10>;
+ clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm12m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm13: pwm@febf0010 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebf0010 0x0 0x10>;
+ clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm13m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm14: pwm@febf0020 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebf0020 0x0 0x10>;
+ clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm14m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm15: pwm@febf0030 {
+ compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
+ reg = <0x0 0xfebf0030 0x0 0x10>;
+ clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>;
+ clock-names = "pwm", "pclk";
+ pinctrl-0 = <&pwm15m0_pins>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ thermal_zones: thermal-zones {
+ /* sensor near the center of the SoC */
+ package_thermal: package-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 0>;
+
+ trips {
+ package_crit: package-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ /* sensor between A76 cores 0 and 1 */
+ bigcore0_thermal: bigcore0-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 1>;
+
+ trips {
+ bigcore0_alert: bigcore0-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ bigcore0_crit: bigcore0-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&bigcore0_alert>;
+ cooling-device =
+ <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ /* sensor between A76 cores 2 and 3 */
+ bigcore2_thermal: bigcore2-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 2>;
+
+ trips {
+ bigcore2_alert: bigcore2-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ bigcore2_crit: bigcore2-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&bigcore2_alert>;
+ cooling-device =
+ <&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ /* sensor between the four A55 cores */
+ little_core_thermal: littlecore-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 3>;
+
+ trips {
+ littlecore_alert: littlecore-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ littlecore_crit: littlecore-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&littlecore_alert>;
+ cooling-device =
+ <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ /* sensor near the PD_CENTER power domain */
+ center_thermal: center-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 4>;
+
+ trips {
+ center_crit: center-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpu_thermal: gpu-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 5>;
+
+ trips {
+ gpu_alert: gpu-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ gpu_crit: gpu-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&gpu_alert>;
+ cooling-device =
+ <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ npu_thermal: npu-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 6>;
+
+ trips {
+ npu_crit: npu-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+ };
+
+ tsadc: tsadc@fec00000 {
+ compatible = "rockchip,rk3588-tsadc";
+ reg = <0x0 0xfec00000 0x0 0x400>;
+ interrupts = <GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru CLK_TSADC>, <&cru PCLK_TSADC>;
+ clock-names = "tsadc", "apb_pclk";
+ assigned-clocks = <&cru CLK_TSADC>;
+ assigned-clock-rates = <2000000>;
+ resets = <&cru SRST_P_TSADC>, <&cru SRST_TSADC>;
+ reset-names = "tsadc-apb", "tsadc";
+ rockchip,hw-tshut-temp = <120000>;
+ rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
+ rockchip,hw-tshut-polarity = <0>; /* tshut polarity 0:LOW 1:HIGH */
+ pinctrl-0 = <&tsadc_gpio_func>;
+ pinctrl-1 = <&tsadc_shut>;
+ pinctrl-names = "gpio", "otpout";
+ #thermal-sensor-cells = <1>;
+ status = "disabled";
+ };
+
+ saradc: adc@fec10000 {
+ compatible = "rockchip,rk3588-saradc";
+ reg = <0x0 0xfec10000 0x0 0x10000>;
+ interrupts = <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH 0>;
+ #io-channel-cells = <1>;
+ clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>;
+ clock-names = "saradc", "apb_pclk";
+ resets = <&cru SRST_P_SARADC>;
+ reset-names = "saradc-apb";
+ status = "disabled";
+ };
+
+ i2c6: i2c@fec80000 {
+ compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0xfec80000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C6>, <&cru PCLK_I2C6>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH 0>;
+ pinctrl-0 = <&i2c6m0_xfer>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c7: i2c@fec90000 {
+ compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0xfec90000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C7>, <&cru PCLK_I2C7>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH 0>;
+ pinctrl-0 = <&i2c7m0_xfer>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c8: i2c@feca0000 {
+ compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0xfeca0000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C8>, <&cru PCLK_I2C8>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH 0>;
+ pinctrl-0 = <&i2c8m0_xfer>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi4: spi@fecb0000 {
+ compatible = "rockchip,rk3588-spi", "rockchip,rk3066-spi";
+ reg = <0x0 0xfecb0000 0x0 0x1000>;
+ interrupts = <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru CLK_SPI4>, <&cru PCLK_SPI4>;
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac2 13>, <&dmac2 14>;
+ dma-names = "tx", "rx";
+ num-cs = <2>;
+ pinctrl-0 = <&spi4m0_cs0 &spi4m0_cs1 &spi4m0_pins>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ otp: efuse@fecc0000 {
+ compatible = "rockchip,rk3588-otp";
+ reg = <0x0 0xfecc0000 0x0 0x400>;
+ clocks = <&cru CLK_OTPC_NS>, <&cru PCLK_OTPC_NS>,
+ <&cru CLK_OTP_PHY_G>, <&cru CLK_OTPC_ARB>;
+ clock-names = "otp", "apb_pclk", "phy", "arb";
+ resets = <&cru SRST_OTPC_NS>, <&cru SRST_P_OTPC_NS>,
+ <&cru SRST_OTPC_ARB>;
+ reset-names = "otp", "apb", "arb";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpu_code: cpu-code@2 {
+ reg = <0x02 0x2>;
+ };
+
+ otp_id: id@7 {
+ reg = <0x07 0x10>;
+ };
+
+ cpub0_leakage: cpu-leakage@17 {
+ reg = <0x17 0x1>;
+ };
+
+ cpub1_leakage: cpu-leakage@18 {
+ reg = <0x18 0x1>;
+ };
+
+ cpul_leakage: cpu-leakage@19 {
+ reg = <0x19 0x1>;
+ };
+
+ log_leakage: log-leakage@1a {
+ reg = <0x1a 0x1>;
+ };
+
+ gpu_leakage: gpu-leakage@1b {
+ reg = <0x1b 0x1>;
+ };
+
+ otp_cpu_version: cpu-version@1c {
+ reg = <0x1c 0x1>;
+ bits = <3 3>;
+ };
+
+ npu_leakage: npu-leakage@28 {
+ reg = <0x28 0x1>;
+ };
+
+ codec_leakage: codec-leakage@29 {
+ reg = <0x29 0x1>;
+ };
+ };
+
+ dmac2: dma-controller@fed10000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x0 0xfed10000 0x0 0x4000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH 0>;
+ arm,pl330-periph-burst;
+ clocks = <&cru ACLK_DMAC2>;
+ clock-names = "apb_pclk";
+ #dma-cells = <1>;
+ };
+
+ hdptxphy_hdmi0: phy@fed60000 {
+ compatible = "rockchip,rk3588-hdptx-phy";
+ reg = <0x0 0xfed60000 0x0 0x2000>;
+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>;
+ clock-names = "ref", "apb";
+ #phy-cells = <0>;
+ resets = <&cru SRST_HDPTX0>, <&cru SRST_P_HDPTX0>,
+ <&cru SRST_HDPTX0_INIT>, <&cru SRST_HDPTX0_CMN>,
+ <&cru SRST_HDPTX0_LANE>, <&cru SRST_HDPTX0_ROPLL>,
+ <&cru SRST_HDPTX0_LCPLL>;
+ reset-names = "phy", "apb", "init", "cmn", "lane", "ropll",
+ "lcpll";
+ rockchip,grf = <&hdptxphy0_grf>;
+ status = "disabled";
+ };
+
+ usbdp_phy0: phy@fed80000 {
+ compatible = "rockchip,rk3588-usbdp-phy";
+ reg = <0x0 0xfed80000 0x0 0x10000>;
+ #phy-cells = <1>;
+ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>,
+ <&cru CLK_USBDP_PHY0_IMMORTAL>,
+ <&cru PCLK_USBDPPHY0>,
+ <&u2phy0>;
+ clock-names = "refclk", "immortal", "pclk", "utmi";
+ resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>,
+ <&cru SRST_USBDP_COMBO_PHY0_CMN>,
+ <&cru SRST_USBDP_COMBO_PHY0_LANE>,
+ <&cru SRST_USBDP_COMBO_PHY0_PCS>,
+ <&cru SRST_P_USBDPPHY0>;
+ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
+ rockchip,u2phy-grf = <&usb2phy0_grf>;
+ rockchip,usb-grf = <&usb_grf>;
+ rockchip,usbdpphy-grf = <&usbdpphy0_grf>;
+ rockchip,vo-grf = <&vo0_grf>;
+ status = "disabled";
+ };
+
+ combphy0_ps: phy@fee00000 {
+ compatible = "rockchip,rk3588-naneng-combphy";
+ reg = <0x0 0xfee00000 0x0 0x100>;
+ clocks = <&cru CLK_REF_PIPE_PHY0>, <&cru PCLK_PCIE_COMBO_PIPE_PHY0>,
+ <&cru PCLK_PHP_ROOT>;
+ clock-names = "ref", "apb", "pipe";
+ assigned-clocks = <&cru CLK_REF_PIPE_PHY0>;
+ assigned-clock-rates = <100000000>;
+ #phy-cells = <1>;
+ resets = <&cru SRST_REF_PIPE_PHY0>, <&cru SRST_P_PCIE2_PHY0>;
+ reset-names = "phy", "apb";
+ rockchip,pipe-grf = <&php_grf>;
+ rockchip,pipe-phy-grf = <&pipe_phy0_grf>;
+ status = "disabled";
+ };
+
+ combphy2_psu: phy@fee20000 {
+ compatible = "rockchip,rk3588-naneng-combphy";
+ reg = <0x0 0xfee20000 0x0 0x100>;
+ clocks = <&cru CLK_REF_PIPE_PHY2>, <&cru PCLK_PCIE_COMBO_PIPE_PHY2>,
+ <&cru PCLK_PHP_ROOT>;
+ clock-names = "ref", "apb", "pipe";
+ assigned-clocks = <&cru CLK_REF_PIPE_PHY2>;
+ assigned-clock-rates = <100000000>;
+ #phy-cells = <1>;
+ resets = <&cru SRST_REF_PIPE_PHY2>, <&cru SRST_P_PCIE2_PHY2>;
+ reset-names = "phy", "apb";
+ rockchip,pipe-grf = <&php_grf>;
+ rockchip,pipe-phy-grf = <&pipe_phy2_grf>;
+ status = "disabled";
+ };
+
+ system_sram2: sram@ff001000 {
+ compatible = "mmio-sram";
+ reg = <0x0 0xff001000 0x0 0xef000>;
+ ranges = <0x0 0x0 0xff001000 0xef000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ pinctrl: pinctrl {
+ compatible = "rockchip,rk3588-pinctrl";
+ ranges;
+ rockchip,grf = <&ioc>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ gpio0: gpio@fd8a0000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x0 0xfd8a0000 0x0 0x100>;
+ interrupts = <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru PCLK_GPIO0>, <&cru DBCLK_GPIO0>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 0 32>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gpio1: gpio@fec20000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x0 0xfec20000 0x0 0x100>;
+ interrupts = <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 32 32>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gpio2: gpio@fec30000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x0 0xfec30000 0x0 0x100>;
+ interrupts = <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru PCLK_GPIO2>, <&cru DBCLK_GPIO2>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 64 32>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gpio3: gpio@fec40000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x0 0xfec40000 0x0 0x100>;
+ interrupts = <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru PCLK_GPIO3>, <&cru DBCLK_GPIO3>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 96 32>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gpio4: gpio@fec50000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x0 0xfec50000 0x0 0x100>;
+ interrupts = <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru PCLK_GPIO4>, <&cru DBCLK_GPIO4>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 128 32>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+ };
+};
+
+#include "rk3588-base-pinctrl.dtsi"
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 709d348cf06b..03fd193be253 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi
@@ -466,3 +466,7 @@
};
};
};
+
+&tsadc {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
index 7be2190244ba..00f660d50127 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
@@ -878,6 +878,8 @@
vdd_cpu_big1_s0: dcdc-reg1 {
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>;
@@ -890,6 +892,8 @@
vdd_cpu_big0_s0: dcdc-reg2 {
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>;
@@ -902,6 +906,8 @@
vdd_cpu_lit_s0: dcdc-reg3 {
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>;
@@ -926,6 +932,8 @@
vdd_cpu_big1_mem_s0: dcdc-reg5 {
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>;
@@ -939,6 +947,8 @@
vdd_cpu_big0_mem_s0: dcdc-reg6 {
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>;
@@ -963,6 +973,8 @@
vdd_cpu_lit_mem_s0: dcdc-reg8 {
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>;
@@ -1131,6 +1143,10 @@
status = "okay";
};
+&tsadc {
+ status = "okay";
+};
+
&u2phy0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi
index 244c66faa161..244c66faa161 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi
new file mode 100644
index 000000000000..0ce0934ec6b7
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi
@@ -0,0 +1,448 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ */
+
+#include "rk3588-base.dtsi"
+#include "rk3588-extra-pinctrl.dtsi"
+
+/ {
+ usb_host1_xhci: usb@fc400000 {
+ compatible = "rockchip,rk3588-dwc3", "snps,dwc3";
+ reg = <0x0 0xfc400000 0x0 0x400000>;
+ interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru REF_CLK_USB3OTG1>, <&cru SUSPEND_CLK_USB3OTG1>,
+ <&cru ACLK_USB3OTG1>;
+ clock-names = "ref_clk", "suspend_clk", "bus_clk";
+ dr_mode = "otg";
+ phys = <&u2phy1_otg>, <&usbdp_phy1 PHY_TYPE_USB3>;
+ phy-names = "usb2-phy", "usb3-phy";
+ phy_type = "utmi_wide";
+ power-domains = <&power RK3588_PD_USB>;
+ resets = <&cru SRST_A_USB3OTG1>;
+ snps,dis_enblslpm_quirk;
+ snps,dis-u2-freeclk-exists-quirk;
+ snps,dis-del-phy-power-chg-quirk;
+ snps,dis-tx-ipgap-linecheck-quirk;
+ status = "disabled";
+ };
+
+ pcie30_phy_grf: syscon@fd5b8000 {
+ compatible = "rockchip,rk3588-pcie3-phy-grf", "syscon";
+ reg = <0x0 0xfd5b8000 0x0 0x10000>;
+ };
+
+ pipe_phy1_grf: syscon@fd5c0000 {
+ compatible = "rockchip,rk3588-pipe-phy-grf", "syscon";
+ reg = <0x0 0xfd5c0000 0x0 0x100>;
+ };
+
+ usbdpphy1_grf: syscon@fd5cc000 {
+ compatible = "rockchip,rk3588-usbdpphy-grf", "syscon";
+ reg = <0x0 0xfd5cc000 0x0 0x4000>;
+ };
+
+ usb2phy1_grf: syscon@fd5d4000 {
+ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
+ reg = <0x0 0xfd5d4000 0x0 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ u2phy1: usb2phy@4000 {
+ compatible = "rockchip,rk3588-usb2phy";
+ reg = <0x4000 0x10>;
+ #clock-cells = <0>;
+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
+ clock-names = "phyclk";
+ clock-output-names = "usb480m_phy1";
+ interrupts = <GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH 0>;
+ resets = <&cru SRST_OTGPHY_U3_1>, <&cru SRST_P_USB2PHY_U3_1_GRF0>;
+ reset-names = "phy", "apb";
+ status = "disabled";
+
+ u2phy1_otg: otg-port {
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ };
+ };
+
+ i2s8_8ch: i2s@fddc8000 {
+ compatible = "rockchip,rk3588-i2s-tdm";
+ reg = <0x0 0xfddc8000 0x0 0x1000>;
+ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S8_8CH_TX>, <&cru MCLK_I2S8_8CH_TX>, <&cru HCLK_I2S8_8CH>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ assigned-clocks = <&cru CLK_I2S8_8CH_TX_SRC>;
+ assigned-clock-parents = <&cru PLL_AUPLL>;
+ dmas = <&dmac2 22>;
+ dma-names = "tx";
+ power-domains = <&power RK3588_PD_VO0>;
+ resets = <&cru SRST_M_I2S8_8CH_TX>;
+ reset-names = "tx-m";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2s6_8ch: i2s@fddf4000 {
+ compatible = "rockchip,rk3588-i2s-tdm";
+ reg = <0x0 0xfddf4000 0x0 0x1000>;
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S6_8CH_TX>, <&cru MCLK_I2S6_8CH_TX>, <&cru HCLK_I2S6_8CH>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ assigned-clocks = <&cru CLK_I2S6_8CH_TX_SRC>;
+ assigned-clock-parents = <&cru PLL_AUPLL>;
+ dmas = <&dmac2 4>;
+ dma-names = "tx";
+ power-domains = <&power RK3588_PD_VO1>;
+ resets = <&cru SRST_M_I2S6_8CH_TX>;
+ reset-names = "tx-m";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2s7_8ch: i2s@fddf8000 {
+ compatible = "rockchip,rk3588-i2s-tdm";
+ reg = <0x0 0xfddf8000 0x0 0x1000>;
+ interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S7_8CH_RX>, <&cru MCLK_I2S7_8CH_RX>, <&cru HCLK_I2S7_8CH>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ assigned-clocks = <&cru CLK_I2S7_8CH_RX_SRC>;
+ assigned-clock-parents = <&cru PLL_AUPLL>;
+ dmas = <&dmac2 21>;
+ dma-names = "rx";
+ power-domains = <&power RK3588_PD_VO1>;
+ resets = <&cru SRST_M_I2S7_8CH_RX>;
+ reset-names = "rx-m";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2s10_8ch: i2s@fde00000 {
+ compatible = "rockchip,rk3588-i2s-tdm";
+ reg = <0x0 0xfde00000 0x0 0x1000>;
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru MCLK_I2S10_8CH_RX>, <&cru MCLK_I2S10_8CH_RX>, <&cru HCLK_I2S10_8CH>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ assigned-clocks = <&cru CLK_I2S10_8CH_RX_SRC>;
+ assigned-clock-parents = <&cru PLL_AUPLL>;
+ dmas = <&dmac2 24>;
+ dma-names = "rx";
+ power-domains = <&power RK3588_PD_VO1>;
+ resets = <&cru SRST_M_I2S10_8CH_RX>;
+ reset-names = "rx-m";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ pcie3x4: pcie@fe150000 {
+ compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x00 0x0f>;
+ 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>;
+ clock-names = "aclk_mst", "aclk_slv",
+ "aclk_dbi", "pclk",
+ "aux", "pipe";
+ device_type = "pci";
+ interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "sys", "pmc", "msg", "legacy", "err";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie3x4_intc 0>,
+ <0 0 0 2 &pcie3x4_intc 1>,
+ <0 0 0 3 &pcie3x4_intc 2>,
+ <0 0 0 4 &pcie3x4_intc 3>;
+ linux,pci-domain = <0>;
+ max-link-speed = <3>;
+ msi-map = <0x0000 &its1 0x0000 0x1000>;
+ num-lanes = <4>;
+ phys = <&pcie30phy>;
+ phy-names = "pcie-phy";
+ power-domains = <&power RK3588_PD_PCIE>;
+ ranges = <0x01000000 0x0 0xf0100000 0x0 0xf0100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf0200000 0x0 0xf0200000 0x0 0x00e00000>,
+ <0x03000000 0x0 0x40000000 0x9 0x00000000 0x0 0x40000000>;
+ reg = <0xa 0x40000000 0x0 0x00400000>,
+ <0x0 0xfe150000 0x0 0x00010000>,
+ <0x0 0xf0000000 0x0 0x00100000>;
+ reg-names = "dbi", "apb", "config";
+ resets = <&cru SRST_PCIE0_POWER_UP>, <&cru SRST_P_PCIE0>;
+ reset-names = "pwr", "pipe";
+ status = "disabled";
+
+ pcie3x4_intc: legacy-interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 260 IRQ_TYPE_EDGE_RISING 0>;
+ };
+ };
+
+ pcie3x4_ep: pcie-ep@fe150000 {
+ compatible = "rockchip,rk3588-pcie-ep";
+ reg = <0xa 0x40000000 0x0 0x00100000>,
+ <0xa 0x40100000 0x0 0x00100000>,
+ <0x0 0xfe150000 0x0 0x00010000>,
+ <0x9 0x00000000 0x0 0x40000000>,
+ <0xa 0x40300000 0x0 0x00100000>;
+ reg-names = "dbi", "dbi2", "apb", "addr_space", "atu";
+ 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>;
+ clock-names = "aclk_mst", "aclk_slv",
+ "aclk_dbi", "pclk",
+ "aux", "pipe";
+ interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "sys", "pmc", "msg", "legacy", "err",
+ "dma0", "dma1", "dma2", "dma3";
+ max-link-speed = <3>;
+ num-lanes = <4>;
+ phys = <&pcie30phy>;
+ phy-names = "pcie-phy";
+ power-domains = <&power RK3588_PD_PCIE>;
+ resets = <&cru SRST_PCIE0_POWER_UP>, <&cru SRST_P_PCIE0>;
+ reset-names = "pwr", "pipe";
+ status = "disabled";
+ };
+
+ pcie3x2: pcie@fe160000 {
+ compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x10 0x1f>;
+ 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>;
+ clock-names = "aclk_mst", "aclk_slv",
+ "aclk_dbi", "pclk",
+ "aux", "pipe";
+ device_type = "pci";
+ interrupts = <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "sys", "pmc", "msg", "legacy", "err";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie3x2_intc 0>,
+ <0 0 0 2 &pcie3x2_intc 1>,
+ <0 0 0 3 &pcie3x2_intc 2>,
+ <0 0 0 4 &pcie3x2_intc 3>;
+ linux,pci-domain = <1>;
+ max-link-speed = <3>;
+ msi-map = <0x1000 &its1 0x1000 0x1000>;
+ num-lanes = <2>;
+ phys = <&pcie30phy>;
+ phy-names = "pcie-phy";
+ power-domains = <&power RK3588_PD_PCIE>;
+ ranges = <0x01000000 0x0 0xf1100000 0x0 0xf1100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf1200000 0x0 0xf1200000 0x0 0x00e00000>,
+ <0x03000000 0x0 0x40000000 0x9 0x40000000 0x0 0x40000000>;
+ reg = <0xa 0x40400000 0x0 0x00400000>,
+ <0x0 0xfe160000 0x0 0x00010000>,
+ <0x0 0xf1000000 0x0 0x00100000>;
+ reg-names = "dbi", "apb", "config";
+ resets = <&cru SRST_PCIE1_POWER_UP>, <&cru SRST_P_PCIE1>;
+ reset-names = "pwr", "pipe";
+ status = "disabled";
+
+ pcie3x2_intc: legacy-interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 255 IRQ_TYPE_EDGE_RISING 0>;
+ };
+ };
+
+ pcie2x1l0: pcie@fe170000 {
+ compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
+ bus-range = <0x20 0x2f>;
+ clocks = <&cru ACLK_PCIE_1L0_MSTR>, <&cru ACLK_PCIE_1L0_SLV>,
+ <&cru ACLK_PCIE_1L0_DBI>, <&cru PCLK_PCIE_1L0>,
+ <&cru CLK_PCIE_AUX2>, <&cru CLK_PCIE1L0_PIPE>;
+ clock-names = "aclk_mst", "aclk_slv",
+ "aclk_dbi", "pclk",
+ "aux", "pipe";
+ device_type = "pci";
+ interrupts = <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "sys", "pmc", "msg", "legacy", "err";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie2x1l0_intc 0>,
+ <0 0 0 2 &pcie2x1l0_intc 1>,
+ <0 0 0 3 &pcie2x1l0_intc 2>,
+ <0 0 0 4 &pcie2x1l0_intc 3>;
+ linux,pci-domain = <2>;
+ max-link-speed = <2>;
+ msi-map = <0x2000 &its0 0x2000 0x1000>;
+ num-lanes = <1>;
+ phys = <&combphy1_ps PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy";
+ power-domains = <&power RK3588_PD_PCIE>;
+ ranges = <0x01000000 0x0 0xf2100000 0x0 0xf2100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf2200000 0x0 0xf2200000 0x0 0x00e00000>,
+ <0x03000000 0x0 0x40000000 0x9 0x80000000 0x0 0x40000000>;
+ reg = <0xa 0x40800000 0x0 0x00400000>,
+ <0x0 0xfe170000 0x0 0x00010000>,
+ <0x0 0xf2000000 0x0 0x00100000>;
+ reg-names = "dbi", "apb", "config";
+ resets = <&cru SRST_PCIE2_POWER_UP>, <&cru SRST_P_PCIE2>;
+ reset-names = "pwr", "pipe";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ status = "disabled";
+
+ pcie2x1l0_intc: legacy-interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 240 IRQ_TYPE_EDGE_RISING 0>;
+ };
+ };
+
+ gmac0: ethernet@fe1b0000 {
+ compatible = "rockchip,rk3588-gmac", "snps,dwmac-4.20a";
+ reg = <0x0 0xfe1b0000 0x0 0x10000>;
+ interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "macirq", "eth_wake_irq";
+ clocks = <&cru CLK_GMAC_125M>, <&cru CLK_GMAC_50M>,
+ <&cru PCLK_GMAC0>, <&cru ACLK_GMAC0>,
+ <&cru CLK_GMAC0_PTP_REF>;
+ clock-names = "stmmaceth", "clk_mac_ref",
+ "pclk_mac", "aclk_mac",
+ "ptp_ref";
+ power-domains = <&power RK3588_PD_GMAC>;
+ resets = <&cru SRST_A_GMAC0>;
+ reset-names = "stmmaceth";
+ rockchip,grf = <&sys_grf>;
+ rockchip,php-grf = <&php_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,wr_osr_lmt = <4>;
+ snps,rd_osr_lmt = <8>;
+ };
+
+ gmac0_mtl_rx_setup: rx-queues-config {
+ snps,rx-queues-to-use = <2>;
+ queue0 {};
+ queue1 {};
+ };
+
+ gmac0_mtl_tx_setup: tx-queues-config {
+ snps,tx-queues-to-use = <2>;
+ queue0 {};
+ queue1 {};
+ };
+ };
+
+ sata1: sata@fe220000 {
+ compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci";
+ reg = <0 0xfe220000 0 0x1000>;
+ interrupts = <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_SATA1>, <&cru CLK_PMALIVE1>,
+ <&cru CLK_RXOOB1>, <&cru CLK_PIPEPHY1_REF>,
+ <&cru CLK_PIPEPHY1_PIPE_ASIC_G>;
+ clock-names = "sata", "pmalive", "rxoob", "ref", "asic";
+ ports-implemented = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ sata-port@0 {
+ reg = <0>;
+ hba-port-cap = <HBA_PORT_FBSCP>;
+ phys = <&combphy1_ps PHY_TYPE_SATA>;
+ phy-names = "sata-phy";
+ snps,rx-ts-max = <32>;
+ snps,tx-ts-max = <32>;
+ };
+ };
+
+ usbdp_phy1: phy@fed90000 {
+ compatible = "rockchip,rk3588-usbdp-phy";
+ reg = <0x0 0xfed90000 0x0 0x10000>;
+ #phy-cells = <1>;
+ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>,
+ <&cru CLK_USBDP_PHY1_IMMORTAL>,
+ <&cru PCLK_USBDPPHY1>,
+ <&u2phy1>;
+ clock-names = "refclk", "immortal", "pclk", "utmi";
+ resets = <&cru SRST_USBDP_COMBO_PHY1_INIT>,
+ <&cru SRST_USBDP_COMBO_PHY1_CMN>,
+ <&cru SRST_USBDP_COMBO_PHY1_LANE>,
+ <&cru SRST_USBDP_COMBO_PHY1_PCS>,
+ <&cru SRST_P_USBDPPHY1>;
+ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
+ rockchip,u2phy-grf = <&usb2phy1_grf>;
+ rockchip,usb-grf = <&usb_grf>;
+ rockchip,usbdpphy-grf = <&usbdpphy1_grf>;
+ rockchip,vo-grf = <&vo0_grf>;
+ status = "disabled";
+ };
+
+ combphy1_ps: phy@fee10000 {
+ compatible = "rockchip,rk3588-naneng-combphy";
+ reg = <0x0 0xfee10000 0x0 0x100>;
+ clocks = <&cru CLK_REF_PIPE_PHY1>, <&cru PCLK_PCIE_COMBO_PIPE_PHY1>,
+ <&cru PCLK_PHP_ROOT>;
+ clock-names = "ref", "apb", "pipe";
+ assigned-clocks = <&cru CLK_REF_PIPE_PHY1>;
+ assigned-clock-rates = <100000000>;
+ #phy-cells = <1>;
+ resets = <&cru SRST_REF_PIPE_PHY1>, <&cru SRST_P_PCIE2_PHY1>;
+ reset-names = "phy", "apb";
+ rockchip,pipe-grf = <&php_grf>;
+ rockchip,pipe-phy-grf = <&pipe_phy1_grf>;
+ status = "disabled";
+ };
+
+ pcie30phy: phy@fee80000 {
+ compatible = "rockchip,rk3588-pcie3-phy";
+ reg = <0x0 0xfee80000 0x0 0x20000>;
+ #phy-cells = <0>;
+ clocks = <&cru PCLK_PCIE_COMBO_PIPE_PHY>;
+ clock-names = "pclk";
+ resets = <&cru SRST_PCIE30_PHY>;
+ reset-names = "phy";
+ rockchip,pipe-grf = <&php_grf>;
+ rockchip,phy-grf = <&pcie30_phy_grf>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dts b/arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dts
new file mode 100644
index 000000000000..83103e4c7216
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dts
@@ -0,0 +1,778 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2023 Thomas McKahan
+ * Copyright (c) 2024 Sebastian Kropatsch
+ *
+ */
+
+/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 "rk3588-friendlyelec-cm3588.dtsi"
+
+/ {
+ model = "FriendlyElec CM3588 NAS";
+ compatible = "friendlyarm,cm3588-nas", "friendlyarm,cm3588", "rockchip,rk3588";
+
+ adc_key_recovery: adc-key-recovery {
+ 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 = <17000>;
+ };
+ };
+
+ analog-sound {
+ compatible = "simple-audio-card";
+ pinctrl-names = "default";
+ pinctrl-0 = <&headphone_detect>;
+
+ simple-audio-card,format = "i2s";
+ simple-audio-card,hp-det-gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_LOW>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,name = "realtek,rt5616-codec";
+
+ simple-audio-card,routing =
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
+ "MIC1", "Microphone Jack",
+ "Microphone Jack", "micbias1";
+ simple-audio-card,widgets =
+ "Headphone", "Headphones",
+ "Microphone", "Microphone Jack";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s0_8ch>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&rt5616>;
+ };
+ };
+
+ buzzer: pwm-beeper {
+ compatible = "pwm-beeper";
+ amp-supply = <&vcc_5v0_sys>;
+ beeper-hz = <500>;
+ pwms = <&pwm8 0 500000 0>;
+ };
+
+ fan: pwm-fan {
+ compatible = "pwm-fan";
+ #cooling-cells = <2>;
+ cooling-levels = <0 50 80 120 160 220>;
+ fan-supply = <&vcc_5v0_sys>;
+ pwms = <&pwm1 0 50000 0>;
+ };
+
+ gpio_keys: gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&key1_pin>;
+
+ button-user {
+ debounce-interval = <50>;
+ gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_LOW>;
+ label = "User Button";
+ linux,code = <BTN_1>;
+ wakeup-source;
+ };
+ };
+
+ ir-receiver {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_LOW>;
+ };
+
+ vcc_12v_dcin: regulator-vcc-12v-dcin {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_12v_dcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc_3v3_m2_a: regulator-vcc-3v3-m2-a {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_m2_a";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_12v_dcin>;
+ };
+
+ vcc_3v3_m2_b: regulator-vcc-3v3-m2-b {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_m2_b";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_12v_dcin>;
+ };
+
+ vcc_3v3_m2_c: regulator-vcc-3v3-m2-c {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_m2_c";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_12v_dcin>;
+ };
+
+ vcc_3v3_m2_d: regulator-vcc-3v3-m2-d {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_m2_d";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_12v_dcin>;
+ };
+
+ /* vcc_5v0_sys powers the peripherals */
+ 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_12v_dcin>;
+ };
+
+ /* SY6280AAC power switch (U14 in schematics) */
+ vcc_5v0_host_20: regulator-vcc-5v0-host-20 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc_5v0_host20_en>;
+ regulator-name = "vcc_5v0_host_20";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_5v0_sys>;
+ };
+
+ /* SY6280AAC power switch (U8 in schematics) */
+ vcc_5v0_host_30_p1: regulator-vcc-5v0-host-30-p1 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc_5v0_host30p1_en>;
+ regulator-name = "vcc_5v0_host_30_p1";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_5v0_sys>;
+ };
+
+ /* SY6280AAC power switch (U9 in schematics) */
+ vcc_5v0_host_30_p2: regulator-vcc-5v0-host-30-p2 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc_5v0_host30p2_en>;
+ regulator-name = "vcc_5v0_host_30_p2";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_5v0_sys>;
+ };
+
+ /* SY6280AAC power switch (U10 in schematics) */
+ vbus_5v0_typec: regulator-vbus-5v0-typec {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec_5v_pwr_en>;
+ regulator-name = "vbus_5v0_typec";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_5v0_sys>;
+ };
+};
+
+/* vcc_4v0_sys powers the RK806 and RK860's */
+&vcc_4v0_sys {
+ vin-supply = <&vcc_12v_dcin>;
+};
+
+/* Combo PHY 1 is configured to act as as PCIe 2.0 PHY */
+/* Used by PCIe controller 2 (pcie2x1l0) */
+&combphy1_ps {
+ status = "okay";
+};
+
+/* Combo PHY 2 is configured to act as USB3 PHY */
+/* Used by USB 3.0 OTG 2 controller (USB 3.0 Type-A port 2) */
+/* CM3588 USB Controller Config Table: USB30 HOST2 */
+&combphy2_psu {
+ status = "okay";
+};
+
+/* GPIO names are in the format "Human-readable-name [SIGNAL_LABEL]" */
+/* Signal labels match the official CM3588 NAS SDK schematic revision 2309 */
+&gpio0 {
+ gpio-line-names =
+ /* GPIO0 A0-A7 */
+ "", "", "", "",
+ "MicroSD detect [SDMMC_DET_L]", "", "", "",
+ /* GPIO0 B0-B7 */
+ "", "", "", "",
+ "", "", "", "",
+ /* GPIO0 C0-C7 */
+ "", "", "", "",
+ "Pin 10 [UART0_RX_M0]", "Pin 08 [UART0_TX_M0/PWM4_M0]", "Pin 32 [PWM5_M1]", "",
+ /* GPIO0 D0-D7 */
+ "", "", "", "USB3 Type-C [CC_INT_L]",
+ "IR receiver [PWM3_IR_M0]", "User Button", "", "";
+};
+
+&gpio1 {
+ gpio-line-names =
+ /* GPIO1 A0-A7 */
+ "Pin 27 [UART6_RX_M1]", "Pin 28 [UART6_TX_M1]", "", "",
+ "USB2 Type-A [USB2_PWREN]", "", "", "Pin 15",
+ /* GPIO1 B0-B7 */
+ "Pin 26", "Pin 21 [SPI0_MISO_M2]", "Pin 19 [SPI0_MOSI_M2/UART4_RX_M2]", "Pin 23 [SPI0_CLK_M2/UART4_TX_M2]",
+ "Pin 24 [SPI0_CS0_M2/UART7_RX_M2]", "Pin 22 [SPI0_CS1_M0/UART7_TX_M2]", "", "CSI-Pin 14 [MIPI_CAM2_CLKOUT]",
+ /* GPIO1 C0-C7 */
+ "", "", "", "",
+ "Headphone detect [HP_DET_L]", "", "", "",
+ /* GPIO1 D0-D7 */
+ "", "", "USB3 Type-C [TYPEC5V_PWREN_H]", "5V Fan [PWM1_M1]",
+ "", "HDMI-in detect [HDMIIRX_DET_L]", "Pin 05 [I2C8_SCL_M2]", "Pin 03 [I2C8_SDA_M2]";
+};
+
+&gpio2 {
+ gpio-line-names =
+ /* GPIO2 A0-A7 */
+ "", "", "", "",
+ "", "", "SPI NOR Flash [FSPI_D0_M1]", "SPI NOR Flash [FSPI_D1_M1]",
+ /* GPIO2 B0-B7 */
+ "SPI NOR Flash [FSPI_D2_M1]", "SPI NOR Flash [FSPI_D3_M1]", "", "SPI NOR Flash [FSPI_CLK_M1]",
+ "SPI NOR Flash [FSPI_CSN0_M1]", "", "", "",
+ /* GPIO2 C0-C7 */
+ "", "CSI-Pin 11 [MIPI_CAM2_RESET_L]", "CSI-Pin 12 [MIPI_CAM2_PDN_L]", "",
+ "", "", "", "",
+ /* GPIO2 D0-D7 */
+ "", "", "", "",
+ "", "", "", "";
+};
+
+&gpio3 {
+ gpio-line-names =
+ /* GPIO3 A0-A7 */
+ "Pin 35 [SPI4_MISO_M1/PWM10_M0]", "Pin 38 [SPI4_MOSI_M1]", "Pin 40 [SPI4_CLK_M1/UART8_TX_M1]", "Pin 36 [SPI4_CS0_M1/UART8_RX_M1]",
+ "Pin 37 [SPI4_CS1_M1]", "USB3-A #2 [USB3_2_PWREN]", "DSI-Pin 12 [LCD_RST]", "Buzzer [PWM8_M0]",
+ /* GPIO3 B0-B7 */
+ "Pin 33 [PWM9_M0]", "DSI-Pin 10 [PWM2_M1/LCD_BL]", "Pin 07", "Pin 16",
+ "Pin 18", "Pin 29 [UART3_TX_M1/PWM12_M0]", "Pin 31 [UART3_RX_M1/PWM13_M0]", "Pin 12",
+ /* GPIO3 C0-C7 */
+ "DSI-Pin 08 [TP_INT_L]", "DSI-Pin 14 [TP_RST_L]", "Pin 11 [PWM14_M0]", "Pin 13 [PWM15_IR_M0]",
+ "", "", "", "DSI-Pin 06 [I2C5_SCL_M0_TP]",
+ /* GPIO3 D0-D7 */
+ "DSI-Pin 05 [I2C5_SDA_M0_TP]", "", "", "",
+ "", "", "", "";
+};
+
+&gpio4 {
+ gpio-line-names =
+ /* GPIO4 A0-A7 */
+ "", "", "M.2 M-Key Slot4 [M2_D_PERST_L]", "",
+ "", "", "", "",
+ /* GPIO4 B0-B7 */
+ "USB3-A #1 [USB3_TYPEC1_PWREN]", "", "", "M.2 M-Key Slot3 [M2_C_PERST_L]",
+ "M.2 M-Key Slot2 [M2_B_PERST_L]", "M.2 M-Key Slot1 [M2_A_CLKREQ_L]", "M.2 M-Key Slot1 [M2_A_PERST_L]", "",
+ /* GPIO4 C0-C7 */
+ "", "", "", "",
+ "", "", "", "",
+ /* GPIO4 D0-D7 */
+ "", "", "", "",
+ "", "", "", "";
+};
+
+/* Connected to MIPI-DSI0 */
+&i2c5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c5m0_xfer>;
+ status = "disabled";
+};
+
+&i2c6 {
+ fusb302: typec-portc@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_5v0_typec>;
+
+ usb_con: connector {
+ compatible = "usb-c-connector";
+ data-role = "dual";
+ label = "USB-C";
+ power-role = "source";
+ source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>;
+ try-power-role = "source";
+ vbus-supply = <&vbus_5v0_typec>;
+
+ 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>;
+ };
+ };
+ };
+ };
+ };
+};
+
+/* Connected to MIPI-CSI1 */
+/* &i2c7 */
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+&i2c8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c8m2_xfer>;
+ status = "okay";
+};
+
+&pcie2x1l0 {
+ /* 2. M.2 socket, CON14: pcie30phy port0 lane1, @fe170000 */
+ max-link-speed = <3>;
+ num-lanes = <1>;
+ phys = <&pcie30phy>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_0_rst>;
+ reset-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc_3v3_m2_b>;
+ status = "okay";
+};
+
+&pcie2x1l1 {
+ /* 4. M.2 socket, CON16: pcie30phy port1 lane1, @fe180000 */
+ max-link-speed = <3>;
+ num-lanes = <1>;
+ phys = <&pcie30phy>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_1_rst>;
+ reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc_3v3_m2_d>;
+ status = "okay";
+};
+
+&pcie30phy {
+ /*
+ * Data lane mapping <1 3 2 4> = x1x1 x1x1 (bifurcation of both ports)
+ * port 0 lane 0 - always mapped to controller 0 (4L)
+ * port 0 lane 1 - map to controller 2 (1L0)
+ * port 1 lane 0 - map to controller 1 (2L)
+ * port 1 lane 1 - map to controller 3 (1L1)
+ */
+ data-lanes = <1 3 2 4>;
+ status = "okay";
+};
+
+&pcie3x4 {
+ /* 1. M.2 socket, CON13: pcie30phy port0 lane0, @fe150000 */
+ max-link-speed = <3>;
+ num-lanes = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3x4_rst>;
+ reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc_3v3_m2_a>;
+ status = "okay";
+};
+
+&pcie3x2 {
+ /* 3. M.2 socket, CON15: pcie30phy port1 lane0, @fe160000 */
+ max-link-speed = <3>;
+ num-lanes = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3x2_rst>;
+ reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc_3v3_m2_c>;
+ status = "okay";
+};
+
+&pinctrl {
+ audio {
+ headphone_detect: headphone-detect {
+ rockchip,pins = <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ gpio-key {
+ key1_pin: key1-pin {
+ rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ pcie {
+ pcie2_0_rst: pcie2-0-rst {
+ rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie2_1_rst: pcie2-1-rst {
+ rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie3x2_rst: pcie3x2-rst {
+ rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie3x4_rst: pcie3x4-rst {
+ rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb {
+ vcc_5v0_host20_en: vcc-5v0-host20-en {
+ rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ vcc_5v0_host30p1_en: vcc-5v0-host30p1-en {
+ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ vcc_5v0_host30p2_en: vcc-5v0-host30p2-en {
+ rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb-typec {
+ usbc0_int: usbc0-int {
+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ typec_5v_pwr_en: typec-5v-pwr-en {
+ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+/* Connected to 5V Fan */
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm1m1_pins>;
+ status = "okay";
+};
+
+/* Connected to MIPI-DSI0 */
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm2m1_pins>;
+};
+
+/* Connected to IR Receiver */
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm3m0_pins>;
+ status = "okay";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with UART0 */
+&pwm4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm4m1_pins>;
+ status = "disabled";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+&pwm5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm5m1_pins>;
+ status = "okay";
+};
+
+/* Connected to Buzzer */
+&pwm8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm8m0_pins>;
+ status = "okay";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+&pwm9 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm9m0_pins>;
+ status = "okay";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with SPI4 */
+&pwm10 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm10m0_pins>;
+ status = "disabled";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with UART3 */
+&pwm12 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm12m0_pins>;
+ status = "disabled";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with UART3 */
+&pwm13 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm13m0_pins>;
+ status = "disabled";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+&pwm14 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm14m0_pins>;
+ status = "okay";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Optimized for infrared applications */
+&pwm15 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm15m0_pins>;
+ status = "disabled";
+};
+
+/* microSD card */
+&sdmmc {
+ status = "okay";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with UART4, UART7 and PWM10 */
+&spi0 {
+ num-cs = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0m2_cs0 &spi0m2_pins>;
+ status = "disabled";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with UART8 */
+&spi4 {
+ num-cs = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi4m1_cs0 &spi4m1_pins>;
+ status = "disabled";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with PWM4 */
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0m0_xfer>;
+ status = "disabled";
+};
+
+/* Debug UART */
+&uart2 {
+ status = "okay";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with PWM12 and PWM13 */
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3m1_xfer>;
+ status = "disabled";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with SPI0 */
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart4m2_xfer>;
+ status = "disabled";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+&uart6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart6m1_xfer>;
+ status = "okay";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with SPI0 */
+&uart7 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart7m2_xfer>;
+ status = "disabled";
+};
+
+/* GPIO Connector, connected to 40-pin GPIO header */
+/* Shared with SPI4 */
+&uart8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart8m1_xfer>;
+ status = "disabled";
+};
+
+/* USB2 PHY for USB Type-C port */
+/* CM3588 USB Controller Config Table: USB20 OTG0 */
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ phy-supply = <&vbus_5v0_typec>;
+ status = "okay";
+};
+
+/* USB2 PHY for USB 3.0 Type-A port 1 */
+/* CM3588 USB Controller Config Table: USB20 OTG1 */
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_otg {
+ phy-supply = <&vcc_5v0_host_30_p1>;
+ status = "okay";
+};
+
+/* USB2 PHY for USB 2.0 Type-A */
+/* CM3588 USB Controller Config Table: USB20 HOST0 */
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ phy-supply = <&vcc_5v0_host_20>;
+ status = "okay";
+};
+
+/* USB2 PHY for USB 3.0 Type-A port 2 */
+/* CM3588 USB Controller Config Table: USB20 HOST1 */
+&u2phy3 {
+ status = "okay";
+};
+
+&u2phy3_host {
+ phy-supply = <&vcc_5v0_host_30_p2>;
+ status = "okay";
+};
+
+/* USB 2.0 Type-A */
+/* PHY: <&u2phy2_host> */
+&usb_host0_ehci {
+ status = "okay";
+};
+
+/* USB 2.0 Type-A */
+/* PHY: <&u2phy2_host> */
+&usb_host0_ohci {
+ status = "okay";
+};
+
+/* USB Type-C */
+/* PHYs: <&u2phy0_otg>, <&usbdp_phy0 PHY_TYPE_USB3> */
+&usb_host0_xhci {
+ usb-role-switch;
+ status = "okay";
+
+ port {
+ dwc3_0_role_switch: endpoint {
+ remote-endpoint = <&usbc0_role_sw>;
+ };
+ };
+};
+
+/* Lower USB 3.0 Type-A (port 2) */
+/* PHY: <&u2phy3_host> */
+&usb_host1_ehci {
+ status = "okay";
+};
+
+/* Lower USB 3.0 Type-A (port 2) */
+/* PHY: <&u2phy3_host> */
+&usb_host1_ohci {
+ status = "okay";
+};
+
+/* Upper USB 3.0 Type-A (port 1) */
+/* PHYs: <&u2phy1_otg>, <&usbdp_phy1 PHY_TYPE_USB3> */
+&usb_host1_xhci {
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* Lower USB 3.0 Type-A (port 2) */
+/* PHYs: <&combphy2_psu PHY_TYPE_USB3> */
+&usb_host2_xhci {
+ status = "okay";
+};
+
+/* USB3 PHY for USB Type-C port */
+/* CM3588 USB Controller Config Table: USB30 OTG0 */
+&usbdp_phy0 {
+ mode-switch;
+ orientation-switch;
+ sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
+ sbu2-dc-gpios = <&gpio4 RK_PA7 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>;
+ };
+ };
+};
+
+/* USB3 PHY for USB 3.0 Type-A port 1 */
+/* CM3588 USB Controller Config Table: USB30 OTG1 */
+&usbdp_phy1 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588.dtsi
new file mode 100644
index 000000000000..e3a9598b99fc
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588.dtsi
@@ -0,0 +1,653 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2023 Thomas McKahan
+ * Copyright (c) 2024 Sebastian Kropatsch
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3588.dtsi"
+
+/ {
+ model = "FriendlyElec CM3588";
+ compatible = "friendlyarm,cm3588", "rockchip,rk3588";
+
+ aliases {
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led_sys: led-0 {
+ color = <LED_COLOR_ID_AMBER>;
+ function = LED_FUNCTION_HEARTBEAT;
+ gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_sys_pin>;
+ };
+
+ led_usr: led-1 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_INDICATOR;
+ gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_usr_pin>;
+ };
+ };
+
+ /* vcc_4v0_sys powers the RK806 and RK860's */
+ vcc_4v0_sys: regulator-vcc-4v0-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_4v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <4000000>;
+ };
+
+ vcc_3v3_pcie20: regulator-vcc-3v3-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>;
+ };
+
+ vcc_3v3_sd_s0: regulator-vcc-3v3-sd-s0 {
+ compatible = "regulator-fixed";
+ gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd_s0_pwr>;
+ regulator-boot-on;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "vcc_3v3_sd_s0";
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ 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_4v0_sys>;
+ };
+};
+
+/* Combo PHY 0 is configured to act as as PCIe 2.0 PHY */
+/* Used by PCIe controller 4 (pcie2x1l2) */
+&combphy0_ps {
+ status = "okay";
+};
+
+&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>;
+};
+
+&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>;
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ sram-supply = <&vdd_gpu_mem_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 = <&vcc_4v0_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 = <&vcc_4v0_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 = <&vcc_4v0_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";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+ wakeup-source;
+ };
+};
+
+&i2c7 {
+ clock-frequency = <200000>;
+ status = "okay";
+
+ rt5616: audio-codec@1b {
+ compatible = "realtek,rt5616";
+ reg = <0x1b>;
+ #sound-dai-cells = <0>;
+ };
+};
+
+&i2s0_8ch {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_lrck
+ &i2s0_mclk
+ &i2s0_sclk
+ &i2s0_sdi0
+ &i2s0_sdo0>;
+ status = "okay";
+};
+
+&i2s5_8ch {
+ status = "okay";
+};
+
+&i2s6_8ch {
+ status = "okay";
+};
+
+&i2s7_8ch {
+ status = "okay";
+};
+
+&pcie2x1l2 {
+ /* r8125 ethernet, @fe190000 */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_2_rst>;
+ reset-gpios = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc_3v3_pcie20>;
+ status = "okay";
+};
+
+&pinctrl {
+ gpio-leds {
+ led_sys_pin: led-sys-pin {
+ rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ led_usr_pin: led-usr-pin {
+ rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ hym8563 {
+ hym8563_int: rtc-int {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ pcie {
+ pcie2_2_rst: pcie2-2-rst {
+ rockchip,pins = <4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sdmmc {
+ sd_s0_pwr: sd-s0-pwr {
+ rockchip,pins = <4 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&saradc {
+ vref-supply = <&avcc_1v8_s0>;
+ status = "okay";
+};
+
+/* eMMC */
+&sdhci {
+ bus-width = <8>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ no-sd;
+ no-sdio;
+ non-removable;
+ vmmc-supply = <&vcc_3v3_s3>;
+ vqmmc-supply = <&vcc_1v8_s3>;
+ status = "okay";
+};
+
+/* microSD card */
+&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>;
+};
+
+&spi2 {
+ assigned-clocks = <&cru CLK_SPI2>;
+ assigned-clock-rates = <200000000>;
+ num-cs = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
+ status = "okay";
+
+ rk806_single: 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 = <&vcc_4v0_sys>;
+ vcc2-supply = <&vcc_4v0_sys>;
+ vcc3-supply = <&vcc_4v0_sys>;
+ vcc4-supply = <&vcc_4v0_sys>;
+ vcc5-supply = <&vcc_4v0_sys>;
+ vcc6-supply = <&vcc_4v0_sys>;
+ vcc7-supply = <&vcc_4v0_sys>;
+ vcc8-supply = <&vcc_4v0_sys>;
+ vcc9-supply = <&vcc_4v0_sys>;
+ vcc10-supply = <&vcc_4v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc_4v0_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcc_4v0_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;
+ };
+ };
+
+ 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;
+ };
+ };
+
+ vcc_3v3_s0: pldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vcc_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>;
+ };
+ };
+
+ vdd_ddr_pll_s0: nldo-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "vdd_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;
+ };
+ };
+
+ vdd_0v85_s0: nldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "vdd_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";
+};
+
+/* Debug UART */
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2m0_xfer>;
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts b/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts
index 009566d881f3..c2a08bdf09e8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts
@@ -261,8 +261,7 @@
&mdio0 {
rgmii_phy0: ethernet-phy@1 {
/* RTL8211F */
- compatible = "ethernet-phy-id001c.c916",
- "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-id001c.c916";
reg = <0x1>;
pinctrl-names = "default";
pinctrl-0 = <&rtl8211f_0_rst>;
@@ -275,8 +274,7 @@
&mdio1 {
rgmii_phy1: ethernet-phy@2 {
/* RTL8211F */
- compatible = "ethernet-phy-id001c.c916",
- "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-id001c.c916";
reg = <0x2>;
pinctrl-names = "default";
pinctrl-0 = <&rtl8211f_1_rst>;
@@ -376,6 +374,10 @@
status = "okay";
};
+&tsadc {
+ status = "okay";
+};
+
&u2phy2 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-opp.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-opp.dtsi
new file mode 100644
index 000000000000..0f1a77697351
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-opp.dtsi
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/ {
+ cluster0_opp_table: opp-table-cluster0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-1008000000 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt = <675000 675000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <712500 712500 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <762500 762500 950000>;
+ clock-latency-ns = <40000>;
+ opp-suspend;
+ };
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <850000 850000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <950000 950000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ cluster1_opp_table: opp-table-cluster1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <675000 675000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <725000 725000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <762500 762500 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-microvolt = <925000 925000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2208000000 {
+ opp-hz = /bits/ 64 <2208000000>;
+ opp-microvolt = <987500 987500 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2400000000 {
+ opp-hz = /bits/ 64 <2400000000>;
+ opp-microvolt = <1000000 1000000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ cluster2_opp_table: opp-table-cluster2 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <675000 675000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <725000 725000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <762500 762500 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-microvolt = <925000 925000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2208000000 {
+ opp-hz = /bits/ 64 <2208000000>;
+ opp-microvolt = <987500 987500 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2400000000 {
+ opp-hz = /bits/ 64 <2400000000>;
+ opp-microvolt = <1000000 1000000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ gpu_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <675000 675000 850000>;
+ };
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <675000 675000 850000>;
+ };
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <675000 675000 850000>;
+ };
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <675000 675000 850000>;
+ };
+ opp-700000000 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <700000 700000 850000>;
+ };
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <750000 750000 850000>;
+ };
+ opp-900000000 {
+ opp-hz = /bits/ 64 <900000000>;
+ opp-microvolt = <800000 800000 850000>;
+ };
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <850000 850000 850000>;
+ };
+ };
+};
+
+&cpu_b0 {
+ operating-points-v2 = <&cluster1_opp_table>;
+};
+
+&cpu_b1 {
+ operating-points-v2 = <&cluster1_opp_table>;
+};
+
+&cpu_b2 {
+ operating-points-v2 = <&cluster2_opp_table>;
+};
+
+&cpu_b3 {
+ operating-points-v2 = <&cluster2_opp_table>;
+};
+
+&cpu_l0 {
+ operating-points-v2 = <&cluster0_opp_table>;
+};
+
+&cpu_l1 {
+ operating-points-v2 = <&cluster0_opp_table>;
+};
+
+&cpu_l2 {
+ operating-points-v2 = <&cluster0_opp_table>;
+};
+
+&cpu_l3 {
+ operating-points-v2 = <&cluster0_opp_table>;
+};
+
+&gpu {
+ operating-points-v2 = <&gpu_opp_table>;
+};
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 1a604429fb26..e74871491ef5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
@@ -444,6 +444,7 @@
&sdmmc {
bus-width = <4>;
cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
disable-wp;
max-frequency = <150000000>;
no-sdio;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
index b4f22d95ac0e..e4a20cda65ed 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
@@ -435,6 +435,7 @@
&sdmmc {
bus-width = <4>;
cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
disable-wp;
max-frequency = <150000000>;
no-sdio;
@@ -832,6 +833,8 @@
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>;
@@ -845,6 +848,8 @@
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>;
@@ -858,6 +863,8 @@
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>;
@@ -884,6 +891,8 @@
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>;
@@ -898,6 +907,8 @@
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>;
@@ -924,6 +935,8 @@
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>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
new file mode 100644
index 000000000000..d0b922b8d67e
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
@@ -0,0 +1,1177 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2024 Radxa Limited
+ * Copyright (c) 2024 Heiko Stuebner <[email protected]>
+ */
+
+/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/pwm/pwm.h>
+#include "dt-bindings/usb/pd.h"
+#include "rk3588.dtsi"
+
+/ {
+ model = "Radxa ROCK 5 ITX";
+ compatible = "radxa,rock-5-itx", "rockchip,rk3588";
+
+ aliases {
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc;
+ mmc2 = &sdio;
+ };
+
+ 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 = <100>;
+
+ button-maskrom {
+ label = "Mask Rom";
+ linux,code = <KEY_SETUP>;
+ press-threshold-microvolt = <1750>;
+ };
+ };
+
+ analog-sound {
+ compatible = "audio-graph-card";
+ label = "rk3588-es8316";
+ dais = <&i2s0_8ch_p0>;
+ hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_detect>;
+ routing = "MIC2", "Mic Jack",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR";
+ widgets = "Microphone", "Mic Jack",
+ "Headphone", "Headphones";
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pins>;
+
+ power-led1 {
+ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "default-on";
+ };
+
+ hdd-led2 {
+ gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "disk-activity";
+ };
+ };
+
+ fan0: pwm-fan {
+ compatible = "pwm-fan";
+ #cooling-cells = <2>;
+ cooling-levels = <0 64 128 192 255>;
+ fan-supply = <&vcc12v_dcin>;
+ pwms = <&pwm14 0 10000 0>;
+ };
+
+ /* M.2 E-KEY */
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&hym8563>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_enable_h>;
+ reset-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_LOW>;
+ };
+
+ typec_vin: regulator-typec-vin {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vbus5v0_typec_en>;
+ regulator-name = "typec_vin";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ 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>;
+ };
+
+ vcc33_io64: regulator-vcc33-io64 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc33_io64";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+
+ vcc3v3_ekey: regulator-vcc3v3-ekey {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ekey_en>;
+ regulator-name = "vcc3v3_ekey";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <50000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc3v3_lan: vcc3v3_lan_phy2: regulator-vcc3v3-lan {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_lan";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc3v3_mkey: regulator-vcc3v3-mkey {
+ 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-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ 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 = <&vcc12v_dcin>;
+ };
+
+ 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_usb20: vcc5v0_usb12: vcc5v0_usb34: regulator-vcc5v0-usb {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_host_pwren_h>;
+ regulator-name = "vcc5v0_usb";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ 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>;
+ };
+};
+
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy1_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>;
+};
+
+&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;
+ };
+ };
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1m2_xfer>;
+ 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;
+ };
+ };
+};
+
+/* CAM0 connector */
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c3m0_xfer>;
+};
+
+/* M.2 E-key */
+&i2c4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c4m1_xfer>;
+};
+
+/* RTC and LCD0 connector */
+&i2c6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c6m0_xfer>;
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "wifi_32kout";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_int>;
+ };
+};
+
+/* Audio codec and CAM1 connector */
+&i2c7 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c7m0_xfer>;
+ status = "okay";
+
+ es8316: 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>;
+ };
+ };
+ };
+};
+
+/* FUSB302 and LCD1 connector */
+&i2c8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c8m4_xfer>;
+ status = "okay";
+
+ usbc0: usb-typec@22 {
+ compatible = "fcs,fusb302";
+ reg = <0x22>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <RK_PB4 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usbc0_int>;
+ vbus-supply = <&typec_vin>;
+
+ usb_con: connector {
+ compatible = "usb-c-connector";
+ data-role = "dual";
+ label = "USB-C";
+ power-role = "source";
+ source-pdos =
+ <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+
+ 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>;
+ };
+ };
+ };
+ };
+ };
+};
+
+&i2c8m4_xfer {
+ rockchip,pins =
+ /* i2c8_scl_m4 */
+ <3 RK_PC2 9 &pcfg_pull_up_drv_level_6>,
+ /* i2c8_sda_m4 */
+ <3 RK_PC3 9 &pcfg_pull_up_drv_level_6>;
+};
+
+&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 {
+ hysteresis = <2000>;
+ temperature = <50000>;
+ type = "active";
+ };
+
+ package_fan1: package-fan1 {
+ hysteresis = <2000>;
+ temperature = <65000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ cooling-device = <&fan0 THERMAL_NO_LIMIT 1>;
+ trip = <&package_fan0>;
+ };
+ map1 {
+ cooling-device = <&fan0 2 THERMAL_NO_LIMIT>;
+ trip = <&package_fan1>;
+ };
+ };
+};
+
+/* M.2 E-key */
+&pcie2x1l0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie30x1_0_perstn_m1_l>;
+ reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_ekey>;
+ status = "okay";
+};
+
+/* RTL8125B_1 */
+&pcie2x1l1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie30x1_1_perstn>;
+ reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_lan>;
+ status = "okay";
+};
+
+/* RTL8125B_2 */
+&pcie2x1l2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie20x1_2_perstn>;
+ reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_lan_phy2>;
+ status = "okay";
+};
+
+&pcie30phy {
+ data-lanes = <1 1 2 2>;
+ /* separate clock lines from the clock generator to phy and devices */
+ rockchip,rx-common-refclk-mode = <0 0 0 0>;
+ status = "okay";
+};
+
+/* ASMedia ASM1164 Sata controller */
+&pcie3x2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie30x2_perstn_m1_l>;
+ reset-gpios = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc33_io64>;
+ status = "okay";
+};
+
+/* M.2 M.key */
+&pcie3x4 {
+ num-lanes = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie30x4_perstn_m1_l>;
+ reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_mkey>;
+ status = "okay";
+};
+
+&pinctrl {
+ hym8563 {
+ rtc_int: rtc-int {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ led_pins: led-pins {
+ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>,
+ <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie {
+ pcie20x1_2_perstn: pcie20x1-2-perstn {
+ rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie30x1_0_perstn_m1_l: pcie30x1-0-perstn-m1-l {
+ rockchip,pins = <4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie30x1_1_perstn: pcie30x1-1-perstn {
+ rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie30x2_perstn_m1_l: pcie30x2-perstn-m1-l {
+ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie30x4_perstn_m1_l: pcie30x4-perstn-m1-l {
+ rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ ekey_en: ekey-en {
+ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+
+ pcie30x4_pwren_h: pcie30x4-pwren-h {
+ rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ sound {
+ hp_detect: hp-detect {
+ rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ usb {
+ usb_host_pwren_h: usb-host-pwren-h {
+ rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ vcc5v0_otg_en: vcc5v0-otg-en {
+ rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ gl3523_reset: rl3523-reset {
+ rockchip,pins = <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb-typec {
+ usbc0_int: usbc0-int {
+ rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ vbus5v0_typec_en: vbus5v0-typec-en {
+ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ hdmirx {
+ hdmirx_det: hdmirx-det {
+ rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sdio-pwrseq {
+ wifi_enable_h: wifi-enable-h {
+ rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wireless-wlan {
+ wifi_host_wake_irq: wifi-host-wake-irq {
+ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ bt {
+ bt_enable_h: bt-enable-h {
+ rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_host_wake_l: bt-host-wake-l {
+ rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_wake_l: bt-wake-l {
+ rockchip,pins = <4 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ dp {
+ dp1_hpd: dp1-hpd {
+ rockchip,pins = <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm14 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm14m1_pins>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&avcc_1v8_s0>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ max-frequency = <200000000>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ mmc-hs200-1_8v;
+ 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;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc_det>;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3_s3>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+/* M.2 E-KEY */
+&sdio {
+ broken-cd;
+ bus-width = <4>;
+ cap-sdio-irq;
+ keep-power-in-suspend;
+ max-frequency = <150000000>;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ no-sd;
+ no-mmc;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdiom0_pins>;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc3v3_ekey>;
+ status = "okay";
+};
+
+&sfc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&fspim2_pins>;
+ status = "okay";
+
+ spi_flash: flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-max-frequency = <50000000>;
+ 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>;
+ 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 = <&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-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-on-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-on-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-on-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;
+ };
+ };
+
+ vcc_3v3_s0: pldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vcc_3v3_s0";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ 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>;
+ };
+ };
+
+ vdd_ddr_pll_s0: nldo-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "vdd_ddr_pll_s0";
+
+ regulator-state-mem {
+ regulator-on-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;
+ };
+ };
+
+ vdd_0v85_s0: nldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "vdd_0v85_s0";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <837500>;
+ };
+ };
+
+ 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-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+ };
+ };
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "okay";
+};
+
+/* Connected to M.2 E-key */
+&uart6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart6m1_xfer &uart6m1_ctsn &uart6m1_rtsn>;
+ status = "okay";
+};
+
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ status = "okay";
+};
+
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_otg {
+ /* connected to USB3 hub, which is powered by vcc5v0_usb12 */
+ phy-supply = <&vcc5v0_usb12>;
+ status = "okay";
+};
+
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ /* connected to USB2 hub, which is powered by vcc5v0_usb20 */
+ phy-supply = <&vcc5v0_usb20>;
+ status = "okay";
+};
+
+&u2phy3 {
+ status = "okay";
+};
+
+&u2phy3_host {
+ phy-supply = <&vcc5v0_usb20>;
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_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_xhci {
+ dr_mode = "host";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ /* 2.0 hub on port 1 */
+ hub_2_0: hub@1 {
+ compatible = "usb5e3,610";
+ reg = <1>;
+ peer-hub = <&hub_3_0>;
+ vdd-supply = <&vcc_3v3_s3>;
+ };
+
+ /* 3.0 hub on port 4 */
+ hub_3_0: hub@2 {
+ compatible = "usb5e3,620";
+ reg = <2>;
+ peer-hub = <&hub_2_0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gl3523_reset>;
+ reset-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&vcc_3v3_s3>;
+ };
+};
+
+&usbdp_phy0 {
+ mode-switch;
+ orientation-switch;
+ sbu1-dc-gpios = <&gpio4 RK_PB7 GPIO_ACTIVE_HIGH>;
+ sbu2-dc-gpios = <&gpio4 RK_PC0 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>;
+ };
+ };
+};
+
+&usbdp_phy1 {
+ rockchip,dp-lane-mux = <2 3>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-pcie-ep.dtso b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-pcie-ep.dtso
new file mode 100644
index 000000000000..672d748fcc67
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-pcie-ep.dtso
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * DT-overlay to run the PCIe3_4L Dual Mode controller in Endpoint mode
+ * in the SRNS (Separate Reference Clock No Spread) configuration.
+ *
+ * NOTE: If using a setup with two ROCK 5B:s, with one board running in
+ * RC mode and the other board running in EP mode, see also the device
+ * tree overlay: rk3588-rock-5b-pcie-srns.dtso.
+ */
+
+/dts-v1/;
+/plugin/;
+
+&pcie30phy {
+ rockchip,rx-common-refclk-mode = <0 0 0 0>;
+};
+
+&pcie3x4 {
+ status = "disabled";
+};
+
+&pcie3x4_ep {
+ vpcie3v3-supply = <&vcc3v3_pcie30>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-pcie-srns.dtso b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-pcie-srns.dtso
new file mode 100644
index 000000000000..1a0f1af65c43
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b-pcie-srns.dtso
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * DT-overlay to run the PCIe3_4L Dual Mode controller in Root Complex
+ * mode in the SRNS (Separate Reference Clock No Spread) configuration.
+ *
+ * This device tree overlay is only needed (on the RC side) when running
+ * a setup with two ROCK 5B:s, with one board running in RC mode and the
+ * other board running in EP mode.
+ */
+
+/dts-v1/;
+/plugin/;
+
+&pcie30phy {
+ rockchip,rx-common-refclk-mode = <0 0 0 0>;
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index b8e15b76a8a6..966bbc582d89 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -52,7 +52,7 @@
fan: pwm-fan {
compatible = "pwm-fan";
- cooling-levels = <0 95 145 195 255>;
+ cooling-levels = <0 120 150 180 210 240 255>;
fan-supply = <&vcc5v0_sys>;
pwms = <&pwm1 0 50000 0>;
#cooling-cells = <2>;
@@ -65,6 +65,13 @@
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: vcc3v3-pcie2x1l0-regulator {
compatible = "regulator-fixed";
enable-active-high;
@@ -279,6 +286,36 @@
};
};
+&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 {
+ map1 {
+ trip = <&package_fan0>;
+ cooling-device = <&fan THERMAL_NO_LIMIT 1>;
+ };
+
+ map2 {
+ trip = <&package_fan1>;
+ cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
+ };
+ };
+};
+
&pcie2x1l0 {
pinctrl-names = "default";
pinctrl-0 = <&pcie2_0_rst>;
@@ -383,6 +420,7 @@
bus-width = <4>;
cap-mmc-highspeed;
cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
disable-wp;
sd-uhs-sdr104;
vmmc-supply = <&vcc_3v3_s3>;
@@ -411,6 +449,20 @@
status = "okay";
};
+&sfc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&fspim2_pins>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <104000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <1>;
+ };
+};
+
&uart6 {
pinctrl-names = "default";
pinctrl-0 = <&uart6m1_xfer &uart6m1_ctsn &uart6m1_rtsn>;
@@ -742,6 +794,10 @@
};
};
+&tsadc {
+ status = "okay";
+};
+
&uart2 {
pinctrl-0 = <&uart2m0_xfer>;
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi
index aebe1fedd2d8..615094bb8ba3 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi
@@ -344,6 +344,11 @@
};
};
+&pwm0 {
+ pinctrl-0 = <&pwm0m1_pins>;
+ pinctrl-names = "default";
+};
+
&saradc {
vref-supply = <&vcc_1v8_s0>;
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts
index 9090c5c99f2a..d0021524e7f9 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts
@@ -648,6 +648,10 @@
};
};
+&tsadc {
+ status = "okay";
+};
+
&u2phy2 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
index 6b9206ce4a03..dbaa94ca69f4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
@@ -198,8 +198,7 @@
&mdio1 {
rgmii_phy: ethernet-phy@1 {
/* RTL8211F */
- compatible = "ethernet-phy-id001c.c916",
- "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-id001c.c916";
reg = <0x1>;
pinctrl-names = "default";
pinctrl-0 = <&rtl8211f_rst>;
@@ -601,6 +600,10 @@
};
};
+&tsadc {
+ status = "okay";
+};
+
&uart2 {
pinctrl-0 = <&uart2m0_xfer>;
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3588.dtsi b/arch/arm64/boot/dts/rockchip/rk3588.dtsi
index 5984016b5f96..7462cc1e1007 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi
@@ -1,413 +1,8 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
- * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ *
*/
-#include "rk3588s.dtsi"
-#include "rk3588-pinctrl.dtsi"
-
-/ {
- usb_host1_xhci: usb@fc400000 {
- compatible = "rockchip,rk3588-dwc3", "snps,dwc3";
- reg = <0x0 0xfc400000 0x0 0x400000>;
- interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru REF_CLK_USB3OTG1>, <&cru SUSPEND_CLK_USB3OTG1>,
- <&cru ACLK_USB3OTG1>;
- clock-names = "ref_clk", "suspend_clk", "bus_clk";
- dr_mode = "otg";
- phys = <&u2phy1_otg>, <&usbdp_phy1 PHY_TYPE_USB3>;
- phy-names = "usb2-phy", "usb3-phy";
- phy_type = "utmi_wide";
- power-domains = <&power RK3588_PD_USB>;
- resets = <&cru SRST_A_USB3OTG1>;
- snps,dis_enblslpm_quirk;
- snps,dis-u2-freeclk-exists-quirk;
- snps,dis-del-phy-power-chg-quirk;
- snps,dis-tx-ipgap-linecheck-quirk;
- status = "disabled";
- };
-
- pcie30_phy_grf: syscon@fd5b8000 {
- compatible = "rockchip,rk3588-pcie3-phy-grf", "syscon";
- reg = <0x0 0xfd5b8000 0x0 0x10000>;
- };
-
- pipe_phy1_grf: syscon@fd5c0000 {
- compatible = "rockchip,rk3588-pipe-phy-grf", "syscon";
- reg = <0x0 0xfd5c0000 0x0 0x100>;
- };
-
- usbdpphy1_grf: syscon@fd5cc000 {
- compatible = "rockchip,rk3588-usbdpphy-grf", "syscon";
- reg = <0x0 0xfd5cc000 0x0 0x4000>;
- };
-
- usb2phy1_grf: syscon@fd5d4000 {
- compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
- reg = <0x0 0xfd5d4000 0x0 0x4000>;
- #address-cells = <1>;
- #size-cells = <1>;
-
- u2phy1: usb2phy@4000 {
- compatible = "rockchip,rk3588-usb2phy";
- reg = <0x4000 0x10>;
- #clock-cells = <0>;
- clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
- clock-names = "phyclk";
- clock-output-names = "usb480m_phy1";
- interrupts = <GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH 0>;
- resets = <&cru SRST_OTGPHY_U3_1>, <&cru SRST_P_USB2PHY_U3_1_GRF0>;
- reset-names = "phy", "apb";
- status = "disabled";
-
- u2phy1_otg: otg-port {
- #phy-cells = <0>;
- status = "disabled";
- };
- };
- };
-
- i2s8_8ch: i2s@fddc8000 {
- compatible = "rockchip,rk3588-i2s-tdm";
- reg = <0x0 0xfddc8000 0x0 0x1000>;
- interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S8_8CH_TX>, <&cru MCLK_I2S8_8CH_TX>, <&cru HCLK_I2S8_8CH>;
- clock-names = "mclk_tx", "mclk_rx", "hclk";
- assigned-clocks = <&cru CLK_I2S8_8CH_TX_SRC>;
- assigned-clock-parents = <&cru PLL_AUPLL>;
- dmas = <&dmac2 22>;
- dma-names = "tx";
- power-domains = <&power RK3588_PD_VO0>;
- resets = <&cru SRST_M_I2S8_8CH_TX>;
- reset-names = "tx-m";
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- i2s6_8ch: i2s@fddf4000 {
- compatible = "rockchip,rk3588-i2s-tdm";
- reg = <0x0 0xfddf4000 0x0 0x1000>;
- interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S6_8CH_TX>, <&cru MCLK_I2S6_8CH_TX>, <&cru HCLK_I2S6_8CH>;
- clock-names = "mclk_tx", "mclk_rx", "hclk";
- assigned-clocks = <&cru CLK_I2S6_8CH_TX_SRC>;
- assigned-clock-parents = <&cru PLL_AUPLL>;
- dmas = <&dmac2 4>;
- dma-names = "tx";
- power-domains = <&power RK3588_PD_VO1>;
- resets = <&cru SRST_M_I2S6_8CH_TX>;
- reset-names = "tx-m";
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- i2s7_8ch: i2s@fddf8000 {
- compatible = "rockchip,rk3588-i2s-tdm";
- reg = <0x0 0xfddf8000 0x0 0x1000>;
- interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S7_8CH_RX>, <&cru MCLK_I2S7_8CH_RX>, <&cru HCLK_I2S7_8CH>;
- clock-names = "mclk_tx", "mclk_rx", "hclk";
- assigned-clocks = <&cru CLK_I2S7_8CH_RX_SRC>;
- assigned-clock-parents = <&cru PLL_AUPLL>;
- dmas = <&dmac2 21>;
- dma-names = "rx";
- power-domains = <&power RK3588_PD_VO1>;
- resets = <&cru SRST_M_I2S7_8CH_RX>;
- reset-names = "rx-m";
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- i2s10_8ch: i2s@fde00000 {
- compatible = "rockchip,rk3588-i2s-tdm";
- reg = <0x0 0xfde00000 0x0 0x1000>;
- interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S10_8CH_RX>, <&cru MCLK_I2S10_8CH_RX>, <&cru HCLK_I2S10_8CH>;
- clock-names = "mclk_tx", "mclk_rx", "hclk";
- assigned-clocks = <&cru CLK_I2S10_8CH_RX_SRC>;
- assigned-clock-parents = <&cru PLL_AUPLL>;
- dmas = <&dmac2 24>;
- dma-names = "rx";
- power-domains = <&power RK3588_PD_VO1>;
- resets = <&cru SRST_M_I2S10_8CH_RX>;
- reset-names = "rx-m";
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- pcie3x4: pcie@fe150000 {
- compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
- #address-cells = <3>;
- #size-cells = <2>;
- bus-range = <0x00 0x0f>;
- 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>;
- clock-names = "aclk_mst", "aclk_slv",
- "aclk_dbi", "pclk",
- "aux", "pipe";
- device_type = "pci";
- interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "sys", "pmc", "msg", "legacy", "err";
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0 0 0 1 &pcie3x4_intc 0>,
- <0 0 0 2 &pcie3x4_intc 1>,
- <0 0 0 3 &pcie3x4_intc 2>,
- <0 0 0 4 &pcie3x4_intc 3>;
- linux,pci-domain = <0>;
- max-link-speed = <3>;
- msi-map = <0x0000 &its1 0x0000 0x1000>;
- num-lanes = <4>;
- phys = <&pcie30phy>;
- phy-names = "pcie-phy";
- power-domains = <&power RK3588_PD_PCIE>;
- ranges = <0x01000000 0x0 0xf0100000 0x0 0xf0100000 0x0 0x00100000>,
- <0x02000000 0x0 0xf0200000 0x0 0xf0200000 0x0 0x00e00000>,
- <0x03000000 0x0 0x40000000 0x9 0x00000000 0x0 0x40000000>;
- reg = <0xa 0x40000000 0x0 0x00400000>,
- <0x0 0xfe150000 0x0 0x00010000>,
- <0x0 0xf0000000 0x0 0x00100000>;
- reg-names = "dbi", "apb", "config";
- resets = <&cru SRST_PCIE0_POWER_UP>, <&cru SRST_P_PCIE0>;
- reset-names = "pwr", "pipe";
- status = "disabled";
-
- pcie3x4_intc: legacy-interrupt-controller {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <1>;
- interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 260 IRQ_TYPE_EDGE_RISING 0>;
- };
- };
-
- pcie3x2: pcie@fe160000 {
- compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
- #address-cells = <3>;
- #size-cells = <2>;
- bus-range = <0x10 0x1f>;
- 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>;
- clock-names = "aclk_mst", "aclk_slv",
- "aclk_dbi", "pclk",
- "aux", "pipe";
- device_type = "pci";
- interrupts = <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "sys", "pmc", "msg", "legacy", "err";
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0 0 0 1 &pcie3x2_intc 0>,
- <0 0 0 2 &pcie3x2_intc 1>,
- <0 0 0 3 &pcie3x2_intc 2>,
- <0 0 0 4 &pcie3x2_intc 3>;
- linux,pci-domain = <1>;
- max-link-speed = <3>;
- msi-map = <0x1000 &its1 0x1000 0x1000>;
- num-lanes = <2>;
- phys = <&pcie30phy>;
- phy-names = "pcie-phy";
- power-domains = <&power RK3588_PD_PCIE>;
- ranges = <0x01000000 0x0 0xf1100000 0x0 0xf1100000 0x0 0x00100000>,
- <0x02000000 0x0 0xf1200000 0x0 0xf1200000 0x0 0x00e00000>,
- <0x03000000 0x0 0x40000000 0x9 0x40000000 0x0 0x40000000>;
- reg = <0xa 0x40400000 0x0 0x00400000>,
- <0x0 0xfe160000 0x0 0x00010000>,
- <0x0 0xf1000000 0x0 0x00100000>;
- reg-names = "dbi", "apb", "config";
- resets = <&cru SRST_PCIE1_POWER_UP>, <&cru SRST_P_PCIE1>;
- reset-names = "pwr", "pipe";
- status = "disabled";
-
- pcie3x2_intc: legacy-interrupt-controller {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <1>;
- interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 255 IRQ_TYPE_EDGE_RISING 0>;
- };
- };
-
- pcie2x1l0: pcie@fe170000 {
- compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
- bus-range = <0x20 0x2f>;
- clocks = <&cru ACLK_PCIE_1L0_MSTR>, <&cru ACLK_PCIE_1L0_SLV>,
- <&cru ACLK_PCIE_1L0_DBI>, <&cru PCLK_PCIE_1L0>,
- <&cru CLK_PCIE_AUX2>, <&cru CLK_PCIE1L0_PIPE>;
- clock-names = "aclk_mst", "aclk_slv",
- "aclk_dbi", "pclk",
- "aux", "pipe";
- device_type = "pci";
- interrupts = <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "sys", "pmc", "msg", "legacy", "err";
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0 0 0 1 &pcie2x1l0_intc 0>,
- <0 0 0 2 &pcie2x1l0_intc 1>,
- <0 0 0 3 &pcie2x1l0_intc 2>,
- <0 0 0 4 &pcie2x1l0_intc 3>;
- linux,pci-domain = <2>;
- max-link-speed = <2>;
- msi-map = <0x2000 &its0 0x2000 0x1000>;
- num-lanes = <1>;
- phys = <&combphy1_ps PHY_TYPE_PCIE>;
- phy-names = "pcie-phy";
- power-domains = <&power RK3588_PD_PCIE>;
- ranges = <0x01000000 0x0 0xf2100000 0x0 0xf2100000 0x0 0x00100000>,
- <0x02000000 0x0 0xf2200000 0x0 0xf2200000 0x0 0x00e00000>,
- <0x03000000 0x0 0x40000000 0x9 0x80000000 0x0 0x40000000>;
- reg = <0xa 0x40800000 0x0 0x00400000>,
- <0x0 0xfe170000 0x0 0x00010000>,
- <0x0 0xf2000000 0x0 0x00100000>;
- reg-names = "dbi", "apb", "config";
- resets = <&cru SRST_PCIE2_POWER_UP>, <&cru SRST_P_PCIE2>;
- reset-names = "pwr", "pipe";
- #address-cells = <3>;
- #size-cells = <2>;
- status = "disabled";
-
- pcie2x1l0_intc: legacy-interrupt-controller {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <1>;
- interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 240 IRQ_TYPE_EDGE_RISING 0>;
- };
- };
-
- gmac0: ethernet@fe1b0000 {
- compatible = "rockchip,rk3588-gmac", "snps,dwmac-4.20a";
- reg = <0x0 0xfe1b0000 0x0 0x10000>;
- interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "macirq", "eth_wake_irq";
- clocks = <&cru CLK_GMAC_125M>, <&cru CLK_GMAC_50M>,
- <&cru PCLK_GMAC0>, <&cru ACLK_GMAC0>,
- <&cru CLK_GMAC0_PTP_REF>;
- clock-names = "stmmaceth", "clk_mac_ref",
- "pclk_mac", "aclk_mac",
- "ptp_ref";
- power-domains = <&power RK3588_PD_GMAC>;
- resets = <&cru SRST_A_GMAC0>;
- reset-names = "stmmaceth";
- rockchip,grf = <&sys_grf>;
- rockchip,php-grf = <&php_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,wr_osr_lmt = <4>;
- snps,rd_osr_lmt = <8>;
- };
-
- gmac0_mtl_rx_setup: rx-queues-config {
- snps,rx-queues-to-use = <2>;
- queue0 {};
- queue1 {};
- };
-
- gmac0_mtl_tx_setup: tx-queues-config {
- snps,tx-queues-to-use = <2>;
- queue0 {};
- queue1 {};
- };
- };
-
- sata1: sata@fe220000 {
- compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci";
- reg = <0 0xfe220000 0 0x1000>;
- interrupts = <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru ACLK_SATA1>, <&cru CLK_PMALIVE1>,
- <&cru CLK_RXOOB1>, <&cru CLK_PIPEPHY1_REF>,
- <&cru CLK_PIPEPHY1_PIPE_ASIC_G>;
- clock-names = "sata", "pmalive", "rxoob", "ref", "asic";
- ports-implemented = <0x1>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
-
- sata-port@0 {
- reg = <0>;
- hba-port-cap = <HBA_PORT_FBSCP>;
- phys = <&combphy1_ps PHY_TYPE_SATA>;
- phy-names = "sata-phy";
- snps,rx-ts-max = <32>;
- snps,tx-ts-max = <32>;
- };
- };
-
- usbdp_phy1: phy@fed90000 {
- compatible = "rockchip,rk3588-usbdp-phy";
- reg = <0x0 0xfed90000 0x0 0x10000>;
- #phy-cells = <1>;
- clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>,
- <&cru CLK_USBDP_PHY1_IMMORTAL>,
- <&cru PCLK_USBDPPHY1>,
- <&u2phy1>;
- clock-names = "refclk", "immortal", "pclk", "utmi";
- resets = <&cru SRST_USBDP_COMBO_PHY1_INIT>,
- <&cru SRST_USBDP_COMBO_PHY1_CMN>,
- <&cru SRST_USBDP_COMBO_PHY1_LANE>,
- <&cru SRST_USBDP_COMBO_PHY1_PCS>,
- <&cru SRST_P_USBDPPHY1>;
- reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
- rockchip,u2phy-grf = <&usb2phy1_grf>;
- rockchip,usb-grf = <&usb_grf>;
- rockchip,usbdpphy-grf = <&usbdpphy1_grf>;
- rockchip,vo-grf = <&vo0_grf>;
- status = "disabled";
- };
-
- combphy1_ps: phy@fee10000 {
- compatible = "rockchip,rk3588-naneng-combphy";
- reg = <0x0 0xfee10000 0x0 0x100>;
- clocks = <&cru CLK_REF_PIPE_PHY1>, <&cru PCLK_PCIE_COMBO_PIPE_PHY1>,
- <&cru PCLK_PHP_ROOT>;
- clock-names = "ref", "apb", "pipe";
- assigned-clocks = <&cru CLK_REF_PIPE_PHY1>;
- assigned-clock-rates = <100000000>;
- #phy-cells = <1>;
- resets = <&cru SRST_REF_PIPE_PHY1>, <&cru SRST_P_PCIE2_PHY1>;
- reset-names = "phy", "apb";
- rockchip,pipe-grf = <&php_grf>;
- rockchip,pipe-phy-grf = <&pipe_phy1_grf>;
- status = "disabled";
- };
-
- pcie30phy: phy@fee80000 {
- compatible = "rockchip,rk3588-pcie3-phy";
- reg = <0x0 0xfee80000 0x0 0x20000>;
- #phy-cells = <0>;
- clocks = <&cru PCLK_PCIE_COMBO_PIPE_PHY>;
- clock-names = "pclk";
- resets = <&cru SRST_PCIE30_PHY>;
- reset-names = "phy";
- rockchip,pipe-grf = <&php_grf>;
- rockchip,phy-grf = <&pcie30_phy_grf>;
- status = "disabled";
- };
-};
+#include "rk3588-extra.dtsi"
+#include "rk3588-opp.dtsi"
diff --git a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
index 38b9dbf38a21..bce72bac4503 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi
@@ -4,4 +4,145 @@
*
*/
-#include "rk3588.dtsi"
+#include "rk3588-extra.dtsi"
+
+/ {
+ cluster0_opp_table: opp-table-cluster0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <750000 750000 950000>;
+ clock-latency-ns = <40000>;
+ opp-suspend;
+ };
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <887500 887500 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1704000000 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <937500 937500 950000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ cluster1_opp_table: opp-table-cluster1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <750000 750000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <787500 787500 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <875000 875000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-microvolt = <950000 950000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ cluster2_opp_table: opp-table-cluster2 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <750000 750000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <787500 787500 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <875000 875000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-microvolt = <950000 950000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ gpu_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <750000 750000 850000>;
+ };
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <750000 750000 850000>;
+ };
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <750000 750000 850000>;
+ };
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <750000 750000 850000>;
+ };
+ opp-700000000 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <750000 750000 850000>;
+ };
+ opp-850000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <787500 787500 850000>;
+ };
+ };
+};
+
+&cpu_b0 {
+ operating-points-v2 = <&cluster1_opp_table>;
+};
+
+&cpu_b1 {
+ operating-points-v2 = <&cluster1_opp_table>;
+};
+
+&cpu_b2 {
+ operating-points-v2 = <&cluster2_opp_table>;
+};
+
+&cpu_b3 {
+ operating-points-v2 = <&cluster2_opp_table>;
+};
+
+&cpu_l0 {
+ operating-points-v2 = <&cluster0_opp_table>;
+};
+
+&cpu_l1 {
+ operating-points-v2 = <&cluster0_opp_table>;
+};
+
+&cpu_l2 {
+ operating-points-v2 = <&cluster0_opp_table>;
+};
+
+&cpu_l3 {
+ operating-points-v2 = <&cluster0_opp_table>;
+};
+
+&gpu {
+ operating-points-v2 = <&gpu_opp_table>;
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
index 3b2ec1d0c542..074c316a9a69 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
@@ -288,9 +288,9 @@
pinctrl-0 = <&i2c7m0_xfer>;
status = "okay";
- es8316: audio-codec@11 {
+ es8316: audio-codec@10 {
compatible = "everest,es8316";
- reg = <0x11>;
+ reg = <0x10>;
assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
assigned-clock-rates = <12288000>;
clocks = <&cru I2S0_8CH_MCLKOUT>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
index 8e2a07612d17..03ed48246d36 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
@@ -366,6 +366,7 @@
bus-width = <4>;
cap-mmc-highspeed;
cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
disable-wp;
max-frequency = <150000000>;
no-sdio;
@@ -376,6 +377,19 @@
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>;
@@ -393,6 +407,7 @@
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>;
@@ -697,6 +712,10 @@
};
};
+&tsadc {
+ status = "okay";
+};
+
&u2phy0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 6ac5ac8b48ab..c7fecf8fe7ec 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -1,2670 +1,8 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
- * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ *
*/
-#include <dt-bindings/clock/rockchip,rk3588-cru.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/power/rk3588-power.h>
-#include <dt-bindings/reset/rockchip,rk3588-cru.h>
-#include <dt-bindings/phy/phy.h>
-#include <dt-bindings/ata/ahci.h>
-
-/ {
- compatible = "rockchip,rk3588";
-
- interrupt-parent = <&gic>;
- #address-cells = <2>;
- #size-cells = <2>;
-
- aliases {
- gpio0 = &gpio0;
- gpio1 = &gpio1;
- gpio2 = &gpio2;
- gpio3 = &gpio3;
- gpio4 = &gpio4;
- i2c0 = &i2c0;
- i2c1 = &i2c1;
- i2c2 = &i2c2;
- i2c3 = &i2c3;
- i2c4 = &i2c4;
- i2c5 = &i2c5;
- i2c6 = &i2c6;
- i2c7 = &i2c7;
- i2c8 = &i2c8;
- serial0 = &uart0;
- serial1 = &uart1;
- serial2 = &uart2;
- serial3 = &uart3;
- serial4 = &uart4;
- serial5 = &uart5;
- serial6 = &uart6;
- serial7 = &uart7;
- serial8 = &uart8;
- serial9 = &uart9;
- spi0 = &spi0;
- spi1 = &spi1;
- spi2 = &spi2;
- spi3 = &spi3;
- spi4 = &spi4;
- };
-
- 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>;
- };
- };
- cluster2 {
- core0 {
- cpu = <&cpu_b2>;
- };
- core1 {
- cpu = <&cpu_b3>;
- };
- };
- };
-
- cpu_l0: cpu@0 {
- device_type = "cpu";
- compatible = "arm,cortex-a55";
- reg = <0x0>;
- enable-method = "psci";
- capacity-dmips-mhz = <530>;
- clocks = <&scmi_clk SCMI_CLK_CPUL>;
- assigned-clocks = <&scmi_clk SCMI_CLK_CPUL>;
- assigned-clock-rates = <816000000>;
- cpu-idle-states = <&CPU_SLEEP>;
- i-cache-size = <32768>;
- i-cache-line-size = <64>;
- i-cache-sets = <128>;
- d-cache-size = <32768>;
- d-cache-line-size = <64>;
- d-cache-sets = <128>;
- next-level-cache = <&l2_cache_l0>;
- dynamic-power-coefficient = <228>;
- #cooling-cells = <2>;
- };
-
- cpu_l1: cpu@100 {
- device_type = "cpu";
- compatible = "arm,cortex-a55";
- reg = <0x100>;
- enable-method = "psci";
- capacity-dmips-mhz = <530>;
- clocks = <&scmi_clk SCMI_CLK_CPUL>;
- cpu-idle-states = <&CPU_SLEEP>;
- i-cache-size = <32768>;
- i-cache-line-size = <64>;
- i-cache-sets = <128>;
- d-cache-size = <32768>;
- d-cache-line-size = <64>;
- d-cache-sets = <128>;
- next-level-cache = <&l2_cache_l1>;
- dynamic-power-coefficient = <228>;
- #cooling-cells = <2>;
- };
-
- cpu_l2: cpu@200 {
- device_type = "cpu";
- compatible = "arm,cortex-a55";
- reg = <0x200>;
- enable-method = "psci";
- capacity-dmips-mhz = <530>;
- clocks = <&scmi_clk SCMI_CLK_CPUL>;
- cpu-idle-states = <&CPU_SLEEP>;
- i-cache-size = <32768>;
- i-cache-line-size = <64>;
- i-cache-sets = <128>;
- d-cache-size = <32768>;
- d-cache-line-size = <64>;
- d-cache-sets = <128>;
- next-level-cache = <&l2_cache_l2>;
- dynamic-power-coefficient = <228>;
- #cooling-cells = <2>;
- };
-
- cpu_l3: cpu@300 {
- device_type = "cpu";
- compatible = "arm,cortex-a55";
- reg = <0x300>;
- enable-method = "psci";
- capacity-dmips-mhz = <530>;
- clocks = <&scmi_clk SCMI_CLK_CPUL>;
- cpu-idle-states = <&CPU_SLEEP>;
- i-cache-size = <32768>;
- i-cache-line-size = <64>;
- i-cache-sets = <128>;
- d-cache-size = <32768>;
- d-cache-line-size = <64>;
- d-cache-sets = <128>;
- next-level-cache = <&l2_cache_l3>;
- dynamic-power-coefficient = <228>;
- #cooling-cells = <2>;
- };
-
- cpu_b0: cpu@400 {
- device_type = "cpu";
- compatible = "arm,cortex-a76";
- reg = <0x400>;
- enable-method = "psci";
- capacity-dmips-mhz = <1024>;
- clocks = <&scmi_clk SCMI_CLK_CPUB01>;
- assigned-clocks = <&scmi_clk SCMI_CLK_CPUB01>;
- assigned-clock-rates = <816000000>;
- cpu-idle-states = <&CPU_SLEEP>;
- i-cache-size = <65536>;
- i-cache-line-size = <64>;
- i-cache-sets = <256>;
- d-cache-size = <65536>;
- d-cache-line-size = <64>;
- d-cache-sets = <256>;
- next-level-cache = <&l2_cache_b0>;
- dynamic-power-coefficient = <416>;
- #cooling-cells = <2>;
- };
-
- cpu_b1: cpu@500 {
- device_type = "cpu";
- compatible = "arm,cortex-a76";
- reg = <0x500>;
- enable-method = "psci";
- capacity-dmips-mhz = <1024>;
- clocks = <&scmi_clk SCMI_CLK_CPUB01>;
- cpu-idle-states = <&CPU_SLEEP>;
- i-cache-size = <65536>;
- i-cache-line-size = <64>;
- i-cache-sets = <256>;
- d-cache-size = <65536>;
- d-cache-line-size = <64>;
- d-cache-sets = <256>;
- next-level-cache = <&l2_cache_b1>;
- dynamic-power-coefficient = <416>;
- #cooling-cells = <2>;
- };
-
- cpu_b2: cpu@600 {
- device_type = "cpu";
- compatible = "arm,cortex-a76";
- reg = <0x600>;
- enable-method = "psci";
- capacity-dmips-mhz = <1024>;
- clocks = <&scmi_clk SCMI_CLK_CPUB23>;
- assigned-clocks = <&scmi_clk SCMI_CLK_CPUB23>;
- assigned-clock-rates = <816000000>;
- cpu-idle-states = <&CPU_SLEEP>;
- i-cache-size = <65536>;
- i-cache-line-size = <64>;
- i-cache-sets = <256>;
- d-cache-size = <65536>;
- d-cache-line-size = <64>;
- d-cache-sets = <256>;
- next-level-cache = <&l2_cache_b2>;
- dynamic-power-coefficient = <416>;
- #cooling-cells = <2>;
- };
-
- cpu_b3: cpu@700 {
- device_type = "cpu";
- compatible = "arm,cortex-a76";
- reg = <0x700>;
- enable-method = "psci";
- capacity-dmips-mhz = <1024>;
- clocks = <&scmi_clk SCMI_CLK_CPUB23>;
- cpu-idle-states = <&CPU_SLEEP>;
- i-cache-size = <65536>;
- i-cache-line-size = <64>;
- i-cache-sets = <256>;
- d-cache-size = <65536>;
- d-cache-line-size = <64>;
- d-cache-sets = <256>;
- next-level-cache = <&l2_cache_b3>;
- dynamic-power-coefficient = <416>;
- #cooling-cells = <2>;
- };
-
- idle-states {
- entry-method = "psci";
- CPU_SLEEP: cpu-sleep {
- compatible = "arm,idle-state";
- local-timer-stop;
- arm,psci-suspend-param = <0x0010000>;
- entry-latency-us = <100>;
- exit-latency-us = <120>;
- min-residency-us = <1000>;
- };
- };
-
- l2_cache_l0: l2-cache-l0 {
- compatible = "cache";
- cache-size = <131072>;
- cache-line-size = <64>;
- cache-sets = <512>;
- cache-level = <2>;
- cache-unified;
- next-level-cache = <&l3_cache>;
- };
-
- l2_cache_l1: l2-cache-l1 {
- compatible = "cache";
- cache-size = <131072>;
- cache-line-size = <64>;
- cache-sets = <512>;
- cache-level = <2>;
- cache-unified;
- next-level-cache = <&l3_cache>;
- };
-
- l2_cache_l2: l2-cache-l2 {
- compatible = "cache";
- cache-size = <131072>;
- cache-line-size = <64>;
- cache-sets = <512>;
- cache-level = <2>;
- cache-unified;
- next-level-cache = <&l3_cache>;
- };
-
- l2_cache_l3: l2-cache-l3 {
- compatible = "cache";
- cache-size = <131072>;
- cache-line-size = <64>;
- cache-sets = <512>;
- cache-level = <2>;
- cache-unified;
- next-level-cache = <&l3_cache>;
- };
-
- l2_cache_b0: l2-cache-b0 {
- compatible = "cache";
- cache-size = <524288>;
- cache-line-size = <64>;
- cache-sets = <1024>;
- cache-level = <2>;
- cache-unified;
- next-level-cache = <&l3_cache>;
- };
-
- l2_cache_b1: l2-cache-b1 {
- compatible = "cache";
- cache-size = <524288>;
- cache-line-size = <64>;
- cache-sets = <1024>;
- cache-level = <2>;
- cache-unified;
- next-level-cache = <&l3_cache>;
- };
-
- l2_cache_b2: l2-cache-b2 {
- compatible = "cache";
- cache-size = <524288>;
- cache-line-size = <64>;
- cache-sets = <1024>;
- cache-level = <2>;
- cache-unified;
- next-level-cache = <&l3_cache>;
- };
-
- l2_cache_b3: l2-cache-b3 {
- compatible = "cache";
- cache-size = <524288>;
- cache-line-size = <64>;
- cache-sets = <1024>;
- cache-level = <2>;
- 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;
- };
- };
-
- display_subsystem: display-subsystem {
- compatible = "rockchip,display-subsystem";
- ports = <&vop_out>;
- };
-
- firmware {
- optee: optee {
- compatible = "linaro,optee-tz";
- method = "smc";
- };
-
- 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>;
- };
-
- scmi_reset: protocol@16 {
- reg = <0x16>;
- #reset-cells = <1>;
- };
- };
- };
-
- pmu-a55 {
- compatible = "arm,cortex-a55-pmu";
- interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition0>;
- };
-
- pmu-a76 {
- compatible = "arm,cortex-a76-pmu";
- interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition1>;
- };
-
- psci {
- compatible = "arm,psci-1.0";
- method = "smc";
- };
-
- spll: clock-0 {
- compatible = "fixed-clock";
- clock-frequency = <702000000>;
- clock-output-names = "spll";
- #clock-cells = <0>;
- };
-
- timer {
- compatible = "arm,armv8-timer";
- interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_PPI 12 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "sec-phys", "phys", "virt", "hyp-phys", "hyp-virt";
- };
-
- xin24m: clock-1 {
- compatible = "fixed-clock";
- clock-frequency = <24000000>;
- clock-output-names = "xin24m";
- #clock-cells = <0>;
- };
-
- xin32k: clock-2 {
- compatible = "fixed-clock";
- clock-frequency = <32768>;
- clock-output-names = "xin32k";
- #clock-cells = <0>;
- };
-
- pmu_sram: sram@10f000 {
- compatible = "mmio-sram";
- reg = <0x0 0x0010f000 0x0 0x100>;
- ranges = <0 0x0 0x0010f000 0x100>;
- #address-cells = <1>;
- #size-cells = <1>;
-
- scmi_shmem: sram@0 {
- compatible = "arm,scmi-shmem";
- reg = <0x0 0x100>;
- };
- };
-
- gpu: gpu@fb000000 {
- compatible = "rockchip,rk3588-mali", "arm,mali-valhall-csf";
- reg = <0x0 0xfb000000 0x0 0x200000>;
- #cooling-cells = <2>;
- assigned-clocks = <&scmi_clk SCMI_CLK_GPU>;
- assigned-clock-rates = <200000000>;
- clocks = <&cru CLK_GPU>, <&cru CLK_GPU_COREGROUP>,
- <&cru CLK_GPU_STACKS>;
- clock-names = "core", "coregroup", "stacks";
- dynamic-power-coefficient = <2982>;
- interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "job", "mmu", "gpu";
- operating-points-v2 = <&gpu_opp_table>;
- power-domains = <&power RK3588_PD_GPU>;
- status = "disabled";
-
- gpu_opp_table: opp-table {
- compatible = "operating-points-v2";
-
- opp-300000000 {
- opp-hz = /bits/ 64 <300000000>;
- opp-microvolt = <675000 675000 850000>;
- };
- opp-400000000 {
- opp-hz = /bits/ 64 <400000000>;
- opp-microvolt = <675000 675000 850000>;
- };
- opp-500000000 {
- opp-hz = /bits/ 64 <500000000>;
- opp-microvolt = <675000 675000 850000>;
- };
- opp-600000000 {
- opp-hz = /bits/ 64 <600000000>;
- opp-microvolt = <675000 675000 850000>;
- };
- opp-700000000 {
- opp-hz = /bits/ 64 <700000000>;
- opp-microvolt = <700000 700000 850000>;
- };
- opp-800000000 {
- opp-hz = /bits/ 64 <800000000>;
- opp-microvolt = <750000 750000 850000>;
- };
- opp-900000000 {
- opp-hz = /bits/ 64 <900000000>;
- opp-microvolt = <800000 800000 850000>;
- };
- opp-1000000000 {
- opp-hz = /bits/ 64 <1000000000>;
- opp-microvolt = <850000 850000 850000>;
- };
- };
- };
-
- usb_host0_xhci: usb@fc000000 {
- compatible = "rockchip,rk3588-dwc3", "snps,dwc3";
- reg = <0x0 0xfc000000 0x0 0x400000>;
- interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru REF_CLK_USB3OTG0>, <&cru SUSPEND_CLK_USB3OTG0>,
- <&cru ACLK_USB3OTG0>;
- clock-names = "ref_clk", "suspend_clk", "bus_clk";
- dr_mode = "otg";
- phys = <&u2phy0_otg>, <&usbdp_phy0 PHY_TYPE_USB3>;
- phy-names = "usb2-phy", "usb3-phy";
- phy_type = "utmi_wide";
- power-domains = <&power RK3588_PD_USB>;
- resets = <&cru SRST_A_USB3OTG0>;
- snps,dis_enblslpm_quirk;
- snps,dis-u1-entry-quirk;
- snps,dis-u2-entry-quirk;
- snps,dis-u2-freeclk-exists-quirk;
- snps,dis-del-phy-power-chg-quirk;
- snps,dis-tx-ipgap-linecheck-quirk;
- status = "disabled";
- };
-
- usb_host0_ehci: usb@fc800000 {
- compatible = "rockchip,rk3588-ehci", "generic-ehci";
- reg = <0x0 0xfc800000 0x0 0x40000>;
- interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST_ARB0>, <&cru ACLK_USB>, <&u2phy2>;
- phys = <&u2phy2_host>;
- phy-names = "usb";
- power-domains = <&power RK3588_PD_USB>;
- status = "disabled";
- };
-
- usb_host0_ohci: usb@fc840000 {
- compatible = "rockchip,rk3588-ohci", "generic-ohci";
- reg = <0x0 0xfc840000 0x0 0x40000>;
- interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST_ARB0>, <&cru ACLK_USB>, <&u2phy2>;
- phys = <&u2phy2_host>;
- phy-names = "usb";
- power-domains = <&power RK3588_PD_USB>;
- status = "disabled";
- };
-
- usb_host1_ehci: usb@fc880000 {
- compatible = "rockchip,rk3588-ehci", "generic-ehci";
- reg = <0x0 0xfc880000 0x0 0x40000>;
- interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST_ARB1>, <&cru ACLK_USB>, <&u2phy3>;
- phys = <&u2phy3_host>;
- phy-names = "usb";
- power-domains = <&power RK3588_PD_USB>;
- status = "disabled";
- };
-
- usb_host1_ohci: usb@fc8c0000 {
- compatible = "rockchip,rk3588-ohci", "generic-ohci";
- reg = <0x0 0xfc8c0000 0x0 0x40000>;
- interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST_ARB1>, <&cru ACLK_USB>, <&u2phy3>;
- phys = <&u2phy3_host>;
- phy-names = "usb";
- power-domains = <&power RK3588_PD_USB>;
- status = "disabled";
- };
-
- usb_host2_xhci: usb@fcd00000 {
- compatible = "rockchip,rk3588-dwc3", "snps,dwc3";
- reg = <0x0 0xfcd00000 0x0 0x400000>;
- interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru REF_CLK_USB3OTG2>, <&cru SUSPEND_CLK_USB3OTG2>,
- <&cru ACLK_USB3OTG2>, <&cru CLK_UTMI_OTG2>,
- <&cru CLK_PIPEPHY2_PIPE_U3_G>;
- clock-names = "ref_clk", "suspend_clk", "bus_clk", "utmi", "pipe";
- dr_mode = "host";
- phys = <&combphy2_psu PHY_TYPE_USB3>;
- phy-names = "usb3-phy";
- phy_type = "utmi_wide";
- resets = <&cru SRST_A_USB3OTG2>;
- snps,dis_enblslpm_quirk;
- snps,dis-u2-freeclk-exists-quirk;
- snps,dis-del-phy-power-chg-quirk;
- snps,dis-tx-ipgap-linecheck-quirk;
- snps,dis_rxdet_inp3_quirk;
- status = "disabled";
- };
-
- mmu600_pcie: iommu@fc900000 {
- compatible = "arm,smmu-v3";
- reg = <0x0 0xfc900000 0x0 0x200000>;
- interrupts = <GIC_SPI 369 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 367 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- mmu600_php: iommu@fcb00000 {
- compatible = "arm,smmu-v3";
- reg = <0x0 0xfcb00000 0x0 0x200000>;
- interrupts = <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- pmu1grf: syscon@fd58a000 {
- compatible = "rockchip,rk3588-pmugrf", "syscon", "simple-mfd";
- reg = <0x0 0xfd58a000 0x0 0x10000>;
- };
-
- sys_grf: syscon@fd58c000 {
- compatible = "rockchip,rk3588-sys-grf", "syscon";
- reg = <0x0 0xfd58c000 0x0 0x1000>;
- };
-
- vop_grf: syscon@fd5a4000 {
- compatible = "rockchip,rk3588-vop-grf", "syscon";
- reg = <0x0 0xfd5a4000 0x0 0x2000>;
- };
-
- vo0_grf: syscon@fd5a6000 {
- compatible = "rockchip,rk3588-vo-grf", "syscon";
- reg = <0x0 0xfd5a6000 0x0 0x2000>;
- clocks = <&cru PCLK_VO0GRF>;
- };
-
- vo1_grf: syscon@fd5a8000 {
- compatible = "rockchip,rk3588-vo-grf", "syscon";
- reg = <0x0 0xfd5a8000 0x0 0x100>;
- clocks = <&cru PCLK_VO1GRF>;
- };
-
- usb_grf: syscon@fd5ac000 {
- compatible = "rockchip,rk3588-usb-grf", "syscon";
- reg = <0x0 0xfd5ac000 0x0 0x4000>;
- };
-
- php_grf: syscon@fd5b0000 {
- compatible = "rockchip,rk3588-php-grf", "syscon";
- reg = <0x0 0xfd5b0000 0x0 0x1000>;
- };
-
- pipe_phy0_grf: syscon@fd5bc000 {
- compatible = "rockchip,rk3588-pipe-phy-grf", "syscon";
- reg = <0x0 0xfd5bc000 0x0 0x100>;
- };
-
- pipe_phy2_grf: syscon@fd5c4000 {
- compatible = "rockchip,rk3588-pipe-phy-grf", "syscon";
- reg = <0x0 0xfd5c4000 0x0 0x100>;
- };
-
- usbdpphy0_grf: syscon@fd5c8000 {
- compatible = "rockchip,rk3588-usbdpphy-grf", "syscon";
- reg = <0x0 0xfd5c8000 0x0 0x4000>;
- };
-
- usb2phy0_grf: syscon@fd5d0000 {
- compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
- reg = <0x0 0xfd5d0000 0x0 0x4000>;
- #address-cells = <1>;
- #size-cells = <1>;
-
- u2phy0: usb2phy@0 {
- compatible = "rockchip,rk3588-usb2phy";
- reg = <0x0 0x10>;
- #clock-cells = <0>;
- clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
- clock-names = "phyclk";
- clock-output-names = "usb480m_phy0";
- interrupts = <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH 0>;
- resets = <&cru SRST_OTGPHY_U3_0>, <&cru SRST_P_USB2PHY_U3_0_GRF0>;
- reset-names = "phy", "apb";
- status = "disabled";
-
- u2phy0_otg: otg-port {
- #phy-cells = <0>;
- status = "disabled";
- };
- };
- };
-
- usb2phy2_grf: syscon@fd5d8000 {
- compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
- reg = <0x0 0xfd5d8000 0x0 0x4000>;
- #address-cells = <1>;
- #size-cells = <1>;
-
- u2phy2: usb2phy@8000 {
- compatible = "rockchip,rk3588-usb2phy";
- reg = <0x8000 0x10>;
- #clock-cells = <0>;
- clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
- clock-names = "phyclk";
- clock-output-names = "usb480m_phy2";
- interrupts = <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH 0>;
- resets = <&cru SRST_OTGPHY_U2_0>, <&cru SRST_P_USB2PHY_U2_0_GRF0>;
- reset-names = "phy", "apb";
- status = "disabled";
-
- u2phy2_host: host-port {
- #phy-cells = <0>;
- status = "disabled";
- };
- };
- };
-
- usb2phy3_grf: syscon@fd5dc000 {
- compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd";
- reg = <0x0 0xfd5dc000 0x0 0x4000>;
- #address-cells = <1>;
- #size-cells = <1>;
-
- u2phy3: usb2phy@c000 {
- compatible = "rockchip,rk3588-usb2phy";
- reg = <0xc000 0x10>;
- #clock-cells = <0>;
- clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
- clock-names = "phyclk";
- clock-output-names = "usb480m_phy3";
- interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH 0>;
- resets = <&cru SRST_OTGPHY_U2_1>, <&cru SRST_P_USB2PHY_U2_1_GRF0>;
- reset-names = "phy", "apb";
- status = "disabled";
-
- u2phy3_host: host-port {
- #phy-cells = <0>;
- status = "disabled";
- };
- };
- };
-
- hdptxphy0_grf: syscon@fd5e0000 {
- compatible = "rockchip,rk3588-hdptxphy-grf", "syscon";
- reg = <0x0 0xfd5e0000 0x0 0x100>;
- };
-
- ioc: syscon@fd5f0000 {
- compatible = "rockchip,rk3588-ioc", "syscon";
- reg = <0x0 0xfd5f0000 0x0 0x10000>;
- };
-
- system_sram1: sram@fd600000 {
- compatible = "mmio-sram";
- reg = <0x0 0xfd600000 0x0 0x100000>;
- ranges = <0x0 0x0 0xfd600000 0x100000>;
- #address-cells = <1>;
- #size-cells = <1>;
- };
-
- cru: clock-controller@fd7c0000 {
- compatible = "rockchip,rk3588-cru";
- reg = <0x0 0xfd7c0000 0x0 0x5c000>;
- assigned-clocks =
- <&cru PLL_PPLL>, <&cru PLL_AUPLL>,
- <&cru PLL_NPLL>, <&cru PLL_GPLL>,
- <&cru ACLK_CENTER_ROOT>,
- <&cru HCLK_CENTER_ROOT>, <&cru ACLK_CENTER_LOW_ROOT>,
- <&cru ACLK_TOP_ROOT>, <&cru PCLK_TOP_ROOT>,
- <&cru ACLK_LOW_TOP_ROOT>, <&cru PCLK_PMU0_ROOT>,
- <&cru HCLK_PMU_CM0_ROOT>, <&cru ACLK_VOP>,
- <&cru ACLK_BUS_ROOT>, <&cru CLK_150M_SRC>,
- <&cru CLK_GPU>;
- assigned-clock-rates =
- <1100000000>, <786432000>,
- <850000000>, <1188000000>,
- <702000000>,
- <400000000>, <500000000>,
- <800000000>, <100000000>,
- <400000000>, <100000000>,
- <200000000>, <500000000>,
- <375000000>, <150000000>,
- <200000000>;
- rockchip,grf = <&php_grf>;
- #clock-cells = <1>;
- #reset-cells = <1>;
- };
-
- i2c0: i2c@fd880000 {
- compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
- reg = <0x0 0xfd880000 0x0 0x1000>;
- interrupts = <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru CLK_I2C0>, <&cru PCLK_I2C0>;
- clock-names = "i2c", "pclk";
- pinctrl-0 = <&i2c0m0_xfer>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- uart0: serial@fd890000 {
- compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
- reg = <0x0 0xfd890000 0x0 0x100>;
- interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
- clock-names = "baudclk", "apb_pclk";
- dmas = <&dmac0 6>, <&dmac0 7>;
- dma-names = "tx", "rx";
- pinctrl-0 = <&uart0m1_xfer>;
- pinctrl-names = "default";
- reg-shift = <2>;
- reg-io-width = <4>;
- status = "disabled";
- };
-
- pwm0: pwm@fd8b0000 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfd8b0000 0x0 0x10>;
- clocks = <&cru CLK_PMU1PWM>, <&cru PCLK_PMU1PWM>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm0m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm1: pwm@fd8b0010 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfd8b0010 0x0 0x10>;
- clocks = <&cru CLK_PMU1PWM>, <&cru PCLK_PMU1PWM>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm1m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm2: pwm@fd8b0020 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfd8b0020 0x0 0x10>;
- clocks = <&cru CLK_PMU1PWM>, <&cru PCLK_PMU1PWM>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm2m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm3: pwm@fd8b0030 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfd8b0030 0x0 0x10>;
- clocks = <&cru CLK_PMU1PWM>, <&cru PCLK_PMU1PWM>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm3m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pmu: power-management@fd8d8000 {
- compatible = "rockchip,rk3588-pmu", "syscon", "simple-mfd";
- reg = <0x0 0xfd8d8000 0x0 0x400>;
-
- power: power-controller {
- compatible = "rockchip,rk3588-power-controller";
- #address-cells = <1>;
- #power-domain-cells = <1>;
- #size-cells = <0>;
- status = "okay";
-
- /* These power domains are grouped by VD_NPU */
- power-domain@RK3588_PD_NPU {
- reg = <RK3588_PD_NPU>;
- #power-domain-cells = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- power-domain@RK3588_PD_NPUTOP {
- reg = <RK3588_PD_NPUTOP>;
- clocks = <&cru HCLK_NPU_ROOT>,
- <&cru PCLK_NPU_ROOT>,
- <&cru CLK_NPU_DSU0>,
- <&cru HCLK_NPU_CM0_ROOT>;
- pm_qos = <&qos_npu0_mwr>,
- <&qos_npu0_mro>,
- <&qos_mcu_npu>;
- #power-domain-cells = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- power-domain@RK3588_PD_NPU1 {
- reg = <RK3588_PD_NPU1>;
- clocks = <&cru HCLK_NPU_ROOT>,
- <&cru PCLK_NPU_ROOT>,
- <&cru CLK_NPU_DSU0>;
- pm_qos = <&qos_npu1>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_NPU2 {
- reg = <RK3588_PD_NPU2>;
- clocks = <&cru HCLK_NPU_ROOT>,
- <&cru PCLK_NPU_ROOT>,
- <&cru CLK_NPU_DSU0>;
- pm_qos = <&qos_npu2>;
- #power-domain-cells = <0>;
- };
- };
- };
- /* These power domains are grouped by VD_GPU */
- power-domain@RK3588_PD_GPU {
- reg = <RK3588_PD_GPU>;
- clocks = <&cru CLK_GPU>,
- <&cru CLK_GPU_COREGROUP>,
- <&cru CLK_GPU_STACKS>;
- pm_qos = <&qos_gpu_m0>,
- <&qos_gpu_m1>,
- <&qos_gpu_m2>,
- <&qos_gpu_m3>;
- #power-domain-cells = <0>;
- };
- /* These power domains are grouped by VD_VCODEC */
- power-domain@RK3588_PD_VCODEC {
- reg = <RK3588_PD_VCODEC>;
- #address-cells = <1>;
- #size-cells = <0>;
- #power-domain-cells = <0>;
-
- power-domain@RK3588_PD_RKVDEC0 {
- reg = <RK3588_PD_RKVDEC0>;
- clocks = <&cru HCLK_RKVDEC0>,
- <&cru HCLK_VDPU_ROOT>,
- <&cru ACLK_VDPU_ROOT>,
- <&cru ACLK_RKVDEC0>,
- <&cru ACLK_RKVDEC_CCU>;
- pm_qos = <&qos_rkvdec0>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_RKVDEC1 {
- reg = <RK3588_PD_RKVDEC1>;
- clocks = <&cru HCLK_RKVDEC1>,
- <&cru HCLK_VDPU_ROOT>,
- <&cru ACLK_VDPU_ROOT>,
- <&cru ACLK_RKVDEC1>;
- pm_qos = <&qos_rkvdec1>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_VENC0 {
- reg = <RK3588_PD_VENC0>;
- clocks = <&cru HCLK_RKVENC0>,
- <&cru ACLK_RKVENC0>;
- pm_qos = <&qos_rkvenc0_m0ro>,
- <&qos_rkvenc0_m1ro>,
- <&qos_rkvenc0_m2wo>;
- #address-cells = <1>;
- #size-cells = <0>;
- #power-domain-cells = <0>;
-
- power-domain@RK3588_PD_VENC1 {
- reg = <RK3588_PD_VENC1>;
- clocks = <&cru HCLK_RKVENC1>,
- <&cru HCLK_RKVENC0>,
- <&cru ACLK_RKVENC0>,
- <&cru ACLK_RKVENC1>;
- pm_qos = <&qos_rkvenc1_m0ro>,
- <&qos_rkvenc1_m1ro>,
- <&qos_rkvenc1_m2wo>;
- #power-domain-cells = <0>;
- };
- };
- };
- /* These power domains are grouped by VD_LOGIC */
- power-domain@RK3588_PD_VDPU {
- reg = <RK3588_PD_VDPU>;
- clocks = <&cru HCLK_VDPU_ROOT>,
- <&cru ACLK_VDPU_LOW_ROOT>,
- <&cru ACLK_VDPU_ROOT>,
- <&cru ACLK_JPEG_DECODER_ROOT>,
- <&cru ACLK_IEP2P0>,
- <&cru HCLK_IEP2P0>,
- <&cru ACLK_JPEG_ENCODER0>,
- <&cru HCLK_JPEG_ENCODER0>,
- <&cru ACLK_JPEG_ENCODER1>,
- <&cru HCLK_JPEG_ENCODER1>,
- <&cru ACLK_JPEG_ENCODER2>,
- <&cru HCLK_JPEG_ENCODER2>,
- <&cru ACLK_JPEG_ENCODER3>,
- <&cru HCLK_JPEG_ENCODER3>,
- <&cru ACLK_JPEG_DECODER>,
- <&cru HCLK_JPEG_DECODER>,
- <&cru ACLK_RGA2>,
- <&cru HCLK_RGA2>;
- pm_qos = <&qos_iep>,
- <&qos_jpeg_dec>,
- <&qos_jpeg_enc0>,
- <&qos_jpeg_enc1>,
- <&qos_jpeg_enc2>,
- <&qos_jpeg_enc3>,
- <&qos_rga2_mro>,
- <&qos_rga2_mwo>;
- #address-cells = <1>;
- #size-cells = <0>;
- #power-domain-cells = <0>;
-
-
- power-domain@RK3588_PD_AV1 {
- reg = <RK3588_PD_AV1>;
- clocks = <&cru PCLK_AV1>,
- <&cru ACLK_AV1>,
- <&cru HCLK_VDPU_ROOT>;
- pm_qos = <&qos_av1>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_RKVDEC0 {
- reg = <RK3588_PD_RKVDEC0>;
- clocks = <&cru HCLK_RKVDEC0>,
- <&cru HCLK_VDPU_ROOT>,
- <&cru ACLK_VDPU_ROOT>,
- <&cru ACLK_RKVDEC0>;
- pm_qos = <&qos_rkvdec0>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_RKVDEC1 {
- reg = <RK3588_PD_RKVDEC1>;
- clocks = <&cru HCLK_RKVDEC1>,
- <&cru HCLK_VDPU_ROOT>,
- <&cru ACLK_VDPU_ROOT>;
- pm_qos = <&qos_rkvdec1>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_RGA30 {
- reg = <RK3588_PD_RGA30>;
- clocks = <&cru ACLK_RGA3_0>,
- <&cru HCLK_RGA3_0>;
- pm_qos = <&qos_rga3_0>;
- #power-domain-cells = <0>;
- };
- };
- power-domain@RK3588_PD_VOP {
- reg = <RK3588_PD_VOP>;
- clocks = <&cru PCLK_VOP_ROOT>,
- <&cru HCLK_VOP_ROOT>,
- <&cru ACLK_VOP>;
- pm_qos = <&qos_vop_m0>,
- <&qos_vop_m1>;
- #address-cells = <1>;
- #size-cells = <0>;
- #power-domain-cells = <0>;
-
- power-domain@RK3588_PD_VO0 {
- reg = <RK3588_PD_VO0>;
- clocks = <&cru PCLK_VO0_ROOT>,
- <&cru PCLK_VO0_S_ROOT>,
- <&cru HCLK_VO0_S_ROOT>,
- <&cru ACLK_VO0_ROOT>,
- <&cru HCLK_HDCP0>,
- <&cru ACLK_HDCP0>,
- <&cru HCLK_VOP_ROOT>;
- pm_qos = <&qos_hdcp0>;
- #power-domain-cells = <0>;
- };
- };
- power-domain@RK3588_PD_VO1 {
- reg = <RK3588_PD_VO1>;
- clocks = <&cru PCLK_VO1_ROOT>,
- <&cru PCLK_VO1_S_ROOT>,
- <&cru HCLK_VO1_S_ROOT>,
- <&cru HCLK_HDCP1>,
- <&cru ACLK_HDCP1>,
- <&cru ACLK_HDMIRX_ROOT>,
- <&cru HCLK_VO1USB_TOP_ROOT>;
- pm_qos = <&qos_hdcp1>,
- <&qos_hdmirx>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_VI {
- reg = <RK3588_PD_VI>;
- clocks = <&cru HCLK_VI_ROOT>,
- <&cru PCLK_VI_ROOT>,
- <&cru HCLK_ISP0>,
- <&cru ACLK_ISP0>,
- <&cru HCLK_VICAP>,
- <&cru ACLK_VICAP>;
- pm_qos = <&qos_isp0_mro>,
- <&qos_isp0_mwo>,
- <&qos_vicap_m0>,
- <&qos_vicap_m1>;
- #address-cells = <1>;
- #size-cells = <0>;
- #power-domain-cells = <0>;
-
- power-domain@RK3588_PD_ISP1 {
- reg = <RK3588_PD_ISP1>;
- clocks = <&cru HCLK_ISP1>,
- <&cru ACLK_ISP1>,
- <&cru HCLK_VI_ROOT>,
- <&cru PCLK_VI_ROOT>;
- pm_qos = <&qos_isp1_mwo>,
- <&qos_isp1_mro>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_FEC {
- reg = <RK3588_PD_FEC>;
- clocks = <&cru HCLK_FISHEYE0>,
- <&cru ACLK_FISHEYE0>,
- <&cru HCLK_FISHEYE1>,
- <&cru ACLK_FISHEYE1>,
- <&cru PCLK_VI_ROOT>;
- pm_qos = <&qos_fisheye0>,
- <&qos_fisheye1>;
- #power-domain-cells = <0>;
- };
- };
- power-domain@RK3588_PD_RGA31 {
- reg = <RK3588_PD_RGA31>;
- clocks = <&cru HCLK_RGA3_1>,
- <&cru ACLK_RGA3_1>;
- pm_qos = <&qos_rga3_1>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_USB {
- reg = <RK3588_PD_USB>;
- clocks = <&cru PCLK_PHP_ROOT>,
- <&cru ACLK_USB_ROOT>,
- <&cru ACLK_USB>,
- <&cru HCLK_USB_ROOT>,
- <&cru HCLK_HOST0>,
- <&cru HCLK_HOST_ARB0>,
- <&cru HCLK_HOST1>,
- <&cru HCLK_HOST_ARB1>;
- pm_qos = <&qos_usb3_0>,
- <&qos_usb3_1>,
- <&qos_usb2host_0>,
- <&qos_usb2host_1>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_GMAC {
- reg = <RK3588_PD_GMAC>;
- clocks = <&cru PCLK_PHP_ROOT>,
- <&cru ACLK_PCIE_ROOT>,
- <&cru ACLK_PHP_ROOT>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_PCIE {
- reg = <RK3588_PD_PCIE>;
- clocks = <&cru PCLK_PHP_ROOT>,
- <&cru ACLK_PCIE_ROOT>,
- <&cru ACLK_PHP_ROOT>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_SDIO {
- reg = <RK3588_PD_SDIO>;
- clocks = <&cru HCLK_SDIO>,
- <&cru HCLK_NVM_ROOT>;
- pm_qos = <&qos_sdio>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_AUDIO {
- reg = <RK3588_PD_AUDIO>;
- clocks = <&cru HCLK_AUDIO_ROOT>,
- <&cru PCLK_AUDIO_ROOT>;
- #power-domain-cells = <0>;
- };
- power-domain@RK3588_PD_SDMMC {
- reg = <RK3588_PD_SDMMC>;
- pm_qos = <&qos_sdmmc>;
- #power-domain-cells = <0>;
- };
- };
- };
-
- av1d: video-codec@fdc70000 {
- compatible = "rockchip,rk3588-av1-vpu";
- reg = <0x0 0xfdc70000 0x0 0x800>;
- interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "vdpu";
- assigned-clocks = <&cru ACLK_AV1>, <&cru PCLK_AV1>;
- assigned-clock-rates = <400000000>, <400000000>;
- clocks = <&cru ACLK_AV1>, <&cru PCLK_AV1>;
- clock-names = "aclk", "hclk";
- power-domains = <&power RK3588_PD_AV1>;
- resets = <&cru SRST_A_AV1>, <&cru SRST_P_AV1>, <&cru SRST_A_AV1_BIU>, <&cru SRST_P_AV1_BIU>;
- };
-
- vop: vop@fdd90000 {
- compatible = "rockchip,rk3588-vop";
- reg = <0x0 0xfdd90000 0x0 0x4200>, <0x0 0xfdd95000 0x0 0x1000>;
- reg-names = "vop", "gamma-lut";
- interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru ACLK_VOP>,
- <&cru HCLK_VOP>,
- <&cru DCLK_VOP0>,
- <&cru DCLK_VOP1>,
- <&cru DCLK_VOP2>,
- <&cru DCLK_VOP3>,
- <&cru PCLK_VOP_ROOT>;
- clock-names = "aclk",
- "hclk",
- "dclk_vp0",
- "dclk_vp1",
- "dclk_vp2",
- "dclk_vp3",
- "pclk_vop";
- iommus = <&vop_mmu>;
- power-domains = <&power RK3588_PD_VOP>;
- rockchip,grf = <&sys_grf>;
- rockchip,vop-grf = <&vop_grf>;
- rockchip,vo1-grf = <&vo1_grf>;
- rockchip,pmu = <&pmu>;
- status = "disabled";
-
- vop_out: ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- vp0: port@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- vp1: port@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- };
-
- vp2: port@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- vp3: port@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
- };
- };
-
- vop_mmu: iommu@fdd97e00 {
- compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu";
- reg = <0x0 0xfdd97e00 0x0 0x100>, <0x0 0xfdd97f00 0x0 0x100>;
- interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
- clock-names = "aclk", "iface";
- #iommu-cells = <0>;
- power-domains = <&power RK3588_PD_VOP>;
- status = "disabled";
- };
-
- i2s4_8ch: i2s@fddc0000 {
- compatible = "rockchip,rk3588-i2s-tdm";
- reg = <0x0 0xfddc0000 0x0 0x1000>;
- interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S4_8CH_TX>, <&cru MCLK_I2S4_8CH_TX>, <&cru HCLK_I2S4_8CH>;
- clock-names = "mclk_tx", "mclk_rx", "hclk";
- assigned-clocks = <&cru CLK_I2S4_8CH_TX_SRC>;
- assigned-clock-parents = <&cru PLL_AUPLL>;
- dmas = <&dmac2 0>;
- dma-names = "tx";
- power-domains = <&power RK3588_PD_VO0>;
- resets = <&cru SRST_M_I2S4_8CH_TX>;
- reset-names = "tx-m";
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- i2s5_8ch: i2s@fddf0000 {
- compatible = "rockchip,rk3588-i2s-tdm";
- reg = <0x0 0xfddf0000 0x0 0x1000>;
- interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S5_8CH_TX>, <&cru MCLK_I2S5_8CH_TX>, <&cru HCLK_I2S5_8CH>;
- clock-names = "mclk_tx", "mclk_rx", "hclk";
- assigned-clocks = <&cru CLK_I2S5_8CH_TX_SRC>;
- assigned-clock-parents = <&cru PLL_AUPLL>;
- dmas = <&dmac2 2>;
- dma-names = "tx";
- power-domains = <&power RK3588_PD_VO1>;
- resets = <&cru SRST_M_I2S5_8CH_TX>;
- reset-names = "tx-m";
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- i2s9_8ch: i2s@fddfc000 {
- compatible = "rockchip,rk3588-i2s-tdm";
- reg = <0x0 0xfddfc000 0x0 0x1000>;
- interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S9_8CH_RX>, <&cru MCLK_I2S9_8CH_RX>, <&cru HCLK_I2S9_8CH>;
- clock-names = "mclk_tx", "mclk_rx", "hclk";
- assigned-clocks = <&cru CLK_I2S9_8CH_RX_SRC>;
- assigned-clock-parents = <&cru PLL_AUPLL>;
- dmas = <&dmac2 23>;
- dma-names = "rx";
- power-domains = <&power RK3588_PD_VO1>;
- resets = <&cru SRST_M_I2S9_8CH_RX>;
- reset-names = "rx-m";
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- qos_gpu_m0: qos@fdf35000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf35000 0x0 0x20>;
- };
-
- qos_gpu_m1: qos@fdf35200 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf35200 0x0 0x20>;
- };
-
- qos_gpu_m2: qos@fdf35400 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf35400 0x0 0x20>;
- };
-
- qos_gpu_m3: qos@fdf35600 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf35600 0x0 0x20>;
- };
-
- qos_rga3_1: qos@fdf36000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf36000 0x0 0x20>;
- };
-
- qos_sdio: qos@fdf39000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf39000 0x0 0x20>;
- };
-
- qos_sdmmc: qos@fdf3d800 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf3d800 0x0 0x20>;
- };
-
- qos_usb3_1: qos@fdf3e000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf3e000 0x0 0x20>;
- };
-
- qos_usb3_0: qos@fdf3e200 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf3e200 0x0 0x20>;
- };
-
- qos_usb2host_0: qos@fdf3e400 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf3e400 0x0 0x20>;
- };
-
- qos_usb2host_1: qos@fdf3e600 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf3e600 0x0 0x20>;
- };
-
- qos_fisheye0: qos@fdf40000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf40000 0x0 0x20>;
- };
-
- qos_fisheye1: qos@fdf40200 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf40200 0x0 0x20>;
- };
-
- qos_isp0_mro: qos@fdf40400 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf40400 0x0 0x20>;
- };
-
- qos_isp0_mwo: qos@fdf40500 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf40500 0x0 0x20>;
- };
-
- qos_vicap_m0: qos@fdf40600 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf40600 0x0 0x20>;
- };
-
- qos_vicap_m1: qos@fdf40800 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf40800 0x0 0x20>;
- };
-
- qos_isp1_mwo: qos@fdf41000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf41000 0x0 0x20>;
- };
-
- qos_isp1_mro: qos@fdf41100 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf41100 0x0 0x20>;
- };
-
- qos_rkvenc0_m0ro: qos@fdf60000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf60000 0x0 0x20>;
- };
-
- qos_rkvenc0_m1ro: qos@fdf60200 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf60200 0x0 0x20>;
- };
-
- qos_rkvenc0_m2wo: qos@fdf60400 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf60400 0x0 0x20>;
- };
-
- qos_rkvenc1_m0ro: qos@fdf61000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf61000 0x0 0x20>;
- };
-
- qos_rkvenc1_m1ro: qos@fdf61200 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf61200 0x0 0x20>;
- };
-
- qos_rkvenc1_m2wo: qos@fdf61400 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf61400 0x0 0x20>;
- };
-
- qos_rkvdec0: qos@fdf62000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf62000 0x0 0x20>;
- };
-
- qos_rkvdec1: qos@fdf63000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf63000 0x0 0x20>;
- };
-
- qos_av1: qos@fdf64000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf64000 0x0 0x20>;
- };
-
- qos_iep: qos@fdf66000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf66000 0x0 0x20>;
- };
-
- qos_jpeg_dec: qos@fdf66200 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf66200 0x0 0x20>;
- };
-
- qos_jpeg_enc0: qos@fdf66400 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf66400 0x0 0x20>;
- };
-
- qos_jpeg_enc1: qos@fdf66600 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf66600 0x0 0x20>;
- };
-
- qos_jpeg_enc2: qos@fdf66800 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf66800 0x0 0x20>;
- };
-
- qos_jpeg_enc3: qos@fdf66a00 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf66a00 0x0 0x20>;
- };
-
- qos_rga2_mro: qos@fdf66c00 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf66c00 0x0 0x20>;
- };
-
- qos_rga2_mwo: qos@fdf66e00 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf66e00 0x0 0x20>;
- };
-
- qos_rga3_0: qos@fdf67000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf67000 0x0 0x20>;
- };
-
- qos_vdpu: qos@fdf67200 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf67200 0x0 0x20>;
- };
-
- qos_npu1: qos@fdf70000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf70000 0x0 0x20>;
- };
-
- qos_npu2: qos@fdf71000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf71000 0x0 0x20>;
- };
-
- qos_npu0_mwr: qos@fdf72000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf72000 0x0 0x20>;
- };
-
- qos_npu0_mro: qos@fdf72200 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf72200 0x0 0x20>;
- };
-
- qos_mcu_npu: qos@fdf72400 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf72400 0x0 0x20>;
- };
-
- qos_hdcp0: qos@fdf80000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf80000 0x0 0x20>;
- };
-
- qos_hdcp1: qos@fdf81000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf81000 0x0 0x20>;
- };
-
- qos_hdmirx: qos@fdf81200 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf81200 0x0 0x20>;
- };
-
- qos_vop_m0: qos@fdf82000 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf82000 0x0 0x20>;
- };
-
- qos_vop_m1: qos@fdf82200 {
- compatible = "rockchip,rk3588-qos", "syscon";
- reg = <0x0 0xfdf82200 0x0 0x20>;
- };
-
- dfi: dfi@fe060000 {
- reg = <0x00 0xfe060000 0x00 0x10000>;
- compatible = "rockchip,rk3588-dfi";
- interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH 0>;
- rockchip,pmu = <&pmu1grf>;
- };
-
- pcie2x1l1: pcie@fe180000 {
- compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
- bus-range = <0x30 0x3f>;
- clocks = <&cru ACLK_PCIE_1L1_MSTR>, <&cru ACLK_PCIE_1L1_SLV>,
- <&cru ACLK_PCIE_1L1_DBI>, <&cru PCLK_PCIE_1L1>,
- <&cru CLK_PCIE_AUX3>, <&cru CLK_PCIE1L1_PIPE>;
- clock-names = "aclk_mst", "aclk_slv",
- "aclk_dbi", "pclk",
- "aux", "pipe";
- device_type = "pci";
- interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "sys", "pmc", "msg", "legacy", "err";
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0 0 0 1 &pcie2x1l1_intc 0>,
- <0 0 0 2 &pcie2x1l1_intc 1>,
- <0 0 0 3 &pcie2x1l1_intc 2>,
- <0 0 0 4 &pcie2x1l1_intc 3>;
- linux,pci-domain = <3>;
- max-link-speed = <2>;
- msi-map = <0x3000 &its0 0x3000 0x1000>;
- num-lanes = <1>;
- phys = <&combphy2_psu PHY_TYPE_PCIE>;
- phy-names = "pcie-phy";
- power-domains = <&power RK3588_PD_PCIE>;
- ranges = <0x01000000 0x0 0xf3100000 0x0 0xf3100000 0x0 0x00100000>,
- <0x02000000 0x0 0xf3200000 0x0 0xf3200000 0x0 0x00e00000>,
- <0x03000000 0x0 0x40000000 0x9 0xc0000000 0x0 0x40000000>;
- reg = <0xa 0x40c00000 0x0 0x00400000>,
- <0x0 0xfe180000 0x0 0x00010000>,
- <0x0 0xf3000000 0x0 0x00100000>;
- reg-names = "dbi", "apb", "config";
- resets = <&cru SRST_PCIE3_POWER_UP>, <&cru SRST_P_PCIE3>;
- reset-names = "pwr", "pipe";
- #address-cells = <3>;
- #size-cells = <2>;
- status = "disabled";
-
- pcie2x1l1_intc: legacy-interrupt-controller {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <1>;
- interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 245 IRQ_TYPE_EDGE_RISING 0>;
- };
- };
-
- pcie2x1l2: pcie@fe190000 {
- compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
- bus-range = <0x40 0x4f>;
- clocks = <&cru ACLK_PCIE_1L2_MSTR>, <&cru ACLK_PCIE_1L2_SLV>,
- <&cru ACLK_PCIE_1L2_DBI>, <&cru PCLK_PCIE_1L2>,
- <&cru CLK_PCIE_AUX4>, <&cru CLK_PCIE1L2_PIPE>;
- clock-names = "aclk_mst", "aclk_slv",
- "aclk_dbi", "pclk",
- "aux", "pipe";
- device_type = "pci";
- interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "sys", "pmc", "msg", "legacy", "err";
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0 0 0 1 &pcie2x1l2_intc 0>,
- <0 0 0 2 &pcie2x1l2_intc 1>,
- <0 0 0 3 &pcie2x1l2_intc 2>,
- <0 0 0 4 &pcie2x1l2_intc 3>;
- linux,pci-domain = <4>;
- max-link-speed = <2>;
- msi-map = <0x4000 &its0 0x4000 0x1000>;
- num-lanes = <1>;
- phys = <&combphy0_ps PHY_TYPE_PCIE>;
- phy-names = "pcie-phy";
- power-domains = <&power RK3588_PD_PCIE>;
- ranges = <0x01000000 0x0 0xf4100000 0x0 0xf4100000 0x0 0x00100000>,
- <0x02000000 0x0 0xf4200000 0x0 0xf4200000 0x0 0x00e00000>,
- <0x03000000 0x0 0x40000000 0xa 0x00000000 0x0 0x40000000>;
- reg = <0xa 0x41000000 0x0 0x00400000>,
- <0x0 0xfe190000 0x0 0x00010000>,
- <0x0 0xf4000000 0x0 0x00100000>;
- reg-names = "dbi", "apb", "config";
- resets = <&cru SRST_PCIE4_POWER_UP>, <&cru SRST_P_PCIE4>;
- reset-names = "pwr", "pipe";
- #address-cells = <3>;
- #size-cells = <2>;
- status = "disabled";
-
- pcie2x1l2_intc: legacy-interrupt-controller {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <1>;
- interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 250 IRQ_TYPE_EDGE_RISING 0>;
- };
- };
-
- gmac1: ethernet@fe1c0000 {
- compatible = "rockchip,rk3588-gmac", "snps,dwmac-4.20a";
- reg = <0x0 0xfe1c0000 0x0 0x10000>;
- interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "macirq", "eth_wake_irq";
- clocks = <&cru CLK_GMAC_125M>, <&cru CLK_GMAC_50M>,
- <&cru PCLK_GMAC1>, <&cru ACLK_GMAC1>,
- <&cru CLK_GMAC1_PTP_REF>;
- clock-names = "stmmaceth", "clk_mac_ref",
- "pclk_mac", "aclk_mac",
- "ptp_ref";
- power-domains = <&power RK3588_PD_GMAC>;
- resets = <&cru SRST_A_GMAC1>;
- reset-names = "stmmaceth";
- rockchip,grf = <&sys_grf>;
- rockchip,php-grf = <&php_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,wr_osr_lmt = <4>;
- snps,rd_osr_lmt = <8>;
- };
-
- gmac1_mtl_rx_setup: rx-queues-config {
- snps,rx-queues-to-use = <2>;
- queue0 {};
- queue1 {};
- };
-
- gmac1_mtl_tx_setup: tx-queues-config {
- snps,tx-queues-to-use = <2>;
- queue0 {};
- queue1 {};
- };
- };
-
- sata0: sata@fe210000 {
- compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci";
- reg = <0 0xfe210000 0 0x1000>;
- interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru ACLK_SATA0>, <&cru CLK_PMALIVE0>,
- <&cru CLK_RXOOB0>, <&cru CLK_PIPEPHY0_REF>,
- <&cru CLK_PIPEPHY0_PIPE_ASIC_G>;
- clock-names = "sata", "pmalive", "rxoob", "ref", "asic";
- ports-implemented = <0x1>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
-
- sata-port@0 {
- reg = <0>;
- hba-port-cap = <HBA_PORT_FBSCP>;
- phys = <&combphy0_ps PHY_TYPE_SATA>;
- phy-names = "sata-phy";
- snps,rx-ts-max = <32>;
- snps,tx-ts-max = <32>;
- };
- };
-
- sata2: sata@fe230000 {
- compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci";
- reg = <0 0xfe230000 0 0x1000>;
- interrupts = <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru ACLK_SATA2>, <&cru CLK_PMALIVE2>,
- <&cru CLK_RXOOB2>, <&cru CLK_PIPEPHY2_REF>,
- <&cru CLK_PIPEPHY2_PIPE_ASIC_G>;
- clock-names = "sata", "pmalive", "rxoob", "ref", "asic";
- ports-implemented = <0x1>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
-
- sata-port@0 {
- reg = <0>;
- hba-port-cap = <HBA_PORT_FBSCP>;
- phys = <&combphy2_psu PHY_TYPE_SATA>;
- phy-names = "sata-phy";
- snps,rx-ts-max = <32>;
- snps,tx-ts-max = <32>;
- };
- };
-
- sfc: spi@fe2b0000 {
- compatible = "rockchip,sfc";
- reg = <0x0 0xfe2b0000 0x0 0x4000>;
- interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>;
- clock-names = "clk_sfc", "hclk_sfc";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- sdmmc: mmc@fe2c0000 {
- compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
- reg = <0x0 0xfe2c0000 0x0 0x4000>;
- interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&scmi_clk SCMI_HCLK_SD>, <&scmi_clk SCMI_CCLK_SD>,
- <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
- clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
- fifo-depth = <0x100>;
- max-frequency = <200000000>;
- pinctrl-names = "default";
- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>;
- power-domains = <&power RK3588_PD_SDMMC>;
- status = "disabled";
- };
-
- sdio: mmc@fe2d0000 {
- compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
- reg = <0x00 0xfe2d0000 0x00 0x4000>;
- interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru HCLK_SDIO>, <&cru CCLK_SRC_SDIO>,
- <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
- clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
- fifo-depth = <0x100>;
- max-frequency = <200000000>;
- pinctrl-names = "default";
- pinctrl-0 = <&sdiom1_pins>;
- power-domains = <&power RK3588_PD_SDIO>;
- status = "disabled";
- };
-
- sdhci: mmc@fe2e0000 {
- compatible = "rockchip,rk3588-dwcmshc";
- reg = <0x0 0xfe2e0000 0x0 0x10000>;
- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH 0>;
- assigned-clocks = <&cru BCLK_EMMC>, <&cru TMCLK_EMMC>, <&cru CCLK_EMMC>;
- assigned-clock-rates = <200000000>, <24000000>, <200000000>;
- clocks = <&cru CCLK_EMMC>, <&cru HCLK_EMMC>,
- <&cru ACLK_EMMC>, <&cru BCLK_EMMC>,
- <&cru TMCLK_EMMC>;
- clock-names = "core", "bus", "axi", "block", "timer";
- max-frequency = <200000000>;
- pinctrl-0 = <&emmc_rstnout>, <&emmc_bus8>, <&emmc_clk>,
- <&emmc_cmd>, <&emmc_data_strobe>;
- pinctrl-names = "default";
- 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";
- status = "disabled";
- };
-
- i2s0_8ch: i2s@fe470000 {
- compatible = "rockchip,rk3588-i2s-tdm";
- reg = <0x0 0xfe470000 0x0 0x1000>;
- interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S0_8CH_TX>, <&cru MCLK_I2S0_8CH_RX>, <&cru HCLK_I2S0_8CH>;
- clock-names = "mclk_tx", "mclk_rx", "hclk";
- assigned-clocks = <&cru CLK_I2S0_8CH_TX_SRC>, <&cru CLK_I2S0_8CH_RX_SRC>;
- assigned-clock-parents = <&cru PLL_AUPLL>, <&cru PLL_AUPLL>;
- dmas = <&dmac0 0>, <&dmac0 1>;
- dma-names = "tx", "rx";
- power-domains = <&power RK3588_PD_AUDIO>;
- resets = <&cru SRST_M_I2S0_8CH_TX>, <&cru SRST_M_I2S0_8CH_RX>;
- reset-names = "tx-m", "rx-m";
- rockchip,trcm-sync-tx-only;
- pinctrl-names = "default";
- pinctrl-0 = <&i2s0_lrck
- &i2s0_sclk
- &i2s0_sdi0
- &i2s0_sdi1
- &i2s0_sdi2
- &i2s0_sdi3
- &i2s0_sdo0
- &i2s0_sdo1
- &i2s0_sdo2
- &i2s0_sdo3>;
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- i2s1_8ch: i2s@fe480000 {
- compatible = "rockchip,rk3588-i2s-tdm";
- reg = <0x0 0xfe480000 0x0 0x1000>;
- interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S1_8CH_TX>, <&cru MCLK_I2S1_8CH_RX>, <&cru HCLK_I2S1_8CH>;
- clock-names = "mclk_tx", "mclk_rx", "hclk";
- dmas = <&dmac0 2>, <&dmac0 3>;
- dma-names = "tx", "rx";
- resets = <&cru SRST_M_I2S1_8CH_TX>, <&cru SRST_M_I2S1_8CH_RX>;
- reset-names = "tx-m", "rx-m";
- rockchip,trcm-sync-tx-only;
- pinctrl-names = "default";
- pinctrl-0 = <&i2s1m0_lrck
- &i2s1m0_sclk
- &i2s1m0_sdi0
- &i2s1m0_sdi1
- &i2s1m0_sdi2
- &i2s1m0_sdi3
- &i2s1m0_sdo0
- &i2s1m0_sdo1
- &i2s1m0_sdo2
- &i2s1m0_sdo3>;
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- i2s2_2ch: i2s@fe490000 {
- compatible = "rockchip,rk3588-i2s", "rockchip,rk3066-i2s";
- reg = <0x0 0xfe490000 0x0 0x1000>;
- interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S2_2CH>, <&cru HCLK_I2S2_2CH>;
- clock-names = "i2s_clk", "i2s_hclk";
- assigned-clocks = <&cru CLK_I2S2_2CH_SRC>;
- assigned-clock-parents = <&cru PLL_AUPLL>;
- dmas = <&dmac1 0>, <&dmac1 1>;
- dma-names = "tx", "rx";
- power-domains = <&power RK3588_PD_AUDIO>;
- pinctrl-names = "default";
- pinctrl-0 = <&i2s2m1_lrck
- &i2s2m1_sclk
- &i2s2m1_sdi
- &i2s2m1_sdo>;
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- i2s3_2ch: i2s@fe4a0000 {
- compatible = "rockchip,rk3588-i2s", "rockchip,rk3066-i2s";
- reg = <0x0 0xfe4a0000 0x0 0x1000>;
- interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru MCLK_I2S3_2CH>, <&cru HCLK_I2S3_2CH>;
- clock-names = "i2s_clk", "i2s_hclk";
- assigned-clocks = <&cru CLK_I2S3_2CH_SRC>;
- assigned-clock-parents = <&cru PLL_AUPLL>;
- dmas = <&dmac1 2>, <&dmac1 3>;
- dma-names = "tx", "rx";
- power-domains = <&power RK3588_PD_AUDIO>;
- pinctrl-names = "default";
- pinctrl-0 = <&i2s3_lrck
- &i2s3_sclk
- &i2s3_sdi
- &i2s3_sdo>;
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
- gic: interrupt-controller@fe600000 {
- compatible = "arm,gic-v3";
- reg = <0x0 0xfe600000 0 0x10000>, /* GICD */
- <0x0 0xfe680000 0 0x100000>; /* GICR */
- interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-controller;
- mbi-alias = <0x0 0xfe610000>;
- mbi-ranges = <424 56>;
- msi-controller;
- ranges;
- #address-cells = <2>;
- #interrupt-cells = <4>;
- #size-cells = <2>;
-
- its0: msi-controller@fe640000 {
- compatible = "arm,gic-v3-its";
- reg = <0x0 0xfe640000 0x0 0x20000>;
- msi-controller;
- #msi-cells = <1>;
- };
-
- its1: msi-controller@fe660000 {
- compatible = "arm,gic-v3-its";
- reg = <0x0 0xfe660000 0x0 0x20000>;
- msi-controller;
- #msi-cells = <1>;
- };
-
- ppi-partitions {
- ppi_partition0: interrupt-partition-0 {
- affinity = <&cpu_l0 &cpu_l1 &cpu_l2 &cpu_l3>;
- };
-
- ppi_partition1: interrupt-partition-1 {
- affinity = <&cpu_b0 &cpu_b1 &cpu_b2 &cpu_b3>;
- };
- };
- };
-
- dmac0: dma-controller@fea10000 {
- compatible = "arm,pl330", "arm,primecell";
- reg = <0x0 0xfea10000 0x0 0x4000>;
- interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH 0>;
- arm,pl330-periph-burst;
- clocks = <&cru ACLK_DMAC0>;
- clock-names = "apb_pclk";
- #dma-cells = <1>;
- };
-
- dmac1: dma-controller@fea30000 {
- compatible = "arm,pl330", "arm,primecell";
- reg = <0x0 0xfea30000 0x0 0x4000>;
- interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH 0>;
- arm,pl330-periph-burst;
- clocks = <&cru ACLK_DMAC1>;
- clock-names = "apb_pclk";
- #dma-cells = <1>;
- };
-
- i2c1: i2c@fea90000 {
- compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
- reg = <0x0 0xfea90000 0x0 0x1000>;
- clocks = <&cru CLK_I2C1>, <&cru PCLK_I2C1>;
- clock-names = "i2c", "pclk";
- interrupts = <GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH 0>;
- pinctrl-0 = <&i2c1m0_xfer>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- i2c2: i2c@feaa0000 {
- compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
- reg = <0x0 0xfeaa0000 0x0 0x1000>;
- clocks = <&cru CLK_I2C2>, <&cru PCLK_I2C2>;
- clock-names = "i2c", "pclk";
- interrupts = <GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH 0>;
- pinctrl-0 = <&i2c2m0_xfer>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- i2c3: i2c@feab0000 {
- compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
- reg = <0x0 0xfeab0000 0x0 0x1000>;
- clocks = <&cru CLK_I2C3>, <&cru PCLK_I2C3>;
- clock-names = "i2c", "pclk";
- interrupts = <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH 0>;
- pinctrl-0 = <&i2c3m0_xfer>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- i2c4: i2c@feac0000 {
- compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
- reg = <0x0 0xfeac0000 0x0 0x1000>;
- clocks = <&cru CLK_I2C4>, <&cru PCLK_I2C4>;
- clock-names = "i2c", "pclk";
- interrupts = <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH 0>;
- pinctrl-0 = <&i2c4m0_xfer>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- i2c5: i2c@fead0000 {
- compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
- reg = <0x0 0xfead0000 0x0 0x1000>;
- clocks = <&cru CLK_I2C5>, <&cru PCLK_I2C5>;
- clock-names = "i2c", "pclk";
- interrupts = <GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH 0>;
- pinctrl-0 = <&i2c5m0_xfer>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- timer0: timer@feae0000 {
- compatible = "rockchip,rk3588-timer", "rockchip,rk3288-timer";
- reg = <0x0 0xfeae0000 0x0 0x20>;
- interrupts = <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru PCLK_BUSTIMER0>, <&cru CLK_BUSTIMER0>;
- clock-names = "pclk", "timer";
- };
-
- wdt: watchdog@feaf0000 {
- compatible = "rockchip,rk3588-wdt", "snps,dw-wdt";
- reg = <0x0 0xfeaf0000 0x0 0x100>;
- clocks = <&cru TCLK_WDT0>, <&cru PCLK_WDT0>;
- clock-names = "tclk", "pclk";
- interrupts = <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH 0>;
- };
-
- spi0: spi@feb00000 {
- compatible = "rockchip,rk3588-spi", "rockchip,rk3066-spi";
- reg = <0x0 0xfeb00000 0x0 0x1000>;
- interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru CLK_SPI0>, <&cru PCLK_SPI0>;
- clock-names = "spiclk", "apb_pclk";
- dmas = <&dmac0 14>, <&dmac0 15>;
- dma-names = "tx", "rx";
- num-cs = <2>;
- pinctrl-0 = <&spi0m0_cs0 &spi0m0_cs1 &spi0m0_pins>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- spi1: spi@feb10000 {
- compatible = "rockchip,rk3588-spi", "rockchip,rk3066-spi";
- reg = <0x0 0xfeb10000 0x0 0x1000>;
- interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru CLK_SPI1>, <&cru PCLK_SPI1>;
- clock-names = "spiclk", "apb_pclk";
- dmas = <&dmac0 16>, <&dmac0 17>;
- dma-names = "tx", "rx";
- num-cs = <2>;
- pinctrl-0 = <&spi1m1_cs0 &spi1m1_cs1 &spi1m1_pins>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- spi2: spi@feb20000 {
- compatible = "rockchip,rk3588-spi", "rockchip,rk3066-spi";
- reg = <0x0 0xfeb20000 0x0 0x1000>;
- interrupts = <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru CLK_SPI2>, <&cru PCLK_SPI2>;
- clock-names = "spiclk", "apb_pclk";
- dmas = <&dmac1 15>, <&dmac1 16>;
- dma-names = "tx", "rx";
- num-cs = <2>;
- pinctrl-0 = <&spi2m2_cs0 &spi2m2_cs1 &spi2m2_pins>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- spi3: spi@feb30000 {
- compatible = "rockchip,rk3588-spi", "rockchip,rk3066-spi";
- reg = <0x0 0xfeb30000 0x0 0x1000>;
- interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru CLK_SPI3>, <&cru PCLK_SPI3>;
- clock-names = "spiclk", "apb_pclk";
- dmas = <&dmac1 17>, <&dmac1 18>;
- dma-names = "tx", "rx";
- num-cs = <2>;
- pinctrl-0 = <&spi3m1_cs0 &spi3m1_cs1 &spi3m1_pins>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- uart1: serial@feb40000 {
- compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
- reg = <0x0 0xfeb40000 0x0 0x100>;
- interrupts = <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
- clock-names = "baudclk", "apb_pclk";
- dmas = <&dmac0 8>, <&dmac0 9>;
- dma-names = "tx", "rx";
- pinctrl-0 = <&uart1m1_xfer>;
- pinctrl-names = "default";
- reg-io-width = <4>;
- reg-shift = <2>;
- status = "disabled";
- };
-
- uart2: serial@feb50000 {
- compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
- reg = <0x0 0xfeb50000 0x0 0x100>;
- interrupts = <GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
- clock-names = "baudclk", "apb_pclk";
- dmas = <&dmac0 10>, <&dmac0 11>;
- dma-names = "tx", "rx";
- pinctrl-0 = <&uart2m1_xfer>;
- pinctrl-names = "default";
- reg-io-width = <4>;
- reg-shift = <2>;
- status = "disabled";
- };
-
- uart3: serial@feb60000 {
- compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
- reg = <0x0 0xfeb60000 0x0 0x100>;
- interrupts = <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
- clock-names = "baudclk", "apb_pclk";
- dmas = <&dmac0 12>, <&dmac0 13>;
- dma-names = "tx", "rx";
- pinctrl-0 = <&uart3m1_xfer>;
- pinctrl-names = "default";
- reg-io-width = <4>;
- reg-shift = <2>;
- status = "disabled";
- };
-
- uart4: serial@feb70000 {
- compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
- reg = <0x0 0xfeb70000 0x0 0x100>;
- interrupts = <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
- clock-names = "baudclk", "apb_pclk";
- dmas = <&dmac1 9>, <&dmac1 10>;
- dma-names = "tx", "rx";
- pinctrl-0 = <&uart4m1_xfer>;
- pinctrl-names = "default";
- reg-io-width = <4>;
- reg-shift = <2>;
- status = "disabled";
- };
-
- uart5: serial@feb80000 {
- compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
- reg = <0x0 0xfeb80000 0x0 0x100>;
- interrupts = <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>;
- clock-names = "baudclk", "apb_pclk";
- dmas = <&dmac1 11>, <&dmac1 12>;
- dma-names = "tx", "rx";
- pinctrl-0 = <&uart5m1_xfer>;
- pinctrl-names = "default";
- reg-io-width = <4>;
- reg-shift = <2>;
- status = "disabled";
- };
-
- uart6: serial@feb90000 {
- compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
- reg = <0x0 0xfeb90000 0x0 0x100>;
- interrupts = <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_UART6>, <&cru PCLK_UART6>;
- clock-names = "baudclk", "apb_pclk";
- dmas = <&dmac1 13>, <&dmac1 14>;
- dma-names = "tx", "rx";
- pinctrl-0 = <&uart6m1_xfer>;
- pinctrl-names = "default";
- reg-io-width = <4>;
- reg-shift = <2>;
- status = "disabled";
- };
-
- uart7: serial@feba0000 {
- compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
- reg = <0x0 0xfeba0000 0x0 0x100>;
- interrupts = <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_UART7>, <&cru PCLK_UART7>;
- clock-names = "baudclk", "apb_pclk";
- dmas = <&dmac2 7>, <&dmac2 8>;
- dma-names = "tx", "rx";
- pinctrl-0 = <&uart7m1_xfer>;
- pinctrl-names = "default";
- reg-io-width = <4>;
- reg-shift = <2>;
- status = "disabled";
- };
-
- uart8: serial@febb0000 {
- compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
- reg = <0x0 0xfebb0000 0x0 0x100>;
- interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_UART8>, <&cru PCLK_UART8>;
- clock-names = "baudclk", "apb_pclk";
- dmas = <&dmac2 9>, <&dmac2 10>;
- dma-names = "tx", "rx";
- pinctrl-0 = <&uart8m1_xfer>;
- pinctrl-names = "default";
- reg-io-width = <4>;
- reg-shift = <2>;
- status = "disabled";
- };
-
- uart9: serial@febc0000 {
- compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
- reg = <0x0 0xfebc0000 0x0 0x100>;
- interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru SCLK_UART9>, <&cru PCLK_UART9>;
- clock-names = "baudclk", "apb_pclk";
- dmas = <&dmac2 11>, <&dmac2 12>;
- dma-names = "tx", "rx";
- pinctrl-0 = <&uart9m1_xfer>;
- pinctrl-names = "default";
- reg-io-width = <4>;
- reg-shift = <2>;
- status = "disabled";
- };
-
- pwm4: pwm@febd0000 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebd0000 0x0 0x10>;
- clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm4m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm5: pwm@febd0010 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebd0010 0x0 0x10>;
- clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm5m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm6: pwm@febd0020 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebd0020 0x0 0x10>;
- clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm6m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm7: pwm@febd0030 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebd0030 0x0 0x10>;
- clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm7m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm8: pwm@febe0000 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebe0000 0x0 0x10>;
- clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm8m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm9: pwm@febe0010 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebe0010 0x0 0x10>;
- clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm9m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm10: pwm@febe0020 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebe0020 0x0 0x10>;
- clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm10m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm11: pwm@febe0030 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebe0030 0x0 0x10>;
- clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm11m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm12: pwm@febf0000 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebf0000 0x0 0x10>;
- clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm12m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm13: pwm@febf0010 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebf0010 0x0 0x10>;
- clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm13m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm14: pwm@febf0020 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebf0020 0x0 0x10>;
- clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm14m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- pwm15: pwm@febf0030 {
- compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
- reg = <0x0 0xfebf0030 0x0 0x10>;
- clocks = <&cru CLK_PWM3>, <&cru PCLK_PWM3>;
- clock-names = "pwm", "pclk";
- pinctrl-0 = <&pwm15m0_pins>;
- pinctrl-names = "default";
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- tsadc: tsadc@fec00000 {
- compatible = "rockchip,rk3588-tsadc";
- reg = <0x0 0xfec00000 0x0 0x400>;
- interrupts = <GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru CLK_TSADC>, <&cru PCLK_TSADC>;
- clock-names = "tsadc", "apb_pclk";
- assigned-clocks = <&cru CLK_TSADC>;
- assigned-clock-rates = <2000000>;
- resets = <&cru SRST_P_TSADC>, <&cru SRST_TSADC>;
- reset-names = "tsadc-apb", "tsadc";
- rockchip,hw-tshut-temp = <120000>;
- rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
- rockchip,hw-tshut-polarity = <0>; /* tshut polarity 0:LOW 1:HIGH */
- pinctrl-0 = <&tsadc_gpio_func>;
- pinctrl-1 = <&tsadc_shut>;
- pinctrl-names = "gpio", "otpout";
- #thermal-sensor-cells = <1>;
- status = "disabled";
- };
-
- saradc: adc@fec10000 {
- compatible = "rockchip,rk3588-saradc";
- reg = <0x0 0xfec10000 0x0 0x10000>;
- interrupts = <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH 0>;
- #io-channel-cells = <1>;
- clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>;
- clock-names = "saradc", "apb_pclk";
- resets = <&cru SRST_P_SARADC>;
- reset-names = "saradc-apb";
- status = "disabled";
- };
-
- i2c6: i2c@fec80000 {
- compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
- reg = <0x0 0xfec80000 0x0 0x1000>;
- clocks = <&cru CLK_I2C6>, <&cru PCLK_I2C6>;
- clock-names = "i2c", "pclk";
- interrupts = <GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH 0>;
- pinctrl-0 = <&i2c6m0_xfer>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- i2c7: i2c@fec90000 {
- compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
- reg = <0x0 0xfec90000 0x0 0x1000>;
- clocks = <&cru CLK_I2C7>, <&cru PCLK_I2C7>;
- clock-names = "i2c", "pclk";
- interrupts = <GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH 0>;
- pinctrl-0 = <&i2c7m0_xfer>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- i2c8: i2c@feca0000 {
- compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
- reg = <0x0 0xfeca0000 0x0 0x1000>;
- clocks = <&cru CLK_I2C8>, <&cru PCLK_I2C8>;
- clock-names = "i2c", "pclk";
- interrupts = <GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH 0>;
- pinctrl-0 = <&i2c8m0_xfer>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- spi4: spi@fecb0000 {
- compatible = "rockchip,rk3588-spi", "rockchip,rk3066-spi";
- reg = <0x0 0xfecb0000 0x0 0x1000>;
- interrupts = <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru CLK_SPI4>, <&cru PCLK_SPI4>;
- clock-names = "spiclk", "apb_pclk";
- dmas = <&dmac2 13>, <&dmac2 14>;
- dma-names = "tx", "rx";
- num-cs = <2>;
- pinctrl-0 = <&spi4m0_cs0 &spi4m0_cs1 &spi4m0_pins>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- otp: efuse@fecc0000 {
- compatible = "rockchip,rk3588-otp";
- reg = <0x0 0xfecc0000 0x0 0x400>;
- clocks = <&cru CLK_OTPC_NS>, <&cru PCLK_OTPC_NS>,
- <&cru CLK_OTP_PHY_G>, <&cru CLK_OTPC_ARB>;
- clock-names = "otp", "apb_pclk", "phy", "arb";
- resets = <&cru SRST_OTPC_NS>, <&cru SRST_P_OTPC_NS>,
- <&cru SRST_OTPC_ARB>;
- reset-names = "otp", "apb", "arb";
- #address-cells = <1>;
- #size-cells = <1>;
-
- cpu_code: cpu-code@2 {
- reg = <0x02 0x2>;
- };
-
- otp_id: id@7 {
- reg = <0x07 0x10>;
- };
-
- cpub0_leakage: cpu-leakage@17 {
- reg = <0x17 0x1>;
- };
-
- cpub1_leakage: cpu-leakage@18 {
- reg = <0x18 0x1>;
- };
-
- cpul_leakage: cpu-leakage@19 {
- reg = <0x19 0x1>;
- };
-
- log_leakage: log-leakage@1a {
- reg = <0x1a 0x1>;
- };
-
- gpu_leakage: gpu-leakage@1b {
- reg = <0x1b 0x1>;
- };
-
- otp_cpu_version: cpu-version@1c {
- reg = <0x1c 0x1>;
- bits = <3 3>;
- };
-
- npu_leakage: npu-leakage@28 {
- reg = <0x28 0x1>;
- };
-
- codec_leakage: codec-leakage@29 {
- reg = <0x29 0x1>;
- };
- };
-
- dmac2: dma-controller@fed10000 {
- compatible = "arm,pl330", "arm,primecell";
- reg = <0x0 0xfed10000 0x0 0x4000>;
- interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH 0>;
- arm,pl330-periph-burst;
- clocks = <&cru ACLK_DMAC2>;
- clock-names = "apb_pclk";
- #dma-cells = <1>;
- };
-
- hdptxphy_hdmi0: phy@fed60000 {
- compatible = "rockchip,rk3588-hdptx-phy";
- reg = <0x0 0xfed60000 0x0 0x2000>;
- clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>;
- clock-names = "ref", "apb";
- #phy-cells = <0>;
- resets = <&cru SRST_HDPTX0>, <&cru SRST_P_HDPTX0>,
- <&cru SRST_HDPTX0_INIT>, <&cru SRST_HDPTX0_CMN>,
- <&cru SRST_HDPTX0_LANE>, <&cru SRST_HDPTX0_ROPLL>,
- <&cru SRST_HDPTX0_LCPLL>;
- reset-names = "phy", "apb", "init", "cmn", "lane", "ropll",
- "lcpll";
- rockchip,grf = <&hdptxphy0_grf>;
- status = "disabled";
- };
-
- usbdp_phy0: phy@fed80000 {
- compatible = "rockchip,rk3588-usbdp-phy";
- reg = <0x0 0xfed80000 0x0 0x10000>;
- #phy-cells = <1>;
- clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>,
- <&cru CLK_USBDP_PHY0_IMMORTAL>,
- <&cru PCLK_USBDPPHY0>,
- <&u2phy0>;
- clock-names = "refclk", "immortal", "pclk", "utmi";
- resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>,
- <&cru SRST_USBDP_COMBO_PHY0_CMN>,
- <&cru SRST_USBDP_COMBO_PHY0_LANE>,
- <&cru SRST_USBDP_COMBO_PHY0_PCS>,
- <&cru SRST_P_USBDPPHY0>;
- reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
- rockchip,u2phy-grf = <&usb2phy0_grf>;
- rockchip,usb-grf = <&usb_grf>;
- rockchip,usbdpphy-grf = <&usbdpphy0_grf>;
- rockchip,vo-grf = <&vo0_grf>;
- status = "disabled";
- };
-
- combphy0_ps: phy@fee00000 {
- compatible = "rockchip,rk3588-naneng-combphy";
- reg = <0x0 0xfee00000 0x0 0x100>;
- clocks = <&cru CLK_REF_PIPE_PHY0>, <&cru PCLK_PCIE_COMBO_PIPE_PHY0>,
- <&cru PCLK_PHP_ROOT>;
- clock-names = "ref", "apb", "pipe";
- assigned-clocks = <&cru CLK_REF_PIPE_PHY0>;
- assigned-clock-rates = <100000000>;
- #phy-cells = <1>;
- resets = <&cru SRST_REF_PIPE_PHY0>, <&cru SRST_P_PCIE2_PHY0>;
- reset-names = "phy", "apb";
- rockchip,pipe-grf = <&php_grf>;
- rockchip,pipe-phy-grf = <&pipe_phy0_grf>;
- status = "disabled";
- };
-
- combphy2_psu: phy@fee20000 {
- compatible = "rockchip,rk3588-naneng-combphy";
- reg = <0x0 0xfee20000 0x0 0x100>;
- clocks = <&cru CLK_REF_PIPE_PHY2>, <&cru PCLK_PCIE_COMBO_PIPE_PHY2>,
- <&cru PCLK_PHP_ROOT>;
- clock-names = "ref", "apb", "pipe";
- assigned-clocks = <&cru CLK_REF_PIPE_PHY2>;
- assigned-clock-rates = <100000000>;
- #phy-cells = <1>;
- resets = <&cru SRST_REF_PIPE_PHY2>, <&cru SRST_P_PCIE2_PHY2>;
- reset-names = "phy", "apb";
- rockchip,pipe-grf = <&php_grf>;
- rockchip,pipe-phy-grf = <&pipe_phy2_grf>;
- status = "disabled";
- };
-
- system_sram2: sram@ff001000 {
- compatible = "mmio-sram";
- reg = <0x0 0xff001000 0x0 0xef000>;
- ranges = <0x0 0x0 0xff001000 0xef000>;
- #address-cells = <1>;
- #size-cells = <1>;
- };
-
- pinctrl: pinctrl {
- compatible = "rockchip,rk3588-pinctrl";
- ranges;
- rockchip,grf = <&ioc>;
- #address-cells = <2>;
- #size-cells = <2>;
-
- gpio0: gpio@fd8a0000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x0 0xfd8a0000 0x0 0x100>;
- interrupts = <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru PCLK_GPIO0>, <&cru DBCLK_GPIO0>;
- gpio-controller;
- gpio-ranges = <&pinctrl 0 0 32>;
- interrupt-controller;
- #gpio-cells = <2>;
- #interrupt-cells = <2>;
- };
-
- gpio1: gpio@fec20000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x0 0xfec20000 0x0 0x100>;
- interrupts = <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>;
- gpio-controller;
- gpio-ranges = <&pinctrl 0 32 32>;
- interrupt-controller;
- #gpio-cells = <2>;
- #interrupt-cells = <2>;
- };
-
- gpio2: gpio@fec30000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x0 0xfec30000 0x0 0x100>;
- interrupts = <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru PCLK_GPIO2>, <&cru DBCLK_GPIO2>;
- gpio-controller;
- gpio-ranges = <&pinctrl 0 64 32>;
- interrupt-controller;
- #gpio-cells = <2>;
- #interrupt-cells = <2>;
- };
-
- gpio3: gpio@fec40000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x0 0xfec40000 0x0 0x100>;
- interrupts = <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru PCLK_GPIO3>, <&cru DBCLK_GPIO3>;
- gpio-controller;
- gpio-ranges = <&pinctrl 0 96 32>;
- interrupt-controller;
- #gpio-cells = <2>;
- #interrupt-cells = <2>;
- };
-
- gpio4: gpio@fec50000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x0 0xfec50000 0x0 0x100>;
- interrupts = <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH 0>;
- clocks = <&cru PCLK_GPIO4>, <&cru DBCLK_GPIO4>;
- gpio-controller;
- gpio-ranges = <&pinctrl 0 128 32>;
- interrupt-controller;
- #gpio-cells = <2>;
- #interrupt-cells = <2>;
- };
- };
-};
-
-#include "rk3588s-pinctrl.dtsi"
+#include "rk3588-base.dtsi"
+#include "rk3588-opp.dtsi"
diff --git a/arch/arm64/boot/dts/sprd/ums512.dtsi b/arch/arm64/boot/dts/sprd/ums512.dtsi
index dbdb79f8e959..4c080df48724 100644
--- a/arch/arm64/boot/dts/sprd/ums512.dtsi
+++ b/arch/arm64/boot/dts/sprd/ums512.dtsi
@@ -136,16 +136,22 @@
<GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>; /* Hipervisor PPI */
};
- pmu {
- compatible = "arm,armv8-pmuv3";
+ pmu-a55 {
+ compatible = "arm,cortex-a55-pmu";
interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>, <&CPU4>, <&CPU5>;
+ };
+
+ pmu-a75 {
+ compatible = "arm,cortex-a75-pmu";
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&CPU6>, <&CPU7>;
};
soc: soc {
diff --git a/arch/arm64/boot/dts/sprd/ums9620.dtsi b/arch/arm64/boot/dts/sprd/ums9620.dtsi
index 2191f0a4811b..2458071320c9 100644
--- a/arch/arm64/boot/dts/sprd/ums9620.dtsi
+++ b/arch/arm64/boot/dts/sprd/ums9620.dtsi
@@ -144,16 +144,22 @@
<GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>; /* Hipervisor PPI */
};
- pmu {
- compatible = "arm,armv8-pmuv3";
+ pmu-a55 {
+ compatible = "arm,cortex-a55-pmu";
interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>;
+ };
+
+ pmu-a76 {
+ compatible = "arm,cortex-a76-pmu";
+ interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>;
};
soc: soc {
diff --git a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
index 7a82896dcbf6..8fdd5f020425 100644
--- a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
@@ -6,6 +6,65 @@
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
&pinctrl {
+ eth2_rgmii_pins_a: eth2-rgmii-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('C', 7, AF10)>, /* ETH_RGMII_TXD0 */
+ <STM32_PINMUX('C', 8, AF10)>, /* ETH_RGMII_TXD1 */
+ <STM32_PINMUX('C', 9, AF10)>, /* ETH_RGMII_TXD2 */
+ <STM32_PINMUX('C', 10, AF10)>, /* ETH_RGMII_TXD3 */
+ <STM32_PINMUX('C', 4, AF10)>; /* ETH_RGMII_TX_CTL */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <3>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('F', 8, AF10)>, /* ETH_RGMII_CLK125 */
+ <STM32_PINMUX('F', 7, AF10)>, /* ETH_RGMII_GTX_CLK */
+ <STM32_PINMUX('C', 6, AF10)>; /* ETH_MDC */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <3>;
+ };
+ pins3 {
+ pinmux = <STM32_PINMUX('C', 5, AF10)>; /* ETH_MDIO */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins4 {
+ pinmux = <STM32_PINMUX('G', 0, AF10)>, /* ETH_RGMII_RXD0 */
+ <STM32_PINMUX('C', 12, AF10)>, /* ETH_RGMII_RXD1 */
+ <STM32_PINMUX('F', 9, AF10)>, /* ETH_RGMII_RXD2 */
+ <STM32_PINMUX('C', 11, AF10)>, /* ETH_RGMII_RXD3 */
+ <STM32_PINMUX('C', 3, AF10)>; /* ETH_RGMII_RX_CTL */
+ bias-disable;
+ };
+ pins5 {
+ pinmux = <STM32_PINMUX('F', 6, AF10)>; /* ETH_RGMII_RX_CLK */
+ bias-disable;
+ };
+ };
+
+ eth2_rgmii_sleep_pins_a: eth2-rgmii-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('C', 7, ANALOG)>, /* ETH_RGMII_TXD0 */
+ <STM32_PINMUX('C', 8, ANALOG)>, /* ETH_RGMII_TXD1 */
+ <STM32_PINMUX('C', 9, ANALOG)>, /* ETH_RGMII_TXD2 */
+ <STM32_PINMUX('C', 10, ANALOG)>, /* ETH_RGMII_TXD3 */
+ <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_TX_CTL */
+ <STM32_PINMUX('F', 8, ANALOG)>, /* ETH_RGMII_CLK125 */
+ <STM32_PINMUX('F', 7, ANALOG)>, /* ETH_RGMII_GTX_CLK */
+ <STM32_PINMUX('C', 6, ANALOG)>, /* ETH_MDC */
+ <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_MDIO */
+ <STM32_PINMUX('G', 0, ANALOG)>, /* ETH_RGMII_RXD0 */
+ <STM32_PINMUX('C', 12, ANALOG)>, /* ETH_RGMII_RXD1 */
+ <STM32_PINMUX('F', 9, ANALOG)>, /* ETH_RGMII_RXD2 */
+ <STM32_PINMUX('C', 11, ANALOG)>, /* ETH_RGMII_RXD3 */
+ <STM32_PINMUX('C', 3, ANALOG)>, /* ETH_RGMII_RX_CTL */
+ <STM32_PINMUX('F', 6, ANALOG)>; /* ETH_RGMII_RX_CLK */
+ };
+ };
+
i2c2_pins_a: i2c2-0 {
pins {
pinmux = <STM32_PINMUX('B', 5, AF9)>, /* I2C2_SCL */
@@ -128,6 +187,47 @@
<STM32_PINMUX('A', 8, ANALOG)>; /* USART2_RX */
};
};
+
+ usart6_pins_a: usart6-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 13, AF3)>, /* USART6_TX */
+ <STM32_PINMUX('G', 5, AF3)>; /* USART6_RTS */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('F', 14, AF3)>, /* USART6_RX */
+ <STM32_PINMUX('F', 15, AF3)>; /* USART6_CTS_NSS */
+ bias-pull-up;
+ };
+ };
+
+ usart6_idle_pins_a: usart6-idle-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 13, ANALOG)>, /* USART6_TX */
+ <STM32_PINMUX('F', 15, ANALOG)>; /* USART6_CTS_NSS */
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('G', 5, AF3)>; /* USART6_RTS */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins3 {
+ pinmux = <STM32_PINMUX('F', 14, AF3)>; /* USART6_RX */
+ bias-pull-up;
+ };
+ };
+
+ usart6_sleep_pins_a: usart6-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 13, ANALOG)>, /* USART6_TX */
+ <STM32_PINMUX('G', 5, ANALOG)>, /* USART6_RTS */
+ <STM32_PINMUX('F', 15, ANALOG)>, /* USART6_CTS_NSS */
+ <STM32_PINMUX('F', 14, ANALOG)>; /* USART6_RX */
+ };
+ };
};
&pinctrl_z {
diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index dcd0656d67a8..1167cf63d7e8 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/clock/st,stm32mp25-rcc.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/st,stm32mp25-rcc.h>
+#include <dt-bindings/regulator/st,stm32mp25-regulator.h>
/ {
#address-cells = <2>;
@@ -20,6 +21,8 @@
device_type = "cpu";
reg = <0>;
enable-method = "psci";
+ power-domains = <&CPU_PD0>;
+ power-domain-names = "psci";
};
};
@@ -51,9 +54,11 @@
};
firmware {
- optee {
+ optee: optee {
compatible = "linaro,optee-tz";
method = "smc";
+ interrupt-parent = <&intc>;
+ interrupts = <GIC_PPI 15 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
};
scmi {
@@ -71,6 +76,40 @@
reg = <0x16>;
#reset-cells = <1>;
};
+
+ scmi_voltd: protocol@17 {
+ reg = <0x17>;
+
+ scmi_regu: regulators {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ scmi_vddio1: regulator@0 {
+ reg = <VOLTD_SCMI_VDDIO1>;
+ regulator-name = "vddio1";
+ };
+ scmi_vddio2: regulator@1 {
+ reg = <VOLTD_SCMI_VDDIO2>;
+ regulator-name = "vddio2";
+ };
+ scmi_vddio3: regulator@2 {
+ reg = <VOLTD_SCMI_VDDIO3>;
+ regulator-name = "vddio3";
+ };
+ scmi_vddio4: regulator@3 {
+ reg = <VOLTD_SCMI_VDDIO4>;
+ regulator-name = "vddio4";
+ };
+ scmi_vdd33ucpd: regulator@5 {
+ reg = <VOLTD_SCMI_UCPD>;
+ regulator-name = "vdd33ucpd";
+ };
+ scmi_vdda18adc: regulator@7 {
+ reg = <VOLTD_SCMI_ADC>;
+ regulator-name = "vdda18adc";
+ };
+ };
+ };
};
};
@@ -88,6 +127,20 @@
psci {
compatible = "arm,psci-1.0";
method = "smc";
+
+ CPU_PD0: power-domain-cpu0 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ };
+
+ CLUSTER_PD: power-domain-cluster {
+ #power-domain-cells = <0>;
+ power-domains = <&RET_PD>;
+ };
+
+ RET_PD: power-domain-retention {
+ #power-domain-cells = <0>;
+ };
};
timer {
@@ -107,6 +160,75 @@
interrupt-parent = <&intc>;
ranges = <0x0 0x0 0x0 0x80000000>;
+ hpdma: dma-controller@40400000 {
+ compatible = "st,stm32mp25-dma3";
+ reg = <0x40400000 0x1000>;
+ interrupts = <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>;
+ clocks = <&scmi_clk CK_SCMI_HPDMA1>;
+ #dma-cells = <3>;
+ };
+
+ hpdma2: dma-controller@40410000 {
+ compatible = "st,stm32mp25-dma3";
+ reg = <0x40410000 0x1000>;
+ interrupts = <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>,
+ <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk CK_SCMI_HPDMA2>;
+ #dma-cells = <3>;
+ };
+
+ hpdma3: dma-controller@40420000 {
+ compatible = "st,stm32mp25-dma3";
+ reg = <0x40420000 0x1000>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 69 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 74 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&scmi_clk CK_SCMI_HPDMA3>;
+ #dma-cells = <3>;
+ };
+
rifsc: bus@42080000 {
compatible = "st,stm32mp25-rifsc", "simple-bus";
reg = <0x42080000 0x1000>;
@@ -148,6 +270,33 @@
status = "disabled";
};
+ usart3: serial@400f0000 {
+ compatible = "st,stm32h7-uart";
+ reg = <0x400f0000 0x400>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_USART3>;
+ access-controllers = <&rifsc 33>;
+ status = "disabled";
+ };
+
+ uart4: serial@40100000 {
+ compatible = "st,stm32h7-uart";
+ reg = <0x40100000 0x400>;
+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_UART4>;
+ access-controllers = <&rifsc 34>;
+ status = "disabled";
+ };
+
+ uart5: serial@40110000 {
+ compatible = "st,stm32h7-uart";
+ reg = <0x40110000 0x400>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_UART5>;
+ access-controllers = <&rifsc 35>;
+ status = "disabled";
+ };
+
i2c1: i2c@40120000 {
compatible = "st,stm32mp25-i2c";
reg = <0x40120000 0x400>;
@@ -239,6 +388,15 @@
status = "disabled";
};
+ usart6: serial@40220000 {
+ compatible = "st,stm32h7-uart";
+ reg = <0x40220000 0x400>;
+ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_USART6>;
+ access-controllers = <&rifsc 36>;
+ status = "disabled";
+ };
+
spi1: spi@40230000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -275,6 +433,24 @@
status = "disabled";
};
+ uart9: serial@402c0000 {
+ compatible = "st,stm32h7-uart";
+ reg = <0x402c0000 0x400>;
+ interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_UART9>;
+ access-controllers = <&rifsc 39>;
+ status = "disabled";
+ };
+
+ usart1: serial@40330000 {
+ compatible = "st,stm32h7-uart";
+ reg = <0x40330000 0x400>;
+ interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_USART1>;
+ access-controllers = <&rifsc 31>;
+ status = "disabled";
+ };
+
spi6: spi@40350000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -299,6 +475,24 @@
status = "disabled";
};
+ uart7: serial@40370000 {
+ compatible = "st,stm32h7-uart";
+ reg = <0x40370000 0x400>;
+ interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_UART7>;
+ access-controllers = <&rifsc 37>;
+ status = "disabled";
+ };
+
+ uart8: serial@40380000 {
+ compatible = "st,stm32h7-uart";
+ reg = <0x40380000 0x400>;
+ interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CK_KER_UART8>;
+ access-controllers = <&rifsc 38>;
+ status = "disabled";
+ };
+
spi8: spi@46020000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -338,6 +532,55 @@
access-controllers = <&rifsc 76>;
status = "disabled";
};
+
+ ethernet1: ethernet@482c0000 {
+ compatible = "st,stm32mp25-dwmac", "snps,dwmac-5.20";
+ reg = <0x482c0000 0x4000>;
+ reg-names = "stmmaceth";
+ interrupts-extended = <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ clock-names = "stmmaceth",
+ "mac-clk-tx",
+ "mac-clk-rx",
+ "ptp_ref",
+ "ethstp",
+ "eth-ck";
+ clocks = <&rcc CK_ETH1_MAC>,
+ <&rcc CK_ETH1_TX>,
+ <&rcc CK_ETH1_RX>,
+ <&rcc CK_KER_ETH1PTP>,
+ <&rcc CK_ETH1_STP>,
+ <&rcc CK_KER_ETH1>;
+ snps,axi-config = <&stmmac_axi_config_1>;
+ snps,mixed-burst;
+ snps,mtl-rx-config = <&mtl_rx_setup_1>;
+ snps,mtl-tx-config = <&mtl_tx_setup_1>;
+ snps,pbl = <2>;
+ snps,tso;
+ st,syscon = <&syscfg 0x3000>;
+ access-controllers = <&rifsc 60>;
+ status = "disabled";
+
+ mtl_rx_setup_1: rx-queues-config {
+ snps,rx-queues-to-use = <2>;
+ queue0 {};
+ queue1 {};
+ };
+
+ mtl_tx_setup_1: tx-queues-config {
+ snps,tx-queues-to-use = <4>;
+ queue0 {};
+ queue1 {};
+ queue2 {};
+ queue3 {};
+ };
+
+ stmmac_axi_config_1: stmmac-axi-config {
+ snps,blen = <0 0 0 0 16 8 4>;
+ snps,rd_osr_lmt = <0x7>;
+ snps,wr_osr_lmt = <0x7>;
+ };
+ };
};
bsec: efuse@44000000 {
@@ -441,6 +684,7 @@
<&scmi_clk CK_SCMI_TIMG2>,
<&scmi_clk CK_SCMI_PLL3>,
<&clk_dsi_txbyte>;
+ access-controllers = <&rifsc 156>;
};
exti1: interrupt-controller@44220000 {
diff --git a/arch/arm64/boot/dts/st/stm32mp253.dtsi b/arch/arm64/boot/dts/st/stm32mp253.dtsi
index 029f88981961..eeceb086252b 100644
--- a/arch/arm64/boot/dts/st/stm32mp253.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp253.dtsi
@@ -12,6 +12,8 @@
device_type = "cpu";
reg = <1>;
enable-method = "psci";
+ power-domains = <&CPU_PD1>;
+ power-domain-names = "psci";
};
};
@@ -21,6 +23,13 @@
interrupt-affinity = <&cpu0>, <&cpu1>;
};
+ psci {
+ CPU_PD1: power-domain-cpu1 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ };
+ };
+
timer {
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
@@ -28,3 +37,58 @@
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
};
};
+
+&optee {
+ interrupts = <GIC_PPI 15 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+};
+
+&rifsc {
+ ethernet2: ethernet@482d0000 {
+ compatible = "st,stm32mp25-dwmac", "snps,dwmac-5.20";
+ reg = <0x482d0000 0x4000>;
+ reg-names = "stmmaceth";
+ interrupts-extended = <&intc GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ clock-names = "stmmaceth",
+ "mac-clk-tx",
+ "mac-clk-rx",
+ "ptp_ref",
+ "ethstp",
+ "eth-ck";
+ clocks = <&rcc CK_ETH2_MAC>,
+ <&rcc CK_ETH2_TX>,
+ <&rcc CK_ETH2_RX>,
+ <&rcc CK_KER_ETH2PTP>,
+ <&rcc CK_ETH2_STP>,
+ <&rcc CK_KER_ETH2>;
+ snps,axi-config = <&stmmac_axi_config_2>;
+ snps,mixed-burst;
+ snps,mtl-rx-config = <&mtl_rx_setup_2>;
+ snps,mtl-tx-config = <&mtl_tx_setup_2>;
+ snps,pbl = <2>;
+ snps,tso;
+ st,syscon = <&syscfg 0x3400>;
+ access-controllers = <&rifsc 61>;
+ status = "disabled";
+
+ mtl_rx_setup_2: rx-queues-config {
+ snps,rx-queues-to-use = <2>;
+ queue0 {};
+ queue1 {};
+ };
+
+ mtl_tx_setup_2: tx-queues-config {
+ snps,tx-queues-to-use = <4>;
+ queue0 {};
+ queue1 {};
+ queue2 {};
+ queue3 {};
+ };
+
+ stmmac_axi_config_2: stmmac-axi-config {
+ snps,blen = <0 0 0 0 16 8 4>;
+ snps,rd_osr_lmt = <0x7>;
+ snps,wr_osr_lmt = <0x7>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 27b7360e5dba..214191a8322b 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -7,6 +7,7 @@
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/regulator/st,stm32mp25-regulator.h>
#include "stm32mp257.dtsi"
#include "stm32mp25xf.dtsi"
#include "stm32mp25-pinctrl.dtsi"
@@ -17,7 +18,9 @@
compatible = "st,stm32mp257f-ev1", "st,stm32mp257";
aliases {
+ ethernet0 = &ethernet2;
serial0 = &usart2;
+ serial1 = &usart6;
};
chosen {
@@ -40,14 +43,6 @@
no-map;
};
};
-
- vdd_sdcard: vdd-sdcard {
- compatible = "regulator-fixed";
- regulator-name = "vdd_sdcard";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
};
&arm_wdt {
@@ -55,6 +50,29 @@
status = "okay";
};
+&ethernet2 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&eth2_rgmii_pins_a>;
+ pinctrl-1 = <&eth2_rgmii_sleep_pins_a>;
+ max-speed = <1000>;
+ phy-handle = <&phy0_eth2>;
+ phy-mode = "rgmii-id";
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+ phy0_eth2: ethernet-phy@1 {
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <1>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <300>;
+ reset-gpios = <&gpiog 6 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
&i2c2 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c2_pins_a>;
@@ -75,6 +93,37 @@
status = "disabled";
};
+&scmi_regu {
+ scmi_vddio1: regulator@0 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ scmi_vddcore: regulator@11 {
+ reg = <VOLTD_SCMI_STPMIC2_BUCK2>;
+ regulator-name = "vddcore";
+ };
+ scmi_v1v8: regulator@14 {
+ reg = <VOLTD_SCMI_STPMIC2_BUCK5>;
+ regulator-name = "v1v8";
+ };
+ scmi_v3v3: regulator@16 {
+ reg = <VOLTD_SCMI_STPMIC2_BUCK7>;
+ regulator-name = "v3v3";
+ };
+ scmi_vdd_emmc: regulator@18 {
+ reg = <VOLTD_SCMI_STPMIC2_LDO2>;
+ regulator-name = "vdd_emmc";
+ };
+ scmi_vdd3v3_usb: regulator@20 {
+ reg = <VOLTD_SCMI_STPMIC2_LDO4>;
+ regulator-name = "vdd3v3_usb";
+ };
+ scmi_vdd_sdcard: regulator@23 {
+ reg = <VOLTD_SCMI_STPMIC2_LDO7>;
+ regulator-name = "vdd_sdcard";
+ };
+};
+
&sdmmc1 {
pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc1_b4_pins_a>;
@@ -84,7 +133,8 @@
disable-wp;
st,neg-edge;
bus-width = <4>;
- vmmc-supply = <&vdd_sdcard>;
+ vmmc-supply = <&scmi_vdd_sdcard>;
+ vqmmc-supply = <&scmi_vddio1>;
status = "okay";
};
@@ -109,3 +159,12 @@
pinctrl-2 = <&usart2_sleep_pins_a>;
status = "okay";
};
+
+&usart6 {
+ pinctrl-names = "default", "idle", "sleep";
+ pinctrl-0 = <&usart6_pins_a>;
+ pinctrl-1 = <&usart6_idle_pins_a>;
+ pinctrl-2 = <&usart6_sleep_pins_a>;
+ uart-has-rtscts;
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
index 2c327cc320cf..e20b27ddf901 100644
--- a/arch/arm64/boot/dts/ti/Makefile
+++ b/arch/arm64/boot/dts/ti/Makefile
@@ -22,11 +22,14 @@ 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-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
# Boards with AM62Ax SoC
dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am62a7-phyboard-lyra-rdk.dtb
# Boards with AM62Px SoC
dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk.dtb
@@ -44,16 +47,26 @@ k3-am642-hummingboard-t-usb3-dtbs := \
k3-am642-hummingboard-t.dtb k3-am642-hummingboard-t-usb3.dtbo
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-hummingboard-t.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am642-hummingboard-t-pcie.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am642-hummingboard-t-usb3.dtb
+k3-am642-evm-nand-dtbs := k3-am642-evm.dtb k3-am642-evm-nand.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am642-evm-nand.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am642-phyboard-electra-rdk.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am642-phyboard-electra-gpio-fan.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am642-phyboard-electra-pcie-usb2.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-am642-sk.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am642-tqma64xxl-mbax4xxl.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am64-tqma64xxl-mbax4xxl-sdcard.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-am64-tqma64xxl-mbax4xxl-wlan.dtbo
+# Common overlays for the phyCORE-AM6* family of boards
+dtb-$(CONFIG_ARCH_K3) += k3-am6xx-phycore-disable-eth-phy.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am6xx-phycore-disable-rtc.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am6xx-phycore-disable-spi-nor.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am6xx-phycore-qspi-nor.dtbo
+
# Boards with AM65x SoC
k3-am654-gp-evm-dtbs := k3-am654-base-board.dtb \
k3-am654-base-board-rocktech-rk101-panel.dtbo \
@@ -81,6 +94,7 @@ dtb-$(CONFIG_ARCH_K3) += k3-j7200-evm.dtb
# Boards with J721e SoC
k3-j721e-evm-dtbs := k3-j721e-common-proc-board.dtb k3-j721e-evm-quad-port-eth-exp.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-j721e-beagleboneai64.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-common-proc-board-infotainment.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm.dtb
dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-gesi-exp-board.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-pcie0-ep.dtbo
@@ -101,14 +115,27 @@ dtb-$(CONFIG_ARCH_K3) += k3-j722s-evm.dtb
# Boards with J784s4 SoC
dtb-$(CONFIG_ARCH_K3) += k3-am69-sk.dtb
dtb-$(CONFIG_ARCH_K3) += k3-j784s4-evm.dtb
+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
# 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 \
+ k3-am6xx-phycore-disable-rtc.dtbo
+k3-am625-phyboard-lyra-disable-spi-nor-dtbs := k3-am625-phyboard-lyra-rdk.dtb \
+ k3-am6xx-phycore-disable-spi-nor.dtbo
k3-am625-phyboard-lyra-gpio-fan-dtbs := k3-am625-phyboard-lyra-rdk.dtb \
k3-am62x-phyboard-lyra-gpio-fan.dtbo
+k3-am625-phyboard-lyra-qspi-nor-dtbs := k3-am625-phyboard-lyra-rdk.dtb \
+ k3-am6xx-phycore-qspi-nor.dtbo
k3-am625-sk-csi2-imx219-dtbs := k3-am625-sk.dtb \
k3-am62x-sk-csi2-imx219.dtbo
k3-am625-sk-csi2-ov5640-dtbs := k3-am625-sk.dtb \
@@ -132,8 +159,20 @@ k3-am62p5-sk-csi2-tevi-ov5640-dtbs := k3-am62p5-sk.dtb \
k3-am62x-sk-csi2-tevi-ov5640.dtbo
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-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 := \
+ k3-am642-phyboard-electra-rdk.dtb k3-am6xx-phycore-disable-rtc.dtbo
+k3-am642-phyboard-electra-disable-spi-nor-dtbs := \
+ k3-am642-phyboard-electra-rdk.dtb k3-am6xx-phycore-disable-spi-nor.dtbo
+k3-am642-phyboard-electra-qspi-nor-dtbs := \
+ k3-am642-phyboard-electra-rdk.dtb k3-am6xx-phycore-qspi-nor.dtbo
k3-am642-phyboard-electra-gpio-fan-dtbs := \
k3-am642-phyboard-electra-rdk.dtb k3-am642-phyboard-electra-gpio-fan.dtbo
+k3-am642-phyboard-electra-pcie-usb2-dtbs := \
+ k3-am642-phyboard-electra-rdk.dtb k3-am642-phyboard-electra-pcie-usb2.dtbo
k3-am642-tqma64xxl-mbax4xxl-sdcard-dtbs := \
k3-am642-tqma64xxl-mbax4xxl.dtb k3-am64-tqma64xxl-mbax4xxl-sdcard.dtbo
k3-am642-tqma64xxl-mbax4xxl-wlan-dtbs := \
@@ -142,12 +181,20 @@ 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-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 \
k3-j721e-evm-pcie0-ep.dtbo
k3-j721e-sk-csi2-dual-imx219-dtbs := k3-j721e-sk.dtb \
k3-j721e-sk-csi2-dual-imx219.dtbo
k3-j721s2-evm-pcie1-ep-dtbs := k3-j721s2-common-proc-board.dtb \
k3-j721s2-evm-pcie1-ep.dtbo
+k3-j784s4-evm-pcie0-pcie1-ep-dtbs := k3-j784s4-evm.dtb \
+ k3-j784s4-evm-pcie0-pcie1-ep.dtbo
+k3-j784s4-evm-quad-port-eth-exp1-dtbs := k3-j784s4-evm.dtb \
+ k3-j784s4-evm-quad-port-eth-exp1.dtbo
+k3-j784s4-evm-usxgmii-exp1-exp2-dtbs := k3-j784s4-evm.dtb \
+ k3-j784s4-evm-usxgmii-exp1-exp2.dtbo
dtb- += k3-am625-beagleplay-csi2-ov5640.dtb \
k3-am625-beagleplay-csi2-tevi-ov5640.dtb \
k3-am625-sk-csi2-imx219.dtb \
@@ -162,17 +209,23 @@ dtb- += k3-am625-beagleplay-csi2-ov5640.dtb \
k3-am62p5-sk-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-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-j721e-common-proc-board-infotainment.dtb \
k3-j721e-evm-pcie0-ep.dtb \
k3-j721e-sk-csi2-dual-imx219.dtb \
- k3-j721s2-evm-pcie1-ep.dtb
+ k3-j721s2-evm-pcie1-ep.dtb \
+ k3-j784s4-evm-pcie0-pcie1-ep.dtb \
+ k3-j784s4-evm-quad-port-eth-exp1.dtb \
+ k3-j784s4-evm-usxgmii-exp1-exp2.dtb
# Enable support for device-tree overlays
DTC_FLAGS_k3-am625-beagleplay += -@
DTC_FLAGS_k3-am625-phyboard-lyra-rdk += -@
+DTC_FLAGS_k3-am62a7-phyboard-lyra-rdk += -@
DTC_FLAGS_k3-am625-sk += -@
DTC_FLAGS_k3-am62-lp-sk += -@
DTC_FLAGS_k3-am62a7-sk += -@
@@ -186,3 +239,4 @@ DTC_FLAGS_k3-am69-sk += -@
DTC_FLAGS_k3-j721e-common-proc-board += -@
DTC_FLAGS_k3-j721e-sk += -@
DTC_FLAGS_k3-j721s2-common-proc-board += -@
+DTC_FLAGS_k3-j784s4-evm += -@
diff --git a/arch/arm64/boot/dts/ti/k3-am62-lp-sk-nand.dtso b/arch/arm64/boot/dts/ti/k3-am62-lp-sk-nand.dtso
new file mode 100644
index 000000000000..173ac60723b6
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am62-lp-sk-nand.dtso
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "k3-pinctrl.h"
+
+&mcasp1 {
+ status = "disabled";
+};
+
+&main_pmx0 {
+ gpmc0_pins_default: gpmc0-pins-default {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x003c, PIN_INPUT, 0) /* (K19) GPMC0_AD0 */
+ AM62X_IOPAD(0x0040, PIN_INPUT, 0) /* (L19) GPMC0_AD1 */
+ AM62X_IOPAD(0x0044, PIN_INPUT, 0) /* (L20) GPMC0_AD2 */
+ AM62X_IOPAD(0x0048, PIN_INPUT, 0) /* (L21) GPMC0_AD3 */
+ AM62X_IOPAD(0x004c, PIN_INPUT, 0) /* (M21) GPMC0_AD4 */
+ AM62X_IOPAD(0x0050, PIN_INPUT, 0) /* (L17) GPMC0_AD5 */
+ AM62X_IOPAD(0x0054, PIN_INPUT, 0) /* (L18) GPMC0_AD6 */
+ AM62X_IOPAD(0x0058, PIN_INPUT, 0) /* (M20) GPMC0_AD7 */
+ AM62X_IOPAD(0x0098, PIN_INPUT, 0) /* (P21) GPMC0_WAIT0 */
+ AM62X_IOPAD(0x00a8, PIN_OUTPUT, 0) /* (J18) GPMC0_CSn0 */
+ AM62X_IOPAD(0x0084, PIN_OUTPUT, 0) /* (K20) GPMC0_ADVn_ALE */
+ AM62X_IOPAD(0x0088, PIN_OUTPUT, 0) /* (K21) GPMC0_OEn_REn */
+ AM62X_IOPAD(0x008c, PIN_OUTPUT, 0) /* (J17) GPMC0_WEn */
+ AM62X_IOPAD(0x0090, PIN_OUTPUT, 0) /* (K17) GPMC0_BE0n_CLE */
+ AM62X_IOPAD(0x00a0, PIN_OUTPUT, 0) /* (J20) GPMC0_WPn */
+ >;
+ };
+};
+
+&elm0 {
+ status = "okay";
+};
+
+&gpmc0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpmc0_pins_default>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ nand@0,0 {
+ compatible = "ti,am64-nand";
+ reg = <0 0 64>; /* device IO registers */
+ interrupt-parent = <&gpmc0>;
+ interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+ <1 IRQ_TYPE_NONE>; /* termcount */
+ rb-gpios = <&gpmc0 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
+ ti,nand-xfer-type = "prefetch-polled";
+ ti,nand-ecc-opt = "bch8"; /* BCH8: Bootrom limitation */
+ ti,elm-id = <&elm0>;
+ nand-bus-width = <8>;
+ gpmc,device-width = <1>;
+ gpmc,sync-clk-ps = <0>;
+ gpmc,cs-on-ns = <0>;
+ gpmc,cs-rd-off-ns = <40>;
+ gpmc,cs-wr-off-ns = <40>;
+ gpmc,adv-on-ns = <0>;
+ gpmc,adv-rd-off-ns = <25>;
+ gpmc,adv-wr-off-ns = <25>;
+ gpmc,we-on-ns = <0>;
+ gpmc,we-off-ns = <20>;
+ gpmc,oe-on-ns = <3>;
+ gpmc,oe-off-ns = <30>;
+ gpmc,access-ns = <30>;
+ gpmc,rd-cycle-ns = <40>;
+ gpmc,wr-cycle-ns = <40>;
+ gpmc,bus-turnaround-ns = <0>;
+ gpmc,cycle2cycle-delay-ns = <0>;
+ gpmc,clk-activation-ns = <0>;
+ gpmc,wr-access-ns = <40>;
+ gpmc,wr-data-mux-bus-ns = <0>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "NAND.tiboot3";
+ reg = <0x00000000 0x00200000>; /* 2M */
+ };
+ partition@200000 {
+ label = "NAND.tispl";
+ reg = <0x00200000 0x00200000>; /* 2M */
+ };
+ partition@400000 {
+ label = "NAND.tiboot3.backup"; /* 2M */
+ reg = <0x00400000 0x00200000>; /* BootROM looks at 4M */
+ };
+ partition@600000 {
+ label = "NAND.u-boot";
+ reg = <0x00600000 0x00400000>; /* 4M */
+ };
+ partition@a00000 {
+ label = "NAND.u-boot-env";
+ reg = <0x00a00000 0x00040000>; /* 256K */
+ };
+ partition@a40000 {
+ label = "NAND.u-boot-env.backup";
+ reg = <0x00a40000 0x00040000>; /* 256K */
+ };
+ partition@a80000 {
+ label = "NAND.file-system";
+ reg = <0x00a80000 0x3f580000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts b/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts
index 9a17bd3e59c9..8e9fc00a6b3c 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts
@@ -228,3 +228,7 @@
&tlv320aic3106 {
DVDD-supply = <&buck2_reg>;
};
+
+&gpmc0 {
+ ranges = <0 0 0x00 0x51000000 0x01000000>; /* CS0 space. Min partition = 16MB */
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
index 448a59dc53a7..328929c740dc 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
@@ -141,8 +141,8 @@
compatible = "ti,am64-dmss-pktdma";
reg = <0x00 0x485c0000 0x00 0x100>,
<0x00 0x4a800000 0x00 0x20000>,
- <0x00 0x4aa00000 0x00 0x40000>,
- <0x00 0x4b800000 0x00 0x400000>,
+ <0x00 0x4aa00000 0x00 0x20000>,
+ <0x00 0x4b800000 0x00 0x200000>,
<0x00 0x485e0000 0x00 0x10000>,
<0x00 0x484a0000 0x00 0x2000>,
<0x00 0x484c0000 0x00 0x2000>,
@@ -207,10 +207,6 @@
crypto: crypto@40900000 {
compatible = "ti,am62-sa3ul";
reg = <0x00 0x40900000 0x00 0x1200>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x00 0x40900000 0x00 0x40900000 0x00 0x30000>;
-
dmas = <&main_pktdma 0xf501 0>, <&main_pktdma 0x7506 0>,
<&main_pktdma 0x7507 0>;
dma-names = "tx", "rx1", "rx2";
@@ -739,7 +735,7 @@
label = "port1";
phys = <&phy_gmii_sel 1>;
mac-address = [00 00 00 00 00 00];
- ti,syscon-efuse = <&wkup_conf 0x200>;
+ ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
};
cpsw_port2: port@2 {
@@ -1057,4 +1053,33 @@
status = "disabled";
};
+ gpmc0: memory-controller@3b000000 {
+ compatible = "ti,am64-gpmc";
+ power-domains = <&k3_pds 80 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 80 0>;
+ clock-names = "fck";
+ reg = <0x00 0x03b000000 0x00 0x400>,
+ <0x00 0x050000000 0x00 0x8000000>;
+ reg-names = "cfg", "data";
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ gpmc,num-cs = <3>;
+ gpmc,num-waitpins = <2>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ elm0: ecc@25010000 {
+ compatible = "ti,am64-elm";
+ reg = <0x00 0x25010000 0x00 0x2000>;
+ interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 54 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 54 0>;
+ clock-names = "fck";
+ status = "disabled";
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi
index 74eec1a1abca..5c1284b802ad 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi
@@ -14,6 +14,7 @@
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 = "verdin-nau8822";
simple-audio-card,routing =
"Headphones", "LHP",
@@ -34,7 +35,6 @@
"Line", "Line In";
codec_dai: simple-audio-card,codec {
- clocks = <&audio_refclk1>;
sound-dai = <&nau8822_1a>;
};
@@ -107,6 +107,8 @@
reg = <0x1a>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2s1_mclk>;
+ clock-names = "mclk";
+ clocks = <&audio_refclk1>;
#sound-dai-cells = <0>;
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
index 2038c5e04639..359f53f3e019 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
@@ -1364,8 +1364,6 @@
0 0 0 0
>;
tdm-slots = <2>;
- rx-num-evt = <32>;
- tx-num-evt = <32>;
#sound-dai-cells = <0>;
status = "disabled";
};
@@ -1382,8 +1380,6 @@
0 0 0 0
>;
tdm-slots = <2>;
- rx-num-evt = <32>;
- tx-num-evt = <32>;
#sound-dai-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
index 66ddf2dc51af..e0afafd532a5 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
@@ -22,6 +22,11 @@
reg = <0x14 0x4>;
};
+ cpsw_mac_syscon: ethernet-mac-syscon@200 {
+ compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
+ reg = <0x200 0x8>;
+ };
+
usb0_phy_ctrl: syscon@4008 {
compatible = "ti,am62-usb-phy-ctrl", "syscon";
reg = <0x4008 0x4>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62.dtsi b/arch/arm64/boot/dts/ti/k3-am62.dtsi
index f0781f2bea29..bfb55ca11323 100644
--- a/arch/arm64/boot/dts/ti/k3-am62.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62.dtsi
@@ -68,11 +68,13 @@
<0x00 0x30200000 0x00 0x30200000 0x00 0x00010000>, /* DSS */
<0x00 0x31000000 0x00 0x31000000 0x00 0x00050000>, /* USB0 DWC3 Core window */
<0x00 0x31100000 0x00 0x31100000 0x00 0x00050000>, /* USB1 DWC3 Core window */
+ <0x00 0x3b000000 0x00 0x3b000000 0x00 0x00000400>, /* GPMC0_CFG */
<0x00 0x40900000 0x00 0x40900000 0x00 0x00030000>, /* SA3UL */
<0x00 0x43600000 0x00 0x43600000 0x00 0x00010000>, /* SA3 sproxy data */
<0x00 0x44043000 0x00 0x44043000 0x00 0x00000fe0>, /* TI SCI DEBUG */
<0x00 0x44860000 0x00 0x44860000 0x00 0x00040000>, /* SA3 sproxy config */
<0x00 0x48000000 0x00 0x48000000 0x00 0x06400000>, /* DMSS */
+ <0x00 0x50000000 0x00 0x50000000 0x00 0x08000000>, /* GPMC0 DATA */
<0x00 0x60000000 0x00 0x60000000 0x00 0x08000000>, /* FSS0 DAT1 */
<0x00 0x70000000 0x00 0x70000000 0x00 0x00010000>, /* OCSRAM */
<0x01 0x00000000 0x01 0x00000000 0x00 0x00310000>, /* A53 PERIPHBASE */
diff --git a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
index 18e3070a8683..70de288d728e 100644
--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
+++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
@@ -924,6 +924,4 @@
0 0 0 0
0 0 0 0
>;
- tx-num-evt = <32>;
- rx-num-evt = <32>;
};
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
new file mode 100644
index 000000000000..6ec6d57ec49c
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-1-4-ghz-opp.dtso
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2024 PHYTEC America LLC
+ * Author: Nathan Morrisson <[email protected]>
+ */
+
+/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-phyboard-lyra-rdk.dts b/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dts
index 50d2573c840e..4fa5efdffcd7 100644
--- a/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dts
@@ -7,477 +7,12 @@
* https://www.phytec.com/product/phyboard-am62x
*/
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/input/input.h>
-#include <dt-bindings/leds/common.h>
-#include <dt-bindings/net/ti-dp83867.h>
#include "k3-am625.dtsi"
#include "k3-am62-phycore-som.dtsi"
+#include "k3-am62x-phyboard-lyra.dtsi"
/ {
compatible = "phytec,am625-phyboard-lyra-rdk",
"phytec,am62-phycore-som", "ti,am625";
model = "PHYTEC phyBOARD-Lyra AM625";
-
- aliases {
- serial2 = &main_uart0;
- serial3 = &main_uart1;
- mmc1 = &sdhci1;
- usb0 = &usb0;
- usb1 = &usb1;
- ethernet1 = &cpsw_port2;
- };
-
- can_tc1: can-phy0 {
- compatible = "ti,tcan1042";
- #phy-cells = <0>;
- max-bitrate = <8000000>;
- standby-gpios = <&gpio_exp 1 GPIO_ACTIVE_HIGH>;
- };
-
- hdmi0: connector-hdmi {
- compatible = "hdmi-connector";
- label = "hdmi";
- type = "a";
-
- port {
- hdmi_connector_in: endpoint {
- remote-endpoint = <&sii9022_out>;
- };
- };
- };
-
- keys {
- compatible = "gpio-keys";
- autorepeat;
- pinctrl-names = "default";
- pinctrl-0 = <&gpio_keys_pins_default>;
-
- key-home {
- label = "home";
- linux,code = <KEY_HOME>;
- gpios = <&main_gpio1 23 GPIO_ACTIVE_HIGH>;
- };
-
- key-menu {
- label = "menu";
- linux,code = <KEY_MENU>;
- gpios = <&gpio_exp 4 GPIO_ACTIVE_HIGH>;
- };
- };
-
- sound {
- compatible = "simple-audio-card";
- simple-audio-card,name = "phyBOARD-Lyra";
- simple-audio-card,widgets =
- "Microphone", "Mic Jack",
- "Headphone", "Headphone Jack",
- "Speaker", "External Speaker";
- simple-audio-card,routing =
- "MIC3R", "Mic Jack",
- "Mic Jack", "Mic Bias",
- "Headphone Jack", "HPLOUT",
- "Headphone Jack", "HPROUT",
- "External Speaker", "SPOP",
- "External Speaker", "SPOM";
- simple-audio-card,format = "dsp_b";
- simple-audio-card,bitclock-master = <&sound_master>;
- simple-audio-card,frame-master = <&sound_master>;
- simple-audio-card,bitclock-inversion;
-
- simple-audio-card,cpu {
- sound-dai = <&mcasp2>;
- };
-
- sound_master: simple-audio-card,codec {
- sound-dai = <&audio_codec>;
- clocks = <&audio_refclk1>;
- };
- };
-
- leds {
- compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&leds_pins_default>, <&user_leds_pins_default>;
-
- led-1 {
- gpios = <&main_gpio0 32 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "mmc0";
- };
-
- led-2 {
- gpios = <&gpio_exp 2 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "mmc1";
- };
- };
-
- 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;
- };
-
- vcc_3v3_mmc: regulator-vcc-3v3-mmc {
- compatible = "regulator-fixed";
- regulator-name = "VCC_3V3_MMC";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- vcc_3v3_sw: regulator-vcc-3v3-sw {
- compatible = "regulator-fixed";
- regulator-name = "VCC_3V3_SW";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
- };
-};
-
-&main_pmx0 {
- audio_ext_refclk1_pins_default: audio-ext-refclk1-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x0a0, PIN_OUTPUT, 1) /* (K25) GPMC0_WPn.AUDIO_EXT_REFCLK1 */
- >;
- };
-
- gpio_keys_pins_default: gpio-keys-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x1d4, PIN_INPUT, 7) /* (B15) UART0_RTSn.GPIO1_23 */
- >;
- };
-
- gpio_exp_int_pins_default: gpio-exp-int-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x244, PIN_INPUT, 7) /* (C17) MMC1_SDWP.GPIO1_49 */
- >;
- };
-
- hdmi_int_pins_default: hdmi-int-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x040, PIN_INPUT, 7) /* (N23) GPMC0_AD1.GPIO0_16 */
- >;
- };
-
- main_dss0_pins_default: main-dss0-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x0b8, PIN_OUTPUT, 0) /* (U22) VOUT0_DATA0 */
- AM62X_IOPAD(0x0bc, PIN_OUTPUT, 0) /* (V24) VOUT0_DATA1 */
- AM62X_IOPAD(0x0e0, PIN_OUTPUT, 0) /* (V20) VOUT0_DATA10 */
- AM62X_IOPAD(0x0e4, PIN_OUTPUT, 0) /* (AA23) VOUT0_DATA11 */
- AM62X_IOPAD(0x0e8, PIN_OUTPUT, 0) /* (AB25) VOUT0_DATA12 */
- AM62X_IOPAD(0x0ec, PIN_OUTPUT, 0) /* (AA24) VOUT0_DATA13 */
- AM62X_IOPAD(0x0f0, PIN_OUTPUT, 0) /* (Y22) VOUT0_DATA14 */
- AM62X_IOPAD(0x0f4, PIN_OUTPUT, 0) /* (AA21) VOUT0_DATA15 */
- AM62X_IOPAD(0x0c0, PIN_OUTPUT, 0) /* (W25) VOUT0_DATA2 */
- AM62X_IOPAD(0x0c4, PIN_OUTPUT, 0) /* (W24) VOUT0_DATA3 */
- AM62X_IOPAD(0x0c8, PIN_OUTPUT, 0) /* (Y25) VOUT0_DATA4 */
- AM62X_IOPAD(0x0cc, PIN_OUTPUT, 0) /* (Y24) VOUT0_DATA5 */
- AM62X_IOPAD(0x0d0, PIN_OUTPUT, 0) /* (Y23) VOUT0_DATA6 */
- AM62X_IOPAD(0x0d4, PIN_OUTPUT, 0) /* (AA25) VOUT0_DATA7 */
- AM62X_IOPAD(0x0d8, PIN_OUTPUT, 0) /* (V21) VOUT0_DATA8 */
- AM62X_IOPAD(0x0dc, PIN_OUTPUT, 0) /* (W21) VOUT0_DATA9 */
- AM62X_IOPAD(0x0fc, PIN_OUTPUT, 0) /* (Y20) VOUT0_DE */
- AM62X_IOPAD(0x0f8, PIN_OUTPUT, 0) /* (AB24) VOUT0_HSYNC */
- AM62X_IOPAD(0x104, PIN_OUTPUT, 0) /* (AC24) VOUT0_PCLK */
- AM62X_IOPAD(0x100, PIN_OUTPUT, 0) /* (AC25) VOUT0_VSYNC */
- >;
- };
-
- main_i2c1_pins_default: main-i2c1-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x1e8, PIN_INPUT_PULLUP, 0) /* (B17) I2C1_SCL */
- AM62X_IOPAD(0x1ec, PIN_INPUT_PULLUP, 0) /* (A17) I2C1_SDA */
- >;
- };
-
- main_mcan0_pins_default: main-mcan0-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x1dc, PIN_INPUT, 0) /* (E15) MCAN0_RX */
- AM62X_IOPAD(0x1d8, PIN_OUTPUT, 0) /* (C15) MCAN0_TX */
- >;
- };
-
- main_mcasp2_pins_default: main-mcasp2-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x070, PIN_INPUT, 3) /* (T24) GPMC0_AD13.MCASP2_ACLKX */
- AM62X_IOPAD(0x06c, PIN_INPUT, 3) /* (T22) GPMC0_AD12.MCASP2_AFSX */
- AM62X_IOPAD(0x064, PIN_OUTPUT, 3) /* (T25) GPMC0_AD10.MCASP2_AXR2 */
- AM62X_IOPAD(0x068, PIN_INPUT, 3) /* (R21) GPMC0_AD11.MCASP2_AXR3 */
- >;
- };
-
- main_mmc1_pins_default: main-mmc1-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x23c, PIN_INPUT_PULLUP, 0) /* (A21) MMC1_CMD */
- AM62X_IOPAD(0x234, PIN_INPUT_PULLDOWN, 0) /* (B22) MMC1_CLK */
- AM62X_IOPAD(0x230, PIN_INPUT_PULLUP, 0) /* (A22) MMC1_DAT0 */
- AM62X_IOPAD(0x22c, PIN_INPUT_PULLUP, 0) /* (B21) MMC1_DAT1 */
- AM62X_IOPAD(0x228, PIN_INPUT_PULLUP, 0) /* (C21) MMC1_DAT2 */
- AM62X_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (D22) MMC1_DAT3 */
- AM62X_IOPAD(0x240, PIN_INPUT_PULLUP, 0) /* (D17) MMC1_SDCD */
- >;
- };
-
- main_rgmii2_pins_default: main-rgmii2-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x184, PIN_INPUT, 0) /* (AE23) RGMII2_RD0 */
- AM62X_IOPAD(0x188, PIN_INPUT, 0) /* (AB20) RGMII2_RD1 */
- AM62X_IOPAD(0x18c, PIN_INPUT, 0) /* (AC21) RGMII2_RD2 */
- AM62X_IOPAD(0x190, PIN_INPUT, 0) /* (AE22) RGMII2_RD3 */
- AM62X_IOPAD(0x180, PIN_INPUT, 0) /* (AD23) RGMII2_RXC */
- AM62X_IOPAD(0x17c, PIN_INPUT, 0) /* (AD22) RGMII2_RX_CTL */
- AM62X_IOPAD(0x16c, PIN_OUTPUT, 0) /* (Y18) RGMII2_TD0 */
- AM62X_IOPAD(0x170, PIN_OUTPUT, 0) /* (AA18) RGMII2_TD1 */
- AM62X_IOPAD(0x174, PIN_OUTPUT, 0) /* (AD21) RGMII2_TD2 */
- AM62X_IOPAD(0x178, PIN_OUTPUT, 0) /* (AC20) RGMII2_TD3 */
- AM62X_IOPAD(0x168, PIN_OUTPUT, 0) /* (AE21) RGMII2_TXC */
- AM62X_IOPAD(0x164, PIN_OUTPUT, 0) /* (AA19) RGMII2_TX_CTL */
- >;
- };
-
- main_uart0_pins_default: main-uart0-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14) UART0_RXD */
- AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */
- >;
- };
-
- main_uart1_pins_default: main-uart1-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x194, PIN_INPUT, 2) /* (B19) MCASP0_AXR3.UART1_CTSn */
- AM62X_IOPAD(0x198, PIN_OUTPUT, 2) /* (A19) MCASP0_AXR2.UART1_RTSn */
- AM62X_IOPAD(0x1ac, PIN_INPUT, 2) /* (E19) MCASP0_AFSR.UART1_RXD */
- AM62X_IOPAD(0x1b0, PIN_OUTPUT, 2) /* (A20) MCASP0_ACLKR.UART1_TXD */
- >;
- };
-
- main_usb1_pins_default: main-usb1-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x258, PIN_OUTPUT, 0) /* (F18) USB1_DRVVBUS */
- >;
- };
-
- user_leds_pins_default: user-leds-default-pins {
- pinctrl-single,pins = <
- AM62X_IOPAD(0x084, PIN_OUTPUT, 7) /* (L23) GPMC0_ADVn_ALE.GPIO0_32 */
- >;
- };
-};
-
-&cpsw3g {
- pinctrl-names = "default";
- pinctrl-0 = <&main_rgmii1_pins_default>, <&main_rgmii2_pins_default>;
-};
-
-&cpsw_port2 {
- phy-mode = "rgmii-rxid";
- phy-handle = <&cpsw3g_phy3>;
-};
-
-&cpsw3g_mdio {
- cpsw3g_phy3: ethernet-phy@3 {
- compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22";
- reg = <3>;
- ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
- ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
- ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
- };
-};
-
-&dss {
- pinctrl-names = "default";
- pinctrl-0 = <&main_dss0_pins_default>;
- status = "okay";
-};
-
-&dss_ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- /* VP2: DPI/HDMI Output */
- port@1 {
- reg = <1>;
-
- dpi1_out: endpoint {
- remote-endpoint = <&sii9022_in>;
- };
- };
-};
-
-&main_i2c1 {
- pinctrl-names = "default";
- pinctrl-0 = <&main_i2c1_pins_default>;
- clock-frequency = <100000>;
- status = "okay";
-
- audio_codec: audio-codec@18 {
- pinctrl-names = "default";
- pinctrl-0 = <&audio_ext_refclk1_pins_default>;
-
- #sound-dai-cells = <0>;
- compatible = "ti,tlv320aic3007";
- reg = <0x18>;
- ai3x-micbias-vg = <2>;
-
- AVDD-supply = <&vcc_3v3_sw>;
- IOVDD-supply = <&vcc_3v3_sw>;
- DRVDD-supply = <&vcc_3v3_sw>;
- DVDD-supply = <&vcc_1v8>;
- };
-
- gpio_exp: gpio-expander@21 {
- pinctrl-names = "default";
- pinctrl-0 = <&gpio_exp_int_pins_default>;
- compatible = "nxp,pcf8574";
- reg = <0x21>;
- interrupt-parent = <&main_gpio1>;
- interrupts = <49 0>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-line-names = "", "GPIO1_CAN0_nEN",
- "GPIO2_LED2", "GPIO3_LVDS_GPIO",
- "GPIO4_BUT2", "GPIO5_LVDS_BKLT_EN",
- "GPIO6_ETH1_USER_RESET", "GPIO7_AUDIO_USER_RESET";
- };
-
- usb-pd@22 {
- compatible = "ti,tps6598x";
- reg = <0x22>;
-
- connector {
- compatible = "usb-c-connector";
- label = "USB-C";
- self-powered;
- data-role = "dual";
- power-role = "sink";
- port {
- usb_con_hs: endpoint {
- remote-endpoint = <&typec_hs>;
- };
- };
- };
- };
-
- sii9022: bridge-hdmi@39 {
- compatible = "sil,sii9022";
- reg = <0x39>;
-
- interrupt-parent = <&main_gpio0>;
- interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
- pinctrl-names = "default";
- pinctrl-0 = <&hdmi_int_pins_default>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
-
- sii9022_in: endpoint {
- remote-endpoint = <&dpi1_out>;
- };
- };
-
- port@1 {
- reg = <1>;
-
- sii9022_out: endpoint {
- remote-endpoint = <&hdmi_connector_in>;
- };
- };
- };
- };
-
- eeprom@51 {
- compatible = "atmel,24c02";
- pagesize = <16>;
- reg = <0x51>;
- };
-};
-
-&main_mcan0 {
- pinctrl-names = "default";
- pinctrl-0 = <&main_mcan0_pins_default>;
- phys = <&can_tc1>;
- status = "okay";
-};
-
-&main_uart0 {
- pinctrl-names = "default";
- pinctrl-0 = <&main_uart0_pins_default>;
- status = "okay";
-};
-
-&main_uart1 {
- pinctrl-names = "default";
- pinctrl-0 = <&main_uart1_pins_default>;
- /* Main UART1 may be used by TIFS firmware */
- status = "okay";
-};
-
-&mcasp2 {
- #sound-dai-cells = <0>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&main_mcasp2_pins_default>;
-
- /* MCASP_IIS_MODE */
- op-mode = <0>;
- tdm-slots = <2>;
-
- /* 0: INACTIVE, 1: TX, 2: RX */
- serial-dir = <
- 0 0 1 2
- 0 0 0 0
- 0 0 0 0
- 0 0 0 0
- >;
- tx-num-evt = <32>;
- rx-num-evt = <32>;
- status = "okay";
-};
-
-&sdhci1 {
- vmmc-supply = <&vcc_3v3_mmc>;
- vqmmc-supply = <&vddshv5_sdio>;
- pinctrl-names = "default";
- pinctrl-0 = <&main_mmc1_pins_default>;
- disable-wp;
- no-1-8-v;
- status = "okay";
-};
-
-&usbss0 {
- ti,vbus-divider;
- status = "okay";
-};
-
-&usbss1 {
- ti,vbus-divider;
- status = "okay";
-};
-
-&usb0 {
- usb-role-switch;
-
- port {
- typec_hs: endpoint {
- remote-endpoint = <&usb_con_hs>;
- };
- };
-};
-
-&usb1 {
- dr_mode = "host";
- pinctrl-names = "default";
- pinctrl-0 = <&main_usb1_pins_default>;
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
index bf9c2d9c6439..916fcf3cc57d 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
@@ -59,6 +59,24 @@
reg = <0x4130 0x4>;
#clock-cells = <1>;
};
+
+ audio_refclk0: clock-controller@82e0 {
+ compatible = "ti,am62-audio-refclk";
+ reg = <0x82e0 0x4>;
+ clocks = <&k3_clks 157 0>;
+ assigned-clocks = <&k3_clks 157 0>;
+ assigned-clock-parents = <&k3_clks 157 8>;
+ #clock-cells = <0>;
+ };
+
+ audio_refclk1: clock-controller@82e4 {
+ compatible = "ti,am62-audio-refclk";
+ reg = <0x82e4 0x4>;
+ clocks = <&k3_clks 157 10>;
+ assigned-clocks = <&k3_clks 157 10>;
+ assigned-clock-parents = <&k3_clks 157 18>;
+ #clock-cells = <0>;
+ };
};
dmss: bus@48000000 {
@@ -120,8 +138,8 @@
compatible = "ti,am64-dmss-pktdma";
reg = <0x00 0x485c0000 0x00 0x100>,
<0x00 0x4a800000 0x00 0x20000>,
- <0x00 0x4aa00000 0x00 0x40000>,
- <0x00 0x4b800000 0x00 0x400000>,
+ <0x00 0x4aa00000 0x00 0x20000>,
+ <0x00 0x4b800000 0x00 0x200000>,
<0x00 0x485e0000 0x00 0x10000>,
<0x00 0x484a0000 0x00 0x2000>,
<0x00 0x484c0000 0x00 0x2000>,
@@ -216,6 +234,14 @@
};
};
+ crypto: crypto@40900000 {
+ compatible = "ti,am62-sa3ul";
+ reg = <0x00 0x40900000 0x00 0x1200>;
+ dmas = <&main_pktdma 0xf501 0>, <&main_pktdma 0x7506 0>,
+ <&main_pktdma 0x7507 0>;
+ dma-names = "tx", "rx1", "rx2";
+ };
+
secure_proxy_sa3: mailbox@43600000 {
compatible = "ti,am654-secure-proxy";
#mbox-cells = <1>;
@@ -713,7 +739,7 @@
label = "port1";
phys = <&phy_gmii_sel 1>;
mac-address = [00 00 00 00 00 00];
- ti,syscon-efuse = <&wkup_conf 0x200>;
+ ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
};
cpsw_port2: port@2 {
diff --git a/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
new file mode 100644
index 000000000000..a5aceaa39670
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
@@ -0,0 +1,330 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2023 - 2024 PHYTEC America LLC
+ * Author: Garrett Giordano <[email protected]>
+ *
+ * Product homepage:
+ * https://www.phytec.com/product/phycore-am62a
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/net/ti-dp83867.h>
+
+/ {
+ model = "PHYTEC phyCORE-AM62Ax";
+ compatible = "phytec,am62a-phycore-som", "ti,am62a7";
+
+ aliases {
+ ethernet0 = &cpsw_port1;
+ gpio0 = &main_gpio0;
+ gpio1 = &main_gpio1;
+ i2c0 = &main_i2c0;
+ mmc0 = &sdhci0;
+ rtc0 = &i2c_som_rtc;
+ spi0 = &ospi0;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&leds_pins_default>;
+
+ led-0 {
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&main_gpio0 13 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ function = LED_FUNCTION_HEARTBEAT;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ /* 2G RAM */
+ reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* global cma region */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x00 0x24000000>;
+ alloc-ranges = <0x00 0xc0000000 0x00 0x24000000>;
+ linux,cma-default;
+ };
+
+ secure_tfa_ddr: tfa@9e780000 {
+ reg = <0x00 0x9e780000 0x00 0x80000>;
+ alignment = <0x1000>;
+ no-map;
+ };
+
+ secure_ddr: optee@9e800000 {
+ reg = <0x00 0x9e800000 0x00 0x01800000>; /* for OP-TEE */
+ alignment = <0x1000>;
+ no-map;
+ };
+
+ wkup_r5fss0_core0_memory_region: r5f-dma-memory@9c900000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0x9c900000 0x00 0x01e00000>;
+ no-map;
+ };
+ };
+
+ vcc_5v0_som: regulator-vcc-5v0-som {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_5V0_SOM";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&main_pmx0 {
+ leds_pins_default: leds-default-pins {
+ pinctrl-single,pins = <
+ AM62AX_IOPAD(0x034, PIN_OUTPUT, 7) /* (K20) OSPI0_CSN2.GPIO0_13 */
+ >;
+ };
+
+ main_i2c0_pins_default: main-i2c0-default-pins {
+ pinctrl-single,pins = <
+ AM62AX_IOPAD(0x1e0, PIN_INPUT_PULLUP, 0) /* (D17) I2C0_SCL */
+ AM62AX_IOPAD(0x1e4, PIN_INPUT_PULLUP, 0) /* (E16) I2C0_SDA */
+ >;
+ };
+
+ main_mdio1_pins_default: main-mdio1-default-pins {
+ pinctrl-single,pins = <
+ AM62AX_IOPAD(0x160, PIN_OUTPUT, 0) /* (V12) MDIO0_MDC */
+ AM62AX_IOPAD(0x15c, PIN_INPUT, 0) /* (V13) MDIO0_MDIO */
+ >;
+ };
+
+ main_mmc0_pins_default: main-mmc0-default-pins {
+ pinctrl-single,pins = <
+ AM62AX_IOPAD(0x220, PIN_INPUT_PULLUP, 0) /* (Y6) MMC0_CMD */
+ AM62AX_IOPAD(0x218, PIN_INPUT_PULLDOWN, 0) /* (AB7) MMC0_CLK */
+ AM62AX_IOPAD(0x214, PIN_INPUT_PULLUP, 0) /* (AA6) MMC0_DAT0 */
+ AM62AX_IOPAD(0x210, PIN_INPUT_PULLUP, 0) /* (AB6) MMC0_DAT1 */
+ AM62AX_IOPAD(0x20c, PIN_INPUT_PULLUP, 0) /* (Y7) MMC0_DAT2 */
+ AM62AX_IOPAD(0x208, PIN_INPUT_PULLUP, 0) /* (AA7) MMC0_DAT3 */
+ AM62AX_IOPAD(0x204, PIN_INPUT_PULLUP, 0) /* (Y8) MMC0_DAT4 */
+ AM62AX_IOPAD(0x200, PIN_INPUT_PULLUP, 0) /* (W7) MMC0_DAT5 */
+ AM62AX_IOPAD(0x1fc, PIN_INPUT_PULLUP, 0) /* (W9) MMC0_DAT6 */
+ AM62AX_IOPAD(0x1f8, PIN_INPUT_PULLUP, 0) /* (AB8) MMC0_DAT7 */
+ >;
+ };
+
+ main_rgmii1_pins_default: main-rgmii1-default-pins {
+ pinctrl-single,pins = <
+ AM62AX_IOPAD(0x14c, PIN_INPUT, 0) /* (AB16) RGMII1_RD0 */
+ AM62AX_IOPAD(0x150, PIN_INPUT, 0) /* (V15) RGMII1_RD1 */
+ AM62AX_IOPAD(0x154, PIN_INPUT, 0) /* (W15) RGMII1_RD2 */
+ AM62AX_IOPAD(0x158, PIN_INPUT, 0) /* (V14) RGMII1_RD3 */
+ AM62AX_IOPAD(0x148, PIN_INPUT, 0) /* (AA16) RGMII1_RXC */
+ AM62AX_IOPAD(0x144, PIN_INPUT, 0) /* (AA15) RGMII1_RX_CTL */
+ AM62AX_IOPAD(0x134, PIN_OUTPUT, 0) /* (Y17) RGMII1_TD0 */
+ AM62AX_IOPAD(0x138, PIN_OUTPUT, 0) /* (V16) RGMII1_TD1 */
+ AM62AX_IOPAD(0x13c, PIN_OUTPUT, 0) /* (Y16) RGMII1_TD2 */
+ AM62AX_IOPAD(0x140, PIN_OUTPUT, 0) /* (AA17) RGMII1_TD3 */
+ AM62AX_IOPAD(0x130, PIN_OUTPUT, 0) /* (AB17) RGMII1_TXC */
+ AM62AX_IOPAD(0x12c, PIN_OUTPUT, 0) /* (W16) RGMII1_TX_CTL */
+ >;
+ };
+
+ ospi0_pins_default: ospi0-default-pins {
+ pinctrl-single,pins = <
+ AM62AX_IOPAD(0x000, PIN_OUTPUT, 0) /* (L22) OSPI0_CLK */
+ AM62AX_IOPAD(0x02c, PIN_OUTPUT, 0) /* (H21) OSPI0_CSn0 */
+ AM62AX_IOPAD(0x038, PIN_OUTPUT, 0) /* (G20) OSPI0_CSn3 */
+ AM62AX_IOPAD(0x00c, PIN_INPUT, 0) /* (J21) OSPI0_D0 */
+ AM62AX_IOPAD(0x010, PIN_INPUT, 0) /* (J18) OSPI0_D1 */
+ AM62AX_IOPAD(0x014, PIN_INPUT, 0) /* (J19) OSPI0_D2 */
+ AM62AX_IOPAD(0x018, PIN_INPUT, 0) /* (H18) OSPI0_D3 */
+ AM62AX_IOPAD(0x01c, PIN_INPUT, 0) /* (K21) OSPI0_D4 */
+ AM62AX_IOPAD(0x020, PIN_INPUT, 0) /* (H19) OSPI0_D5 */
+ AM62AX_IOPAD(0x024, PIN_INPUT, 0) /* (J20) OSPI0_D6 */
+ AM62AX_IOPAD(0x028, PIN_INPUT, 0) /* (J22) OSPI0_D7 */
+ AM62AX_IOPAD(0x008, PIN_INPUT, 0) /* (L21) OSPI0_DQS */
+ >;
+ };
+
+ pmic_irq_pins_default: pmic-irq-default-pins {
+ pinctrl-single,pins = <
+ AM62AX_IOPAD(0x1f4, PIN_INPUT, 0) /* (D16) EXTINTn */
+ >;
+ };
+};
+
+&cpsw3g {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_rgmii1_pins_default>;
+};
+
+&cpsw_port1 {
+ phy-mode = "rgmii-rxid";
+ phy-handle = <&cpsw3g_phy1>;
+};
+
+&cpsw3g_mdio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mdio1_pins_default>;
+
+ cpsw3g_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+};
+
+&fss {
+ status = "okay";
+};
+
+&main_i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c0_pins_default>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ pmic@30 {
+ compatible = "ti,tps65219";
+ reg = <0x30>;
+ buck1-supply = <&vcc_5v0_som>;
+ buck2-supply = <&vcc_5v0_som>;
+ buck3-supply = <&vcc_5v0_som>;
+ ldo1-supply = <&vdd_3v3>;
+ ldo2-supply = <&vdd_1v8>;
+ ldo3-supply = <&vcc_5v0_som>;
+ ldo4-supply = <&vcc_5v0_som>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_irq_pins_default>;
+ interrupt-parent = <&gic500>;
+ interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ ti,power-button;
+ system-power-controller;
+
+ regulators {
+ vdd_3v3: buck1 {
+ regulator-name = "VDD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vdd_1v8: buck2 {
+ regulator-name = "VDD_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vdd_lpddr4: buck3 {
+ regulator-name = "VDD_LPDDR4";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vddshv5_sdio: ldo1 {
+ regulator-name = "VDDSHV5_SDIO";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-allow-bypass;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vddr_core: ldo2 {
+ regulator-name = "VDDR_CORE";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vdda_1v8: ldo3 {
+ regulator-name = "VDDA_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vdd_2v5: ldo4 {
+ regulator-name = "VDD_2V5";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c32";
+ pagesize = <32>;
+ reg = <0x50>;
+ };
+
+ i2c_som_rtc: rtc@52 {
+ compatible = "microcrystal,rv3028";
+ reg = <0x52>;
+ };
+};
+
+&main_gpio0 {
+ status = "okay";
+};
+
+&main_gpio1 {
+ status = "okay";
+};
+
+&main_gpio_intr {
+ status = "okay";
+};
+
+&ospi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ospi0_pins_default>;
+ status = "okay";
+
+ serial_flash: 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 = <0>;
+ };
+};
+
+&sdhci0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mmc0_pins_default>;
+ disable-wp;
+ non-removable;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi
index 98043e9aa316..f5ac101a04df 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi
@@ -6,9 +6,8 @@
*/
&cbass_wakeup {
- wkup_conf: syscon@43000000 {
- compatible = "ti,j721e-system-controller", "syscon", "simple-mfd";
- reg = <0x00 0x43000000 0x00 0x20000>;
+ wkup_conf: bus@43000000 {
+ compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00 0x00 0x43000000 0x20000>;
@@ -18,6 +17,11 @@
reg = <0x14 0x4>;
};
+ cpsw_mac_syscon: ethernet-mac-syscon@200 {
+ compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
+ reg = <0x200 0x8>;
+ };
+
usb0_phy_ctrl: syscon@4008 {
compatible = "ti,am62-usb-phy-ctrl", "syscon";
reg = <0x4008 0x4>;
@@ -59,7 +63,6 @@
clock-names = "vbus", "osc32k";
power-domains = <&k3_pds 117 TI_SCI_PD_EXCLUSIVE>;
wakeup-source;
- status = "disabled";
};
wkup_rti0: watchdog@2b000000 {
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
new file mode 100644
index 000000000000..3b93409b23e7
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-phyboard-lyra-rdk.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2023 - 2024 PHYTEC America LLC
+ * Author: Garrett Giordano <[email protected]>
+ *
+ * Product homepage:
+ * https://www.phytec.com/product/phyboard-am62a
+ */
+
+#include "k3-am62a7.dtsi"
+#include "k3-am62a-phycore-som.dtsi"
+#include "k3-am62x-phyboard-lyra.dtsi"
+
+/ {
+ compatible = "phytec,am62a7-phyboard-lyra-rdk",
+ "phytec,am62a-phycore-som", "ti,am62a7";
+ model = "PHYTEC phyBOARD-Lyra AM62A7";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
index fa43cd0b631e..67faf46d7a35 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
@@ -40,6 +40,15 @@
#size-cells = <2>;
ranges;
+ /* global cma region */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x00 0x24000000>;
+ alloc-ranges = <0x00 0xc0000000 0x00 0x24000000>;
+ linux,cma-default;
+ };
+
secure_tfa_ddr: tfa@9e780000 {
reg = <0x00 0x9e780000 0x00 0x80000>;
alignment = <0x1000>;
@@ -701,8 +710,6 @@
0 0 0 0
0 0 0 0
>;
- tx-num-evt = <32>;
- rx-num-evt = <32>;
};
&dss {
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
new file mode 100644
index 000000000000..9701fc69aed9
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi
@@ -0,0 +1,1062 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree file for the MAIN domain peripherals shared by AM62P and J722S
+ *
+ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+&cbass_main {
+ oc_sram: sram@70000000 {
+ compatible = "mmio-sram";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ gic500: interrupt-controller@1800000 {
+ compatible = "arm,gic-v3";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00 0x01800000 0x00 0x10000>, /* GICD */
+ <0x00 0x01880000 0x00 0xc0000>, /* GICR */
+ <0x01 0x00000000 0x00 0x2000>, /* GICC */
+ <0x01 0x00010000 0x00 0x1000>, /* GICH */
+ <0x01 0x00020000 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_conf: bus@100000 {
+ compatible = "simple-bus";
+ reg = <0x00 0x00100000 0x00 0x20000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x00 0x00 0x00100000 0x20000>;
+
+ phy_gmii_sel: phy@4044 {
+ compatible = "ti,am654-phy-gmii-sel";
+ reg = <0x4044 0x8>;
+ #phy-cells = <1>;
+ };
+
+ epwm_tbclk: clock-controller@4130 {
+ compatible = "ti,am62-epwm-tbclk";
+ reg = <0x4130 0x4>;
+ #clock-cells = <1>;
+ };
+ };
+
+ dmss: bus@48000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dma-ranges;
+ ranges = <0x00 0x48000000 0x00 0x48000000 0x00 0x06400000>;
+ bootph-all;
+
+ ti,sci-dev-id = <25>;
+
+ secure_proxy_main: mailbox@4d000000 {
+ compatible = "ti,am654-secure-proxy";
+ #mbox-cells = <1>;
+ reg-names = "target_data", "rt", "scfg";
+ reg = <0x00 0x4d000000 0x00 0x80000>,
+ <0x00 0x4a600000 0x00 0x80000>,
+ <0x00 0x4a400000 0x00 0x80000>;
+ interrupt-names = "rx_012";
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ bootph-all;
+ };
+
+ inta_main_dmss: interrupt-controller@48000000 {
+ compatible = "ti,sci-inta";
+ reg = <0x00 0x48000000 0x00 0x100000>;
+ #interrupt-cells = <0>;
+ interrupt-controller;
+ interrupt-parent = <&gic500>;
+ msi-controller;
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <28>;
+ ti,unmapped-event-sources = <&main_bcdma>, <&main_pktdma>;
+ };
+
+ main_bcdma: dma-controller@485c0100 {
+ compatible = "ti,am64-dmss-bcdma";
+ reg = <0x00 0x485c0100 0x00 0x100>,
+ <0x00 0x4c000000 0x00 0x20000>,
+ <0x00 0x4a820000 0x00 0x20000>,
+ <0x00 0x4aa40000 0x00 0x20000>,
+ <0x00 0x4bc00000 0x00 0x100000>,
+ <0x00 0x48600000 0x00 0x8000>,
+ <0x00 0x484a4000 0x00 0x2000>,
+ <0x00 0x484c2000 0x00 0x2000>,
+ <0x00 0x48420000 0x00 0x2000>;
+ reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt",
+ "ring", "tchan", "rchan", "bchan";
+ msi-parent = <&inta_main_dmss>;
+ #dma-cells = <3>;
+
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <26>;
+ ti,sci-rm-range-bchan = <0x20>; /* BLOCK_COPY_CHAN */
+ ti,sci-rm-range-rchan = <0x21>; /* SPLIT_TR_RX_CHAN */
+ ti,sci-rm-range-tchan = <0x22>; /* SPLIT_TR_TX_CHAN */
+ bootph-all;
+ };
+
+ main_pktdma: dma-controller@485c0000 {
+ compatible = "ti,am64-dmss-pktdma";
+ reg = <0x00 0x485c0000 0x00 0x100>,
+ <0x00 0x4a800000 0x00 0x20000>,
+ <0x00 0x4aa00000 0x00 0x20000>,
+ <0x00 0x4b800000 0x00 0x200000>,
+ <0x00 0x485e0000 0x00 0x10000>,
+ <0x00 0x484a0000 0x00 0x2000>,
+ <0x00 0x484c0000 0x00 0x2000>,
+ <0x00 0x48430000 0x00 0x1000>;
+ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt",
+ "ring", "tchan", "rchan", "rflow";
+ msi-parent = <&inta_main_dmss>;
+ #dma-cells = <2>;
+ bootph-all;
+
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <30>;
+ ti,sci-rm-range-tchan = <0x23>, /* UNMAPPED_TX_CHAN */
+ <0x24>, /* CPSW_TX_CHAN */
+ <0x25>, /* SAUL_TX_0_CHAN */
+ <0x26>; /* SAUL_TX_1_CHAN */
+ ti,sci-rm-range-tflow = <0x10>, /* RING_UNMAPPED_TX_CHAN */
+ <0x11>, /* RING_CPSW_TX_CHAN */
+ <0x12>, /* RING_SAUL_TX_0_CHAN */
+ <0x13>; /* RING_SAUL_TX_1_CHAN */
+ ti,sci-rm-range-rchan = <0x29>, /* UNMAPPED_RX_CHAN */
+ <0x2b>, /* CPSW_RX_CHAN */
+ <0x2d>, /* SAUL_RX_0_CHAN */
+ <0x2f>, /* SAUL_RX_1_CHAN */
+ <0x31>, /* SAUL_RX_2_CHAN */
+ <0x33>; /* SAUL_RX_3_CHAN */
+ ti,sci-rm-range-rflow = <0x2a>, /* FLOW_UNMAPPED_RX_CHAN */
+ <0x2c>, /* FLOW_CPSW_RX_CHAN */
+ <0x2e>, /* FLOW_SAUL_RX_0/1_CHAN */
+ <0x32>; /* FLOW_SAUL_RX_2/3_CHAN */
+ };
+ };
+
+ dmss_csi: bus@4e000000 {
+ compatible = "simple-bus";
+ ranges = <0x00 0x4e000000 0x00 0x4e000000 0x00 0x408000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dma-ranges;
+ ti,sci-dev-id = <198>;
+
+ inta_main_dmss_csi: interrupt-controller@4e400000 {
+ compatible = "ti,sci-inta";
+ reg = <0x00 0x4e400000 0x00 0x8000>;
+ #interrupt-cells = <0>;
+ interrupt-controller;
+ interrupt-parent = <&gic500>;
+ msi-controller;
+ power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <200>;
+ ti,interrupt-ranges = <0 237 8>;
+ ti,unmapped-event-sources = <&main_bcdma_csi>;
+ };
+
+ main_bcdma_csi: dma-controller@4e230000 {
+ compatible = "ti,am62a-dmss-bcdma-csirx";
+ reg = <0x00 0x4e230000 0x00 0x100>,
+ <0x00 0x4e180000 0x00 0x8000>,
+ <0x00 0x4e100000 0x00 0x10000>;
+ reg-names = "gcfg", "rchanrt", "ringrt";
+ #dma-cells = <3>;
+ msi-parent = <&inta_main_dmss_csi>;
+ power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <199>;
+ ti,sci-rm-range-rchan = <0x21>;
+ };
+ };
+
+ dmsc: system-controller@44043000 {
+ compatible = "ti,k2g-sci";
+ ti,host-id = <12>;
+ mbox-names = "rx", "tx";
+ mboxes = <&secure_proxy_main 12>,
+ <&secure_proxy_main 13>;
+ reg-names = "debug_messages";
+ reg = <0x00 0x44043000 0x00 0xfe0>;
+ bootph-all;
+
+ 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;
+ };
+ };
+
+ crypto: crypto@40900000 {
+ compatible = "ti,am62-sa3ul";
+ reg = <0x00 0x40900000 0x00 0x1200>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dmas = <&main_pktdma 0xf501 0>, <&main_pktdma 0x7506 0>,
+ <&main_pktdma 0x7507 0>;
+ dma-names = "tx", "rx1", "rx2";
+ };
+
+ secure_proxy_sa3: mailbox@43600000 {
+ compatible = "ti,am654-secure-proxy";
+ #mbox-cells = <1>;
+ reg-names = "target_data", "rt", "scfg";
+ reg = <0x00 0x43600000 0x00 0x10000>,
+ <0x00 0x44880000 0x00 0x20000>,
+ <0x00 0x44860000 0x00 0x20000>;
+ /*
+ * Marked Disabled:
+ * Node is incomplete as it is meant for bootloaders and
+ * firmware on non-MPU processors
+ */
+ status = "disabled";
+ bootph-all;
+ };
+
+ main_pmx0: pinctrl@f4000 {
+ compatible = "pinctrl-single";
+ reg = <0x00 0xf4000 0x00 0x2ac>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0xffffffff>;
+ bootph-all;
+ };
+
+ main_esm: esm@420000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x420000 0x00 0x1000>;
+ ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>;
+ bootph-pre-ram;
+ };
+
+ main_timer0: timer@2400000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2400000 0x00 0x400>;
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 36 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 36 2>;
+ assigned-clock-parents = <&k3_clks 36 3>;
+ power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ bootph-all;
+ };
+
+ main_timer1: timer@2410000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2410000 0x00 0x400>;
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 37 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 37 2>;
+ assigned-clock-parents = <&k3_clks 37 3>;
+ power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer2: timer@2420000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2420000 0x00 0x400>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 38 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 38 2>;
+ assigned-clock-parents = <&k3_clks 38 3>;
+ power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer3: timer@2430000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2430000 0x00 0x400>;
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 39 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 39 2>;
+ assigned-clock-parents = <&k3_clks 39 3>;
+ power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer4: timer@2440000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2440000 0x00 0x400>;
+ interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 40 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 40 2>;
+ assigned-clock-parents = <&k3_clks 40 3>;
+ power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer5: timer@2450000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2450000 0x00 0x400>;
+ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 41 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 41 2>;
+ assigned-clock-parents = <&k3_clks 41 3>;
+ power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer6: timer@2460000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2460000 0x00 0x400>;
+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 42 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 42 2>;
+ assigned-clock-parents = <&k3_clks 42 3>;
+ power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer7: timer@2470000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2470000 0x00 0x400>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 43 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 43 2>;
+ assigned-clock-parents = <&k3_clks 43 3>;
+ power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_uart0: serial@2800000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02800000 0x00 0x100>;
+ interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 146 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_uart1: serial@2810000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02810000 0x00 0x100>;
+ interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 152 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_uart2: serial@2820000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02820000 0x00 0x100>;
+ interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 153 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_uart3: serial@2830000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02830000 0x00 0x100>;
+ interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 154 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_uart4: serial@2840000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02840000 0x00 0x100>;
+ interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 155 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 155 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_uart5: serial@2850000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02850000 0x00 0x100>;
+ interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 156 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_uart6: serial@2860000 {
+ compatible = "ti,am64-uart", "ti,am654-uart";
+ reg = <0x00 0x02860000 0x00 0x100>;
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 158 0>;
+ clock-names = "fclk";
+ status = "disabled";
+ };
+
+ main_i2c0: i2c@20000000 {
+ compatible = "ti,am64-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x20000000 0x00 0x100>;
+ interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 102 2>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ main_i2c1: i2c@20010000 {
+ compatible = "ti,am64-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x20010000 0x00 0x100>;
+ interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 103 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 103 2>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ main_i2c2: i2c@20020000 {
+ compatible = "ti,am64-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x20020000 0x00 0x100>;
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 104 2>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ main_i2c3: i2c@20030000 {
+ compatible = "ti,am64-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x20030000 0x00 0x100>;
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 105 2>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ main_spi0: spi@20100000 {
+ compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+ reg = <0x00 0x20100000 0x00 0x400>;
+ interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 141 0>;
+ status = "disabled";
+ };
+
+ main_spi1: spi@20110000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x20110000 0x00 0x400>;
+ interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 142 0>;
+ status = "disabled";
+ };
+
+ main_spi2: spi@20120000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x20120000 0x00 0x400>;
+ interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 143 0>;
+ status = "disabled";
+ };
+
+ 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 = <&dmsc>;
+ ti,sci-dev-id = <3>;
+ ti,interrupt-ranges = <0 32 16>;
+ };
+
+ main_gpio0: gpio@600000 {
+ compatible = "ti,am64-gpio", "ti,keystone-gpio";
+ reg = <0x00 0x00600000 0x00 0x100>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&main_gpio_intr>;
+ interrupts = <190>, <191>, <192>,
+ <193>, <194>, <195>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ ti,davinci-gpio-unbanked = <0>;
+ power-domains = <&k3_pds 77 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 77 0>;
+ clock-names = "gpio";
+ };
+
+ main_gpio1: gpio@601000 {
+ compatible = "ti,am64-gpio", "ti,keystone-gpio";
+ reg = <0x00 0x00601000 0x00 0x100>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&main_gpio_intr>;
+ interrupts = <180>, <181>, <182>,
+ <183>, <184>, <185>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ ti,davinci-gpio-unbanked = <0>;
+ power-domains = <&k3_pds 78 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 78 0>;
+ clock-names = "gpio";
+ };
+
+ sdhci0: mmc@fa10000 {
+ compatible = "ti,am64-sdhci-8bit";
+ reg = <0x00 0x0fa10000 0x00 0x1000>, <0x00 0x0fa18000 0x00 0x400>;
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 57 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 57 1>, <&k3_clks 57 2>;
+ clock-names = "clk_ahb", "clk_xin";
+ assigned-clocks = <&k3_clks 57 2>;
+ assigned-clock-parents = <&k3_clks 57 4>;
+ bus-width = <8>;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ ti,clkbuf-sel = <0x7>;
+ ti,strobe-sel = <0x77>;
+ ti,trm-icp = <0x8>;
+ ti,otap-del-sel-legacy = <0x1>;
+ ti,otap-del-sel-mmc-hs = <0x1>;
+ 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,itap-del-sel-ddr52 = <0x3>;
+ status = "disabled";
+ };
+
+ sdhci1: mmc@fa00000 {
+ compatible = "ti,am62-sdhci";
+ reg = <0x00 0x0fa00000 0x00 0x1000>, <0x00 0x0fa08000 0x00 0x400>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 58 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 58 5>, <&k3_clks 58 6>;
+ clock-names = "clk_ahb", "clk_xin";
+ bus-width = <4>;
+ ti,clkbuf-sel = <0x7>;
+ 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-ddr50 = <0x9>;
+ ti,otap-del-sel-sdr104 = <0x6>;
+ 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";
+ };
+
+ sdhci2: mmc@fa20000 {
+ compatible = "ti,am62-sdhci";
+ reg = <0x00 0x0fa20000 0x00 0x1000>, <0x00 0x0fa28000 0x00 0x400>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 184 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 184 5>, <&k3_clks 184 6>;
+ clock-names = "clk_ahb", "clk_xin";
+ bus-width = <4>;
+ ti,clkbuf-sel = <0x7>;
+ 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-ddr50 = <0x9>;
+ ti,otap-del-sel-sdr104 = <0x6>;
+ 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";
+ };
+
+ usbss0: usb@f900000 {
+ compatible = "ti,am62-usb";
+ reg = <0x00 0x0f900000 0x00 0x800>,
+ <0x00 0x0f908000 0x00 0x400>;
+ clocks = <&k3_clks 161 3>;
+ clock-names = "ref";
+ ti,syscon-phy-pll-refclk = <&usb0_phy_ctrl 0x0>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ power-domains = <&k3_pds 178 TI_SCI_PD_EXCLUSIVE>;
+ ranges;
+ status = "disabled";
+
+ usb0: usb@31000000 {
+ compatible = "snps,dwc3";
+ reg = <0x00 0x31000000 0x00 0x50000>;
+ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
+ <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; /* irq.0 */
+ interrupt-names = "host", "peripheral";
+ maximum-speed = "high-speed";
+ dr_mode = "otg";
+ snps,usb2-gadget-lpm-disable;
+ snps,usb2-lpm-disable;
+ };
+ };
+
+ fss: bus@fc00000 {
+ compatible = "simple-bus";
+ reg = <0x00 0x0fc00000 0x00 0x70000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ospi0: spi@fc40000 {
+ compatible = "ti,am654-ospi", "cdns,qspi-nor";
+ reg = <0x00 0x0fc40000 0x00 0x100>,
+ <0x05 0x00000000 0x01 0x00000000>;
+ interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+ cdns,fifo-depth = <256>;
+ cdns,fifo-width = <4>;
+ cdns,trigger-address = <0x0>;
+ clocks = <&k3_clks 75 7>;
+ assigned-clocks = <&k3_clks 75 7>;
+ assigned-clock-parents = <&k3_clks 75 8>;
+ assigned-clock-rates = <166666666>;
+ power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ };
+
+ cpsw3g: ethernet@8000000 {
+ compatible = "ti,am642-cpsw-nuss";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ reg = <0x00 0x08000000 0x00 0x200000>;
+ reg-names = "cpsw_nuss";
+ ranges = <0x00 0x00 0x00 0x08000000 0x00 0x200000>;
+ clocks = <&k3_clks 13 0>;
+ assigned-clocks = <&k3_clks 13 3>;
+ assigned-clock-parents = <&k3_clks 13 11>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 13 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+
+ dmas = <&main_pktdma 0xc600 15>,
+ <&main_pktdma 0xc601 15>,
+ <&main_pktdma 0xc602 15>,
+ <&main_pktdma 0xc603 15>,
+ <&main_pktdma 0xc604 15>,
+ <&main_pktdma 0xc605 15>,
+ <&main_pktdma 0xc606 15>,
+ <&main_pktdma 0xc607 15>,
+ <&main_pktdma 0x4600 15>;
+ dma-names = "tx0", "tx1", "tx2", "tx3", "tx4", "tx5", "tx6",
+ "tx7", "rx";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpsw_port1: port@1 {
+ reg = <1>;
+ ti,mac-only;
+ label = "port1";
+ phys = <&phy_gmii_sel 1>;
+ mac-address = [00 00 00 00 00 00];
+ ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
+ status = "disabled";
+ };
+
+ cpsw_port2: port@2 {
+ reg = <2>;
+ ti,mac-only;
+ label = "port2";
+ phys = <&phy_gmii_sel 2>;
+ mac-address = [00 00 00 00 00 00];
+ status = "disabled";
+ };
+ };
+
+ cpsw3g_mdio: mdio@f00 {
+ compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+ reg = <0x00 0xf00 0x00 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 13 0>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ status = "disabled";
+ };
+
+ cpts@3d000 {
+ compatible = "ti,j721e-cpts";
+ reg = <0x00 0x3d000 0x00 0x400>;
+ clocks = <&k3_clks 13 3>;
+ clock-names = "cpts";
+ interrupts-extended = <&gic500 GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cpts";
+ ti,cpts-ext-ts-inputs = <4>;
+ ti,cpts-periodic-outputs = <2>;
+ };
+ };
+
+ hwspinlock: spinlock@2a000000 {
+ compatible = "ti,am64-hwspinlock";
+ reg = <0x00 0x2a000000 0x00 0x1000>;
+ #hwlock-cells = <1>;
+ };
+
+ mailbox0_cluster0: mailbox@29000000 {
+ compatible = "ti,am64-mailbox";
+ reg = <0x00 0x29000000 0x00 0x200>;
+ interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ };
+
+ mailbox0_cluster1: mailbox@29010000 {
+ compatible = "ti,am64-mailbox";
+ reg = <0x00 0x29010000 0x00 0x200>;
+ interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ };
+
+ mailbox0_cluster2: mailbox@29020000 {
+ compatible = "ti,am64-mailbox";
+ reg = <0x00 0x29020000 0x00 0x200>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ };
+
+ mailbox0_cluster3: mailbox@29030000 {
+ compatible = "ti,am64-mailbox";
+ reg = <0x00 0x29030000 0x00 0x200>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ };
+
+ ecap0: pwm@23100000 {
+ compatible = "ti,am3352-ecap";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23100000 0x00 0x100>;
+ power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 51 0>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ ecap1: pwm@23110000 {
+ compatible = "ti,am3352-ecap";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23110000 0x00 0x100>;
+ power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 52 0>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ ecap2: pwm@23120000 {
+ compatible = "ti,am3352-ecap";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23120000 0x00 0x100>;
+ power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 53 0>;
+ clock-names = "fck";
+ status = "disabled";
+ };
+
+ main_mcan0: can@20701000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x20701000 0x00 0x200>,
+ <0x00 0x20708000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 98 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 98 6>, <&k3_clks 98 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan1: can@20711000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x20711000 0x00 0x200>,
+ <0x00 0x20718000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 99 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 99 6>, <&k3_clks 99 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_rti0: watchdog@e000000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x0e000000 0x00 0x100>;
+ clocks = <&k3_clks 125 0>;
+ power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 125 0>;
+ assigned-clock-parents = <&k3_clks 125 2>;
+ };
+
+ main_rti1: watchdog@e010000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x0e010000 0x00 0x100>;
+ clocks = <&k3_clks 126 0>;
+ power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 126 0>;
+ assigned-clock-parents = <&k3_clks 126 2>;
+ };
+
+ main_rti2: watchdog@e020000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x0e020000 0x00 0x100>;
+ clocks = <&k3_clks 127 0>;
+ power-domains = <&k3_pds 127 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 127 0>;
+ assigned-clock-parents = <&k3_clks 127 2>;
+ };
+
+ main_rti3: watchdog@e030000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x0e030000 0x00 0x100>;
+ clocks = <&k3_clks 128 0>;
+ power-domains = <&k3_pds 128 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 128 0>;
+ assigned-clock-parents = <&k3_clks 128 2>;
+ };
+
+ main_rti15: watchdog@e0f0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x0e0f0000 0x00 0x100>;
+ clocks = <&k3_clks 130 0>;
+ power-domains = <&k3_pds 130 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 130 0>;
+ assigned-clock-parents = <&k3_clks 130 2>;
+ };
+
+ epwm0: pwm@23000000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23000000 0x00 0x100>;
+ power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ epwm1: pwm@23010000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23010000 0x00 0x100>;
+ power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ epwm2: pwm@23020000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x23020000 0x00 0x100>;
+ power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ mcasp0: audio-controller@2b00000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b00000 0x00 0x2000>,
+ <0x00 0x02b08000 0x00 0x400>;
+ reg-names = "mpu", "dat";
+ interrupts = <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+
+ dmas = <&main_bcdma 0 0xc500 0>, <&main_bcdma 0 0x4500 0>;
+ dma-names = "tx", "rx";
+
+ clocks = <&k3_clks 190 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 190 0>;
+ assigned-clock-parents = <&k3_clks 190 2>;
+ power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ mcasp1: audio-controller@2b10000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b10000 0x00 0x2000>,
+ <0x00 0x02b18000 0x00 0x400>;
+ reg-names = "mpu", "dat";
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+
+ dmas = <&main_bcdma 0 0xc501 0>, <&main_bcdma 0 0x4501 0>;
+ dma-names = "tx", "rx";
+
+ clocks = <&k3_clks 191 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 191 0>;
+ assigned-clock-parents = <&k3_clks 191 2>;
+ power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ mcasp2: audio-controller@2b20000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b20000 0x00 0x2000>,
+ <0x00 0x02b28000 0x00 0x400>;
+ reg-names = "mpu", "dat";
+ interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+
+ dmas = <&main_bcdma 0 0xc502 0>, <&main_bcdma 0 0x4502 0>;
+ dma-names = "tx", "rx";
+
+ clocks = <&k3_clks 192 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 192 0>;
+ assigned-clock-parents = <&k3_clks 192 2>;
+ power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ ti_csi2rx0: ticsi2rx@30102000 {
+ compatible = "ti,j721e-csi2rx-shim";
+ reg = <0x00 0x30102000 0x00 0x1000>;
+ ranges;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dmas = <&main_bcdma_csi 0 0x5000 0>;
+ dma-names = "rx0";
+ power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+
+ cdns_csi2rx0: csi-bridge@30101000 {
+ compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
+ reg = <0x00 0x30101000 0x00 0x1000>;
+ clocks = <&k3_clks 182 0>, <&k3_clks 182 3>, <&k3_clks 182 0>,
+ <&k3_clks 182 0>, <&k3_clks 182 4>, <&k3_clks 182 4>;
+ 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";
+ };
+ };
+ };
+ };
+
+ dphy0: phy@30110000 {
+ compatible = "cdns,dphy-rx";
+ reg = <0x00 0x30110000 0x00 0x1100>;
+ #phy-cells = <0>;
+ power-domains = <&k3_pds 185 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ vpu: video-codec@30210000 {
+ compatible = "ti,j721s2-wave521c", "cnm,wave521c";
+ reg = <0x00 0x30210000 0x00 0x10000>;
+ interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 204 2>;
+ power-domains = <&k3_pds 204 TI_SCI_PD_EXCLUSIVE>;
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi
index b973b550eb9d..e65db6ce02bf 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
- * Device Tree file for the AM62P MCU domain peripherals
+ * Device Tree file for the MCU domain peripherals shared by AM62P and J722S
+ *
* Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/
*/
@@ -11,7 +12,15 @@
#pinctrl-cells = <1>;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0xffffffff>;
+ pinctrl-single,gpio-range =
+ <&mcu_pmx_range 0 21 PIN_GPIO_RANGE_IOPAD>,
+ <&mcu_pmx_range 23 1 PIN_GPIO_RANGE_IOPAD>,
+ <&mcu_pmx_range 32 2 PIN_GPIO_RANGE_IOPAD>;
bootph-all;
+
+ mcu_pmx_range: gpio-range {
+ #pinctrl-single,gpio-range-cells = <3>;
+ };
};
mcu_esm: esm@4100000 {
diff --git a/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-thermal.dtsi
index c7486fb2a5b4..c7486fb2a5b4 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-thermal.dtsi
diff --git a/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-wakeup.dtsi
index c71d9624ea27..315d0092e736 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-wakeup.dtsi
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
- * Device Tree file for the AM62P wakeup domain peripherals
+ * Device Tree file for the WAKEUP domain peripherals shared by AM62P and J722S
+ *
* Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/
*/
@@ -19,6 +20,11 @@
bootph-all;
};
+ cpsw_mac_syscon: ethernet-mac-syscon@200 {
+ compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
+ reg = <0x200 0x8>;
+ };
+
usb0_phy_ctrl: syscon@4008 {
compatible = "ti,am62-usb-phy-ctrl", "syscon";
reg = <0x4008 0x4>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi
index 900d1f9530a2..57383bd2eaeb 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi
@@ -1,666 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
- * Device Tree file for the AM62P main domain peripherals
+ * Device Tree file for the AM62P MAIN domain peripherals
+ *
* Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/
*/
&cbass_main {
- oc_sram: sram@70000000 {
- compatible = "mmio-sram";
- reg = <0x00 0x70000000 0x00 0x10000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x00 0x00 0x70000000 0x10000>;
- };
-
- gic500: interrupt-controller@1800000 {
- compatible = "arm,gic-v3";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
- #interrupt-cells = <3>;
- interrupt-controller;
- reg = <0x00 0x01800000 0x00 0x10000>, /* GICD */
- <0x00 0x01880000 0x00 0xc0000>, /* GICR */
- <0x01 0x00000000 0x00 0x2000>, /* GICC */
- <0x01 0x00010000 0x00 0x1000>, /* GICH */
- <0x01 0x00020000 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_conf: bus@100000 {
- compatible = "simple-bus";
- reg = <0x00 0x00100000 0x00 0x20000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x00 0x00 0x00100000 0x20000>;
-
- phy_gmii_sel: phy@4044 {
- compatible = "ti,am654-phy-gmii-sel";
- reg = <0x4044 0x8>;
- #phy-cells = <1>;
- };
-
- epwm_tbclk: clock-controller@4130 {
- compatible = "ti,am62-epwm-tbclk";
- reg = <0x4130 0x4>;
- #clock-cells = <1>;
- };
- };
-
- dmss: bus@48000000 {
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <2>;
- dma-ranges;
- ranges = <0x00 0x48000000 0x00 0x48000000 0x00 0x06400000>;
- bootph-all;
-
- ti,sci-dev-id = <25>;
-
- secure_proxy_main: mailbox@4d000000 {
- compatible = "ti,am654-secure-proxy";
- #mbox-cells = <1>;
- reg-names = "target_data", "rt", "scfg";
- reg = <0x00 0x4d000000 0x00 0x80000>,
- <0x00 0x4a600000 0x00 0x80000>,
- <0x00 0x4a400000 0x00 0x80000>;
- interrupt-names = "rx_012";
- interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
- bootph-all;
- };
-
- inta_main_dmss: interrupt-controller@48000000 {
- compatible = "ti,sci-inta";
- reg = <0x00 0x48000000 0x00 0x100000>;
- #interrupt-cells = <0>;
- interrupt-controller;
- interrupt-parent = <&gic500>;
- msi-controller;
- ti,sci = <&dmsc>;
- ti,sci-dev-id = <28>;
- ti,interrupt-ranges = <5 69 35>;
- ti,unmapped-event-sources = <&main_bcdma>, <&main_pktdma>;
- };
-
- main_bcdma: dma-controller@485c0100 {
- compatible = "ti,am64-dmss-bcdma";
- reg = <0x00 0x485c0100 0x00 0x100>,
- <0x00 0x4c000000 0x00 0x20000>,
- <0x00 0x4a820000 0x00 0x20000>,
- <0x00 0x4aa40000 0x00 0x20000>,
- <0x00 0x4bc00000 0x00 0x100000>,
- <0x00 0x48600000 0x00 0x8000>,
- <0x00 0x484a4000 0x00 0x2000>,
- <0x00 0x484c2000 0x00 0x2000>,
- <0x00 0x48420000 0x00 0x2000>;
- reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt",
- "ring", "tchan", "rchan", "bchan";
- msi-parent = <&inta_main_dmss>;
- #dma-cells = <3>;
-
- ti,sci = <&dmsc>;
- ti,sci-dev-id = <26>;
- ti,sci-rm-range-bchan = <0x20>; /* BLOCK_COPY_CHAN */
- ti,sci-rm-range-rchan = <0x21>; /* SPLIT_TR_RX_CHAN */
- ti,sci-rm-range-tchan = <0x22>; /* SPLIT_TR_TX_CHAN */
- bootph-all;
- };
-
- main_pktdma: dma-controller@485c0000 {
- compatible = "ti,am64-dmss-pktdma";
- reg = <0x00 0x485c0000 0x00 0x100>,
- <0x00 0x4a800000 0x00 0x20000>,
- <0x00 0x4aa00000 0x00 0x40000>,
- <0x00 0x4b800000 0x00 0x400000>,
- <0x00 0x485e0000 0x00 0x10000>,
- <0x00 0x484a0000 0x00 0x2000>,
- <0x00 0x484c0000 0x00 0x2000>,
- <0x00 0x48430000 0x00 0x1000>;
- reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt",
- "ring", "tchan", "rchan", "rflow";
- msi-parent = <&inta_main_dmss>;
- #dma-cells = <2>;
- bootph-all;
-
- ti,sci = <&dmsc>;
- ti,sci-dev-id = <30>;
- ti,sci-rm-range-tchan = <0x23>, /* UNMAPPED_TX_CHAN */
- <0x24>, /* CPSW_TX_CHAN */
- <0x25>, /* SAUL_TX_0_CHAN */
- <0x26>; /* SAUL_TX_1_CHAN */
- ti,sci-rm-range-tflow = <0x10>, /* RING_UNMAPPED_TX_CHAN */
- <0x11>, /* RING_CPSW_TX_CHAN */
- <0x12>, /* RING_SAUL_TX_0_CHAN */
- <0x13>; /* RING_SAUL_TX_1_CHAN */
- ti,sci-rm-range-rchan = <0x29>, /* UNMAPPED_RX_CHAN */
- <0x2b>, /* CPSW_RX_CHAN */
- <0x2d>, /* SAUL_RX_0_CHAN */
- <0x2f>, /* SAUL_RX_1_CHAN */
- <0x31>, /* SAUL_RX_2_CHAN */
- <0x33>; /* SAUL_RX_3_CHAN */
- ti,sci-rm-range-rflow = <0x2a>, /* FLOW_UNMAPPED_RX_CHAN */
- <0x2c>, /* FLOW_CPSW_RX_CHAN */
- <0x2e>, /* FLOW_SAUL_RX_0/1_CHAN */
- <0x32>; /* FLOW_SAUL_RX_2/3_CHAN */
- };
- };
-
- dmss_csi: bus@4e000000 {
- compatible = "simple-bus";
- ranges = <0x00 0x4e000000 0x00 0x4e000000 0x00 0x408000>;
- #address-cells = <2>;
- #size-cells = <2>;
- dma-ranges;
- ti,sci-dev-id = <198>;
-
- inta_main_dmss_csi: interrupt-controller@4e400000 {
- compatible = "ti,sci-inta";
- reg = <0x00 0x4e400000 0x00 0x8000>;
- #interrupt-cells = <0>;
- interrupt-controller;
- interrupt-parent = <&gic500>;
- msi-controller;
- power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
- ti,sci = <&dmsc>;
- ti,sci-dev-id = <200>;
- ti,interrupt-ranges = <0 237 8>;
- ti,unmapped-event-sources = <&main_bcdma_csi>;
- };
-
- main_bcdma_csi: dma-controller@4e230000 {
- compatible = "ti,am62a-dmss-bcdma-csirx";
- reg = <0x00 0x4e230000 0x00 0x100>,
- <0x00 0x4e180000 0x00 0x8000>,
- <0x00 0x4e100000 0x00 0x10000>;
- reg-names = "gcfg", "rchanrt", "ringrt";
- #dma-cells = <3>;
- msi-parent = <&inta_main_dmss_csi>;
- power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
- ti,sci = <&dmsc>;
- ti,sci-dev-id = <199>;
- ti,sci-rm-range-rchan = <0x21>;
- };
- };
-
- dmsc: system-controller@44043000 {
- compatible = "ti,k2g-sci";
- ti,host-id = <12>;
- mbox-names = "rx", "tx";
- mboxes = <&secure_proxy_main 12>,
- <&secure_proxy_main 13>;
- reg-names = "debug_messages";
- reg = <0x00 0x44043000 0x00 0xfe0>;
- bootph-all;
-
- 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;
- };
- };
-
- crypto: crypto@40900000 {
- compatible = "ti,am62-sa3ul";
- reg = <0x00 0x40900000 0x00 0x1200>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x00 0x40900000 0x00 0x40900000 0x00 0x30000>;
-
- dmas = <&main_pktdma 0xf501 0>, <&main_pktdma 0x7506 0>,
- <&main_pktdma 0x7507 0>;
- dma-names = "tx", "rx1", "rx2";
- };
-
- secure_proxy_sa3: mailbox@43600000 {
- compatible = "ti,am654-secure-proxy";
- #mbox-cells = <1>;
- reg-names = "target_data", "rt", "scfg";
- reg = <0x00 0x43600000 0x00 0x10000>,
- <0x00 0x44880000 0x00 0x20000>,
- <0x00 0x44860000 0x00 0x20000>;
- /*
- * Marked Disabled:
- * Node is incomplete as it is meant for bootloaders and
- * firmware on non-MPU processors
- */
- status = "disabled";
- bootph-all;
- };
-
- main_pmx0: pinctrl@f4000 {
- compatible = "pinctrl-single";
- reg = <0x00 0xf4000 0x00 0x2ac>;
- #pinctrl-cells = <1>;
- pinctrl-single,register-width = <32>;
- pinctrl-single,function-mask = <0xffffffff>;
- bootph-all;
- };
-
- main_esm: esm@420000 {
- compatible = "ti,j721e-esm";
- reg = <0x00 0x420000 0x00 0x1000>;
- ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>;
- bootph-pre-ram;
- };
-
- main_timer0: timer@2400000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2400000 0x00 0x400>;
- interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 36 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 36 2>;
- assigned-clock-parents = <&k3_clks 36 3>;
- power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- bootph-all;
- };
-
- main_timer1: timer@2410000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2410000 0x00 0x400>;
- interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 37 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 37 2>;
- assigned-clock-parents = <&k3_clks 37 3>;
- power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer2: timer@2420000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2420000 0x00 0x400>;
- interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 38 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 38 2>;
- assigned-clock-parents = <&k3_clks 38 3>;
- power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer3: timer@2430000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2430000 0x00 0x400>;
- interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 39 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 39 2>;
- assigned-clock-parents = <&k3_clks 39 3>;
- power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer4: timer@2440000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2440000 0x00 0x400>;
- interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 40 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 40 2>;
- assigned-clock-parents = <&k3_clks 40 3>;
- power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer5: timer@2450000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2450000 0x00 0x400>;
- interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 41 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 41 2>;
- assigned-clock-parents = <&k3_clks 41 3>;
- power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer6: timer@2460000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2460000 0x00 0x400>;
- interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 42 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 42 2>;
- assigned-clock-parents = <&k3_clks 42 3>;
- power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer7: timer@2470000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2470000 0x00 0x400>;
- interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 43 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 43 2>;
- assigned-clock-parents = <&k3_clks 43 3>;
- power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_uart0: serial@2800000 {
- compatible = "ti,am64-uart", "ti,am654-uart";
- reg = <0x00 0x02800000 0x00 0x100>;
- interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 146 0>;
- clock-names = "fclk";
- status = "disabled";
- };
-
- main_uart1: serial@2810000 {
- compatible = "ti,am64-uart", "ti,am654-uart";
- reg = <0x00 0x02810000 0x00 0x100>;
- interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 152 0>;
- clock-names = "fclk";
- status = "disabled";
- };
-
- main_uart2: serial@2820000 {
- compatible = "ti,am64-uart", "ti,am654-uart";
- reg = <0x00 0x02820000 0x00 0x100>;
- interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 153 0>;
- clock-names = "fclk";
- status = "disabled";
- };
-
- main_uart3: serial@2830000 {
- compatible = "ti,am64-uart", "ti,am654-uart";
- reg = <0x00 0x02830000 0x00 0x100>;
- interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 154 0>;
- clock-names = "fclk";
- status = "disabled";
- };
-
- main_uart4: serial@2840000 {
- compatible = "ti,am64-uart", "ti,am654-uart";
- reg = <0x00 0x02840000 0x00 0x100>;
- interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 155 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 155 0>;
- clock-names = "fclk";
- status = "disabled";
- };
-
- main_uart5: serial@2850000 {
- compatible = "ti,am64-uart", "ti,am654-uart";
- reg = <0x00 0x02850000 0x00 0x100>;
- interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 156 0>;
- clock-names = "fclk";
- status = "disabled";
- };
-
- main_uart6: serial@2860000 {
- compatible = "ti,am64-uart", "ti,am654-uart";
- reg = <0x00 0x02860000 0x00 0x100>;
- interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 158 0>;
- clock-names = "fclk";
- status = "disabled";
- };
-
- main_i2c0: i2c@20000000 {
- compatible = "ti,am64-i2c", "ti,omap4-i2c";
- reg = <0x00 0x20000000 0x00 0x100>;
- interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 102 2>;
- clock-names = "fck";
- status = "disabled";
- };
-
- main_i2c1: i2c@20010000 {
- compatible = "ti,am64-i2c", "ti,omap4-i2c";
- reg = <0x00 0x20010000 0x00 0x100>;
- interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 103 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 103 2>;
- clock-names = "fck";
- status = "disabled";
- };
-
- main_i2c2: i2c@20020000 {
- compatible = "ti,am64-i2c", "ti,omap4-i2c";
- reg = <0x00 0x20020000 0x00 0x100>;
- interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 104 2>;
- clock-names = "fck";
- status = "disabled";
- };
-
- main_i2c3: i2c@20030000 {
- compatible = "ti,am64-i2c", "ti,omap4-i2c";
- reg = <0x00 0x20030000 0x00 0x100>;
- interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 105 2>;
- clock-names = "fck";
- status = "disabled";
- };
-
- main_spi0: spi@20100000 {
- compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
- reg = <0x00 0x20100000 0x00 0x400>;
- interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 141 0>;
- status = "disabled";
- };
-
- main_spi1: spi@20110000 {
- compatible = "ti,am654-mcspi","ti,omap4-mcspi";
- reg = <0x00 0x20110000 0x00 0x400>;
- interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 142 0>;
- status = "disabled";
- };
-
- main_spi2: spi@20120000 {
- compatible = "ti,am654-mcspi","ti,omap4-mcspi";
- reg = <0x00 0x20120000 0x00 0x400>;
- interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 143 0>;
- status = "disabled";
- };
-
- 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 = <&dmsc>;
- ti,sci-dev-id = <3>;
- ti,interrupt-ranges = <0 32 16>;
- };
-
- main_gpio0: gpio@600000 {
- compatible = "ti,am64-gpio", "ti,keystone-gpio";
- reg = <0x00 0x00600000 0x00 0x100>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-parent = <&main_gpio_intr>;
- interrupts = <190>, <191>, <192>,
- <193>, <194>, <195>;
- interrupt-controller;
- #interrupt-cells = <2>;
- ti,ngpio = <92>;
- ti,davinci-gpio-unbanked = <0>;
- power-domains = <&k3_pds 77 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 77 0>;
- clock-names = "gpio";
- };
-
- main_gpio1: gpio@601000 {
- compatible = "ti,am64-gpio", "ti,keystone-gpio";
- reg = <0x00 0x00601000 0x00 0x100>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-parent = <&main_gpio_intr>;
- interrupts = <180>, <181>, <182>,
- <183>, <184>, <185>;
- interrupt-controller;
- #interrupt-cells = <2>;
- ti,ngpio = <52>;
- ti,davinci-gpio-unbanked = <0>;
- power-domains = <&k3_pds 78 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 78 0>;
- clock-names = "gpio";
- };
-
- sdhci0: mmc@fa10000 {
- compatible = "ti,am64-sdhci-8bit";
- reg = <0x00 0x0fa10000 0x00 0x1000>, <0x00 0x0fa18000 0x00 0x400>;
- interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 57 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 57 1>, <&k3_clks 57 2>;
- clock-names = "clk_ahb", "clk_xin";
- assigned-clocks = <&k3_clks 57 2>;
- assigned-clock-parents = <&k3_clks 57 4>;
- bus-width = <8>;
- mmc-ddr-1_8v;
- mmc-hs200-1_8v;
- mmc-hs400-1_8v;
- ti,clkbuf-sel = <0x7>;
- ti,strobe-sel = <0x77>;
- ti,trm-icp = <0x8>;
- ti,otap-del-sel-legacy = <0x1>;
- ti,otap-del-sel-mmc-hs = <0x1>;
- 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,itap-del-sel-ddr52 = <0x3>;
- status = "disabled";
- };
-
- sdhci1: mmc@fa00000 {
- compatible = "ti,am62-sdhci";
- reg = <0x00 0x0fa00000 0x00 0x1000>, <0x00 0x0fa08000 0x00 0x400>;
- interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 58 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 58 5>, <&k3_clks 58 6>;
- clock-names = "clk_ahb", "clk_xin";
- bus-width = <4>;
- ti,clkbuf-sel = <0x7>;
- 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-ddr50 = <0x9>;
- ti,otap-del-sel-sdr104 = <0x6>;
- 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";
- };
-
- sdhci2: mmc@fa20000 {
- compatible = "ti,am62-sdhci";
- reg = <0x00 0x0fa20000 0x00 0x1000>, <0x00 0x0fa28000 0x00 0x400>;
- interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 184 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 184 5>, <&k3_clks 184 6>;
- clock-names = "clk_ahb", "clk_xin";
- bus-width = <4>;
- ti,clkbuf-sel = <0x7>;
- 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-ddr50 = <0x9>;
- ti,otap-del-sel-sdr104 = <0x6>;
- 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";
- };
-
- usbss0: usb@f900000 {
- compatible = "ti,am62-usb";
- reg = <0x00 0x0f900000 0x00 0x800>,
- <0x00 0x0f908000 0x00 0x400>;
- clocks = <&k3_clks 161 3>;
- clock-names = "ref";
- ti,syscon-phy-pll-refclk = <&usb0_phy_ctrl 0x0>;
- #address-cells = <2>;
- #size-cells = <2>;
- power-domains = <&k3_pds 178 TI_SCI_PD_EXCLUSIVE>;
- ranges;
- status = "disabled";
-
- usb0: usb@31000000 {
- compatible = "snps,dwc3";
- reg = <0x00 0x31000000 0x00 0x50000>;
- interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
- <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; /* irq.0 */
- interrupt-names = "host", "peripheral";
- maximum-speed = "high-speed";
- dr_mode = "otg";
- snps,usb2-gadget-lpm-disable;
- snps,usb2-lpm-disable;
- };
- };
-
usbss1: usb@f910000 {
compatible = "ti,am62-usb";
reg = <0x00 0x0f910000 0x00 0x800>,
@@ -686,408 +31,38 @@
snps,usb2-lpm-disable;
};
};
+};
- fss: bus@fc00000 {
- compatible = "simple-bus";
- reg = <0x00 0x0fc00000 0x00 0x70000>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- ospi0: spi@fc40000 {
- compatible = "ti,am654-ospi", "cdns,qspi-nor";
- reg = <0x00 0x0fc40000 0x00 0x100>,
- <0x05 0x00000000 0x01 0x00000000>;
- interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
- cdns,fifo-depth = <256>;
- cdns,fifo-width = <4>;
- cdns,trigger-address = <0x0>;
- clocks = <&k3_clks 75 7>;
- assigned-clocks = <&k3_clks 75 7>;
- assigned-clock-parents = <&k3_clks 75 8>;
- assigned-clock-rates = <166666666>;
- power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
- };
-
- cpsw3g: ethernet@8000000 {
- compatible = "ti,am642-cpsw-nuss";
- #address-cells = <2>;
- #size-cells = <2>;
- reg = <0x00 0x08000000 0x00 0x200000>;
- reg-names = "cpsw_nuss";
- ranges = <0x00 0x00 0x00 0x08000000 0x00 0x200000>;
- clocks = <&k3_clks 13 0>;
- assigned-clocks = <&k3_clks 13 3>;
- assigned-clock-parents = <&k3_clks 13 11>;
- clock-names = "fck";
- power-domains = <&k3_pds 13 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
-
- dmas = <&main_pktdma 0xc600 15>,
- <&main_pktdma 0xc601 15>,
- <&main_pktdma 0xc602 15>,
- <&main_pktdma 0xc603 15>,
- <&main_pktdma 0xc604 15>,
- <&main_pktdma 0xc605 15>,
- <&main_pktdma 0xc606 15>,
- <&main_pktdma 0xc607 15>,
- <&main_pktdma 0x4600 15>;
- dma-names = "tx0", "tx1", "tx2", "tx3", "tx4", "tx5", "tx6",
- "tx7", "rx";
-
- ethernet-ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpsw_port1: port@1 {
- reg = <1>;
- ti,mac-only;
- label = "port1";
- phys = <&phy_gmii_sel 1>;
- mac-address = [00 00 00 00 00 00];
- status = "disabled";
- };
-
- cpsw_port2: port@2 {
- reg = <2>;
- ti,mac-only;
- label = "port2";
- phys = <&phy_gmii_sel 2>;
- mac-address = [00 00 00 00 00 00];
- status = "disabled";
- };
- };
-
- cpsw3g_mdio: mdio@f00 {
- compatible = "ti,cpsw-mdio","ti,davinci_mdio";
- reg = <0x00 0xf00 0x00 0x100>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&k3_clks 13 0>;
- clock-names = "fck";
- bus_freq = <1000000>;
- status = "disabled";
- };
-
- cpts@3d000 {
- compatible = "ti,j721e-cpts";
- reg = <0x00 0x3d000 0x00 0x400>;
- clocks = <&k3_clks 13 3>;
- clock-names = "cpts";
- interrupts-extended = <&gic500 GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cpts";
- ti,cpts-ext-ts-inputs = <4>;
- ti,cpts-periodic-outputs = <2>;
- };
- };
-
- hwspinlock: spinlock@2a000000 {
- compatible = "ti,am64-hwspinlock";
- reg = <0x00 0x2a000000 0x00 0x1000>;
- #hwlock-cells = <1>;
- };
-
- mailbox0_cluster0: mailbox@29000000 {
- compatible = "ti,am64-mailbox";
- reg = <0x00 0x29000000 0x00 0x200>;
- interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- };
-
- mailbox0_cluster1: mailbox@29010000 {
- compatible = "ti,am64-mailbox";
- reg = <0x00 0x29010000 0x00 0x200>;
- interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- };
-
- mailbox0_cluster2: mailbox@29020000 {
- compatible = "ti,am64-mailbox";
- reg = <0x00 0x29020000 0x00 0x200>;
- interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- };
-
- mailbox0_cluster3: mailbox@29030000 {
- compatible = "ti,am64-mailbox";
- reg = <0x00 0x29030000 0x00 0x200>;
- interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- };
-
- ecap0: pwm@23100000 {
- compatible = "ti,am3352-ecap";
- #pwm-cells = <3>;
- reg = <0x00 0x23100000 0x00 0x100>;
- power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 51 0>;
- clock-names = "fck";
- status = "disabled";
- };
-
- ecap1: pwm@23110000 {
- compatible = "ti,am3352-ecap";
- #pwm-cells = <3>;
- reg = <0x00 0x23110000 0x00 0x100>;
- power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 52 0>;
- clock-names = "fck";
- status = "disabled";
- };
-
- ecap2: pwm@23120000 {
- compatible = "ti,am3352-ecap";
- #pwm-cells = <3>;
- reg = <0x00 0x23120000 0x00 0x100>;
- power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 53 0>;
- clock-names = "fck";
- status = "disabled";
- };
-
- main_mcan0: can@20701000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x20701000 0x00 0x200>,
- <0x00 0x20708000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 98 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 98 6>, <&k3_clks 98 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan1: can@20711000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x20711000 0x00 0x200>,
- <0x00 0x20718000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 99 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 99 6>, <&k3_clks 99 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_rti0: watchdog@e000000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x0e000000 0x00 0x100>;
- clocks = <&k3_clks 125 0>;
- power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 125 0>;
- assigned-clock-parents = <&k3_clks 125 2>;
- };
-
- main_rti1: watchdog@e010000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x0e010000 0x00 0x100>;
- clocks = <&k3_clks 126 0>;
- power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 126 0>;
- assigned-clock-parents = <&k3_clks 126 2>;
- };
-
- main_rti2: watchdog@e020000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x0e020000 0x00 0x100>;
- clocks = <&k3_clks 127 0>;
- power-domains = <&k3_pds 127 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 127 0>;
- assigned-clock-parents = <&k3_clks 127 2>;
- };
-
- main_rti3: watchdog@e030000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x0e030000 0x00 0x100>;
- clocks = <&k3_clks 128 0>;
- power-domains = <&k3_pds 128 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 128 0>;
- assigned-clock-parents = <&k3_clks 128 2>;
- };
-
- main_rti15: watchdog@e0f0000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x0e0f0000 0x00 0x100>;
- clocks = <&k3_clks 130 0>;
- power-domains = <&k3_pds 130 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 130 0>;
- assigned-clock-parents = <&k3_clks 130 2>;
- };
-
- epwm0: pwm@23000000 {
- compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
- #pwm-cells = <3>;
- reg = <0x00 0x23000000 0x00 0x100>;
- power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
- clock-names = "tbclk", "fck";
- status = "disabled";
- };
-
- epwm1: pwm@23010000 {
- compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
- #pwm-cells = <3>;
- reg = <0x00 0x23010000 0x00 0x100>;
- power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>;
- clock-names = "tbclk", "fck";
- status = "disabled";
- };
-
- epwm2: pwm@23020000 {
- compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
- #pwm-cells = <3>;
- reg = <0x00 0x23020000 0x00 0x100>;
- power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>;
- clock-names = "tbclk", "fck";
- status = "disabled";
- };
-
- mcasp0: audio-controller@2b00000 {
- compatible = "ti,am33xx-mcasp-audio";
- reg = <0x00 0x02b00000 0x00 0x2000>,
- <0x00 0x02b08000 0x00 0x400>;
- reg-names = "mpu", "dat";
- interrupts = <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "tx", "rx";
-
- dmas = <&main_bcdma 0 0xc500 0>, <&main_bcdma 0 0x4500 0>;
- dma-names = "tx", "rx";
-
- clocks = <&k3_clks 190 0>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 190 0>;
- assigned-clock-parents = <&k3_clks 190 2>;
- power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- mcasp1: audio-controller@2b10000 {
- compatible = "ti,am33xx-mcasp-audio";
- reg = <0x00 0x02b10000 0x00 0x2000>,
- <0x00 0x02b18000 0x00 0x400>;
- reg-names = "mpu", "dat";
- interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "tx", "rx";
-
- dmas = <&main_bcdma 0 0xc501 0>, <&main_bcdma 0 0x4501 0>;
- dma-names = "tx", "rx";
-
- clocks = <&k3_clks 191 0>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 191 0>;
- assigned-clock-parents = <&k3_clks 191 2>;
- power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- mcasp2: audio-controller@2b20000 {
- compatible = "ti,am33xx-mcasp-audio";
- reg = <0x00 0x02b20000 0x00 0x2000>,
- <0x00 0x02b28000 0x00 0x400>;
- reg-names = "mpu", "dat";
- interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "tx", "rx";
-
- dmas = <&main_bcdma 0 0xc502 0>, <&main_bcdma 0 0x4502 0>;
- dma-names = "tx", "rx";
-
- clocks = <&k3_clks 192 0>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 192 0>;
- assigned-clock-parents = <&k3_clks 192 2>;
- power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- ti_csi2rx0: ticsi2rx@30102000 {
- compatible = "ti,j721e-csi2rx-shim";
- reg = <0x00 0x30102000 0x00 0x1000>;
- ranges;
- #address-cells = <2>;
- #size-cells = <2>;
- dmas = <&main_bcdma_csi 0 0x5000 0>;
- dma-names = "rx0";
- power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
-
- cdns_csi2rx0: csi-bridge@30101000 {
- compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
- reg = <0x00 0x30101000 0x00 0x1000>;
- clocks = <&k3_clks 182 0>, <&k3_clks 182 3>, <&k3_clks 182 0>,
- <&k3_clks 182 0>, <&k3_clks 182 4>, <&k3_clks 182 4>;
- 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";
- };
+&oc_sram {
+ reg = <0x00 0x70000000 0x00 0x10000>;
+ ranges = <0x00 0x00 0x70000000 0x10000>;
+};
- csi0_port2: port@2 {
- reg = <2>;
- status = "disabled";
- };
+&inta_main_dmss {
+ ti,interrupt-ranges = <5 69 35>;
+};
- csi0_port3: port@3 {
- reg = <3>;
- status = "disabled";
- };
+&main_pmx0 {
+ pinctrl-single,gpio-range =
+ <&main_pmx0_range 0 32 PIN_GPIO_RANGE_IOPAD>,
+ <&main_pmx0_range 33 92 PIN_GPIO_RANGE_IOPAD>,
+ <&main_pmx0_range 137 5 PIN_GPIO_RANGE_IOPAD>,
+ <&main_pmx0_range 143 3 PIN_GPIO_RANGE_IOPAD>,
+ <&main_pmx0_range 149 2 PIN_GPIO_RANGE_IOPAD>;
- csi0_port4: port@4 {
- reg = <4>;
- status = "disabled";
- };
- };
- };
+ main_pmx0_range: gpio-range {
+ #pinctrl-single,gpio-range-cells = <3>;
};
+};
- dphy0: phy@30110000 {
- compatible = "cdns,dphy-rx";
- reg = <0x00 0x30110000 0x00 0x1100>;
- #phy-cells = <0>;
- power-domains = <&k3_pds 185 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
+&main_gpio0 {
+ gpio-ranges = <&main_pmx0 0 0 32>, <&main_pmx0 32 33 38>,
+ <&main_pmx0 70 72 22>;
+ ti,ngpio = <92>;
+};
- vpu: video-codec@30210000 {
- compatible = "ti,j721s2-wave521c", "cnm,wave521c";
- reg = <0x00 0x30210000 0x00 0x10000>;
- interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 204 2>;
- power-domains = <&k3_pds 204 TI_SCI_PD_EXCLUSIVE>;
- };
+&main_gpio1 {
+ gpio-ranges = <&main_pmx0 0 94 32>, <&main_pmx0 42 137 5>,
+ <&main_pmx0 47 143 3>, <&main_pmx0 50 149 2>;
+ ti,ngpio = <52>;
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62p.dtsi b/arch/arm64/boot/dts/ti/k3-am62p.dtsi
index 94babc412575..75a15c368c11 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p.dtsi
@@ -116,10 +116,13 @@
};
};
- #include "k3-am62p-thermal.dtsi"
+ #include "k3-am62p-j722s-common-thermal.dtsi"
};
/* Now include peripherals for each bus segment */
+#include "k3-am62p-j722s-common-main.dtsi"
+#include "k3-am62p-j722s-common-mcu.dtsi"
+#include "k3-am62p-j722s-common-wakeup.dtsi"
+
+/* Include AM62P specific peripherals */
#include "k3-am62p-main.dtsi"
-#include "k3-am62p-mcu.dtsi"
-#include "k3-am62p-wakeup.dtsi"
diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
index 6e7234659111..ff65955551a3 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
@@ -207,7 +207,7 @@
pinctrl-single,pins = <
AM62PX_IOPAD(0x0090, PIN_INPUT, 2) /* (U24) GPMC0_BE0n_CLE.MCASP1_ACLKX */
AM62PX_IOPAD(0x0098, PIN_INPUT, 2) /* (AA24) GPMC0_WAIT0.MCASP1_AFSX */
- AM62PX_IOPAD(0x008c, PIN_INPUT, 2) /* (T25) GPMC0_WEn.MCASP1_AXR0 */
+ AM62PX_IOPAD(0x008c, PIN_OUTPUT, 2) /* (T25) GPMC0_WEn.MCASP1_AXR0 */
AM62PX_IOPAD(0x0084, PIN_INPUT, 2) /* (R25) GPMC0_ADVn_ALE.MCASP1_AXR2 */
>;
};
@@ -364,14 +364,9 @@
self-powered;
data-role = "dual";
power-role = "sink";
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- usb_con_hs: endpoint {
- remote-endpoint = <&usb0_hs_ep>;
- };
+ port {
+ usb_con_hs: endpoint {
+ remote-endpoint = <&usb0_hs_ep>;
};
};
};
@@ -516,11 +511,8 @@
&usb0 {
usb-role-switch;
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
+ port {
usb0_hs_ep: endpoint {
remote-endpoint = <&usb_con_hs>;
};
@@ -549,8 +541,6 @@
0 0 0 0
0 0 0 0
>;
- tx-num-evt = <32>;
- rx-num-evt = <32>;
};
&fss {
diff --git a/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi
new file mode 100644
index 000000000000..e4633af87eb9
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi
@@ -0,0 +1,475 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2022-2024 PHYTEC Messtechnik GmbH
+ * Author: Wadim Egorov <[email protected]>
+ *
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/net/ti-dp83867.h>
+
+/ {
+ aliases {
+ serial2 = &main_uart0;
+ serial3 = &main_uart1;
+ mmc1 = &sdhci1;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ ethernet1 = &cpsw_port2;
+ };
+
+ can_tc1: can-phy0 {
+ compatible = "ti,tcan1042";
+ #phy-cells = <0>;
+ max-bitrate = <8000000>;
+ standby-gpios = <&gpio_exp 1 GPIO_ACTIVE_HIGH>;
+ };
+
+ hdmi0: connector-hdmi {
+ compatible = "hdmi-connector";
+ label = "hdmi";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&sii9022_out>;
+ };
+ };
+ };
+
+ keys {
+ compatible = "gpio-keys";
+ autorepeat;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_keys_pins_default>;
+
+ key-home {
+ label = "home";
+ linux,code = <KEY_HOME>;
+ gpios = <&main_gpio1 23 GPIO_ACTIVE_HIGH>;
+ };
+
+ key-menu {
+ label = "menu";
+ linux,code = <KEY_MENU>;
+ gpios = <&gpio_exp 4 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "phyBOARD-Lyra";
+ simple-audio-card,widgets =
+ "Microphone", "Mic Jack",
+ "Headphone", "Headphone Jack",
+ "Speaker", "External Speaker";
+ simple-audio-card,routing =
+ "MIC3R", "Mic Jack",
+ "Mic Jack", "Mic Bias",
+ "Headphone Jack", "HPLOUT",
+ "Headphone Jack", "HPROUT",
+ "External Speaker", "SPOP",
+ "External Speaker", "SPOM";
+ simple-audio-card,format = "dsp_b";
+ simple-audio-card,bitclock-master = <&sound_master>;
+ simple-audio-card,frame-master = <&sound_master>;
+ simple-audio-card,bitclock-inversion;
+
+ simple-audio-card,cpu {
+ sound-dai = <&mcasp2>;
+ };
+
+ sound_master: simple-audio-card,codec {
+ sound-dai = <&audio_codec>;
+ clocks = <&audio_refclk1>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&leds_pins_default>, <&user_leds_pins_default>;
+
+ led-1 {
+ gpios = <&main_gpio0 32 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "mmc0";
+ };
+
+ led-2 {
+ gpios = <&gpio_exp 2 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "mmc1";
+ };
+ };
+
+ 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;
+ };
+
+ vcc_3v3_mmc: regulator-vcc-3v3-mmc {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_3V3_MMC";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vcc_3v3_sw: regulator-vcc-3v3-sw {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_3V3_SW";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&main_pmx0 {
+ audio_ext_refclk1_pins_default: audio-ext-refclk1-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x0a0, PIN_OUTPUT, 1) /* (K25) GPMC0_WPn.AUDIO_EXT_REFCLK1 */
+ >;
+ };
+
+ gpio_keys_pins_default: gpio-keys-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x1d4, PIN_INPUT, 7) /* (B15) UART0_RTSn.GPIO1_23 */
+ >;
+ };
+
+ gpio_exp_int_pins_default: gpio-exp-int-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x244, PIN_INPUT, 7) /* (C17) MMC1_SDWP.GPIO1_49 */
+ >;
+ };
+
+ hdmi_int_pins_default: hdmi-int-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x040, PIN_INPUT, 7) /* (N23) GPMC0_AD1.GPIO0_16 */
+ >;
+ };
+
+ main_dss0_pins_default: main-dss0-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x0b8, PIN_OUTPUT, 0) /* (U22) VOUT0_DATA0 */
+ AM62X_IOPAD(0x0bc, PIN_OUTPUT, 0) /* (V24) VOUT0_DATA1 */
+ AM62X_IOPAD(0x0e0, PIN_OUTPUT, 0) /* (V20) VOUT0_DATA10 */
+ AM62X_IOPAD(0x0e4, PIN_OUTPUT, 0) /* (AA23) VOUT0_DATA11 */
+ AM62X_IOPAD(0x0e8, PIN_OUTPUT, 0) /* (AB25) VOUT0_DATA12 */
+ AM62X_IOPAD(0x0ec, PIN_OUTPUT, 0) /* (AA24) VOUT0_DATA13 */
+ AM62X_IOPAD(0x0f0, PIN_OUTPUT, 0) /* (Y22) VOUT0_DATA14 */
+ AM62X_IOPAD(0x0f4, PIN_OUTPUT, 0) /* (AA21) VOUT0_DATA15 */
+ AM62X_IOPAD(0x0c0, PIN_OUTPUT, 0) /* (W25) VOUT0_DATA2 */
+ AM62X_IOPAD(0x0c4, PIN_OUTPUT, 0) /* (W24) VOUT0_DATA3 */
+ AM62X_IOPAD(0x0c8, PIN_OUTPUT, 0) /* (Y25) VOUT0_DATA4 */
+ AM62X_IOPAD(0x0cc, PIN_OUTPUT, 0) /* (Y24) VOUT0_DATA5 */
+ AM62X_IOPAD(0x0d0, PIN_OUTPUT, 0) /* (Y23) VOUT0_DATA6 */
+ AM62X_IOPAD(0x0d4, PIN_OUTPUT, 0) /* (AA25) VOUT0_DATA7 */
+ AM62X_IOPAD(0x0d8, PIN_OUTPUT, 0) /* (V21) VOUT0_DATA8 */
+ AM62X_IOPAD(0x0dc, PIN_OUTPUT, 0) /* (W21) VOUT0_DATA9 */
+ AM62X_IOPAD(0x0fc, PIN_OUTPUT, 0) /* (Y20) VOUT0_DE */
+ AM62X_IOPAD(0x0f8, PIN_OUTPUT, 0) /* (AB24) VOUT0_HSYNC */
+ AM62X_IOPAD(0x104, PIN_OUTPUT, 0) /* (AC24) VOUT0_PCLK */
+ AM62X_IOPAD(0x100, PIN_OUTPUT, 0) /* (AC25) VOUT0_VSYNC */
+ >;
+ };
+
+ main_i2c1_pins_default: main-i2c1-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x1e8, PIN_INPUT_PULLUP, 0) /* (B17) I2C1_SCL */
+ AM62X_IOPAD(0x1ec, PIN_INPUT_PULLUP, 0) /* (A17) I2C1_SDA */
+ >;
+ };
+
+ main_mcan0_pins_default: main-mcan0-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x1dc, PIN_INPUT, 0) /* (E15) MCAN0_RX */
+ AM62X_IOPAD(0x1d8, PIN_OUTPUT, 0) /* (C15) MCAN0_TX */
+ >;
+ };
+
+ main_mcasp2_pins_default: main-mcasp2-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x070, PIN_INPUT, 3) /* (T24) GPMC0_AD13.MCASP2_ACLKX */
+ AM62X_IOPAD(0x06c, PIN_INPUT, 3) /* (T22) GPMC0_AD12.MCASP2_AFSX */
+ AM62X_IOPAD(0x064, PIN_OUTPUT, 3) /* (T25) GPMC0_AD10.MCASP2_AXR2 */
+ AM62X_IOPAD(0x068, PIN_INPUT, 3) /* (R21) GPMC0_AD11.MCASP2_AXR3 */
+ >;
+ };
+
+ main_mmc1_pins_default: main-mmc1-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x23c, PIN_INPUT_PULLUP, 0) /* (A21) MMC1_CMD */
+ AM62X_IOPAD(0x234, PIN_INPUT_PULLDOWN, 0) /* (B22) MMC1_CLK */
+ AM62X_IOPAD(0x230, PIN_INPUT_PULLUP, 0) /* (A22) MMC1_DAT0 */
+ AM62X_IOPAD(0x22c, PIN_INPUT_PULLUP, 0) /* (B21) MMC1_DAT1 */
+ AM62X_IOPAD(0x228, PIN_INPUT_PULLUP, 0) /* (C21) MMC1_DAT2 */
+ AM62X_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (D22) MMC1_DAT3 */
+ AM62X_IOPAD(0x240, PIN_INPUT_PULLUP, 0) /* (D17) MMC1_SDCD */
+ >;
+ };
+
+ main_rgmii2_pins_default: main-rgmii2-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x184, PIN_INPUT, 0) /* (AE23) RGMII2_RD0 */
+ AM62X_IOPAD(0x188, PIN_INPUT, 0) /* (AB20) RGMII2_RD1 */
+ AM62X_IOPAD(0x18c, PIN_INPUT, 0) /* (AC21) RGMII2_RD2 */
+ AM62X_IOPAD(0x190, PIN_INPUT, 0) /* (AE22) RGMII2_RD3 */
+ AM62X_IOPAD(0x180, PIN_INPUT, 0) /* (AD23) RGMII2_RXC */
+ AM62X_IOPAD(0x17c, PIN_INPUT, 0) /* (AD22) RGMII2_RX_CTL */
+ AM62X_IOPAD(0x16c, PIN_OUTPUT, 0) /* (Y18) RGMII2_TD0 */
+ AM62X_IOPAD(0x170, PIN_OUTPUT, 0) /* (AA18) RGMII2_TD1 */
+ AM62X_IOPAD(0x174, PIN_OUTPUT, 0) /* (AD21) RGMII2_TD2 */
+ AM62X_IOPAD(0x178, PIN_OUTPUT, 0) /* (AC20) RGMII2_TD3 */
+ AM62X_IOPAD(0x168, PIN_OUTPUT, 0) /* (AE21) RGMII2_TXC */
+ AM62X_IOPAD(0x164, PIN_OUTPUT, 0) /* (AA19) RGMII2_TX_CTL */
+ >;
+ };
+
+ main_uart0_pins_default: main-uart0-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14) UART0_RXD */
+ AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */
+ >;
+ };
+
+ main_uart1_pins_default: main-uart1-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x194, PIN_INPUT, 2) /* (B19) MCASP0_AXR3.UART1_CTSn */
+ AM62X_IOPAD(0x198, PIN_OUTPUT, 2) /* (A19) MCASP0_AXR2.UART1_RTSn */
+ AM62X_IOPAD(0x1ac, PIN_INPUT, 2) /* (E19) MCASP0_AFSR.UART1_RXD */
+ AM62X_IOPAD(0x1b0, PIN_OUTPUT, 2) /* (A20) MCASP0_ACLKR.UART1_TXD */
+ >;
+ };
+
+ main_usb1_pins_default: main-usb1-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x258, PIN_OUTPUT, 0) /* (F18) USB1_DRVVBUS */
+ >;
+ };
+
+ user_leds_pins_default: user-leds-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x084, PIN_OUTPUT, 7) /* (L23) GPMC0_ADVn_ALE.GPIO0_32 */
+ >;
+ };
+};
+
+&cpsw3g {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_rgmii1_pins_default>, <&main_rgmii2_pins_default>;
+};
+
+&cpsw_port2 {
+ phy-mode = "rgmii-rxid";
+ phy-handle = <&cpsw3g_phy3>;
+};
+
+&cpsw3g_mdio {
+ cpsw3g_phy3: ethernet-phy@3 {
+ compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22";
+ reg = <3>;
+ ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+};
+
+&dss {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_dss0_pins_default>;
+ status = "okay";
+};
+
+&dss_ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* VP2: DPI/HDMI Output */
+ port@1 {
+ reg = <1>;
+
+ dpi1_out: endpoint {
+ remote-endpoint = <&sii9022_in>;
+ };
+ };
+};
+
+&main_i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c1_pins_default>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ audio_codec: audio-codec@18 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&audio_ext_refclk1_pins_default>;
+
+ #sound-dai-cells = <0>;
+ compatible = "ti,tlv320aic3007";
+ reg = <0x18>;
+ ai3x-micbias-vg = <2>;
+
+ AVDD-supply = <&vcc_3v3_sw>;
+ IOVDD-supply = <&vcc_3v3_sw>;
+ DRVDD-supply = <&vcc_3v3_sw>;
+ DVDD-supply = <&vcc_1v8>;
+ };
+
+ gpio_exp: gpio-expander@21 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_exp_int_pins_default>;
+ compatible = "nxp,pcf8574";
+ reg = <0x21>;
+ interrupt-parent = <&main_gpio1>;
+ interrupts = <49 0>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-line-names = "", "GPIO1_CAN0_nEN",
+ "GPIO2_LED2", "GPIO3_LVDS_GPIO",
+ "GPIO4_BUT2", "GPIO5_LVDS_BKLT_EN",
+ "GPIO6_ETH1_USER_RESET", "GPIO7_AUDIO_USER_RESET";
+ };
+
+ usb-pd@22 {
+ compatible = "ti,tps6598x";
+ reg = <0x22>;
+
+ connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ self-powered;
+ data-role = "dual";
+ power-role = "sink";
+ port {
+ usb_con_hs: endpoint {
+ remote-endpoint = <&typec_hs>;
+ };
+ };
+ };
+ };
+
+ sii9022: bridge-hdmi@39 {
+ compatible = "sil,sii9022";
+ reg = <0x39>;
+
+ interrupt-parent = <&main_gpio0>;
+ interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_int_pins_default>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ sii9022_in: endpoint {
+ remote-endpoint = <&dpi1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ sii9022_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+ };
+ };
+ };
+
+ eeprom@51 {
+ compatible = "atmel,24c02";
+ pagesize = <16>;
+ reg = <0x51>;
+ };
+};
+
+&main_mcan0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcan0_pins_default>;
+ phys = <&can_tc1>;
+ status = "okay";
+};
+
+&main_uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_uart0_pins_default>;
+ status = "okay";
+};
+
+&main_uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_uart1_pins_default>;
+ /* Main UART1 may be used by TIFS firmware */
+ status = "okay";
+};
+
+&mcasp2 {
+ #sound-dai-cells = <0>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcasp2_pins_default>;
+
+ /* MCASP_IIS_MODE */
+ op-mode = <0>;
+ tdm-slots = <2>;
+
+ /* 0: INACTIVE, 1: TX, 2: RX */
+ serial-dir = <
+ 0 0 1 2
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ >;
+ tx-num-evt = <32>;
+ rx-num-evt = <32>;
+ status = "okay";
+};
+
+&sdhci1 {
+ vmmc-supply = <&vcc_3v3_mmc>;
+ vqmmc-supply = <&vddshv5_sdio>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mmc1_pins_default>;
+ disable-wp;
+ no-1-8-v;
+ status = "okay";
+};
+
+&usbss0 {
+ ti,vbus-divider;
+ status = "okay";
+};
+
+&usbss1 {
+ ti,vbus-divider;
+ status = "okay";
+};
+
+&usb0 {
+ usb-role-switch;
+
+ port {
+ typec_hs: endpoint {
+ remote-endpoint = <&usb_con_hs>;
+ };
+ };
+};
+
+&usb1 {
+ dr_mode = "host";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_usb1_pins_default>;
+};
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 3c45782ab2b7..44ff67b6bf1e 100644
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
@@ -48,6 +48,14 @@
pmsg-size = <0x8000>;
};
+ /* global cma region */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x00 0x8000000>;
+ linux,cma-default;
+ };
+
secure_tfa_ddr: tfa@9e780000 {
reg = <0x00 0x9e780000 0x00 0x80000>;
alignment = <0x1000>;
@@ -128,6 +136,10 @@
};
};
+&phy_gmii_sel {
+ bootph-all;
+};
+
&main_pmx0 {
/* First pad number is ALW package and second is AMC package */
main_uart0_pins_default: main-uart0-default-pins {
@@ -156,6 +168,7 @@
};
main_i2c1_pins_default: main-i2c1-default-pins {
+ bootph-all;
pinctrl-single,pins = <
AM62X_IOPAD(0x1e8, PIN_INPUT_PULLUP, 0) /* (B17/A17) I2C1_SCL */
AM62X_IOPAD(0x1ec, PIN_INPUT_PULLUP, 0) /* (A17/A16) I2C1_SDA */
@@ -335,15 +348,9 @@
self-powered;
data-role = "dual";
power-role = "sink";
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- usb_con_hs: endpoint {
- remote-endpoint = <&usb0_hs_ep>;
- };
+ port {
+ usb_con_hs: endpoint {
+ remote-endpoint = <&usb0_hs_ep>;
};
};
};
@@ -470,12 +477,9 @@
&usb0 {
bootph-all;
- #address-cells = <1>;
- #size-cells = <0>;
usb-role-switch;
- port@0 {
- reg = <0>;
+ port {
usb0_hs_ep: endpoint {
remote-endpoint = <&usb_con_hs>;
};
@@ -504,8 +508,6 @@
0 0 0 0
0 0 0 0
>;
- tx-num-evt = <32>;
- rx-num-evt = <32>;
};
&dss {
diff --git a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
index 6f9aa5e02138..f8370dd03350 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
@@ -1283,6 +1283,9 @@
<0x22400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am64x-pru0_0-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <16 2 2>;
+ interrupt-names = "vring";
};
rtu0_0: rtu@4000 {
@@ -1292,6 +1295,9 @@
<0x23400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am64x-rtu0_0-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <20 4 4>;
+ interrupt-names = "vring";
};
tx_pru0_0: txpru@a000 {
@@ -1310,6 +1316,9 @@
<0x24400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am64x-pru0_1-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <18 3 3>;
+ interrupt-names = "vring";
};
rtu0_1: rtu@6000 {
@@ -1319,6 +1328,9 @@
<0x23c00 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am64x-rtu0_1-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <22 5 5>;
+ interrupt-names = "vring";
};
tx_pru0_1: txpru@c000 {
@@ -1436,6 +1448,9 @@
<0x22400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am64x-pru1_0-fw";
+ interrupt-parent = <&icssg1_intc>;
+ interrupts = <16 2 2>;
+ interrupt-names = "vring";
};
rtu1_0: rtu@4000 {
@@ -1445,6 +1460,9 @@
<0x23400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am64x-rtu1_0-fw";
+ interrupt-parent = <&icssg1_intc>;
+ interrupts = <20 4 4>;
+ interrupt-names = "vring";
};
tx_pru1_0: txpru@a000 {
@@ -1463,6 +1481,9 @@
<0x24400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am64x-pru1_1-fw";
+ interrupt-parent = <&icssg1_intc>;
+ interrupts = <18 3 3>;
+ interrupt-names = "vring";
};
rtu1_1: rtu@6000 {
@@ -1472,6 +1493,9 @@
<0x23c00 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am64x-rtu1_1-fw";
+ interrupt-parent = <&icssg1_intc>;
+ interrupts = <22 5 5>;
+ interrupt-names = "vring";
};
tx_pru1_1: txpru@c000 {
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 125e507966fb..ea7c58fb67e2 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
@@ -265,6 +265,50 @@
interrupts = <70 IRQ_TYPE_EDGE_FALLING>;
wakeup-source;
};
+
+ pmic@61 {
+ compatible = "ti,lp8733";
+ reg = <0x61>;
+
+ buck0-in-supply = <&vcc_5v0_som>;
+ buck1-in-supply = <&vcc_5v0_som>;
+ ldo0-in-supply = <&vdd_3v3>;
+ ldo1-in-supply = <&vdd_3v3>;
+
+ regulators {
+ vdd_core: buck0 {
+ regulator-name = "VDD_CORE";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vdd_3v3: buck1 {
+ regulator-name = "VDD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vdd_1v8_ldo0: ldo0 {
+ regulator-name = "VDD_1V8_LDO0";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vdda_1v8: ldo1 {
+ regulator-name = "VDDA_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+ };
};
&main_r5fss0_core0 {
@@ -296,7 +340,7 @@
pinctrl-names = "default";
pinctrl-0 = <&ospi0_pins_default>;
- flash@0 {
+ serial_flash: flash@0 {
compatible = "jedec,spi-nor";
reg = <0x0>;
spi-tx-bus-width = <8>;
diff --git a/arch/arm64/boot/dts/ti/k3-am64-tqma64xxl-mbax4xxl-sdcard.dtso b/arch/arm64/boot/dts/ti/k3-am64-tqma64xxl-mbax4xxl-sdcard.dtso
index 79ed19c6c0e9..c4525024ba5d 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-tqma64xxl-mbax4xxl-sdcard.dtso
+++ b/arch/arm64/boot/dts/ti/k3-am64-tqma64xxl-mbax4xxl-sdcard.dtso
@@ -1,6 +1,6 @@
-// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
- * Copyright (c) 2022-2023 TQ-Systems GmbH <[email protected]>, D-82229 Seefeld, Germany.
+ * Copyright (c) 2022-2024 TQ-Systems GmbH <[email protected]>, D-82229 Seefeld, Germany.
*/
/dts-v1/;
diff --git a/arch/arm64/boot/dts/ti/k3-am64-tqma64xxl-mbax4xxl-wlan.dtso b/arch/arm64/boot/dts/ti/k3-am64-tqma64xxl-mbax4xxl-wlan.dtso
index 32596a84b7ba..82f8a21b6cbf 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-tqma64xxl-mbax4xxl-wlan.dtso
+++ b/arch/arm64/boot/dts/ti/k3-am64-tqma64xxl-mbax4xxl-wlan.dtso
@@ -1,6 +1,6 @@
-// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
- * Copyright (c) 2022-2023 TQ-Systems GmbH <[email protected]>, D-82229 Seefeld, Germany.
+ * Copyright (c) 2022-2024 TQ-Systems GmbH <[email protected]>, D-82229 Seefeld, Germany.
*/
/dts-v1/;
diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac-mii.dtso b/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac-mii.dtso
new file mode 100644
index 000000000000..423d6027278d
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac-mii.dtso
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/**
+ * DT overlay for enabling both ICSSG1 port on AM642 EVM in MII mode
+ *
+ * Copyright (C) 2020-2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+ aliases {
+ ethernet1 = "/icssg1-eth/ethernet-ports/port@1";
+ };
+
+ mdio-mux-2 {
+ compatible = "mdio-mux-multiplexer";
+ mux-controls = <&mdio_mux>;
+ mdio-parent-bus = <&icssg1_mdio>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ icssg1_phy2: ethernet-phy@3 {
+ reg = <3>;
+ };
+ };
+ };
+};
+
+&main_pmx0 {
+ icssg1_mii1_pins_default: icssg1-mii1-default-pins {
+ pinctrl-single,pins = <
+ AM64X_IOPAD(0x00f8, PIN_INPUT, 1) /* (V9) PRG1_PRU0_GPO16.PR1_MII_MT0_CLK */
+ AM64X_IOPAD(0x00f4, PIN_OUTPUT, 0) /* (Y9) PRG1_PRU0_GPO15.PR1_MII0_TXEN */
+ AM64X_IOPAD(0x00f0, PIN_OUTPUT, 0) /* (AA9) PRG1_PRU0_GPO14.PR1_MII0_TXD3 */
+ AM64X_IOPAD(0x00ec, PIN_OUTPUT, 0) /* (W9) PRG1_PRU0_GPO13.PR1_MII0_TXD2 */
+ AM64X_IOPAD(0x00e8, PIN_OUTPUT, 0) /* (U9) PRG1_PRU0_GPO12.PR1_MII0_TXD1 */
+ AM64X_IOPAD(0x00e4, PIN_OUTPUT, 0) /* (AA8) PRG1_PRU0_GPO11.PR1_MII0_TXD0 */
+ AM64X_IOPAD(0x00c8, PIN_INPUT, 1) /* (Y8) PRG1_PRU0_GPO4.PR1_MII0_RXDV */
+ AM64X_IOPAD(0x00d0, PIN_INPUT, 1) /* (AA7) PRG1_PRU0_GPO6.PR1_MII_MR0_CLK */
+ AM64X_IOPAD(0x00c4, PIN_INPUT, 1) /* (V8) PRG1_PRU0_GPO3.PR1_MII0_RXD3 */
+ AM64X_IOPAD(0x00c0, PIN_INPUT, 1) /* (W8) PRG1_PRU0_GPO2.PR1_MII0_RXD2 */
+ AM64X_IOPAD(0x00cc, PIN_INPUT, 1) /* (V13) PRG1_PRU0_GPO5.PR1_MII0_RXER */
+ AM64X_IOPAD(0x00bc, PIN_INPUT, 1) /* (U8) PRG1_PRU0_GPO1.PR1_MII0_RXD1 */
+ AM64X_IOPAD(0x00b8, PIN_INPUT, 1) /* (Y7) PRG1_PRU0_GPO0.PR1_MII0_RXD0 */
+ AM64X_IOPAD(0x00d8, PIN_INPUT, 1) /* (W13) PRG1_PRU0_GPO8.PR1_MII0_RXLINK */
+ >;
+ };
+
+ icssg1_mii2_pins_default: icssg1-mii2-default-pins {
+ pinctrl-single,pins = <
+ AM64X_IOPAD(0x0148, PIN_INPUT, 1) /* (Y10) PRG1_PRU1_GPO16.PR1_MII_MT1_CLK */
+ AM64X_IOPAD(0x0144, PIN_OUTPUT, 0) /* (Y11) PRG1_PRU1_GPO15.PR1_MII1_TXEN */
+ AM64X_IOPAD(0x0140, PIN_OUTPUT, 0) /* (AA11) PRG1_PRU1_GPO14.PR1_MII1_TXD3 */
+ AM64X_IOPAD(0x013c, PIN_OUTPUT, 0) /* (U10) PRG1_PRU1_GPO13.PR1_MII1_TXD2 */
+ AM64X_IOPAD(0x0138, PIN_OUTPUT, 0) /* (V10) PRG1_PRU1_GPO12.PR1_MII1_TXD1 */
+ AM64X_IOPAD(0x0134, PIN_OUTPUT, 0) /* (AA10) PRG1_PRU1_GPO11.PR1_MII1_TXD0 */
+ AM64X_IOPAD(0x0118, PIN_INPUT, 1) /* (W12) PRG1_PRU1_GPO4.PR1_MII1_RXDV */
+ AM64X_IOPAD(0x0120, PIN_INPUT, 1) /* (U11) PRG1_PRU1_GPO6.PR1_MII_MR1_CLK */
+ AM64X_IOPAD(0x0114, PIN_INPUT, 1) /* (Y12) PRG1_PRU1_GPO3.PR1_MII1_RXD3 */
+ AM64X_IOPAD(0x0110, PIN_INPUT, 1) /* (AA12) PRG1_PRU1_GPO2.PR1_MII1_RXD2 */
+ AM64X_IOPAD(0x011c, PIN_INPUT, 1) /* (AA13) PRG1_PRU1_GPO5.PR1_MII1_RXER */
+ AM64X_IOPAD(0x010c, PIN_INPUT, 1) /* (V11) PRG1_PRU1_GPO1.PR1_MII1_RXD1 */
+ AM64X_IOPAD(0x0108, PIN_INPUT, 1) /* (W11) PRG1_PRU1_GPO0.PR1_MII1_RXD0 */
+ AM64X_IOPAD(0x0128, PIN_INPUT, 1) /* (U12) PRG1_PRU1_GPO8.PR1_MII1_RXLINK */
+ >;
+ };
+};
+
+&cpsw3g {
+ pinctrl-0 = <&rgmii1_pins_default>;
+};
+
+&cpsw_port2 {
+ status = "disabled";
+};
+
+&mdio_mux_1 {
+ status = "disabled";
+};
+
+&icssg1_eth {
+ pinctrl-0 = <&icssg1_mii1_pins_default &icssg1_mii2_pins_default>;
+};
+
+&icssg1_emac0 {
+ phy-mode = "mii";
+};
+
+&icssg1_emac1 {
+ status = "okay";
+ phy-handle = <&icssg1_phy2>;
+ phy-mode = "mii";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso b/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso
new file mode 100644
index 000000000000..f08c0e272b53
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/**
+ * DT overlay for HSE NAND expansion card on AM642 EVM
+ *
+ * Copyright (C) 2021-2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+ gpmc0_pins_default: gpmc0-pins-default {
+ bootph-all;
+ pinctrl-single,pins = <
+ AM64X_IOPAD(0x0094, PIN_INPUT, 7) /* (T19) GPMC0_BE1n.GPIO0_36 */
+ AM64X_IOPAD(0x003c, PIN_INPUT, 0) /* (T20) GPMC0_AD0 */
+ AM64X_IOPAD(0x0040, PIN_INPUT, 0) /* (U21) GPMC0_AD1 */
+ AM64X_IOPAD(0x0064, PIN_INPUT, 0) /* (R16) GPMC0_AD10 */
+ AM64X_IOPAD(0x0068, PIN_INPUT, 0) /* (W20) GPMC0_AD11 */
+ AM64X_IOPAD(0x006c, PIN_INPUT, 0) /* (W21) GPMC0_AD12 */
+ AM64X_IOPAD(0x0070, PIN_INPUT, 0) /* (V18) GPMC0_AD13 */
+ AM64X_IOPAD(0x0074, PIN_INPUT, 0) /* (Y21) GPMC0_AD14 */
+ AM64X_IOPAD(0x0078, PIN_INPUT, 0) /* (Y20) GPMC0_AD15 */
+ AM64X_IOPAD(0x0044, PIN_INPUT, 0) /* (T18) GPMC0_AD2 */
+ AM64X_IOPAD(0x0048, PIN_INPUT, 0) /* (U20) GPMC0_AD3 */
+ AM64X_IOPAD(0x004c, PIN_INPUT, 0) /* (U18) GPMC0_AD4 */
+ AM64X_IOPAD(0x0050, PIN_INPUT, 0) /* (U19) GPMC0_AD5 */
+ AM64X_IOPAD(0x0054, PIN_INPUT, 0) /* (V20) GPMC0_AD6 */
+ AM64X_IOPAD(0x0058, PIN_INPUT, 0) /* (V21) GPMC0_AD7 */
+ AM64X_IOPAD(0x005c, PIN_INPUT, 0) /* (V19) GPMC0_AD8 */
+ AM64X_IOPAD(0x0060, PIN_INPUT, 0) /* (T17) GPMC0_AD9 */
+ AM64X_IOPAD(0x0098, PIN_INPUT_PULLUP, 0) /* (W19) GPMC0_WAIT0 */
+ AM64X_IOPAD(0x009c, PIN_INPUT_PULLUP, 0) /* (Y18) GPMC0_WAIT1 */
+ AM64X_IOPAD(0x00a8, PIN_OUTPUT_PULLUP, 0) /* (R19) GPMC0_CSn0 */
+ AM64X_IOPAD(0x00ac, PIN_OUTPUT_PULLUP, 0) /* (R20) GPMC0_CSn1 */
+ AM64X_IOPAD(0x00b0, PIN_OUTPUT_PULLUP, 0) /* (P19) GPMC0_CSn2 */
+ AM64X_IOPAD(0x00b4, PIN_OUTPUT_PULLUP, 0) /* (R21) GPMC0_CSn3 */
+ AM64X_IOPAD(0x007c, PIN_OUTPUT, 0) /* (R17) GPMC0_CLK */
+ AM64X_IOPAD(0x0084, PIN_OUTPUT, 0) /* (P16) GPMC0_ADVn_ALE */
+ AM64X_IOPAD(0x0088, PIN_OUTPUT, 0) /* (R18) GPMC0_OEn_REn */
+ AM64X_IOPAD(0x008c, PIN_OUTPUT, 0) /* (T21) GPMC0_WEn */
+ AM64X_IOPAD(0x0090, PIN_OUTPUT, 0) /* (P17) GPMC0_BE0n_CLE */
+ AM64X_IOPAD(0x00a0, PIN_OUTPUT_PULLUP, 0) /* (N16) GPMC0_WPn */
+ AM64X_IOPAD(0x00a4, PIN_OUTPUT, 0) /* (N17) GPMC0_DIR */
+ >;
+ };
+};
+
+&main_gpio0 {
+ gpio0-36 {
+ bootph-all;
+ gpio-hog;
+ gpios = <36 0>;
+ input;
+ line-name = "GPMC0_MUX_DIR";
+ };
+};
+
+&elm0 {
+ bootph-all;
+ status = "okay";
+};
+
+&gpmc0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpmc0_pins_default>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ nand@0,0 {
+ compatible = "ti,am64-nand";
+ reg = <0 0 64>; /* device IO registers */
+ interrupt-parent = <&gpmc0>;
+ interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+ <1 IRQ_TYPE_NONE>; /* termcount */
+ rb-gpios = <&gpmc0 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
+ ti,nand-xfer-type = "prefetch-polled";
+ ti,nand-ecc-opt = "bch8"; /* BCH8: Bootrom limitation */
+ ti,elm-id = <&elm0>;
+ nand-bus-width = <8>;
+ gpmc,device-width = <1>;
+ gpmc,sync-clk-ps = <0>;
+ gpmc,cs-on-ns = <0>;
+ gpmc,cs-rd-off-ns = <40>;
+ gpmc,cs-wr-off-ns = <40>;
+ gpmc,adv-on-ns = <0>;
+ gpmc,adv-rd-off-ns = <25>;
+ gpmc,adv-wr-off-ns = <25>;
+ gpmc,we-on-ns = <0>;
+ gpmc,we-off-ns = <20>;
+ gpmc,oe-on-ns = <3>;
+ gpmc,oe-off-ns = <30>;
+ gpmc,access-ns = <30>;
+ gpmc,rd-cycle-ns = <40>;
+ gpmc,wr-cycle-ns = <40>;
+ gpmc,bus-turnaround-ns = <0>;
+ gpmc,cycle2cycle-delay-ns = <0>;
+ gpmc,clk-activation-ns = <0>;
+ gpmc,wr-access-ns = <40>;
+ gpmc,wr-data-mux-bus-ns = <0>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ bootph-all;
+ label = "NAND.tiboot3";
+ reg = <0x00000000 0x00200000>; /* 2M */
+ };
+ partition@200000 {
+ bootph-all;
+ label = "NAND.tispl";
+ reg = <0x00200000 0x00200000>; /* 2M */
+ };
+ partition@400000 {
+ bootph-all;
+ label = "NAND.tiboot3.backup"; /* 2M */
+ reg = <0x00400000 0x00200000>; /* BootROM looks at 4M */
+ };
+ partition@600000 {
+ bootph-all;
+ label = "NAND.u-boot";
+ reg = <0x00600000 0x00400000>; /* 4M */
+ };
+ partition@a00000 {
+ bootph-all;
+ label = "NAND.u-boot-env";
+ reg = <0x00a00000 0x00040000>; /* 256K */
+ };
+ partition@a40000 {
+ bootph-all;
+ label = "NAND.u-boot-env.backup";
+ reg = <0x00a40000 0x00040000>; /* 256K */
+ };
+ partition@a80000 {
+ bootph-all;
+ label = "NAND.file-system";
+ reg = <0x00a80000 0x3f580000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm.dts b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
index e20e4ffd0f1f..6bb1ad2e56ec 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
@@ -466,6 +466,12 @@
AM64X_IOPAD(0x00f4, PIN_INPUT, 2) /* (Y9) PRG1_PRU0_GPO15.PRG1_RGMII1_TX_CTL */
>;
};
+
+ icssg1_iep0_pins_default: icssg1-iep0-default-pins {
+ pinctrl-single,pins = <
+ AM64X_IOPAD(0x0104, PIN_OUTPUT, 2) /* (W7) PRG1_PRU0_GPO19.PRG1_IEP0_EDC_SYNC_OUT0 */
+ >;
+ };
};
&main_uart0 {
@@ -817,3 +823,12 @@
rx-internal-delay-ps = <2000>;
};
};
+
+&gpmc0 {
+ ranges = <0 0 0x00 0x51000000 0x01000000>; /* CS0 space. Min partition = 16MB */
+};
+
+&icssg1_iep0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&icssg1_iep0_pins_default>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am642-hummingboard-t.dts b/arch/arm64/boot/dts/ti/k3-am642-hummingboard-t.dts
index 234d76e4e944..5b5e9eeec5ac 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-hummingboard-t.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-hummingboard-t.dts
@@ -282,7 +282,6 @@
pinctrl-names = "default";
pinctrl-0 = <&main_uart3_default_pins>;
uart-has-rtscts;
- rs485-rts-active-low;
linux,rs485-enabled-at-boot-time;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-pcie-usb2.dtso b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-pcie-usb2.dtso
new file mode 100644
index 000000000000..7a5ce4bc02f3
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-pcie-usb2.dtso
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * DT overlay for PCIe support (limits USB to 2.0/high-speed)
+ *
+ * Copyright (C) 2021 PHYTEC America, LLC - https://www.phytec.com
+ * Author: Matt McKee <[email protected]>
+ *
+ * Copyright (C) 2024 PHYTEC America, LLC - https://www.phytec.com
+ * Author: Nathan Morrisson <[email protected]>
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/phy-cadence.h>
+
+#include "k3-pinctrl.h"
+#include "k3-serdes.h"
+
+&{/} {
+ pcie_refclk0: pcie-refclk0 {
+ compatible = "gpio-gate-clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_usb_sel_pins_default>;
+ clocks = <&serdes_refclk>;
+ #clock-cells = <0>;
+ enable-gpios = <&main_gpio1 7 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&main_pmx0 {
+ pcie_usb_sel_pins_default: pcie-usb-sel-default-pins {
+ pinctrl-single,pins = <
+ AM64X_IOPAD(0x017c, PIN_OUTPUT, 7) /* (T1) PRG0_PRU0_GPO7.GPIO1_7 */
+ >;
+ };
+
+ pcie_pins_default: pcie-default-pins {
+ pinctrl-single,pins = <
+ AM64X_IOPAD(0x0098, PIN_OUTPUT, 7) /* (W19) GPMC0_WAIT0.GPIO0_37 */
+ >;
+ };
+};
+
+&pcie0_rc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_pins_default>;
+ reset-gpios = <&main_gpio0 37 GPIO_ACTIVE_HIGH>;
+ phys = <&serdes0_pcie_usb_link>;
+ phy-names = "pcie-phy";
+ num-lanes = <1>;
+ status = "okay";
+};
+
+&serdes0_pcie_usb_link {
+ cdns,phy-type = <PHY_TYPE_PCIE>;
+};
+
+&serdes_ln_ctrl {
+ idle-states = <AM64_SERDES0_LANE0_PCIE0>;
+};
+
+&serdes0 {
+ assigned-clock-parents = <&pcie_refclk0>, <&pcie_refclk0>, <&pcie_refclk0>;
+};
+
+&serdes_refclk {
+ clock-frequency = <100000000>;
+};
+
+/*
+ * Assign pcie_refclk0 to serdes_wiz0 as ext_ref_clk.
+ * This makes sure that the clock generator gets enabled at the right time.
+ */
+&serdes_wiz0 {
+ clocks = <&k3_clks 162 0>, <&k3_clks 162 1>, <&pcie_refclk0>;
+};
+
+&usbss0 {
+ ti,usb2-only;
+};
+
+&usb0 {
+ maximum-speed = "high-speed";
+};
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 6df331ccb970..30729b49dd69 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
@@ -190,18 +190,6 @@
>;
};
- pcie_usb_sel_pins_default: pcie-usb-sel-default-pins {
- pinctrl-single,pins = <
- AM64X_IOPAD(0x017c, PIN_OUTPUT, 7) /* (T1) PRG0_PRU0_GPO7.GPIO1_7 */
- >;
- };
-
- pcie0_pins_default: pcie0-default-pins {
- pinctrl-single,pins = <
- AM64X_IOPAD(0x0098, PIN_OUTPUT, 7) /* (W19) GPMC0_WAIT0.GPIO0_37 */
- >;
- };
-
user_leds_pins_default: user-leds-default-pins {
pinctrl-single,pins = <
AM64X_IOPAD(0x003c, PIN_OUTPUT, 7) /* (T20) GPMC0_AD0.GPIO0_15 */
diff --git a/arch/arm64/boot/dts/ti/k3-am642-sk.dts b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
index 5b028b3a3192..44ecbcf1c844 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
@@ -430,6 +430,18 @@
#gpio-cells = <2>;
gpio-line-names = "LED1","LED2","LED3","LED4","LED5","LED6","LED7","LED8";
};
+
+ /* SoC power supply temperature */
+ tmp100@48 {
+ compatible = "ti,tmp100";
+ reg = <0x48>;
+ };
+
+ /* DDR power supply temperature */
+ tmp100@49 {
+ compatible = "ti,tmp100";
+ reg = <0x49>;
+ };
};
/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */
diff --git a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts
index 1f4dc5ad1696..c40ad67cee01 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts
@@ -1,7 +1,7 @@
-// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
* Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
- * Copyright (c) 2022-2023 TQ-Systems GmbH <[email protected]>, D-82229 Seefeld, Germany.
+ * Copyright (c) 2022-2024 TQ-Systems GmbH <[email protected]>, D-82229 Seefeld, Germany.
*/
/dts-v1/;
diff --git a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi
index 6c785eff7d2f..828d815d6bdf 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi
@@ -1,7 +1,7 @@
-// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
* Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
- * Copyright (c) 2022-2023 TQ-Systems GmbH <[email protected]>, D-82229 Seefeld, Germany.
+ * Copyright (c) 2022-2024 TQ-Systems GmbH <[email protected]>, D-82229 Seefeld, Germany.
*/
#include "k3-am642.dtsi"
diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
index ed71561c5bd9..1af3dedde1f6 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
@@ -1185,6 +1185,9 @@
<0x22400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-pru0_0-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <16 2 2>;
+ interrupt-names = "vring";
};
rtu0_0: rtu@4000 {
@@ -1194,6 +1197,9 @@
<0x23400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-rtu0_0-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <20 4 4>;
+ interrupt-names = "vring";
};
tx_pru0_0: txpru@a000 {
@@ -1212,6 +1218,9 @@
<0x24400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-pru0_1-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <18 3 3>;
+ interrupt-names = "vring";
};
rtu0_1: rtu@6000 {
@@ -1221,6 +1230,9 @@
<0x23c00 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-rtu0_1-fw";
+ interrupt-parent = <&icssg0_intc>;
+ interrupts = <22 5 5>;
+ interrupt-names = "vring";
};
tx_pru0_1: txpru@c000 {
@@ -1339,6 +1351,9 @@
<0x22400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-pru1_0-fw";
+ interrupt-parent = <&icssg1_intc>;
+ interrupts = <16 2 2>;
+ interrupt-names = "vring";
};
rtu1_0: rtu@4000 {
@@ -1348,6 +1363,9 @@
<0x23400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-rtu1_0-fw";
+ interrupt-parent = <&icssg1_intc>;
+ interrupts = <20 4 4>;
+ interrupt-names = "vring";
};
tx_pru1_0: txpru@a000 {
@@ -1366,6 +1384,9 @@
<0x24400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-pru1_1-fw";
+ interrupt-parent = <&icssg1_intc>;
+ interrupts = <18 3 3>;
+ interrupt-names = "vring";
};
rtu1_1: rtu@6000 {
@@ -1375,6 +1396,9 @@
<0x23c00 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-rtu1_1-fw";
+ interrupt-parent = <&icssg1_intc>;
+ interrupts = <22 5 5>;
+ interrupt-names = "vring";
};
tx_pru1_1: txpru@c000 {
@@ -1493,6 +1517,9 @@
<0x22400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-pru2_0-fw";
+ interrupt-parent = <&icssg2_intc>;
+ interrupts = <16 2 2>;
+ interrupt-names = "vring";
};
rtu2_0: rtu@4000 {
@@ -1502,6 +1529,9 @@
<0x23400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-rtu2_0-fw";
+ interrupt-parent = <&icssg2_intc>;
+ interrupts = <20 4 4>;
+ interrupt-names = "vring";
};
tx_pru2_0: txpru@a000 {
@@ -1520,6 +1550,9 @@
<0x24400 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-pru2_1-fw";
+ interrupt-parent = <&icssg2_intc>;
+ interrupts = <18 3 3>;
+ interrupt-names = "vring";
};
rtu2_1: rtu@6000 {
@@ -1529,6 +1562,9 @@
<0x23c00 0x100>;
reg-names = "iram", "control", "debug";
firmware-name = "am65x-rtu2_1-fw";
+ interrupt-parent = <&icssg2_intc>;
+ interrupts = <22 5 5>;
+ interrupt-names = "vring";
};
tx_pru2_1: txpru@c000 {
diff --git a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi
index 8feab9317644..43c6118d2bf0 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi
@@ -6,13 +6,17 @@
*/
&cbass_mcu {
- mcu_conf: scm-conf@40f00000 {
- compatible = "syscon", "simple-mfd";
- reg = <0x0 0x40f00000 0x0 0x20000>;
+ mcu_conf: bus@40f00000 {
+ compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0x40f00000 0x20000>;
+ cpsw_mac_syscon: ethernet-mac-syscon@200 {
+ compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
+ reg = <0x200 0x8>;
+ };
+
phy_gmii_sel: phy@4040 {
compatible = "ti,am654-phy-gmii-sel";
reg = <0x4040 0x4>;
@@ -358,7 +362,7 @@
reg = <1>;
ti,mac-only;
label = "port1";
- ti,syscon-efuse = <&mcu_conf 0x200>;
+ ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
phys = <&phy_gmii_sel 1>;
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
index aba0c52b1213..aa7139cc8a92 100644
--- a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
+++ b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
@@ -33,6 +33,7 @@
memory@80000000 {
device_type = "memory";
+ bootph-all;
/* 4G RAM */
reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
<0x00000008 0x80000000 0x00000000 0x80000000>;
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 d743f023cdd9..90dbe31c5b81 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
@@ -414,6 +414,82 @@
pinctrl-0 = <&wkup_uart0_pins_default>;
};
+&wkup_i2c0 {
+ bootph-all;
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wkup_i2c0_pins_default>;
+ status = "okay";
+
+ lp8733: pmic@60 {
+ compatible = "ti,lp8733";
+ reg = <0x60>;
+ buck0-in-supply = <&vsys_3v3>;
+ buck1-in-supply = <&vsys_3v3>;
+ ldo0-in-supply = <&vsys_3v3>;
+ ldo1-in-supply = <&vsys_3v3>;
+
+ lp8733_regulators: regulators {
+ lp8733_buck0_reg: buck0 {
+ /* FB_B0 -> LP8733-BUCK1 - VDD_MCU_0V85 */
+ regulator-name = "lp8733-buck0";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ lp8733_buck1_reg: buck1 {
+ /* FB_B1 -> LP8733-BUCK2 - VDD_DDR_1V1 */
+ regulator-name = "lp8733-buck1";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ lp8733_ldo0_reg: ldo0 {
+ /* LDO0 -> LP8733-LDO1 - VDA_DLL_0V8 */
+ regulator-name = "lp8733-ldo0";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ lp8733_ldo1_reg: ldo1 {
+ /* LDO1 -> LP8733-LDO2 - VDA_LN_1V8 */
+ regulator-name = "lp8733-ldo1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+ };
+
+ tps62873a: regulator@40 {
+ compatible = "ti,tps62873";
+ reg = <0x40>;
+ bootph-pre-ram;
+ regulator-name = "VDD_CPU_AVS";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ tps62873b: regulator@43 {
+ compatible = "ti,tps62873";
+ reg = <0x43>;
+ regulator-name = "VDD_CORE_0V8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+};
+
&mcu_uart0 {
status = "okay";
pinctrl-names = "default";
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 0f4a5da0ebc4..5c66e0ec6e82 100644
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
@@ -11,9 +11,10 @@
/ {
memory@80000000 {
device_type = "memory";
+ bootph-all;
/* 16 GB RAM */
- reg = <0x00 0x80000000 0x00 0x80000000>,
- <0x08 0x80000000 0x03 0x80000000>;
+ reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+ <0x00000008 0x80000000 0x00000003 0x80000000>;
};
reserved_memory: reserved-memory {
@@ -130,6 +131,25 @@
};
};
+&wkup_pmx0 {
+ mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+ J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (D19) MCU_OSPI0_CLK */
+ J721S2_WKUP_IOPAD(0x02c, PIN_OUTPUT, 0) /* (F15) MCU_OSPI0_CSn0 */
+ J721S2_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (C19) MCU_OSPI0_D0 */
+ J721S2_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (F16) MCU_OSPI0_D1 */
+ J721S2_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (G15) MCU_OSPI0_D2 */
+ J721S2_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (F18) MCU_OSPI0_D3 */
+ J721S2_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (E19) MCU_OSPI0_D4 */
+ J721S2_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (G19) MCU_OSPI0_D5 */
+ J721S2_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (F19) MCU_OSPI0_D6 */
+ J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (F20) MCU_OSPI0_D7 */
+ J721S2_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (E18) MCU_OSPI0_DQS */
+ >;
+ };
+};
+
&wkup_pmx2 {
wkup_i2c0_pins_default: wkup-i2c0-default-pins {
pinctrl-single,pins = <
@@ -152,6 +172,68 @@
};
};
+&ospi0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_fss0_ospi0_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 {
+ bootph-all;
+ 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@740000 {
+ label = "ospi.env.backup";
+ reg = <0x740000 0x40000>;
+ };
+
+ partition@800000 {
+ label = "ospi.rootfs";
+ reg = <0x800000 0x37c0000>;
+ };
+
+ partition@3fc0000 {
+ bootph-pre-ram;
+ label = "ospi.phypattern";
+ reg = <0x3fc0000 0x40000>;
+ };
+ };
+ };
+};
+
&mailbox0_cluster0 {
status = "okay";
interrupts = <436>;
diff --git a/arch/arm64/boot/dts/ti/k3-am69-sk.dts b/arch/arm64/boot/dts/ti/k3-am69-sk.dts
index d88651c297a2..3f655852244e 100644
--- a/arch/arm64/boot/dts/ti/k3-am69-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am69-sk.dts
@@ -35,8 +35,8 @@
device_type = "memory";
bootph-all;
/* 32G RAM */
- reg = <0x00 0x80000000 0x00 0x80000000>,
- <0x08 0x80000000 0x07 0x80000000>;
+ reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+ <0x00000008 0x80000000 0x00000007 0x80000000>;
};
reserved_memory: reserved-memory {
@@ -814,6 +814,27 @@
};
};
};
+
+ tps62873a: regulator@40 {
+ compatible = "ti,tps62873";
+ reg = <0x40>;
+ bootph-pre-ram;
+ regulator-name = "VDD_CPU_AVS";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <900000>;
+ 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;
+ };
};
&wkup_gpio0 {
@@ -1203,3 +1224,65 @@
};
};
};
+
+&serdes_ln_ctrl {
+ idle-states = <J784S4_SERDES0_LANE0_PCIE1_LANE0>, <J784S4_SERDES0_LANE1_PCIE1_LANE1>,
+ <J784S4_SERDES0_LANE2_PCIE3_LANE0>, <J784S4_SERDES0_LANE3_USB>,
+ <J784S4_SERDES1_LANE0_PCIE0_LANE0>, <J784S4_SERDES1_LANE1_PCIE0_LANE1>,
+ <J784S4_SERDES1_LANE2_PCIE0_LANE2>, <J784S4_SERDES1_LANE3_PCIE0_LANE3>;
+};
+
+&serdes_wiz0 {
+ status = "okay";
+};
+
+&serdes0 {
+ status = "okay";
+
+ serdes0_pcie_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <3>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_PCIE>;
+ resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>, <&serdes_wiz0 3>;
+ };
+};
+
+&serdes_wiz1 {
+ status = "okay";
+};
+
+&serdes1 {
+ status = "okay";
+
+ serdes1_pcie_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>;
+ };
+};
+
+&pcie0_rc {
+ status = "okay";
+ reset-gpios = <&exp1 4 GPIO_ACTIVE_HIGH>;
+ phys = <&serdes1_pcie_link>;
+ phy-names = "pcie-phy";
+};
+
+&pcie1_rc {
+ status = "okay";
+ reset-gpios = <&exp1 5 GPIO_ACTIVE_HIGH>;
+ phys = <&serdes0_pcie_link>;
+ phy-names = "pcie-phy";
+ num-lanes = <2>;
+};
+
+&pcie3_rc {
+ status = "okay";
+ reset-gpios = <&exp1 6 GPIO_ACTIVE_HIGH>;
+ phys = <&serdes0_pcie_link>;
+ phy-names = "pcie-phy";
+ num-lanes = <1>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-eth-phy.dtso b/arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-eth-phy.dtso
new file mode 100644
index 000000000000..356c82bbe143
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-eth-phy.dtso
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2023 PHYTEC America, LLC
+ * Author: Garrett Giordano <[email protected]>
+ *
+ * Copyright (C) 2024 PHYTEC America, LLC
+ * Author: Nathan Morrisson <[email protected]>
+ */
+
+/dts-v1/;
+/plugin/;
+
+&cpsw3g_phy1 {
+ status = "disabled";
+};
+
+&cpsw_port1 {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-rtc.dtso b/arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-rtc.dtso
new file mode 100644
index 000000000000..8b24191f5948
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-rtc.dtso
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2023 PHYTEC America, LLC
+ * Author: Garrett Giordano <[email protected]>
+ *
+ * Copyright (C) 2024 PHYTEC America, LLC
+ * Author: Nathan Morrisson <[email protected]>
+ */
+
+/dts-v1/;
+/plugin/;
+
+&i2c_som_rtc {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-spi-nor.dtso b/arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-spi-nor.dtso
new file mode 100644
index 000000000000..cc0cf269b6e4
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am6xx-phycore-disable-spi-nor.dtso
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2023 PHYTEC America, LLC
+ * Author: Garrett Giordano <[email protected]>
+ *
+ * Copyright (C) 2024 PHYTEC America, LLC
+ * Author: Nathan Morrisson <[email protected]>
+ */
+
+/dts-v1/;
+/plugin/;
+
+&serial_flash {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am6xx-phycore-qspi-nor.dtso b/arch/arm64/boot/dts/ti/k3-am6xx-phycore-qspi-nor.dtso
new file mode 100644
index 000000000000..969dfebcd637
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am6xx-phycore-qspi-nor.dtso
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2024 PHYTEC America LLC
+ * Author: Nathan Morrisson <[email protected]>
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "k3-pinctrl.h"
+
+&serial_flash {
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+};
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 fccaabfb1348..5097d192c2b2 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
@@ -164,12 +164,16 @@
ti,timer-pwm;
};
- mcu_conf: syscon@40f00000 {
- compatible = "syscon", "simple-mfd";
- reg = <0x00 0x40f00000 0x00 0x20000>;
+ mcu_conf: bus@40f00000 {
+ compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0x00 0x00 0x40f00000 0x20000>;
+ ranges = <0x0 0x0 0x40f00000 0x20000>;
+
+ cpsw_mac_syscon: ethernet-mac-syscon@200 {
+ compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
+ reg = <0x200 0x8>;
+ };
phy_gmii_sel: phy@4040 {
compatible = "ti,am654-phy-gmii-sel";
@@ -420,7 +424,7 @@
reg = <1>;
ti,mac-only;
label = "port1";
- ti,syscon-efuse = <&mcu_conf 0x200>;
+ ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
phys = <&phy_gmii_sel 1>;
};
};
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 7e6a584ac6f0..21fe194a5766 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
@@ -12,9 +12,10 @@
/ {
memory@80000000 {
device_type = "memory";
+ bootph-all;
/* 4G RAM */
- reg = <0x00 0x80000000 0x00 0x80000000>,
- <0x08 0x80000000 0x00 0x80000000>;
+ reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+ <0x00000008 0x80000000 0x00000000 0x80000000>;
};
reserved_memory: reserved-memory {
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board-infotainment.dtso b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board-infotainment.dtso
new file mode 100644
index 000000000000..65a7e54f0884
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board-infotainment.dtso
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Infotainment Expansion Board for j721e-evm
+ * User Guide: <https://www.ti.com/lit/ug/spruit0a/spruit0a.pdf>
+ *
+ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ label = "hdmi";
+ type = "a";
+ ddc-i2c-bus = <&main_i2c1>;
+ digital;
+ /* P12 - HDMI_HPD */
+ hpd-gpios = <&exp6 10 GPIO_ACTIVE_HIGH>;
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&tfp410_out>;
+ };
+ };
+ };
+
+ dvi-bridge {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "ti,tfp410";
+ /* P10 - HDMI_PDn */
+ powerdown-gpios = <&exp6 8 GPIO_ACTIVE_LOW>;
+
+ port@0 {
+ reg = <0>;
+
+ tfp410_in: endpoint {
+ remote-endpoint = <&dpi_out0>;
+ pclk-sample = <1>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ tfp410_out: endpoint {
+ remote-endpoint =
+ <&hdmi_connector_in>;
+ };
+ };
+ };
+};
+
+&main_pmx0 {
+ main_i2c1_exp6_pins_default: main-i2c1-exp6-default-pins {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x264, PIN_INPUT, 7) /* (T29) MMC2_DAT2.GPIO1_24 */
+ >;
+ };
+
+ dss_vout0_pins_default: dss-vout0-default-pins {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x58, PIN_OUTPUT, 10) /* (AE22) PRG1_PRU1_GPO0.VOUT0_DATA0 */
+ J721E_IOPAD(0x5c, PIN_OUTPUT, 10) /* (AG23) PRG1_PRU1_GPO1.VOUT0_DATA1 */
+ J721E_IOPAD(0x60, PIN_OUTPUT, 10) /* (AF23) PRG1_PRU1_GPO2.VOUT0_DATA2 */
+ J721E_IOPAD(0x64, PIN_OUTPUT, 10) /* (AD23) PRG1_PRU1_GPO3.VOUT0_DATA3 */
+ J721E_IOPAD(0x68, PIN_OUTPUT, 10) /* (AH24) PRG1_PRU1_GPO4.VOUT0_DATA4 */
+ J721E_IOPAD(0x6c, PIN_OUTPUT, 10) /* (AG21) PRG1_PRU1_GPO5.VOUT0_DATA5 */
+ J721E_IOPAD(0x70, PIN_OUTPUT, 10) /* (AE23) PRG1_PRU1_GPO6.VOUT0_DATA6 */
+ J721E_IOPAD(0x74, PIN_OUTPUT, 10) /* (AC21) PRG1_PRU1_GPO7.VOUT0_DATA7 */
+ J721E_IOPAD(0x78, PIN_OUTPUT, 10) /* (Y23) PRG1_PRU1_GPO8.VOUT0_DATA8 */
+ J721E_IOPAD(0x7c, PIN_OUTPUT, 10) /* (AF21) PRG1_PRU1_GPO9.VOUT0_DATA9 */
+ J721E_IOPAD(0x80, PIN_OUTPUT, 10) /* (AB23) PRG1_PRU1_GPO10.VOUT0_DATA10 */
+ J721E_IOPAD(0x84, PIN_OUTPUT, 10) /* (AJ25) PRG1_PRU1_GPO11.VOUT0_DATA11 */
+ J721E_IOPAD(0x88, PIN_OUTPUT, 10) /* (AH25) PRG1_PRU1_GPO12.VOUT0_DATA12 */
+ J721E_IOPAD(0x8c, PIN_OUTPUT, 10) /* (AG25) PRG1_PRU1_GPO13.VOUT0_DATA13 */
+ J721E_IOPAD(0x90, PIN_OUTPUT, 10) /* (AH26) PRG1_PRU1_GPO14.VOUT0_DATA14 */
+ J721E_IOPAD(0x94, PIN_OUTPUT, 10) /* (AJ27) PRG1_PRU1_GPO15.VOUT0_DATA15 */
+ J721E_IOPAD(0x30, PIN_OUTPUT, 10) /* (AF24) PRG1_PRU0_GPO11.VOUT0_DATA16 */
+ J721E_IOPAD(0x34, PIN_OUTPUT, 10) /* (AJ24) PRG1_PRU0_GPO12.VOUT0_DATA17 */
+ J721E_IOPAD(0x38, PIN_OUTPUT, 10) /* (AG24) PRG1_PRU0_GPO13.VOUT0_DATA18 */
+ J721E_IOPAD(0x3c, PIN_OUTPUT, 10) /* (AD24) PRG1_PRU0_GPO14.VOUT0_DATA19 */
+ J721E_IOPAD(0x40, PIN_OUTPUT, 10) /* (AC24) PRG1_PRU0_GPO15.VOUT0_DATA20 */
+ J721E_IOPAD(0x44, PIN_OUTPUT, 10) /* (AE24) PRG1_PRU0_GPO16.VOUT0_DATA21 */
+ J721E_IOPAD(0x24, PIN_OUTPUT, 10) /* (AJ20) PRG1_PRU0_GPO8.VOUT0_DATA22 */
+ J721E_IOPAD(0x28, PIN_OUTPUT, 10) /* (AG20) PRG1_PRU0_GPO9.VOUT0_DATA23 */
+ J721E_IOPAD(0x9c, PIN_OUTPUT, 10) /* (AC22) PRG1_PRU1_GPO17.VOUT0_DE */
+ J721E_IOPAD(0x98, PIN_OUTPUT, 10) /* (AJ26) PRG1_PRU1_GPO16.VOUT0_HSYNC */
+ J721E_IOPAD(0xa4, PIN_OUTPUT, 10) /* (AH22) PRG1_PRU1_GPO19.VOUT0_PCLK */
+ J721E_IOPAD(0xa0, PIN_OUTPUT, 10) /* (AJ22) PRG1_PRU1_GPO18.VOUT0_VSYNC */
+ >;
+ };
+};
+
+&exp1 {
+ p14-hog {
+ /* P14 - VINOUT_MUX_SEL0 */
+ gpio-hog;
+ gpios = <12 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "VINOUT_MUX_SEL0";
+ };
+
+ p15-hog {
+ /* P15 - VINOUT_MUX_SEL1 */
+ gpio-hog;
+ gpios = <13 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "VINOUT_MUX_SEL1";
+ };
+};
+
+&main_i2c1 {
+ /* i2c1 is used for DVI DDC, so we need to use 100kHz */
+ clock-frequency = <100000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ exp6: gpio@21 {
+ compatible = "ti,tca6416";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c1_exp6_pins_default>;
+ interrupt-parent = <&main_gpio1>;
+ interrupts = <24 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ p11-hog {
+ /* P11 - HDMI_DDC_OE */
+ gpio-hog;
+ gpios = <9 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "HDMI_DDC_OE";
+ };
+ };
+};
+
+&dss {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dss_vout0_pins_default>;
+};
+
+&dss_ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ reg = <1>;
+
+ dpi_out0: endpoint {
+ remote-endpoint = <&tfp410_in>;
+ };
+ };
+};
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 9349ae07c046..6b6ef6a30614 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
@@ -34,13 +34,17 @@
};
};
- mcu_conf: syscon@40f00000 {
- compatible = "syscon", "simple-mfd";
- reg = <0x0 0x40f00000 0x0 0x20000>;
+ mcu_conf: bus@40f00000 {
+ compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0x40f00000 0x20000>;
+ cpsw_mac_syscon: ethernet-mac-syscon@200 {
+ compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
+ reg = <0x200 0x8>;
+ };
+
phy_gmii_sel: phy@4040 {
compatible = "ti,am654-phy-gmii-sel";
reg = <0x4040 0x4>;
@@ -546,7 +550,7 @@
reg = <1>;
ti,mac-only;
label = "port1";
- ti,syscon-efuse = <&mcu_conf 0x200>;
+ ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
phys = <&phy_gmii_sel 1>;
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
index 0c4575ad8d7c..89fbfb21e5d3 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
@@ -31,6 +31,7 @@
memory@80000000 {
device_type = "memory";
+ bootph-all;
/* 4G RAM */
reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
<0x00000008 0x80000000 0x00000000 0x80000000>;
@@ -210,6 +211,42 @@
<3300000 0x1>;
};
+ transceiver1: can-phy1 {
+ compatible = "ti,tcan1042";
+ #phy-cells = <0>;
+ max-bitrate = <5000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_mcan0_gpio_pins_default>;
+ standby-gpios = <&wkup_gpio0 3 GPIO_ACTIVE_HIGH>;
+ };
+
+ transceiver2: can-phy2 {
+ compatible = "ti,tcan1042";
+ #phy-cells = <0>;
+ max-bitrate = <5000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcan0_gpio_pins_default>;
+ standby-gpios = <&main_gpio0 65 GPIO_ACTIVE_HIGH>;
+ };
+
+ transceiver3: can-phy3 {
+ compatible = "ti,tcan1042";
+ #phy-cells = <0>;
+ max-bitrate = <5000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcan5_gpio_pins_default>;
+ standby-gpios = <&main_gpio0 66 GPIO_ACTIVE_HIGH>;
+ };
+
+ transceiver4: can-phy4 {
+ compatible = "ti,tcan1042";
+ #phy-cells = <0>;
+ max-bitrate = <5000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcan9_gpio_pins_default>;
+ standby-gpios = <&main_gpio0 67 GPIO_ACTIVE_HIGH>;
+ };
+
dp_pwr_3v3: fixedregulator-dp-prw {
compatible = "regulator-fixed";
regulator-name = "dp-pwr";
@@ -367,6 +404,45 @@
>;
};
+ main_mcan0_pins_default: main-mcan0-default-pins {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x208, PIN_INPUT, 0) /* (W5) MCAN0_RX */
+ J721E_IOPAD(0x20c, PIN_OUTPUT, 0) /* (W6) MCAN0_TX */
+ >;
+ };
+
+ main_mcan0_gpio_pins_default: main-mcan0-gpio-default-pins {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x108, PIN_INPUT, 7) /* (AD27) PRG0_PRU1_GPO2.GPIO0_65 */
+ >;
+ };
+
+ main_mcan5_pins_default: main-mcan5-default-pins {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x050, PIN_INPUT, 6) /* (AE21) PRG1_PRU0_GPO18.MCAN5_RX */
+ J721E_IOPAD(0x04c, PIN_OUTPUT, 6) /* (AJ21) PRG1_PRU0_GPO17.MCAN5_TX */
+ >;
+ };
+
+ main_mcan5_gpio_pins_default: main-mcan5-gpio-default-pins {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x10c, PIN_INPUT, 7) /* (AC25) PRG0_PRU1_GPO3.GPIO0_66 */
+ >;
+ };
+
+ main_mcan9_pins_default: main-mcan9-default-pins {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x0d0, PIN_INPUT, 6) /* (AC27) PRG0_PRU0_GPO8.MCAN9_RX */
+ J721E_IOPAD(0x0cc, PIN_OUTPUT, 6) /* (AC28) PRG0_PRU0_GPO7.MCAN9_TX */
+ >;
+ };
+
+ main_mcan9_gpio_pins_default: main-mcan9-gpio-default-pins {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x110, PIN_INPUT, 7) /* (AD29) PRG0_PRU1_GPO4.GPIO0_67 */
+ >;
+ };
+
dp0_pins_default: dp0-default-pins {
pinctrl-single,pins = <
J721E_IOPAD(0x1c4, PIN_INPUT, 5) /* SPI0_CS1.DP0_HPD */
@@ -555,6 +631,19 @@
>;
};
+ mcu_mcan0_pins_default: mcu-mcan0-default-pins {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0x0ac, PIN_INPUT, 0) /* (C29) MCU_MCAN0_RX */
+ J721E_WKUP_IOPAD(0x0a8, PIN_OUTPUT, 0) /* (D29) MCU_MCAN0_TX */
+ >;
+ };
+
+ mcu_mcan0_gpio_pins_default: mcu-mcan0-gpio-default-pins {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0x0bc, PIN_INPUT, 7) /* (F27) WKUP_GPIO0_3 */
+ >;
+ };
+
/* Reset for M.2 M Key slot on PCIe1 */
mkey_reset_pins_default: mkey-reset-pns-default-pins {
pinctrl-single,pins = <
@@ -1108,6 +1197,34 @@
num-lanes = <2>;
};
+&mcu_mcan0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_mcan0_pins_default>;
+ phys = <&transceiver1>;
+ status = "okay";
+};
+
+&main_mcan0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcan0_pins_default>;
+ phys = <&transceiver2>;
+ status = "okay";
+};
+
+&main_mcan5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcan5_pins_default>;
+ phys = <&transceiver3>;
+ status = "okay";
+};
+
+&main_mcan9 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcan9_pins_default>;
+ phys = <&transceiver4>;
+ status = "okay";
+};
+
&ufs_wrapper {
status = "disabled";
};
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 1fae6495db07..5ba947771b84 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
@@ -12,6 +12,7 @@
/ {
memory@80000000 {
device_type = "memory";
+ bootph-all;
/* 4G RAM */
reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
<0x00000008 0x80000000 0x00000000 0x80000000>;
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 5ccb04c7c462..8feb42c89e47 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
@@ -139,13 +139,17 @@
ti,interrupt-ranges = <16 960 16>;
};
- mcu_conf: syscon@40f00000 {
- compatible = "syscon", "simple-mfd";
- reg = <0x0 0x40f00000 0x0 0x20000>;
+ mcu_conf: bus@40f00000 {
+ compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0x40f00000 0x20000>;
+ cpsw_mac_syscon: ethernet-mac-syscon@200 {
+ compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
+ reg = <0x200 0x8>;
+ };
+
phy_gmii_sel: phy@4040 {
compatible = "ti,am654-phy-gmii-sel";
reg = <0x4040 0x4>;
@@ -544,7 +548,7 @@
reg = <1>;
ti,mac-only;
label = "port1";
- ti,syscon-efuse = <&mcu_conf 0x200>;
+ ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
phys = <&phy_gmii_sel 1>;
};
};
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 623c8421525d..82aacc01e8fe 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
@@ -13,9 +13,10 @@
/ {
memory@80000000 {
device_type = "memory";
+ bootph-all;
/* 16 GB RAM */
- reg = <0x00 0x80000000 0x00 0x80000000>,
- <0x08 0x80000000 0x03 0x80000000>;
+ reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+ <0x00000008 0x80000000 0x00000003 0x80000000>;
};
/* Reserving memory regions still pending */
diff --git a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts
index bf3c246d13d1..dd3b5f7039d7 100644
--- a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts
@@ -9,7 +9,9 @@
/dts-v1/;
#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy.h>
#include "k3-j722s.dtsi"
+#include "k3-serdes.h"
/ {
compatible = "ti,j722s-evm", "ti,j722s";
@@ -105,6 +107,15 @@
<3300000 0x1>;
};
+ vsys_io_3v3: regulator-vsys-io-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vsys_io_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
vsys_io_1v8: regulator-vsys-io-1v8 {
compatible = "regulator-fixed";
regulator-name = "vsys_io_1v8";
@@ -122,6 +133,35 @@
regulator-always-on;
regulator-boot-on;
};
+
+ codec_audio: sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "J722S-EVM";
+ simple-audio-card,widgets =
+ "Headphone", "Headphone Jack",
+ "Line", "Line In",
+ "Microphone", "Microphone Jack";
+ simple-audio-card,routing =
+ "Headphone Jack", "HPLOUT",
+ "Headphone Jack", "HPROUT",
+ "LINE1L", "Line In",
+ "LINE1R", "Line In",
+ "MIC3R", "Microphone Jack",
+ "Microphone Jack", "Mic Bias";
+ simple-audio-card,format = "dsp_b";
+ simple-audio-card,bitclock-master = <&sound_master>;
+ simple-audio-card,frame-master = <&sound_master>;
+ simple-audio-card,bitclock-inversion;
+
+ simple-audio-card,cpu {
+ sound-dai = <&mcasp1>;
+ };
+
+ sound_master: simple-audio-card,codec {
+ sound-dai = <&tlv320aic3106>;
+ clocks = <&audio_refclk1>;
+ };
+ };
};
&main_pmx0 {
@@ -202,6 +242,27 @@
J722S_IOPAD(0x012c, PIN_OUTPUT, 0) /* (AF25) RGMII1_TX_CTL */
>;
};
+
+ main_usb1_pins_default: main-usb1-default-pins {
+ pinctrl-single,pins = <
+ J722S_IOPAD(0x0258, PIN_INPUT, 0) /* (B27) USB1_DRVVBUS */
+ >;
+ };
+
+ main_mcasp1_pins_default: main-mcasp1-default-pins {
+ pinctrl-single,pins = <
+ J722S_IOPAD(0x0090, PIN_INPUT, 2) /* (P27) GPMC0_BE0n_CLE.MCASP1_ACLKX */
+ J722S_IOPAD(0x0098, PIN_INPUT, 2) /* (V21) GPMC0_WAIT0.MCASP1_AFSX */
+ J722S_IOPAD(0x008c, PIN_OUTPUT, 2) /* (N23) GPMC0_WEn.MCASP1_AXR0 */
+ J722S_IOPAD(0x0084, PIN_INPUT, 2) /* (N21) GPMC0_ADVn_ALE.MCASP1_AXR2 */
+ >;
+ };
+
+ audio_ext_refclk1_pins_default: audio-ext-refclk1-default-pins {
+ pinctrl-single,pins = <
+ J722S_IOPAD(0x00a0, PIN_OUTPUT, 1) /* (N24) GPMC0_WPn.AUDIO_EXT_REFCLK1 */
+ >;
+ };
};
&cpsw3g {
@@ -277,6 +338,12 @@
bootph-all;
};
+&k3_clks {
+ /* Configure AUDIO_EXT_REFCLK1 pin as output */
+ pinctrl-names = "default";
+ pinctrl-0 = <&audio_ext_refclk1_pins_default>;
+};
+
&main_i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
@@ -301,6 +368,48 @@
"PCIe0_1L_RC_RSTz", "PCIe0_1L_PRSNT#",
"ENET1_EXP_SPARE2", "ENET1_EXP_PWRDN",
"PD_I2ENET1_I2CMUX_SELC_IRQ", "ENET1_EXP_RESETZ";
+
+ p05-hog {
+ /* P05 - USB2.0_MUX_SEL */
+ gpio-hog;
+ gpios = <5 GPIO_ACTIVE_HIGH>;
+ output-high;
+ };
+
+ p01_hog: p01-hog {
+ /* P01 - TRC_MUX_SEL */
+ gpio-hog;
+ gpios = <0 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "TRC_MUX_SEL";
+ };
+
+ p02_hog: p02-hog {
+ /* P02 - MCASP1_FET_SEL */
+ gpio-hog;
+ gpios = <2 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "MCASP1_FET_SEL";
+ };
+
+ p13_hog: p13-hog {
+ /* P13 - GPIO_AUD_RSTn */
+ gpio-hog;
+ gpios = <13 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "GPIO_AUD_RSTn";
+ };
+ };
+
+ tlv320aic3106: audio-codec@1b {
+ #sound-dai-cells = <0>;
+ compatible = "ti,tlv320aic3106";
+ reg = <0x1b>;
+ ai3x-micbias-vg = <1>; /* 2.0V */
+ AVDD-supply = <&vsys_io_3v3>;
+ IOVDD-supply = <&vsys_io_3v3>;
+ DRVDD-supply = <&vsys_io_3v3>;
+ DVDD-supply = <&vsys_io_1v8>;
};
};
@@ -384,3 +493,76 @@
status = "okay";
bootph-all;
};
+
+&serdes_ln_ctrl {
+ idle-states = <J722S_SERDES0_LANE0_USB>,
+ <J722S_SERDES1_LANE0_PCIE0_LANE0>;
+};
+
+&serdes0 {
+ status = "okay";
+ serdes0_usb_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <1>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_USB3>;
+ resets = <&serdes_wiz0 1>;
+ };
+};
+
+&serdes1 {
+ status = "okay";
+ serdes1_pcie_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <1>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_PCIE>;
+ resets = <&serdes_wiz1 1>;
+ };
+};
+
+&pcie0_rc {
+ reset-gpios = <&exp1 18 GPIO_ACTIVE_HIGH>;
+ phys = <&serdes1_pcie_link>;
+ phy-names = "pcie-phy";
+ status = "okay";
+};
+
+&usbss0 {
+ ti,vbus-divider;
+ status = "okay";
+};
+
+&usb0 {
+ dr_mode = "otg";
+ usb-role-switch;
+};
+
+&usbss1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_usb1_pins_default>;
+ ti,vbus-divider;
+ status = "okay";
+};
+
+&usb1 {
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+ phys = <&serdes0_usb_link>;
+ phy-names = "cdns3,usb3-phy";
+};
+
+&mcasp1 {
+ status = "okay";
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcasp1_pins_default>;
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 1 0 2 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ >;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi b/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi
new file mode 100644
index 000000000000..c797980528ec
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree file for the J722S MAIN domain peripherals
+ *
+ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <dt-bindings/phy/phy-cadence.h>
+#include <dt-bindings/phy/phy-ti.h>
+
+/ {
+ serdes_refclk: clk-0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+};
+
+&cbass_main {
+ serdes_wiz0: phy@f000000 {
+ compatible = "ti,am64-wiz-10g";
+ ranges = <0x0f000000 0x0 0x0f000000 0x00010000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ power-domains = <&k3_pds 279 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 279 0>, <&k3_clks 279 1>, <&serdes_refclk>;
+ clock-names = "fck", "core_ref_clk", "ext_ref_clk";
+ num-lanes = <1>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+
+ assigned-clocks = <&k3_clks 279 1>;
+ assigned-clock-parents = <&k3_clks 279 5>;
+
+ serdes0: serdes@f000000 {
+ compatible = "ti,j721e-serdes-10g";
+ reg = <0x0f000000 0x00010000>;
+ 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 279 1>,
+ <&k3_clks 279 1>,
+ <&k3_clks 279 1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+
+ status = "disabled"; /* Needs lane config */
+ };
+ };
+
+ serdes_wiz1: phy@f010000 {
+ compatible = "ti,am64-wiz-10g";
+ ranges = <0x0f010000 0x0 0x0f010000 0x00010000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ power-domains = <&k3_pds 280 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 280 0>, <&k3_clks 280 1>, <&serdes_refclk>;
+ clock-names = "fck", "core_ref_clk", "ext_ref_clk";
+ num-lanes = <1>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+
+ assigned-clocks = <&k3_clks 280 1>;
+ assigned-clock-parents = <&k3_clks 280 5>;
+
+ serdes1: serdes@f010000 {
+ compatible = "ti,j721e-serdes-10g";
+ reg = <0x0f010000 0x00010000>;
+ 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 280 1>,
+ <&k3_clks 280 1>,
+ <&k3_clks 280 1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+
+ status = "disabled"; /* Needs lane config */
+ };
+ };
+
+ pcie0_rc: pcie@f102000 {
+ compatible = "ti,j722s-pcie-host", "ti,j721e-pcie-host";
+ reg = <0x00 0x0f102000 0x00 0x1000>,
+ <0x00 0x0f100000 0x00 0x400>,
+ <0x00 0x0d000000 0x00 0x00800000>,
+ <0x00 0x68000000 0x00 0x00001000>;
+ reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
+ ranges = <0x01000000 0x00 0x68001000 0x00 0x68001000 0x00 0x0010000>,
+ <0x02000000 0x00 0x68011000 0x00 0x68011000 0x00 0x7fef000>;
+ dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+ interrupt-names = "link_state";
+ interrupts = <GIC_SPI 99 IRQ_TYPE_EDGE_RISING>;
+ device_type = "pci";
+ max-link-speed = <3>;
+ num-lanes = <1>;
+ power-domains = <&k3_pds 259 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 259 0>, <&serdes1 CDNS_TORRENT_REFCLK_DRIVER>;
+ clock-names = "fck", "pcie_refclk";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x0 0xff>;
+ vendor-id = <0x104c>;
+ device-id = <0xb010>;
+ cdns,no-bar-match-nbits = <64>;
+ ti,syscon-pcie-ctrl = <&pcie0_ctrl 0x0>;
+ msi-map = <0x0 &gic_its 0x0 0x10000>;
+ status = "disabled";
+ };
+
+ usbss1: usb@f920000 {
+ compatible = "ti,j721e-usb";
+ reg = <0x00 0x0f920000 0x00 0x100>;
+ power-domains = <&k3_pds 278 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 278 3>, <&k3_clks 278 1>;
+ clock-names = "ref", "lpm";
+ assigned-clocks = <&k3_clks 278 3>; /* USB2_REFCLK */
+ assigned-clock-parents = <&k3_clks 278 4>; /* HF0SC0 */
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ status = "disabled";
+
+ usb1: usb@31200000{
+ compatible = "cdns,usb3";
+ reg = <0x00 0x31200000 0x00 0x10000>,
+ <0x00 0x31210000 0x00 0x10000>,
+ <0x00 0x31220000 0x00 0x10000>;
+ reg-names = "otg",
+ "xhci",
+ "dev";
+ interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
+ <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>, /* irq.6 */
+ <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>; /* otgirq */
+ interrupt-names = "host",
+ "peripheral",
+ "otg";
+ maximum-speed = "super-speed";
+ dr_mode = "otg";
+ };
+ };
+};
+
+&main_conf {
+ serdes_ln_ctrl: mux-controller@4080 {
+ compatible = "reg-mux";
+ reg = <0x4080 0x14>;
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x00 0x3>, /* SERDES0 lane0 select */
+ <0x10 0x3>; /* SERDES1 lane0 select */
+ };
+
+ audio_refclk1: clock@82e4 {
+ compatible = "ti,am62-audio-refclk";
+ reg = <0x82e4 0x4>;
+ clocks = <&k3_clks 157 18>;
+ assigned-clocks = <&k3_clks 157 18>;
+ assigned-clock-parents = <&k3_clks 157 33>;
+ #clock-cells = <0>;
+ };
+};
+
+&wkup_conf {
+ pcie0_ctrl: pcie0-ctrl@4070 {
+ compatible = "ti,j784s4-pcie-ctrl", "syscon";
+ reg = <0x4070 0x4>;
+ };
+};
+
+&oc_sram {
+ reg = <0x00 0x70000000 0x00 0x40000>;
+ ranges = <0x00 0x00 0x70000000 0x40000>;
+};
+
+&inta_main_dmss {
+ ti,interrupt-ranges = <7 71 21>;
+};
+
+&main_pmx0 {
+ pinctrl-single,gpio-range =
+ <&main_pmx0_range 0 32 PIN_GPIO_RANGE_IOPAD>,
+ <&main_pmx0_range 33 55 PIN_GPIO_RANGE_IOPAD>,
+ <&main_pmx0_range 101 25 PIN_GPIO_RANGE_IOPAD>,
+ <&main_pmx0_range 137 5 PIN_GPIO_RANGE_IOPAD>,
+ <&main_pmx0_range 143 3 PIN_GPIO_RANGE_IOPAD>,
+ <&main_pmx0_range 149 2 PIN_GPIO_RANGE_IOPAD>;
+
+ main_pmx0_range: gpio-range {
+ #pinctrl-single,gpio-range-cells = <3>;
+ };
+};
+
+&main_gpio0 {
+ gpio-ranges = <&main_pmx0 0 0 32>, <&main_pmx0 32 33 38>,
+ <&main_pmx0 70 72 17>;
+ ti,ngpio = <87>;
+};
+
+&main_gpio1 {
+ gpio-ranges = <&main_pmx0 7 101 25>, <&main_pmx0 42 137 5>,
+ <&main_pmx0 47 143 3>, <&main_pmx0 50 149 2>;
+ ti,ngpio = <73>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j722s.dtsi b/arch/arm64/boot/dts/ti/k3-j722s.dtsi
index c75744edb143..14c6c6a332ef 100644
--- a/arch/arm64/boot/dts/ti/k3-j722s.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j722s.dtsi
@@ -10,11 +10,133 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/soc/ti,sci_pm_domain.h>
-#include "k3-am62p5.dtsi"
+#include "k3-pinctrl.h"
/ {
model = "Texas Instruments K3 J722S SoC";
compatible = "ti,j722s";
+ interrupt-parent = <&gic500>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ 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-a53";
+ reg = <0x000>;
+ device_type = "cpu";
+ enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_0>;
+ clocks = <&k3_clks 135 0>;
+ };
+
+ cpu1: cpu@1 {
+ compatible = "arm,cortex-a53";
+ reg = <0x001>;
+ device_type = "cpu";
+ enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_0>;
+ clocks = <&k3_clks 136 0>;
+ };
+
+ cpu2: cpu@2 {
+ compatible = "arm,cortex-a53";
+ reg = <0x002>;
+ device_type = "cpu";
+ enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_0>;
+ clocks = <&k3_clks 137 0>;
+ };
+
+ cpu3: cpu@3 {
+ compatible = "arm,cortex-a53";
+ reg = <0x003>;
+ device_type = "cpu";
+ enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2_0>;
+ clocks = <&k3_clks 138 0>;
+ };
+ };
+
+ l2_0: l2-cache0 {
+ compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
+ cache-size = <0x80000>;
+ cache-line-size = <64>;
+ cache-sets = <512>;
+ };
+
+ firmware {
+ optee {
+ compatible = "linaro,optee-tz";
+ method = "smc";
+ };
+
+ psci: psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+ };
+
+ a53_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-a53-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ };
cbass_main: bus@f0000 {
compatible = "simple-bus";
@@ -74,16 +196,39 @@
<0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>,
<0x00 0x78000000 0x00 0x78000000 0x00 0x00008000>,
<0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>;
- };
-};
-/* Main domain overrides */
+ cbass_mcu: bus@4000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>, /* Peripheral window */
+ <0x00 0x79000000 0x00 0x79000000 0x00 0x00008000>, /* MCU R5 ATCM */
+ <0x00 0x79020000 0x00 0x79020000 0x00 0x00008000>, /* MCU R5 BTCM */
+ <0x00 0x79100000 0x00 0x79100000 0x00 0x00040000>, /* MCU IRAM0 */
+ <0x00 0x79140000 0x00 0x79140000 0x00 0x00040000>; /* MCU IRAM1 */
+ bootph-all;
+ };
-&inta_main_dmss {
- ti,interrupt-ranges = <7 71 21>;
-};
+ cbass_wakeup: bus@b00000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>, /* VTM */
+ <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>, /* Peripheral Window */
+ <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>, /* WKUP CTRL MMR */
+ <0x00 0x78000000 0x00 0x78000000 0x00 0x00008000>, /* DM R5 ATCM*/
+ <0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>; /* DM R5 BTCM*/
+ bootph-all;
+ };
+ };
-&oc_sram {
- reg = <0x00 0x70000000 0x00 0x40000>;
- ranges = <0x00 0x00 0x70000000 0x40000>;
+ #include "k3-am62p-j722s-common-thermal.dtsi"
};
+
+/* Include peripherals shared with AM62P */
+#include "k3-am62p-j722s-common-main.dtsi"
+#include "k3-am62p-j722s-common-mcu.dtsi"
+#include "k3-am62p-j722s-common-wakeup.dtsi"
+
+/* Include J722S specific peripherals */
+#include "k3-j722s-main.dtsi"
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-evm-pcie0-pcie1-ep.dtso b/arch/arm64/boot/dts/ti/k3-j784s4-evm-pcie0-pcie1-ep.dtso
new file mode 100644
index 000000000000..685305092bd8
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm-pcie0-pcie1-ep.dtso
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/**
+ * DT Overlay for enabling PCIE0 and PCIE1 instances in Endpoint Configuration
+ * on J784S4 EVM.
+ *
+ * J784S4 EVM Product Link: https://www.ti.com/tool/J784S4XEVM
+ *
+ * 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";
+};
+
+&pcie1_rc {
+ status = "disabled";
+};
+
+&cbass_main {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&gic500>;
+
+ pcie0_ep: pcie-ep@2900000 {
+ compatible = "ti,j784s4-pcie-ep";
+ reg = <0x00 0x02900000 0x00 0x1000>,
+ <0x00 0x02907000 0x00 0x400>,
+ <0x00 0x0d000000 0x00 0x00800000>,
+ <0x00 0x10000000 0x00 0x08000000>;
+ reg-names = "intd_cfg", "user_cfg", "reg", "mem";
+ interrupt-names = "link_state";
+ interrupts = <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>;
+ 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";
+ max-functions = /bits/ 8 <6>;
+ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>;
+ dma-coherent;
+ phys = <&serdes1_pcie0_link>;
+ phy-names = "pcie-phy";
+ };
+
+ pcie1_ep: pcie-ep@2910000 {
+ compatible = "ti,j784s4-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>;
+ ti,syscon-pcie-ctrl = <&pcie1_ctrl 0x0>;
+ max-link-speed = <3>;
+ num-lanes = <2>;
+ power-domains = <&k3_pds 333 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 333 0>;
+ clock-names = "fck";
+ max-functions = /bits/ 8 <6>;
+ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>;
+ dma-coherent;
+ phys = <&serdes0_pcie1_link>;
+ phy-names = "pcie-phy";
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-evm-quad-port-eth-exp1.dtso b/arch/arm64/boot/dts/ti/k3-j784s4-evm-quad-port-eth-exp1.dtso
new file mode 100644
index 000000000000..dcd2c7c39ec3
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm-quad-port-eth-exp1.dtso
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+/**
+ * DT Overlay for CPSW9G in QSGMII mode using J7 Quad Port ETH EXP Add-On Ethernet Card with
+ * J784S4 EVM. The Add-On Ethernet Card has to be connected to ENET Expansion 1 slot on the
+ * board.
+ *
+ * Product Datasheet: https://www.ti.com/lit/ug/spruj74/spruj74.pdf
+ *
+ * Link to QSGMII Daughtercard: https://www.ti.com/tool/J721EXENETXPANEVM
+ *
+ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/phy/phy-cadence.h>
+#include <dt-bindings/phy/phy.h>
+
+#include "k3-pinctrl.h"
+#include "k3-serdes.h"
+
+&{/} {
+ aliases {
+ ethernet1 = "/bus@100000/ethernet@c000000/ethernet-ports/port@5";
+ ethernet2 = "/bus@100000/ethernet@c000000/ethernet-ports/port@6";
+ ethernet3 = "/bus@100000/ethernet@c000000/ethernet-ports/port@7";
+ ethernet4 = "/bus@100000/ethernet@c000000/ethernet-ports/port@8";
+ ethernet5 = "/bus@100000/ethernet@c200000/ethernet-ports/port@1";
+ };
+};
+
+&main_cpsw0 {
+ status = "okay";
+};
+
+&main_cpsw0_port5 {
+ phy-handle = <&cpsw9g_phy1>;
+ phy-mode = "qsgmii";
+ mac-address = [00 00 00 00 00 00];
+ phys = <&cpsw0_phy_gmii_sel 5>, <&serdes2_qsgmii_link>;
+ phy-names = "mac", "serdes";
+ status = "okay";
+};
+
+&main_cpsw0_port6 {
+ phy-handle = <&cpsw9g_phy2>;
+ phy-mode = "qsgmii";
+ mac-address = [00 00 00 00 00 00];
+ phys = <&cpsw0_phy_gmii_sel 6>, <&serdes2_qsgmii_link>;
+ phy-names = "mac", "serdes";
+ status = "okay";
+};
+
+&main_cpsw0_port7 {
+ phy-handle = <&cpsw9g_phy0>;
+ phy-mode = "qsgmii";
+ mac-address = [00 00 00 00 00 00];
+ phys = <&cpsw0_phy_gmii_sel 7>, <&serdes2_qsgmii_link>;
+ phy-names = "mac", "serdes";
+ status = "okay";
+};
+
+&main_cpsw0_port8 {
+ phy-handle = <&cpsw9g_phy3>;
+ phy-mode = "qsgmii";
+ mac-address = [00 00 00 00 00 00];
+ phys = <&cpsw0_phy_gmii_sel 8>, <&serdes2_qsgmii_link>;
+ phy-names = "mac", "serdes";
+ status = "okay";
+};
+
+&main_cpsw0_mdio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mdio0_default_pins>;
+ bus_freq = <1000000>;
+ reset-gpios = <&exp2 17 GPIO_ACTIVE_LOW>;
+ reset-post-delay-us = <120000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ cpsw9g_phy0: ethernet-phy@16 {
+ reg = <16>;
+ };
+ cpsw9g_phy1: ethernet-phy@17 {
+ reg = <17>;
+ };
+ cpsw9g_phy2: ethernet-phy@18 {
+ reg = <18>;
+ };
+ cpsw9g_phy3: ethernet-phy@19 {
+ reg = <19>;
+ };
+};
+
+&exp2 {
+ /* Power-up ENET1 EXPANDER PHY. */
+ qsgmii-line-hog {
+ gpio-hog;
+ gpios = <16 GPIO_ACTIVE_HIGH>;
+ output-low;
+ };
+
+ /* Toggle MUX2 for MDIO lines */
+ mux-sel-hog {
+ gpio-hog;
+ gpios = <13 GPIO_ACTIVE_HIGH>, <14 GPIO_ACTIVE_HIGH>, <15 GPIO_ACTIVE_HIGH>;
+ output-high;
+ };
+};
+
+&main_pmx0 {
+ mdio0_default_pins: mdio0-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x05c, PIN_INPUT, 4) /* (AC36) MCASP2_AXR0.MDIO1_MDIO */
+ J784S4_IOPAD(0x058, PIN_INPUT, 4) /* (AE37) MCASP2_AFSX.MDIO1_MDC */
+ >;
+ };
+};
+
+&serdes_ln_ctrl {
+ 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_QSGMII_LANE5>, <J784S4_SERDES2_LANE1_QSGMII_LANE6>,
+ <J784S4_SERDES2_LANE2_QSGMII_LANE7>, <J784S4_SERDES2_LANE3_QSGMII_LANE8>;
+};
+
+&serdes_wiz2 {
+ status = "okay";
+};
+
+&serdes2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+ serdes2_qsgmii_link: phy@0 {
+ reg = <2>;
+ cdns,num-lanes = <1>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_QSGMII>;
+ resets = <&serdes_wiz2 3>;
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-evm-usxgmii-exp1-exp2.dtso b/arch/arm64/boot/dts/ti/k3-j784s4-evm-usxgmii-exp1-exp2.dtso
new file mode 100644
index 000000000000..d5f8c8531923
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm-usxgmii-exp1-exp2.dtso
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+/**
+ * DT Overlay for CPSW9G in dual port fixed-link USXGMII mode using ENET-1
+ * and ENET-2 Expansion slots of J784S4 EVM.
+ *
+ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/phy/phy-cadence.h>
+#include <dt-bindings/phy/phy.h>
+
+#include "k3-serdes.h"
+
+&{/} {
+ aliases {
+ ethernet1 = "/bus@100000/ethernet@c000000/ethernet-ports/port@1";
+ ethernet2 = "/bus@100000/ethernet@c000000/ethernet-ports/port@2";
+ ethernet3 = "/bus@100000/ethernet@c200000/ethernet-ports/port@1";
+ };
+};
+
+&main_cpsw0 {
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&main_cpsw0_port1 {
+ phy-mode = "usxgmii";
+ mac-address = [00 00 00 00 00 00];
+ phys = <&cpsw0_phy_gmii_sel 1>, <&serdes2_usxgmii_link>;
+ phy-names = "mac", "serdes";
+ status = "okay";
+ fixed-link {
+ speed = <5000>;
+ full-duplex;
+ };
+};
+
+&main_cpsw0_port2 {
+ phy-mode = "usxgmii";
+ mac-address = [00 00 00 00 00 00];
+ phys = <&cpsw0_phy_gmii_sel 2>, <&serdes2_usxgmii_link>;
+ phy-names = "mac", "serdes";
+ status = "okay";
+ fixed-link {
+ speed = <5000>;
+ full-duplex;
+ };
+};
+
+&serdes_wiz2 {
+ assigned-clock-parents = <&k3_clks 406 9>; /* Use 156.25 MHz clock for USXGMII */
+ status = "okay";
+};
+
+&serdes2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ serdes2_usxgmii_link: phy@2 {
+ reg = <2>;
+ cdns,num-lanes = <2>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_USXGMII>;
+ resets = <&serdes_wiz2 3>, <&serdes_wiz2 4>;
+ };
+};
+
+&serdes_ln_ctrl {
+ 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>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
index d511b25d62e3..9338d987180d 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
@@ -27,14 +27,16 @@
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 = <0x00 0x80000000 0x00 0x80000000>,
- <0x08 0x80000000 0x07 0x80000000>;
+ reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+ <0x00000008 0x80000000 0x00000007 0x80000000>;
};
reserved_memory: reserved-memory {
@@ -272,6 +274,59 @@
};
};
};
+
+ 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 {
@@ -280,6 +335,30 @@
&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 = <
@@ -336,6 +415,49 @@
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 {
@@ -415,6 +537,32 @@
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 {
@@ -579,6 +727,27 @@
};
};
};
+
+ 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 {
@@ -748,6 +917,14 @@
"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 {
@@ -763,6 +940,22 @@
"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";
+ };
};
};
@@ -832,6 +1025,31 @@
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>;
@@ -1041,6 +1259,40 @@
<&k3_clks 218 22>;
};
+&serdes0 {
+ status = "okay";
+
+ 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";
};
@@ -1105,3 +1357,130 @@
};
};
};
+
+&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>;
+};
+
+&serdes0 {
+ status = "okay";
+
+ serdes0_pcie1_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <4>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_PCIE>;
+ resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>,
+ <&serdes_wiz0 3>, <&serdes_wiz0 4>;
+ };
+};
+
+&serdes_wiz0 {
+ status = "okay";
+};
+
+&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 = <2>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_PCIE>;
+ resets = <&serdes_wiz1 1>, <&serdes_wiz1 2>;
+ };
+};
+
+&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-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
index 6a4554c6c9c1..f170f80f00c1 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
@@ -48,6 +48,39 @@
#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>;
@@ -75,6 +108,88 @@
<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 {
@@ -568,6 +683,38 @@
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>;
@@ -907,6 +1054,122 @@
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";
+ };
+
+ pcie2_rc: pcie@2920000 {
+ compatible = "ti,j784s4-pcie-host";
+ reg = <0x00 0x02920000 0x00 0x1000>,
+ <0x00 0x02927000 0x00 0x400>,
+ <0x00 0x0e000000 0x00 0x00800000>,
+ <0x44 0x00000000 0x00 0x00001000>;
+ 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>;
+ clocks = <&k3_clks 334 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 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>;
+ status = "disabled";
+ };
+
+ pcie3_rc: pcie@2930000 {
+ compatible = "ti,j784s4-pcie-host";
+ reg = <0x00 0x02930000 0x00 0x1000>,
+ <0x00 0x02937000 0x00 0x400>,
+ <0x00 0x0e800000 0x00 0x00800000>,
+ <0x44 0x10000000 0x00 0x00001000>;
+ 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>;
+ clocks = <&k3_clks 335 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 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>;
+ status = "disabled";
+ };
+
serdes_wiz0: wiz@5060000 {
compatible = "ti,j784s4-wiz-10g";
#address-cells = <1>;
@@ -1427,6 +1690,180 @@
};
};
+ 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>,
@@ -2255,4 +2692,94 @@
*/
};
};
+
+ 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 0xc500>, <&main_udmap 0x4500>;
+ 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 0xc501>, <&main_udmap 0x4501>;
+ 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-mcu-wakeup.dtsi
index 2e18d91ae92f..f3a6ed1c979d 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi
@@ -145,12 +145,16 @@
status = "reserved";
};
- mcu_conf: syscon@40f00000 {
- compatible = "ti,j721e-system-controller", "syscon", "simple-mfd";
- reg = <0x00 0x40f00000 0x00 0x20000>;
+ mcu_conf: bus@40f00000 {
+ compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0x00 0x00 0x40f00000 0x20000>;
+ ranges = <0x0 0x0 0x40f00000 0x20000>;
+
+ cpsw_mac_syscon: ethernet-mac-syscon@200 {
+ compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
+ reg = <0x200 0x8>;
+ };
phy_gmii_sel: phy@4040 {
compatible = "ti,am654-phy-gmii-sel";
@@ -553,7 +557,7 @@
reg = <1>;
ti,mac-only;
label = "port1";
- ti,syscon-efuse = <&mcu_conf 0x200>;
+ ti,syscon-efuse = <&cpsw_mac_syscon 0x0>;
phys = <&phy_gmii_sel 1>;
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi
index da7368ed6b52..73cc3c1fec08 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi
@@ -238,7 +238,10 @@
<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 0x01000000>, /* PCIe Core*/
+ <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 */
@@ -248,7 +251,12 @@
<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 */
diff --git a/arch/arm64/boot/dts/ti/k3-pinctrl.h b/arch/arm64/boot/dts/ti/k3-pinctrl.h
index 4cd2df467d0b..22b8d73cfd32 100644
--- a/arch/arm64/boot/dts/ti/k3-pinctrl.h
+++ b/arch/arm64/boot/dts/ti/k3-pinctrl.h
@@ -38,6 +38,9 @@
#define PIN_DEBOUNCE_CONF5 (5 << DEBOUNCE_SHIFT)
#define PIN_DEBOUNCE_CONF6 (6 << DEBOUNCE_SHIFT)
+/* Default mux configuration for gpio-ranges to use with pinctrl */
+#define PIN_GPIO_RANGE_IOPAD (PIN_INPUT | 7)
+
#define AM62AX_IOPAD(pa, val, muxmode) (((pa) & 0x1fff)) ((val) | (muxmode))
#define AM62AX_MCU_IOPAD(pa, val, muxmode) (((pa) & 0x1fff)) ((val) | (muxmode))
diff --git a/arch/arm64/boot/dts/ti/k3-serdes.h b/arch/arm64/boot/dts/ti/k3-serdes.h
index a011ad893b44..ef3606068140 100644
--- a/arch/arm64/boot/dts/ti/k3-serdes.h
+++ b/arch/arm64/boot/dts/ti/k3-serdes.h
@@ -201,4 +201,12 @@
#define J784S4_SERDES4_LANE3_USB 0x2
#define J784S4_SERDES4_LANE3_IP4_UNUSED 0x3
+/* J722S */
+
+#define J722S_SERDES0_LANE0_USB 0x0
+#define J722S_SERDES0_LANE0_QSGMII_LANE2 0x1
+
+#define J722S_SERDES1_LANE0_PCIE0_LANE0 0x0
+#define J722S_SERDES1_LANE0_QSGMII_LANE1 0x1
+
#endif /* DTS_ARM64_TI_K3_SERDES_H */
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi
index dd4569e7bd95..60d1b1acf9a0 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi
@@ -70,6 +70,22 @@
clocks = <&zynqmp_clk ACPU>;
};
+&cpu0_debug {
+ clocks = <&zynqmp_clk DBF_FPD>;
+};
+
+&cpu1_debug {
+ clocks = <&zynqmp_clk DBF_FPD>;
+};
+
+&cpu2_debug {
+ clocks = <&zynqmp_clk DBF_FPD>;
+};
+
+&cpu3_debug {
+ clocks = <&zynqmp_clk DBF_FPD>;
+};
+
&fpd_dma_chan1 {
clocks = <&zynqmp_clk GDMA_REF>, <&zynqmp_clk LPD_LSBUS>;
};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso
index d7535a77b45e..95d16904d765 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso
@@ -22,6 +22,17 @@
/plugin/;
&{/} {
+ compatible = "xlnx,zynqmp-sk-kv260-revA",
+ "xlnx,zynqmp-sk-kv260-revY",
+ "xlnx,zynqmp-sk-kv260-revZ",
+ "xlnx,zynqmp-sk-kv260", "xlnx,zynqmp";
+ model = "ZynqMP KV260 revA";
+
+ ina260-u14 {
+ compatible = "iio-hwmon";
+ io-channels = <&u14 0>, <&u14 1>, <&u14 2>;
+ };
+
si5332_0: si5332-0 { /* u17 */
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -68,7 +79,12 @@
scl-gpios = <&gpio 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
sda-gpios = <&gpio 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
- /* u14 - 0x40 - ina260 */
+ u14: ina260@40 { /* u14 */
+ compatible = "ti,ina260";
+ #io-channel-cells = <1>;
+ label = "ina260-u14";
+ reg = <0x40>;
+ };
/* u27 - 0xe0 - STDP4320 DP/HDMI splitter */
};
@@ -321,6 +337,7 @@
slew-rate = <SLEW_RATE_SLOW>;
power-source = <IO_STANDARD_LVCMOS18>;
bias-disable;
+ output-enable;
};
conf-cd {
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso
index a7b8fffad499..a74d0ac7e07a 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso
@@ -17,6 +17,17 @@
/plugin/;
&{/} {
+ compatible = "xlnx,zynqmp-sk-kv260-rev2",
+ "xlnx,zynqmp-sk-kv260-rev1",
+ "xlnx,zynqmp-sk-kv260-revB",
+ "xlnx,zynqmp-sk-kv260", "xlnx,zynqmp";
+ model = "ZynqMP KV260 revB";
+
+ ina260-u14 {
+ compatible = "iio-hwmon";
+ io-channels = <&u14 0>, <&u14 1>, <&u14 2>;
+ };
+
si5332_0: si5332-0 { /* u17 */
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -52,6 +63,18 @@
#clock-cells = <0>;
clock-frequency = <27000000>;
};
+
+ dpcon {
+ compatible = "dp-connector";
+ label = "P11";
+ type = "full-size";
+
+ port {
+ dpcon_in: endpoint {
+ remote-endpoint = <&dpsub_dp_out>;
+ };
+ };
+ };
};
&i2c1 { /* I2C_SCK C23/C24 - MIO from SOM */
@@ -63,8 +86,13 @@
scl-gpios = <&gpio 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
sda-gpios = <&gpio 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
- /* u14 - 0x40 - ina260 */
- /* u43 - 0x2d - usb5744 */
+ u14: ina260@40 { /* u14 */
+ compatible = "ti,ina260";
+ #io-channel-cells = <1>;
+ label = "ina260-u14";
+ reg = <0x40>;
+ };
+ /* u43 - 0x2d - USB hub */
/* u27 - 0xe0 - STDP4320 DP/HDMI splitter */
};
@@ -81,6 +109,14 @@
phy-names = "dp-phy0", "dp-phy1";
phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>;
assigned-clock-rates = <27000000>, <25000000>, <300000000>;
+
+ ports {
+ port@5 {
+ dpsub_dp_out: endpoint {
+ remote-endpoint = <&dpcon_in>;
+ };
+ };
+ };
};
&zynqmp_dpdma {
@@ -305,6 +341,7 @@
slew-rate = <SLEW_RATE_SLOW>;
power-source = <IO_STANDARD_LVCMOS18>;
bias-disable;
+ output-enable;
};
conf-cd {
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 51622896b1b1..86e6c4990560 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * dts file for Xilinx ZynqMP SM-K26 rev1/B/A
+ * dts file for Xilinx ZynqMP SM-K26 rev2/1/B/A
*
* (C) Copyright 2020 - 2021, Xilinx, Inc.
+ * (C) Copyright 2023 - 2024, Advanced Micro Devices, Inc.
*
* Michal Simek <[email protected]>
*/
@@ -17,8 +18,9 @@
#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
/ {
- model = "ZynqMP SM-K26 Rev1/B/A";
- compatible = "xlnx,zynqmp-sm-k26-rev1", "xlnx,zynqmp-sm-k26-revB",
+ model = "ZynqMP SM-K26 Rev2/1/B/A";
+ compatible = "xlnx,zynqmp-sm-k26-rev2",
+ "xlnx,zynqmp-sm-k26-rev1", "xlnx,zynqmp-sm-k26-revB",
"xlnx,zynqmp-sm-k26-revA", "xlnx,zynqmp-sm-k26",
"xlnx,zynqmp";
@@ -101,12 +103,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";
+ pwms = <&ttc0 2 40000 0>;
+ };
};
&modepin_gpio {
label = "modepin";
};
+&ttc0 {
+ status = "okay";
+ #pwm-cells = <3>;
+};
+
&uart1 { /* MIO36/MIO37 */
status = "okay";
};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-smk-k26-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-smk-k26-revA.dts
index 85b0d1677240..b804abe89d1d 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-smk-k26-revA.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-smk-k26-revA.dts
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * dts file for Xilinx ZynqMP SMK-K26 rev1/B/A
+ * dts file for Xilinx ZynqMP SMK-K26 rev2/1/B/A
*
* (C) Copyright 2020 - 2021, Xilinx, Inc.
+ * (C) Copyright 2023 - 2024, Advanced Micro Devices, Inc.
*
* Michal Simek <[email protected]>
*/
@@ -10,8 +11,9 @@
#include "zynqmp-sm-k26-revA.dts"
/ {
- model = "ZynqMP SMK-K26 Rev1/B/A";
- compatible = "xlnx,zynqmp-smk-k26-rev1", "xlnx,zynqmp-smk-k26-revB",
+ model = "ZynqMP SMK-K26 Rev2/1/B/A";
+ compatible = "xlnx,zynqmp-smk-k26-rev2",
+ "xlnx,zynqmp-smk-k26-rev1", "xlnx,zynqmp-smk-k26-revB",
"xlnx,zynqmp-smk-k26-revA", "xlnx,zynqmp-smk-k26",
"xlnx,zynqmp";
};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
index c8f71a1aec89..495ca94b45db 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
@@ -14,6 +14,14 @@
compatible = "xlnx,zynqmp-zcu102-rev1.0", "xlnx,zynqmp-zcu102", "xlnx,zynqmp";
};
+&rproc_split {
+ status = "okay";
+};
+
+&rproc_lockstep {
+ status = "disabled";
+};
+
&eeprom {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index d99830c9b85f..b1b31dcf6291 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -207,13 +207,71 @@
mbox-names = "tx", "rx";
};
- nvmem-firmware {
+ soc-nvmem {
compatible = "xlnx,zynqmp-nvmem-fw";
- #address-cells = <1>;
- #size-cells = <1>;
-
- soc_revision: soc-revision@0 {
- reg = <0x0 0x4>;
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ soc_revision: soc-revision@0 {
+ reg = <0x0 0x4>;
+ };
+ /* efuse access */
+ efuse_dna: efuse-dna@c {
+ reg = <0xc 0xc>;
+ };
+ efuse_usr0: efuse-usr0@20 {
+ reg = <0x20 0x4>;
+ };
+ efuse_usr1: efuse-usr1@24 {
+ reg = <0x24 0x4>;
+ };
+ efuse_usr2: efuse-usr2@28 {
+ reg = <0x28 0x4>;
+ };
+ efuse_usr3: efuse-usr3@2c {
+ reg = <0x2c 0x4>;
+ };
+ efuse_usr4: efuse-usr4@30 {
+ reg = <0x30 0x4>;
+ };
+ efuse_usr5: efuse-usr5@34 {
+ reg = <0x34 0x4>;
+ };
+ efuse_usr6: efuse-usr6@38 {
+ reg = <0x38 0x4>;
+ };
+ efuse_usr7: efuse-usr7@3c {
+ reg = <0x3c 0x4>;
+ };
+ efuse_miscusr: efuse-miscusr@40 {
+ reg = <0x40 0x4>;
+ };
+ efuse_chash: efuse-chash@50 {
+ reg = <0x50 0x4>;
+ };
+ efuse_pufmisc: efuse-pufmisc@54 {
+ reg = <0x54 0x4>;
+ };
+ efuse_sec: efuse-sec@58 {
+ reg = <0x58 0x4>;
+ };
+ efuse_spkid: efuse-spkid@5c {
+ reg = <0x5c 0x4>;
+ };
+ efuse_aeskey: efuse-aeskey@60 {
+ reg = <0x60 0x20>;
+ };
+ efuse_ppk0hash: efuse-ppk0hash@a0 {
+ reg = <0xa0 0x30>;
+ };
+ efuse_ppk1hash: efuse-ppk1hash@d0 {
+ reg = <0xd0 0x30>;
+ };
+ efuse_pufuser: efuse-pufuser@100 {
+ reg = <0x100 0x7F>;
+ };
};
};
@@ -252,7 +310,7 @@
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
};
- fpga_full: fpga-full {
+ fpga_full: fpga-region {
compatible = "fpga-region";
fpga-mgr = <&zynqmp_pcap>;
#address-cells = <2>;
@@ -260,19 +318,76 @@
ranges;
};
- remoteproc {
+ rproc_lockstep: remoteproc@ffe00000 {
compatible = "xlnx,zynqmp-r5fss";
xlnx,cluster-mode = <1>;
+ xlnx,tcm-mode = <1>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
- r5f-0 {
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x10000>,
+ <0x0 0x20000 0x0 0xffe20000 0x0 0x10000>,
+ <0x0 0x10000 0x0 0xffe10000 0x0 0x10000>,
+ <0x0 0x30000 0x0 0xffe30000 0x0 0x10000>;
+
+ r5f@0 {
compatible = "xlnx,zynqmp-r5f";
- power-domains = <&zynqmp_firmware PD_RPU_0>;
+ reg = <0x0 0x0 0x0 0x10000>,
+ <0x0 0x20000 0x0 0x10000>,
+ <0x0 0x10000 0x0 0x10000>,
+ <0x0 0x30000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0", "atcm1", "btcm1";
+ power-domains = <&zynqmp_firmware PD_RPU_0>,
+ <&zynqmp_firmware PD_R5_0_ATCM>,
+ <&zynqmp_firmware PD_R5_0_BTCM>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
memory-region = <&rproc_0_fw_image>;
};
- r5f-1 {
+ r5f@1 {
compatible = "xlnx,zynqmp-r5f";
- power-domains = <&zynqmp_firmware PD_RPU_1>;
+ reg = <0x1 0x0 0x0 0x10000>, <0x1 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_1>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
+ memory-region = <&rproc_1_fw_image>;
+ };
+ };
+
+ rproc_split: remoteproc-split@ffe00000 {
+ status = "disabled";
+ compatible = "xlnx,zynqmp-r5fss";
+ xlnx,cluster-mode = <0>;
+ xlnx,tcm-mode = <0>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x10000>,
+ <0x0 0x20000 0x0 0xffe20000 0x0 0x10000>,
+ <0x1 0x0 0x0 0xffe90000 0x0 0x10000>,
+ <0x1 0x20000 0x0 0xffeb0000 0x0 0x10000>;
+
+ r5f@0 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x0 0x0 0x0 0x10000>, <0x0 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_0>,
+ <&zynqmp_firmware PD_R5_0_ATCM>,
+ <&zynqmp_firmware PD_R5_0_BTCM>;
+ memory-region = <&rproc_0_fw_image>;
+ };
+
+ r5f@1 {
+ compatible = "xlnx,zynqmp-r5f";
+ reg = <0x1 0x0 0x0 0x10000>, <0x1 0x20000 0x0 0x10000>;
+ reg-names = "atcm0", "btcm0";
+ power-domains = <&zynqmp_firmware PD_RPU_1>,
+ <&zynqmp_firmware PD_R5_1_ATCM>,
+ <&zynqmp_firmware PD_R5_1_BTCM>;
memory-region = <&rproc_1_fw_image>;
};
};
@@ -330,6 +445,34 @@
};
};
+ cpu0_debug: debug@fec10000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ reg = <0x0 0xfec10000 0x0 0x1000>;
+ clock-names = "apb_pclk";
+ cpu = <&cpu0>;
+ };
+
+ cpu1_debug: debug@fed10000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ reg = <0x0 0xfed10000 0x0 0x1000>;
+ clock-names = "apb_pclk";
+ cpu = <&cpu1>;
+ };
+
+ cpu2_debug: debug@fee10000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ reg = <0x0 0xfee10000 0x0 0x1000>;
+ clock-names = "apb_pclk";
+ cpu = <&cpu2>;
+ };
+
+ cpu3_debug: debug@fef10000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ reg = <0x0 0xfef10000 0x0 0x1000>;
+ clock-names = "apb_pclk";
+ cpu = <&cpu3>;
+ };
+
/* GDMA */
fpd_dma_chan1: dma-controller@fd500000 {
status = "disabled";
@@ -684,6 +827,13 @@
power-domains = <&zynqmp_firmware PD_I2C_1>;
};
+ ocm: memory-controller@ff960000 {
+ compatible = "xlnx,zynqmp-ocmc-1.0";
+ reg = <0x0 0xff960000 0x0 0x1000>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
pcie: pcie@fd0e0000 {
compatible = "xlnx,nwl-pcie-2.11";
status = "disabled";
@@ -941,10 +1091,11 @@
status = "disabled";
reg = <0x0 0xfe200000 0x0 0x40000>;
interrupt-parent = <&gic>;
- interrupt-names = "host", "peripheral", "otg";
+ interrupt-names = "host", "peripheral", "otg", "wakeup";
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "ref";
/* iommus = <&smmu 0x860>; */
snps,quirk-frame-length-adjustment = <0x20>;
@@ -972,10 +1123,11 @@
status = "disabled";
reg = <0x0 0xfe300000 0x0 0x40000>;
interrupt-parent = <&gic>;
- interrupt-names = "host", "peripheral", "otg";
+ interrupt-names = "host", "peripheral", "otg", "wakeup";
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "ref";
/* iommus = <&smmu 0x861>; */
snps,quirk-frame-length-adjustment = <0x20>;
@@ -1024,8 +1176,6 @@
compatible = "xlnx,zynqmp-ams-pl";
status = "disabled";
reg = <0x400 0x400>;
- #address-cells = <1>;
- #size-cells = <0>;
};
};
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 57a9abe78ee4..ef2235838c44 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -233,6 +233,8 @@ CONFIG_PCIE_HISI_STB=y
CONFIG_PCIE_ARMADA_8K=y
CONFIG_PCIE_TEGRA194_HOST=m
CONFIG_PCIE_QCOM=y
+CONFIG_PCIE_RCAR_GEN4_HOST=m
+CONFIG_PCIE_RCAR_GEN4_EP=m
CONFIG_PCIE_ROCKCHIP_DW_HOST=y
CONFIG_PCIE_VISCONTI_HOST=y
CONFIG_PCIE_LAYERSCAPE_GEN4=y
@@ -256,6 +258,7 @@ CONFIG_GOOGLE_CBMEM=m
CONFIG_GOOGLE_COREBOOT_TABLE=m
CONFIG_EFI_CAPSULE_LOADER=y
CONFIG_IMX_SCU=y
+CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE=y
CONFIG_QCOM_QSEECOM=y
CONFIG_QCOM_QSEECOM_UEFISECAPP=y
CONFIG_GNSS=m
@@ -279,6 +282,8 @@ CONFIG_MTD_NAND_FSL_IFC=y
CONFIG_MTD_NAND_QCOM=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_UBI=m
+CONFIG_MTD_HYPERBUS=m
+CONFIG_HBMC_AM654=m
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=m
CONFIG_VIRTIO_BLK=y
@@ -375,6 +380,7 @@ CONFIG_AQUANTIA_PHY=y
CONFIG_BCM54140_PHY=m
CONFIG_MARVELL_PHY=m
CONFIG_MARVELL_10G_PHY=y
+CONFIG_MARVELL_88Q2XXX_PHY=y
CONFIG_MICREL_PHY=y
CONFIG_MICROSEMI_PHY=y
CONFIG_AT803X_PHY=y
@@ -414,6 +420,9 @@ CONFIG_ATH11K_AHB=m
CONFIG_ATH11K_PCI=m
CONFIG_ATH12K=m
CONFIG_BRCMFMAC=m
+CONFIG_IWLWIFI=m
+CONFIG_IWLDVM=m
+CONFIG_IWLMVM=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_SDIO=m
CONFIG_MWIFIEX_PCIE=m
@@ -745,6 +754,7 @@ CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_SL28CPLD=y
CONFIG_RZ_MTU3=y
CONFIG_MFD_TI_AM335X_TSCADC=m
+CONFIG_MFD_TI_LP873X=m
CONFIG_MFD_TPS65219=y
CONFIG_MFD_TPS6594_I2C=m
CONFIG_MFD_ROHM_BD718XX=y
@@ -760,6 +770,7 @@ CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_HI6421V530=y
CONFIG_REGULATOR_HI655X=y
+CONFIG_REGULATOR_LP873X=m
CONFIG_REGULATOR_MAX77620=y
CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_MAX20411=m
@@ -1036,6 +1047,7 @@ CONFIG_SND_AUDIO_GRAPH_CARD2=m
CONFIG_HID_MULTITOUCH=m
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_XHCI_HCD=y
@@ -1062,6 +1074,7 @@ CONFIG_USB_MTU3=y
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_MUSB_SUNXI=y
CONFIG_USB_DWC3=y
+CONFIG_OMAP_USB2=m
CONFIG_USB_DWC2=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
@@ -1215,6 +1228,7 @@ CONFIG_QCOM_BAM_DMA=y
CONFIG_QCOM_GPI_DMA=m
CONFIG_QCOM_HIDMA_MGMT=y
CONFIG_QCOM_HIDMA=y
+CONFIG_DW_EDMA=m
CONFIG_RCAR_DMAC=y
CONFIG_RENESAS_USB_DMAC=m
CONFIG_RZ_DMAC=y
@@ -1333,6 +1347,7 @@ CONFIG_SM_GCC_8650=y
CONFIG_SM_GPUCC_6115=m
CONFIG_SM_GPUCC_8150=y
CONFIG_SM_GPUCC_8250=y
+CONFIG_SM_GPUCC_8350=m
CONFIG_SM_GPUCC_8450=m
CONFIG_SM_GPUCC_8550=m
CONFIG_SM_GPUCC_8650=m
@@ -1555,6 +1570,7 @@ CONFIG_ARM_SPE_PMU=m
CONFIG_ARM_DMC620_PMU=m
CONFIG_HISI_PMU=y
CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU=m
+CONFIG_NVIDIA_CORESIGHT_PMU_ARCH_SYSTEM_PMU=m
CONFIG_MESON_DDR_PMU=m
CONFIG_NVMEM_LAYOUT_SL28_VPD=m
CONFIG_NVMEM_IMX_OCOTP=y
@@ -1564,6 +1580,7 @@ CONFIG_NVMEM_LAYERSCAPE_SFP=m
CONFIG_NVMEM_MESON_EFUSE=m
CONFIG_NVMEM_MTK_EFUSE=y
CONFIG_NVMEM_QCOM_QFPROM=y
+CONFIG_NVMEM_QCOM_SEC_QFPROM=m
CONFIG_NVMEM_RMEM=m
CONFIG_NVMEM_ROCKCHIP_EFUSE=y
CONFIG_NVMEM_ROCKCHIP_OTP=y
@@ -1593,7 +1610,7 @@ CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=y
CONFIG_INTERCONNECT_QCOM=y
CONFIG_INTERCONNECT_QCOM_MSM8916=m
-CONFIG_INTERCONNECT_QCOM_MSM8996=m
+CONFIG_INTERCONNECT_QCOM_MSM8996=y
CONFIG_INTERCONNECT_QCOM_OSM_L3=m
CONFIG_INTERCONNECT_QCOM_QCM2290=y
CONFIG_INTERCONNECT_QCOM_QCS404=m
@@ -1606,9 +1623,9 @@ CONFIG_INTERCONNECT_QCOM_SC8280XP=y
CONFIG_INTERCONNECT_QCOM_SDM845=y
CONFIG_INTERCONNECT_QCOM_SDX75=y
CONFIG_INTERCONNECT_QCOM_SM6115=y
-CONFIG_INTERCONNECT_QCOM_SM8150=m
+CONFIG_INTERCONNECT_QCOM_SM8150=y
CONFIG_INTERCONNECT_QCOM_SM8250=y
-CONFIG_INTERCONNECT_QCOM_SM8350=m
+CONFIG_INTERCONNECT_QCOM_SM8350=y
CONFIG_INTERCONNECT_QCOM_SM8450=y
CONFIG_INTERCONNECT_QCOM_SM8550=y
CONFIG_INTERCONNECT_QCOM_SM8650=y
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 4b6d2d52053e..7d7d97ad3cd5 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -1,4 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += syscall_table_32.h
+syscall-y += syscall_table_64.h
+
+# arm32 syscall table used by lib/compat_audit.c:
+syscall-y += unistd_32.h
+# same constants with prefixes, used by vdso, seccomp and sigreturn:
+syscall-y += unistd_compat_32.h
+
generic-y += early_ioremap.h
generic-y += mcs_spinlock.h
generic-y += qrwlock.h
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index 6792a1f83f2a..a407f9cd549e 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -119,6 +119,18 @@ static inline u32 get_acpi_id_for_cpu(unsigned int cpu)
return acpi_cpu_get_madt_gicc(cpu)->uid;
}
+static inline int get_cpu_for_acpi_id(u32 uid)
+{
+ int cpu;
+
+ for (cpu = 0; cpu < nr_cpu_ids; cpu++)
+ if (acpi_cpu_get_madt_gicc(cpu) &&
+ uid == get_acpi_id_for_cpu(cpu))
+ return cpu;
+
+ return -EINVAL;
+}
+
static inline void arch_fix_phys_package_id(int num, u32 slot) { }
void __init acpi_init_cpus(void);
int apei_claim_sea(struct pt_regs *regs);
diff --git a/arch/arm64/include/asm/arch_gicv3.h b/arch/arm64/include/asm/arch_gicv3.h
index 5f172611654b..9e96f024b2f1 100644
--- a/arch/arm64/include/asm/arch_gicv3.h
+++ b/arch/arm64/include/asm/arch_gicv3.h
@@ -175,21 +175,6 @@ static inline bool gic_prio_masking_enabled(void)
static inline void gic_pmr_mask_irqs(void)
{
- BUILD_BUG_ON(GICD_INT_DEF_PRI < (__GIC_PRIO_IRQOFF |
- GIC_PRIO_PSR_I_SET));
- BUILD_BUG_ON(GICD_INT_DEF_PRI >= GIC_PRIO_IRQON);
- /*
- * Need to make sure IRQON allows IRQs when SCR_EL3.FIQ is cleared
- * and non-secure PMR accesses are not subject to the shifts that
- * are applied to IRQ priorities
- */
- BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) >= GIC_PRIO_IRQON);
- /*
- * Same situation as above, but now we make sure that we can mask
- * regular interrupts.
- */
- BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) < (__GIC_PRIO_IRQOFF_NS |
- GIC_PRIO_PSR_I_SET));
gic_write_pmr(GIC_PRIO_IRQOFF);
}
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index 934c658ee947..f5794d50f51d 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -15,7 +15,7 @@
#include <linux/bug.h>
#include <linux/init.h>
#include <linux/jump_label.h>
-#include <linux/smp.h>
+#include <linux/percpu.h>
#include <linux/types.h>
#include <clocksource/arm_arch_timer.h>
diff --git a/arch/arm64/include/asm/arm_pmuv3.h b/arch/arm64/include/asm/arm_pmuv3.h
index c27404fa4418..a4697a0b6835 100644
--- a/arch/arm64/include/asm/arm_pmuv3.h
+++ b/arch/arm64/include/asm/arm_pmuv3.h
@@ -6,7 +6,7 @@
#ifndef __ASM_PMUV3_H
#define __ASM_PMUV3_H
-#include <linux/kvm_host.h>
+#include <asm/kvm_host.h>
#include <asm/cpufeature.h>
#include <asm/sysreg.h>
diff --git a/arch/arm64/include/asm/asm-extable.h b/arch/arm64/include/asm/asm-extable.h
index 980d1dd8e1a3..b8a5861dc7b7 100644
--- a/arch/arm64/include/asm/asm-extable.h
+++ b/arch/arm64/include/asm/asm-extable.h
@@ -112,6 +112,9 @@
#define _ASM_EXTABLE_KACCESS_ERR(insn, fixup, err) \
_ASM_EXTABLE_KACCESS_ERR_ZERO(insn, fixup, err, wzr)
+#define _ASM_EXTABLE_KACCESS(insn, fixup) \
+ _ASM_EXTABLE_KACCESS_ERR_ZERO(insn, fixup, wzr, wzr)
+
#define _ASM_EXTABLE_LOAD_UNALIGNED_ZEROPAD(insn, fixup, data, addr) \
__DEFINE_ASM_GPR_NUMS \
__ASM_EXTABLE_RAW(#insn, #fixup, \
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 7529c0263933..a6e5b07b64fd 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -59,7 +59,7 @@ cpucap_is_possible(const unsigned int cap)
case ARM64_WORKAROUND_REPEAT_TLBI:
return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
case ARM64_WORKAROUND_SPECULATIVE_SSBS:
- return IS_ENABLED(CONFIG_ARM64_WORKAROUND_SPECULATIVE_SSBS);
+ return IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386);
}
return true;
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 8b904a757bd3..558434267271 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -588,14 +588,14 @@ static inline bool id_aa64pfr0_32bit_el1(u64 pfr0)
{
u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL1_EL1_SHIFT);
- return val == ID_AA64PFR0_EL1_ELx_32BIT_64BIT;
+ return val == ID_AA64PFR0_EL1_EL1_AARCH32;
}
static inline bool id_aa64pfr0_32bit_el0(u64 pfr0)
{
u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL1_EL0_SHIFT);
- return val == ID_AA64PFR0_EL1_ELx_32BIT_64BIT;
+ return val == ID_AA64PFR0_EL1_EL0_AARCH32;
}
static inline bool id_aa64pfr0_sve(u64 pfr0)
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 7b32b99023a2..1cb0704c6163 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -86,9 +86,12 @@
#define ARM_CPU_PART_CORTEX_X2 0xD48
#define ARM_CPU_PART_NEOVERSE_N2 0xD49
#define ARM_CPU_PART_CORTEX_A78C 0xD4B
+#define ARM_CPU_PART_CORTEX_X3 0xD4E
#define ARM_CPU_PART_NEOVERSE_V2 0xD4F
+#define ARM_CPU_PART_CORTEX_A720 0xD81
#define ARM_CPU_PART_CORTEX_X4 0xD82
#define ARM_CPU_PART_NEOVERSE_V3 0xD84
+#define ARM_CPU_PART_CORTEX_X925 0xD85
#define APM_CPU_PART_XGENE 0x000
#define APM_CPU_VAR_POTENZA 0x00
@@ -162,9 +165,12 @@
#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
#define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
+#define MIDR_CORTEX_X3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X3)
#define MIDR_NEOVERSE_V2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V2)
+#define MIDR_CORTEX_A720 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720)
#define MIDR_CORTEX_X4 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X4)
#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3)
+#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925)
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index 7abf09df7033..3f482500f71f 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -121,6 +121,14 @@
#define ESR_ELx_FSC_SECC (0x18)
#define ESR_ELx_FSC_SECC_TTW(n) (0x1c + (n))
+/* Status codes for individual page table levels */
+#define ESR_ELx_FSC_ACCESS_L(n) (ESR_ELx_FSC_ACCESS + n)
+#define ESR_ELx_FSC_PERM_L(n) (ESR_ELx_FSC_PERM + n)
+
+#define ESR_ELx_FSC_FAULT_nL (0x2C)
+#define ESR_ELx_FSC_FAULT_L(n) (((n) < 0 ? ESR_ELx_FSC_FAULT_nL : \
+ ESR_ELx_FSC_FAULT) + (n))
+
/* ISS field definitions for Data Aborts */
#define ESR_ELx_ISV_SHIFT (24)
#define ESR_ELx_ISV (UL(1) << ESR_ELx_ISV_SHIFT)
@@ -388,20 +396,33 @@ static inline bool esr_is_data_abort(unsigned long esr)
static inline bool esr_fsc_is_translation_fault(unsigned long esr)
{
- /* Translation fault, level -1 */
- if ((esr & ESR_ELx_FSC) == 0b101011)
- return true;
- return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_FAULT;
+ esr = esr & ESR_ELx_FSC;
+
+ return (esr == ESR_ELx_FSC_FAULT_L(3)) ||
+ (esr == ESR_ELx_FSC_FAULT_L(2)) ||
+ (esr == ESR_ELx_FSC_FAULT_L(1)) ||
+ (esr == ESR_ELx_FSC_FAULT_L(0)) ||
+ (esr == ESR_ELx_FSC_FAULT_L(-1));
}
static inline bool esr_fsc_is_permission_fault(unsigned long esr)
{
- return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_PERM;
+ esr = esr & ESR_ELx_FSC;
+
+ return (esr == ESR_ELx_FSC_PERM_L(3)) ||
+ (esr == ESR_ELx_FSC_PERM_L(2)) ||
+ (esr == ESR_ELx_FSC_PERM_L(1)) ||
+ (esr == ESR_ELx_FSC_PERM_L(0));
}
static inline bool esr_fsc_is_access_flag_fault(unsigned long esr)
{
- return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_ACCESS;
+ esr = esr & ESR_ELx_FSC;
+
+ return (esr == ESR_ELx_FSC_ACCESS_L(3)) ||
+ (esr == ESR_ELx_FSC_ACCESS_L(2)) ||
+ (esr == ESR_ELx_FSC_ACCESS_L(1)) ||
+ (esr == ESR_ELx_FSC_ACCESS_L(0));
}
/* Indicate whether ESR.EC==0x1A is for an ERETAx instruction */
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index c768d16b81a4..bd19f4c758b7 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -72,11 +72,11 @@ static inline void __cpu_set_tcr_t0sz(unsigned long t0sz)
{
unsigned long tcr = read_sysreg(tcr_el1);
- if ((tcr & TCR_T0SZ_MASK) >> TCR_T0SZ_OFFSET == t0sz)
+ if ((tcr & TCR_T0SZ_MASK) == t0sz)
return;
tcr &= ~TCR_T0SZ_MASK;
- tcr |= t0sz << TCR_T0SZ_OFFSET;
+ tcr |= t0sz;
write_sysreg(tcr, tcr_el1);
isb();
}
diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h
index 91fbd5c8a391..0f84518632b4 100644
--- a/arch/arm64/include/asm/mte.h
+++ b/arch/arm64/include/asm/mte.h
@@ -182,7 +182,7 @@ void mte_check_tfsr_el1(void);
static inline void mte_check_tfsr_entry(void)
{
- if (!system_supports_mte())
+ if (!kasan_hw_tags_enabled())
return;
mte_check_tfsr_el1();
@@ -190,7 +190,7 @@ static inline void mte_check_tfsr_entry(void)
static inline void mte_check_tfsr_exit(void)
{
- if (!system_supports_mte())
+ if (!kasan_hw_tags_enabled())
return;
/*
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 47ec58031f11..0abe975d68a8 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -21,35 +21,12 @@
#define INIT_PSTATE_EL2 \
(PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL2h)
-/*
- * PMR values used to mask/unmask interrupts.
- *
- * GIC priority masking works as follows: if an IRQ's priority is a higher value
- * than the value held in PMR, that IRQ is masked. Lowering the value of PMR
- * means masking more IRQs (or at least that the same IRQs remain masked).
- *
- * To mask interrupts, we clear the most significant bit of PMR.
- *
- * Some code sections either automatically switch back to PSR.I or explicitly
- * require to not use priority masking. If bit GIC_PRIO_PSR_I_SET is included
- * in the priority mask, it indicates that PSR.I should be set and
- * interrupt disabling temporarily does not rely on IRQ priorities.
- */
-#define GIC_PRIO_IRQON 0xe0
-#define __GIC_PRIO_IRQOFF (GIC_PRIO_IRQON & ~0x80)
-#define __GIC_PRIO_IRQOFF_NS 0xa0
-#define GIC_PRIO_PSR_I_SET (1 << 4)
-
-#define GIC_PRIO_IRQOFF \
- ({ \
- extern struct static_key_false gic_nonsecure_priorities;\
- u8 __prio = __GIC_PRIO_IRQOFF; \
- \
- if (static_branch_unlikely(&gic_nonsecure_priorities)) \
- __prio = __GIC_PRIO_IRQOFF_NS; \
- \
- __prio; \
- })
+#include <linux/irqchip/arm-gic-v3-prio.h>
+
+#define GIC_PRIO_IRQON GICV3_PRIO_UNMASKED
+#define GIC_PRIO_IRQOFF GICV3_PRIO_IRQ
+
+#define GIC_PRIO_PSR_I_SET GICV3_PRIO_PSR_I_SET
/* Additional SPSR bits not exposed in the UABI */
#define PSR_MODE_THREAD_BIT (1 << 0)
diff --git a/arch/arm64/include/asm/runtime-const.h b/arch/arm64/include/asm/runtime-const.h
new file mode 100644
index 000000000000..be5915669d23
--- /dev/null
+++ b/arch/arm64/include/asm/runtime-const.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RUNTIME_CONST_H
+#define _ASM_RUNTIME_CONST_H
+
+#include <asm/cacheflush.h>
+
+/* Sigh. You can still run arm64 in BE mode */
+#include <asm/byteorder.h>
+
+#define runtime_const_ptr(sym) ({ \
+ typeof(sym) __ret; \
+ asm_inline("1:\t" \
+ "movz %0, #0xcdef\n\t" \
+ "movk %0, #0x89ab, lsl #16\n\t" \
+ "movk %0, #0x4567, lsl #32\n\t" \
+ "movk %0, #0x0123, lsl #48\n\t" \
+ ".pushsection runtime_ptr_" #sym ",\"a\"\n\t" \
+ ".long 1b - .\n\t" \
+ ".popsection" \
+ :"=r" (__ret)); \
+ __ret; })
+
+#define runtime_const_shift_right_32(val, sym) ({ \
+ unsigned long __ret; \
+ asm_inline("1:\t" \
+ "lsr %w0,%w1,#12\n\t" \
+ ".pushsection runtime_shift_" #sym ",\"a\"\n\t" \
+ ".long 1b - .\n\t" \
+ ".popsection" \
+ :"=r" (__ret) \
+ :"r" (0u+(val))); \
+ __ret; })
+
+#define runtime_const_init(type, sym) do { \
+ extern s32 __start_runtime_##type##_##sym[]; \
+ extern s32 __stop_runtime_##type##_##sym[]; \
+ runtime_const_fixup(__runtime_fixup_##type, \
+ (unsigned long)(sym), \
+ __start_runtime_##type##_##sym, \
+ __stop_runtime_##type##_##sym); \
+} while (0)
+
+/* 16-bit immediate for wide move (movz and movk) in bits 5..20 */
+static inline void __runtime_fixup_16(__le32 *p, unsigned int val)
+{
+ u32 insn = le32_to_cpu(*p);
+ insn &= 0xffe0001f;
+ insn |= (val & 0xffff) << 5;
+ *p = cpu_to_le32(insn);
+}
+
+static inline void __runtime_fixup_caches(void *where, unsigned int insns)
+{
+ unsigned long va = (unsigned long)where;
+ caches_clean_inval_pou(va, va + 4*insns);
+}
+
+static inline void __runtime_fixup_ptr(void *where, unsigned long val)
+{
+ __le32 *p = lm_alias(where);
+ __runtime_fixup_16(p, val);
+ __runtime_fixup_16(p+1, val >> 16);
+ __runtime_fixup_16(p+2, val >> 32);
+ __runtime_fixup_16(p+3, val >> 48);
+ __runtime_fixup_caches(where, 4);
+}
+
+/* Immediate value is 6 bits starting at bit #16 */
+static inline void __runtime_fixup_shift(void *where, unsigned long val)
+{
+ __le32 *p = lm_alias(where);
+ u32 insn = le32_to_cpu(*p);
+ insn &= 0xffc0ffff;
+ insn |= (val & 63) << 16;
+ *p = cpu_to_le32(insn);
+ __runtime_fixup_caches(where, 1);
+}
+
+static inline void runtime_const_fixup(void (*fn)(void *, unsigned long),
+ unsigned long val, s32 *start, s32 *end)
+{
+ while (start < end) {
+ fn(*start + (void *)start, val);
+ start++;
+ }
+}
+
+#endif
diff --git a/arch/arm64/include/asm/seccomp.h b/arch/arm64/include/asm/seccomp.h
index 30256233788b..b83975555314 100644
--- a/arch/arm64/include/asm/seccomp.h
+++ b/arch/arm64/include/asm/seccomp.h
@@ -8,13 +8,13 @@
#ifndef _ASM_SECCOMP_H
#define _ASM_SECCOMP_H
-#include <asm/unistd.h>
+#include <asm/unistd_compat_32.h>
#ifdef CONFIG_COMPAT
-#define __NR_seccomp_read_32 __NR_compat_read
-#define __NR_seccomp_write_32 __NR_compat_write
-#define __NR_seccomp_exit_32 __NR_compat_exit
-#define __NR_seccomp_sigreturn_32 __NR_compat_rt_sigreturn
+#define __NR_seccomp_read_32 __NR_compat32_read
+#define __NR_seccomp_write_32 __NR_compat32_write
+#define __NR_seccomp_exit_32 __NR_compat32_exit
+#define __NR_seccomp_sigreturn_32 __NR_compat32_rt_sigreturn
#endif /* CONFIG_COMPAT */
#include <asm-generic/seccomp.h>
@@ -23,8 +23,9 @@
#define SECCOMP_ARCH_NATIVE_NR NR_syscalls
#define SECCOMP_ARCH_NATIVE_NAME "aarch64"
#ifdef CONFIG_COMPAT
+#include <asm/unistd_compat_32.h>
# define SECCOMP_ARCH_COMPAT AUDIT_ARCH_ARM
-# define SECCOMP_ARCH_COMPAT_NR __NR_compat_syscalls
+# define SECCOMP_ARCH_COMPAT_NR __NR_compat32_syscalls
# define SECCOMP_ARCH_COMPAT_NAME "arm"
#endif
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index efb13112b408..2510eec026f7 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -25,22 +25,11 @@
#ifndef __ASSEMBLY__
-#include <asm/percpu.h>
-
#include <linux/threads.h>
#include <linux/cpumask.h>
#include <linux/thread_info.h>
-DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
-
-/*
- * We don't use this_cpu_read(cpu_number) as that has implicit writes to
- * preempt_count, and associated (compiler) barriers, that we'd like to avoid
- * the expense of. If we're preemptible, the value can be stale at use anyway.
- * And we can't use this_cpu_ptr() either, as that winds up recursing back
- * here under CONFIG_DEBUG_PREEMPT=y.
- */
-#define raw_smp_processor_id() (*raw_cpu_ptr(&cpu_number))
+#define raw_smp_processor_id() (current_thread_info()->cpu)
/*
* Logical CPU mapping.
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index af3b206fa423..1b6e436dbb55 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -872,10 +872,6 @@
/* Position the attr at the correct index */
#define MAIR_ATTRIDX(attr, idx) ((attr) << ((idx) * 8))
-/* id_aa64pfr0 */
-#define ID_AA64PFR0_EL1_ELx_64BIT_ONLY 0x1
-#define ID_AA64PFR0_EL1_ELx_32BIT_64BIT 0x2
-
/* id_aa64mmfr0 */
#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MIN 0x0
#define ID_AA64MMFR0_EL1_TGRAN4_LPA2 ID_AA64MMFR0_EL1_TGRAN4_52_BIT
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 14be5000c5a0..28f665e0975a 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -184,29 +184,40 @@ static inline void __user *__uaccess_mask_ptr(const void __user *ptr)
* The "__xxx_error" versions set the third argument to -EFAULT if an error
* occurs, and leave it unchanged on success.
*/
-#define __get_mem_asm(load, reg, x, addr, err, type) \
+#ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
+#define __get_mem_asm(load, reg, x, addr, label, type) \
+ asm_goto_output( \
+ "1: " load " " reg "0, [%1]\n" \
+ _ASM_EXTABLE_##type##ACCESS_ERR(1b, %l2, %w0) \
+ : "=r" (x) \
+ : "r" (addr) : : label)
+#else
+#define __get_mem_asm(load, reg, x, addr, label, type) do { \
+ int __gma_err = 0; \
asm volatile( \
"1: " load " " reg "1, [%2]\n" \
"2:\n" \
_ASM_EXTABLE_##type##ACCESS_ERR_ZERO(1b, 2b, %w0, %w1) \
- : "+r" (err), "=r" (x) \
- : "r" (addr))
+ : "+r" (__gma_err), "=r" (x) \
+ : "r" (addr)); \
+ if (__gma_err) goto label; } while (0)
+#endif
-#define __raw_get_mem(ldr, x, ptr, err, type) \
+#define __raw_get_mem(ldr, x, ptr, label, type) \
do { \
unsigned long __gu_val; \
switch (sizeof(*(ptr))) { \
case 1: \
- __get_mem_asm(ldr "b", "%w", __gu_val, (ptr), (err), type); \
+ __get_mem_asm(ldr "b", "%w", __gu_val, (ptr), label, type); \
break; \
case 2: \
- __get_mem_asm(ldr "h", "%w", __gu_val, (ptr), (err), type); \
+ __get_mem_asm(ldr "h", "%w", __gu_val, (ptr), label, type); \
break; \
case 4: \
- __get_mem_asm(ldr, "%w", __gu_val, (ptr), (err), type); \
+ __get_mem_asm(ldr, "%w", __gu_val, (ptr), label, type); \
break; \
case 8: \
- __get_mem_asm(ldr, "%x", __gu_val, (ptr), (err), type); \
+ __get_mem_asm(ldr, "%x", __gu_val, (ptr), label, type); \
break; \
default: \
BUILD_BUG(); \
@@ -219,27 +230,34 @@ do { \
* uaccess_ttbr0_disable(). As `x` and `ptr` could contain blocking functions,
* we must evaluate these outside of the critical section.
*/
-#define __raw_get_user(x, ptr, err) \
+#define __raw_get_user(x, ptr, label) \
do { \
__typeof__(*(ptr)) __user *__rgu_ptr = (ptr); \
__typeof__(x) __rgu_val; \
__chk_user_ptr(ptr); \
- \
- uaccess_ttbr0_enable(); \
- __raw_get_mem("ldtr", __rgu_val, __rgu_ptr, err, U); \
- uaccess_ttbr0_disable(); \
- \
- (x) = __rgu_val; \
+ do { \
+ __label__ __rgu_failed; \
+ uaccess_ttbr0_enable(); \
+ __raw_get_mem("ldtr", __rgu_val, __rgu_ptr, __rgu_failed, U); \
+ uaccess_ttbr0_disable(); \
+ (x) = __rgu_val; \
+ break; \
+ __rgu_failed: \
+ uaccess_ttbr0_disable(); \
+ goto label; \
+ } while (0); \
} while (0)
#define __get_user_error(x, ptr, err) \
do { \
+ __label__ __gu_failed; \
__typeof__(*(ptr)) __user *__p = (ptr); \
might_fault(); \
if (access_ok(__p, sizeof(*__p))) { \
__p = uaccess_mask_ptr(__p); \
- __raw_get_user((x), __p, (err)); \
+ __raw_get_user((x), __p, __gu_failed); \
} else { \
+ __gu_failed: \
(x) = (__force __typeof__(x))0; (err) = -EFAULT; \
} \
} while (0)
@@ -262,40 +280,42 @@ do { \
do { \
__typeof__(dst) __gkn_dst = (dst); \
__typeof__(src) __gkn_src = (src); \
- int __gkn_err = 0; \
- \
- __mte_enable_tco_async(); \
- __raw_get_mem("ldr", *((type *)(__gkn_dst)), \
- (__force type *)(__gkn_src), __gkn_err, K); \
- __mte_disable_tco_async(); \
+ do { \
+ __label__ __gkn_label; \
\
- if (unlikely(__gkn_err)) \
+ __mte_enable_tco_async(); \
+ __raw_get_mem("ldr", *((type *)(__gkn_dst)), \
+ (__force type *)(__gkn_src), __gkn_label, K); \
+ __mte_disable_tco_async(); \
+ break; \
+ __gkn_label: \
+ __mte_disable_tco_async(); \
goto err_label; \
+ } while (0); \
} while (0)
-#define __put_mem_asm(store, reg, x, addr, err, type) \
- asm volatile( \
- "1: " store " " reg "1, [%2]\n" \
+#define __put_mem_asm(store, reg, x, addr, label, type) \
+ asm goto( \
+ "1: " store " " reg "0, [%1]\n" \
"2:\n" \
- _ASM_EXTABLE_##type##ACCESS_ERR(1b, 2b, %w0) \
- : "+r" (err) \
- : "rZ" (x), "r" (addr))
+ _ASM_EXTABLE_##type##ACCESS(1b, %l2) \
+ : : "rZ" (x), "r" (addr) : : label)
-#define __raw_put_mem(str, x, ptr, err, type) \
+#define __raw_put_mem(str, x, ptr, label, type) \
do { \
__typeof__(*(ptr)) __pu_val = (x); \
switch (sizeof(*(ptr))) { \
case 1: \
- __put_mem_asm(str "b", "%w", __pu_val, (ptr), (err), type); \
+ __put_mem_asm(str "b", "%w", __pu_val, (ptr), label, type); \
break; \
case 2: \
- __put_mem_asm(str "h", "%w", __pu_val, (ptr), (err), type); \
+ __put_mem_asm(str "h", "%w", __pu_val, (ptr), label, type); \
break; \
case 4: \
- __put_mem_asm(str, "%w", __pu_val, (ptr), (err), type); \
+ __put_mem_asm(str, "%w", __pu_val, (ptr), label, type); \
break; \
case 8: \
- __put_mem_asm(str, "%x", __pu_val, (ptr), (err), type); \
+ __put_mem_asm(str, "%x", __pu_val, (ptr), label, type); \
break; \
default: \
BUILD_BUG(); \
@@ -307,25 +327,34 @@ do { \
* uaccess_ttbr0_disable(). As `x` and `ptr` could contain blocking functions,
* we must evaluate these outside of the critical section.
*/
-#define __raw_put_user(x, ptr, err) \
+#define __raw_put_user(x, ptr, label) \
do { \
+ __label__ __rpu_failed; \
__typeof__(*(ptr)) __user *__rpu_ptr = (ptr); \
__typeof__(*(ptr)) __rpu_val = (x); \
__chk_user_ptr(__rpu_ptr); \
\
- uaccess_ttbr0_enable(); \
- __raw_put_mem("sttr", __rpu_val, __rpu_ptr, err, U); \
- uaccess_ttbr0_disable(); \
+ do { \
+ uaccess_ttbr0_enable(); \
+ __raw_put_mem("sttr", __rpu_val, __rpu_ptr, __rpu_failed, U); \
+ uaccess_ttbr0_disable(); \
+ break; \
+ __rpu_failed: \
+ uaccess_ttbr0_disable(); \
+ goto label; \
+ } while (0); \
} while (0)
#define __put_user_error(x, ptr, err) \
do { \
+ __label__ __pu_failed; \
__typeof__(*(ptr)) __user *__p = (ptr); \
might_fault(); \
if (access_ok(__p, sizeof(*__p))) { \
__p = uaccess_mask_ptr(__p); \
- __raw_put_user((x), __p, (err)); \
+ __raw_put_user((x), __p, __pu_failed); \
} else { \
+ __pu_failed: \
(err) = -EFAULT; \
} \
} while (0)
@@ -348,15 +377,18 @@ do { \
do { \
__typeof__(dst) __pkn_dst = (dst); \
__typeof__(src) __pkn_src = (src); \
- int __pkn_err = 0; \
\
- __mte_enable_tco_async(); \
- __raw_put_mem("str", *((type *)(__pkn_src)), \
- (__force type *)(__pkn_dst), __pkn_err, K); \
- __mte_disable_tco_async(); \
- \
- if (unlikely(__pkn_err)) \
+ do { \
+ __label__ __pkn_err; \
+ __mte_enable_tco_async(); \
+ __raw_put_mem("str", *((type *)(__pkn_src)), \
+ (__force type *)(__pkn_dst), __pkn_err, K); \
+ __mte_disable_tco_async(); \
+ break; \
+ __pkn_err: \
+ __mte_disable_tco_async(); \
goto err_label; \
+ } while (0); \
} while(0)
extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
@@ -381,6 +413,51 @@ extern unsigned long __must_check __arch_copy_to_user(void __user *to, const voi
__actu_ret; \
})
+static __must_check __always_inline bool user_access_begin(const void __user *ptr, size_t len)
+{
+ if (unlikely(!access_ok(ptr,len)))
+ return 0;
+ uaccess_ttbr0_enable();
+ return 1;
+}
+#define user_access_begin(a,b) user_access_begin(a,b)
+#define user_access_end() uaccess_ttbr0_disable()
+#define unsafe_put_user(x, ptr, label) \
+ __raw_put_mem("sttr", x, uaccess_mask_ptr(ptr), label, U)
+#define unsafe_get_user(x, ptr, label) \
+ __raw_get_mem("ldtr", x, uaccess_mask_ptr(ptr), label, U)
+
+/*
+ * KCSAN uses these to save and restore ttbr state.
+ * We do not support KCSAN with ARM64_SW_TTBR0_PAN, so
+ * they are no-ops.
+ */
+static inline unsigned long user_access_save(void) { return 0; }
+static inline void user_access_restore(unsigned long enabled) { }
+
+/*
+ * We want the unsafe accessors to always be inlined and use
+ * the error labels - thus the macro games.
+ */
+#define unsafe_copy_loop(dst, src, len, type, label) \
+ while (len >= sizeof(type)) { \
+ unsafe_put_user(*(type *)(src),(type __user *)(dst),label); \
+ dst += sizeof(type); \
+ src += sizeof(type); \
+ len -= sizeof(type); \
+ }
+
+#define unsafe_copy_to_user(_dst,_src,_len,label) \
+do { \
+ char __user *__ucu_dst = (_dst); \
+ const char *__ucu_src = (_src); \
+ size_t __ucu_len = (_len); \
+ unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u64, label); \
+ unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u32, label); \
+ unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u16, label); \
+ unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u8, label); \
+} while (0)
+
#define INLINE_COPY_TO_USER
#define INLINE_COPY_FROM_USER
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 1346579f802f..80618c9bbcd8 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -17,35 +17,17 @@
#define __ARCH_WANT_SYS_VFORK
/*
- * Compat syscall numbers used by the AArch64 kernel.
- */
-#define __NR_compat_restart_syscall 0
-#define __NR_compat_exit 1
-#define __NR_compat_read 3
-#define __NR_compat_write 4
-#define __NR_compat_gettimeofday 78
-#define __NR_compat_sigreturn 119
-#define __NR_compat_rt_sigreturn 173
-#define __NR_compat_clock_gettime 263
-#define __NR_compat_clock_getres 264
-#define __NR_compat_clock_gettime64 403
-#define __NR_compat_clock_getres_time64 406
-
-/*
* The following SVCs are ARM private.
*/
#define __ARM_NR_COMPAT_BASE 0x0f0000
#define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE + 2)
#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
#define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)
-
-#define __NR_compat_syscalls 463
#endif
#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_NEW_STAT
-#ifndef __COMPAT_SYSCALL_NR
-#include <uapi/asm/unistd.h>
-#endif
+#include <asm/unistd_64.h>
#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index 1386e8e751f2..e0b1a0b57f75 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -1,938 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * AArch32 (compat) system call definitions.
- *
- * Copyright (C) 2001-2005 Russell King
- * Copyright (C) 2012 ARM Ltd.
- */
+#ifndef _UAPI__ASM_ARM_UNISTD_H
+#define _UAPI__ASM_ARM_UNISTD_H
-#ifndef __SYSCALL
-#define __SYSCALL(x, y)
-#endif
+#include <asm/unistd_32.h>
-#define __NR_restart_syscall 0
-__SYSCALL(__NR_restart_syscall, sys_restart_syscall)
-#define __NR_exit 1
-__SYSCALL(__NR_exit, sys_exit)
-#define __NR_fork 2
-__SYSCALL(__NR_fork, sys_fork)
-#define __NR_read 3
-__SYSCALL(__NR_read, sys_read)
-#define __NR_write 4
-__SYSCALL(__NR_write, sys_write)
-#define __NR_open 5
-__SYSCALL(__NR_open, compat_sys_open)
-#define __NR_close 6
-__SYSCALL(__NR_close, sys_close)
- /* 7 was sys_waitpid */
-__SYSCALL(7, sys_ni_syscall)
-#define __NR_creat 8
-__SYSCALL(__NR_creat, sys_creat)
-#define __NR_link 9
-__SYSCALL(__NR_link, sys_link)
-#define __NR_unlink 10
-__SYSCALL(__NR_unlink, sys_unlink)
-#define __NR_execve 11
-__SYSCALL(__NR_execve, compat_sys_execve)
-#define __NR_chdir 12
-__SYSCALL(__NR_chdir, sys_chdir)
- /* 13 was sys_time */
-__SYSCALL(13, sys_ni_syscall)
-#define __NR_mknod 14
-__SYSCALL(__NR_mknod, sys_mknod)
-#define __NR_chmod 15
-__SYSCALL(__NR_chmod, sys_chmod)
-#define __NR_lchown 16
-__SYSCALL(__NR_lchown, sys_lchown16)
- /* 17 was sys_break */
-__SYSCALL(17, sys_ni_syscall)
- /* 18 was sys_stat */
-__SYSCALL(18, sys_ni_syscall)
-#define __NR_lseek 19
-__SYSCALL(__NR_lseek, compat_sys_lseek)
-#define __NR_getpid 20
-__SYSCALL(__NR_getpid, sys_getpid)
-#define __NR_mount 21
-__SYSCALL(__NR_mount, sys_mount)
- /* 22 was sys_umount */
-__SYSCALL(22, sys_ni_syscall)
-#define __NR_setuid 23
-__SYSCALL(__NR_setuid, sys_setuid16)
-#define __NR_getuid 24
-__SYSCALL(__NR_getuid, sys_getuid16)
- /* 25 was sys_stime */
-__SYSCALL(25, sys_ni_syscall)
-#define __NR_ptrace 26
-__SYSCALL(__NR_ptrace, compat_sys_ptrace)
- /* 27 was sys_alarm */
-__SYSCALL(27, sys_ni_syscall)
- /* 28 was sys_fstat */
-__SYSCALL(28, sys_ni_syscall)
-#define __NR_pause 29
-__SYSCALL(__NR_pause, sys_pause)
- /* 30 was sys_utime */
-__SYSCALL(30, sys_ni_syscall)
- /* 31 was sys_stty */
-__SYSCALL(31, sys_ni_syscall)
- /* 32 was sys_gtty */
-__SYSCALL(32, sys_ni_syscall)
-#define __NR_access 33
-__SYSCALL(__NR_access, sys_access)
-#define __NR_nice 34
-__SYSCALL(__NR_nice, sys_nice)
- /* 35 was sys_ftime */
-__SYSCALL(35, sys_ni_syscall)
-#define __NR_sync 36
-__SYSCALL(__NR_sync, sys_sync)
-#define __NR_kill 37
-__SYSCALL(__NR_kill, sys_kill)
-#define __NR_rename 38
-__SYSCALL(__NR_rename, sys_rename)
-#define __NR_mkdir 39
-__SYSCALL(__NR_mkdir, sys_mkdir)
-#define __NR_rmdir 40
-__SYSCALL(__NR_rmdir, sys_rmdir)
-#define __NR_dup 41
-__SYSCALL(__NR_dup, sys_dup)
-#define __NR_pipe 42
-__SYSCALL(__NR_pipe, sys_pipe)
-#define __NR_times 43
-__SYSCALL(__NR_times, compat_sys_times)
- /* 44 was sys_prof */
-__SYSCALL(44, sys_ni_syscall)
-#define __NR_brk 45
-__SYSCALL(__NR_brk, sys_brk)
-#define __NR_setgid 46
-__SYSCALL(__NR_setgid, sys_setgid16)
-#define __NR_getgid 47
-__SYSCALL(__NR_getgid, sys_getgid16)
- /* 48 was sys_signal */
-__SYSCALL(48, sys_ni_syscall)
-#define __NR_geteuid 49
-__SYSCALL(__NR_geteuid, sys_geteuid16)
-#define __NR_getegid 50
-__SYSCALL(__NR_getegid, sys_getegid16)
-#define __NR_acct 51
-__SYSCALL(__NR_acct, sys_acct)
-#define __NR_umount2 52
-__SYSCALL(__NR_umount2, sys_umount)
- /* 53 was sys_lock */
-__SYSCALL(53, sys_ni_syscall)
-#define __NR_ioctl 54
-__SYSCALL(__NR_ioctl, compat_sys_ioctl)
-#define __NR_fcntl 55
-__SYSCALL(__NR_fcntl, compat_sys_fcntl)
- /* 56 was sys_mpx */
-__SYSCALL(56, sys_ni_syscall)
-#define __NR_setpgid 57
-__SYSCALL(__NR_setpgid, sys_setpgid)
- /* 58 was sys_ulimit */
-__SYSCALL(58, sys_ni_syscall)
- /* 59 was sys_olduname */
-__SYSCALL(59, sys_ni_syscall)
-#define __NR_umask 60
-__SYSCALL(__NR_umask, sys_umask)
-#define __NR_chroot 61
-__SYSCALL(__NR_chroot, sys_chroot)
-#define __NR_ustat 62
-__SYSCALL(__NR_ustat, compat_sys_ustat)
-#define __NR_dup2 63
-__SYSCALL(__NR_dup2, sys_dup2)
-#define __NR_getppid 64
-__SYSCALL(__NR_getppid, sys_getppid)
-#define __NR_getpgrp 65
-__SYSCALL(__NR_getpgrp, sys_getpgrp)
-#define __NR_setsid 66
-__SYSCALL(__NR_setsid, sys_setsid)
-#define __NR_sigaction 67
-__SYSCALL(__NR_sigaction, compat_sys_sigaction)
- /* 68 was sys_sgetmask */
-__SYSCALL(68, sys_ni_syscall)
- /* 69 was sys_ssetmask */
-__SYSCALL(69, sys_ni_syscall)
-#define __NR_setreuid 70
-__SYSCALL(__NR_setreuid, sys_setreuid16)
-#define __NR_setregid 71
-__SYSCALL(__NR_setregid, sys_setregid16)
-#define __NR_sigsuspend 72
-__SYSCALL(__NR_sigsuspend, sys_sigsuspend)
-#define __NR_sigpending 73
-__SYSCALL(__NR_sigpending, compat_sys_sigpending)
-#define __NR_sethostname 74
-__SYSCALL(__NR_sethostname, sys_sethostname)
-#define __NR_setrlimit 75
-__SYSCALL(__NR_setrlimit, compat_sys_setrlimit)
- /* 76 was compat_sys_getrlimit */
-__SYSCALL(76, sys_ni_syscall)
-#define __NR_getrusage 77
-__SYSCALL(__NR_getrusage, compat_sys_getrusage)
-#define __NR_gettimeofday 78
-__SYSCALL(__NR_gettimeofday, compat_sys_gettimeofday)
-#define __NR_settimeofday 79
-__SYSCALL(__NR_settimeofday, compat_sys_settimeofday)
-#define __NR_getgroups 80
-__SYSCALL(__NR_getgroups, sys_getgroups16)
-#define __NR_setgroups 81
-__SYSCALL(__NR_setgroups, sys_setgroups16)
- /* 82 was compat_sys_select */
-__SYSCALL(82, sys_ni_syscall)
-#define __NR_symlink 83
-__SYSCALL(__NR_symlink, sys_symlink)
- /* 84 was sys_lstat */
-__SYSCALL(84, sys_ni_syscall)
-#define __NR_readlink 85
-__SYSCALL(__NR_readlink, sys_readlink)
-#define __NR_uselib 86
-__SYSCALL(__NR_uselib, sys_uselib)
-#define __NR_swapon 87
-__SYSCALL(__NR_swapon, sys_swapon)
-#define __NR_reboot 88
-__SYSCALL(__NR_reboot, sys_reboot)
- /* 89 was sys_readdir */
-__SYSCALL(89, sys_ni_syscall)
- /* 90 was sys_mmap */
-__SYSCALL(90, sys_ni_syscall)
-#define __NR_munmap 91
-__SYSCALL(__NR_munmap, sys_munmap)
-#define __NR_truncate 92
-__SYSCALL(__NR_truncate, compat_sys_truncate)
-#define __NR_ftruncate 93
-__SYSCALL(__NR_ftruncate, compat_sys_ftruncate)
-#define __NR_fchmod 94
-__SYSCALL(__NR_fchmod, sys_fchmod)
-#define __NR_fchown 95
-__SYSCALL(__NR_fchown, sys_fchown16)
-#define __NR_getpriority 96
-__SYSCALL(__NR_getpriority, sys_getpriority)
-#define __NR_setpriority 97
-__SYSCALL(__NR_setpriority, sys_setpriority)
- /* 98 was sys_profil */
-__SYSCALL(98, sys_ni_syscall)
-#define __NR_statfs 99
-__SYSCALL(__NR_statfs, compat_sys_statfs)
-#define __NR_fstatfs 100
-__SYSCALL(__NR_fstatfs, compat_sys_fstatfs)
- /* 101 was sys_ioperm */
-__SYSCALL(101, sys_ni_syscall)
- /* 102 was sys_socketcall */
-__SYSCALL(102, sys_ni_syscall)
-#define __NR_syslog 103
-__SYSCALL(__NR_syslog, sys_syslog)
-#define __NR_setitimer 104
-__SYSCALL(__NR_setitimer, compat_sys_setitimer)
-#define __NR_getitimer 105
-__SYSCALL(__NR_getitimer, compat_sys_getitimer)
-#define __NR_stat 106
-__SYSCALL(__NR_stat, compat_sys_newstat)
-#define __NR_lstat 107
-__SYSCALL(__NR_lstat, compat_sys_newlstat)
-#define __NR_fstat 108
-__SYSCALL(__NR_fstat, compat_sys_newfstat)
- /* 109 was sys_uname */
-__SYSCALL(109, sys_ni_syscall)
- /* 110 was sys_iopl */
-__SYSCALL(110, sys_ni_syscall)
-#define __NR_vhangup 111
-__SYSCALL(__NR_vhangup, sys_vhangup)
- /* 112 was sys_idle */
-__SYSCALL(112, sys_ni_syscall)
- /* 113 was sys_syscall */
-__SYSCALL(113, sys_ni_syscall)
-#define __NR_wait4 114
-__SYSCALL(__NR_wait4, compat_sys_wait4)
-#define __NR_swapoff 115
-__SYSCALL(__NR_swapoff, sys_swapoff)
-#define __NR_sysinfo 116
-__SYSCALL(__NR_sysinfo, compat_sys_sysinfo)
- /* 117 was sys_ipc */
-__SYSCALL(117, sys_ni_syscall)
-#define __NR_fsync 118
-__SYSCALL(__NR_fsync, sys_fsync)
-#define __NR_sigreturn 119
-__SYSCALL(__NR_sigreturn, compat_sys_sigreturn)
-#define __NR_clone 120
-__SYSCALL(__NR_clone, sys_clone)
-#define __NR_setdomainname 121
-__SYSCALL(__NR_setdomainname, sys_setdomainname)
-#define __NR_uname 122
-__SYSCALL(__NR_uname, sys_newuname)
- /* 123 was sys_modify_ldt */
-__SYSCALL(123, sys_ni_syscall)
-#define __NR_adjtimex 124
-__SYSCALL(__NR_adjtimex, sys_adjtimex_time32)
-#define __NR_mprotect 125
-__SYSCALL(__NR_mprotect, sys_mprotect)
-#define __NR_sigprocmask 126
-__SYSCALL(__NR_sigprocmask, compat_sys_sigprocmask)
- /* 127 was sys_create_module */
-__SYSCALL(127, sys_ni_syscall)
-#define __NR_init_module 128
-__SYSCALL(__NR_init_module, sys_init_module)
-#define __NR_delete_module 129
-__SYSCALL(__NR_delete_module, sys_delete_module)
- /* 130 was sys_get_kernel_syms */
-__SYSCALL(130, sys_ni_syscall)
-#define __NR_quotactl 131
-__SYSCALL(__NR_quotactl, sys_quotactl)
-#define __NR_getpgid 132
-__SYSCALL(__NR_getpgid, sys_getpgid)
-#define __NR_fchdir 133
-__SYSCALL(__NR_fchdir, sys_fchdir)
-#define __NR_bdflush 134
-__SYSCALL(__NR_bdflush, sys_ni_syscall)
-#define __NR_sysfs 135
-__SYSCALL(__NR_sysfs, sys_sysfs)
-#define __NR_personality 136
-__SYSCALL(__NR_personality, sys_personality)
- /* 137 was sys_afs_syscall */
-__SYSCALL(137, sys_ni_syscall)
-#define __NR_setfsuid 138
-__SYSCALL(__NR_setfsuid, sys_setfsuid16)
-#define __NR_setfsgid 139
-__SYSCALL(__NR_setfsgid, sys_setfsgid16)
-#define __NR__llseek 140
-__SYSCALL(__NR__llseek, sys_llseek)
-#define __NR_getdents 141
-__SYSCALL(__NR_getdents, compat_sys_getdents)
-#define __NR__newselect 142
-__SYSCALL(__NR__newselect, compat_sys_select)
-#define __NR_flock 143
-__SYSCALL(__NR_flock, sys_flock)
-#define __NR_msync 144
-__SYSCALL(__NR_msync, sys_msync)
-#define __NR_readv 145
-__SYSCALL(__NR_readv, sys_readv)
-#define __NR_writev 146
-__SYSCALL(__NR_writev, sys_writev)
-#define __NR_getsid 147
-__SYSCALL(__NR_getsid, sys_getsid)
-#define __NR_fdatasync 148
-__SYSCALL(__NR_fdatasync, sys_fdatasync)
- /* 149 was sys_sysctl */
-__SYSCALL(149, sys_ni_syscall)
-#define __NR_mlock 150
-__SYSCALL(__NR_mlock, sys_mlock)
-#define __NR_munlock 151
-__SYSCALL(__NR_munlock, sys_munlock)
-#define __NR_mlockall 152
-__SYSCALL(__NR_mlockall, sys_mlockall)
-#define __NR_munlockall 153
-__SYSCALL(__NR_munlockall, sys_munlockall)
-#define __NR_sched_setparam 154
-__SYSCALL(__NR_sched_setparam, sys_sched_setparam)
-#define __NR_sched_getparam 155
-__SYSCALL(__NR_sched_getparam, sys_sched_getparam)
-#define __NR_sched_setscheduler 156
-__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler)
-#define __NR_sched_getscheduler 157
-__SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler)
-#define __NR_sched_yield 158
-__SYSCALL(__NR_sched_yield, sys_sched_yield)
-#define __NR_sched_get_priority_max 159
-__SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max)
-#define __NR_sched_get_priority_min 160
-__SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min)
-#define __NR_sched_rr_get_interval 161
-__SYSCALL(__NR_sched_rr_get_interval, sys_sched_rr_get_interval_time32)
-#define __NR_nanosleep 162
-__SYSCALL(__NR_nanosleep, sys_nanosleep_time32)
-#define __NR_mremap 163
-__SYSCALL(__NR_mremap, sys_mremap)
-#define __NR_setresuid 164
-__SYSCALL(__NR_setresuid, sys_setresuid16)
-#define __NR_getresuid 165
-__SYSCALL(__NR_getresuid, sys_getresuid16)
- /* 166 was sys_vm86 */
-__SYSCALL(166, sys_ni_syscall)
- /* 167 was sys_query_module */
-__SYSCALL(167, sys_ni_syscall)
-#define __NR_poll 168
-__SYSCALL(__NR_poll, sys_poll)
-#define __NR_nfsservctl 169
-__SYSCALL(__NR_nfsservctl, sys_ni_syscall)
-#define __NR_setresgid 170
-__SYSCALL(__NR_setresgid, sys_setresgid16)
-#define __NR_getresgid 171
-__SYSCALL(__NR_getresgid, sys_getresgid16)
-#define __NR_prctl 172
-__SYSCALL(__NR_prctl, sys_prctl)
-#define __NR_rt_sigreturn 173
-__SYSCALL(__NR_rt_sigreturn, compat_sys_rt_sigreturn)
-#define __NR_rt_sigaction 174
-__SYSCALL(__NR_rt_sigaction, compat_sys_rt_sigaction)
-#define __NR_rt_sigprocmask 175
-__SYSCALL(__NR_rt_sigprocmask, compat_sys_rt_sigprocmask)
-#define __NR_rt_sigpending 176
-__SYSCALL(__NR_rt_sigpending, compat_sys_rt_sigpending)
-#define __NR_rt_sigtimedwait 177
-__SYSCALL(__NR_rt_sigtimedwait, compat_sys_rt_sigtimedwait_time32)
-#define __NR_rt_sigqueueinfo 178
-__SYSCALL(__NR_rt_sigqueueinfo, compat_sys_rt_sigqueueinfo)
-#define __NR_rt_sigsuspend 179
-__SYSCALL(__NR_rt_sigsuspend, compat_sys_rt_sigsuspend)
-#define __NR_pread64 180
-__SYSCALL(__NR_pread64, compat_sys_aarch32_pread64)
-#define __NR_pwrite64 181
-__SYSCALL(__NR_pwrite64, compat_sys_aarch32_pwrite64)
-#define __NR_chown 182
-__SYSCALL(__NR_chown, sys_chown16)
-#define __NR_getcwd 183
-__SYSCALL(__NR_getcwd, sys_getcwd)
-#define __NR_capget 184
-__SYSCALL(__NR_capget, sys_capget)
-#define __NR_capset 185
-__SYSCALL(__NR_capset, sys_capset)
-#define __NR_sigaltstack 186
-__SYSCALL(__NR_sigaltstack, compat_sys_sigaltstack)
-#define __NR_sendfile 187
-__SYSCALL(__NR_sendfile, compat_sys_sendfile)
- /* 188 reserved */
-__SYSCALL(188, sys_ni_syscall)
- /* 189 reserved */
-__SYSCALL(189, sys_ni_syscall)
-#define __NR_vfork 190
-__SYSCALL(__NR_vfork, sys_vfork)
-#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */
-__SYSCALL(__NR_ugetrlimit, compat_sys_getrlimit) /* SuS compliant getrlimit */
-#define __NR_mmap2 192
-__SYSCALL(__NR_mmap2, compat_sys_aarch32_mmap2)
-#define __NR_truncate64 193
-__SYSCALL(__NR_truncate64, compat_sys_aarch32_truncate64)
-#define __NR_ftruncate64 194
-__SYSCALL(__NR_ftruncate64, compat_sys_aarch32_ftruncate64)
-#define __NR_stat64 195
-__SYSCALL(__NR_stat64, sys_stat64)
-#define __NR_lstat64 196
-__SYSCALL(__NR_lstat64, sys_lstat64)
-#define __NR_fstat64 197
-__SYSCALL(__NR_fstat64, sys_fstat64)
-#define __NR_lchown32 198
-__SYSCALL(__NR_lchown32, sys_lchown)
-#define __NR_getuid32 199
-__SYSCALL(__NR_getuid32, sys_getuid)
-#define __NR_getgid32 200
-__SYSCALL(__NR_getgid32, sys_getgid)
-#define __NR_geteuid32 201
-__SYSCALL(__NR_geteuid32, sys_geteuid)
-#define __NR_getegid32 202
-__SYSCALL(__NR_getegid32, sys_getegid)
-#define __NR_setreuid32 203
-__SYSCALL(__NR_setreuid32, sys_setreuid)
-#define __NR_setregid32 204
-__SYSCALL(__NR_setregid32, sys_setregid)
-#define __NR_getgroups32 205
-__SYSCALL(__NR_getgroups32, sys_getgroups)
-#define __NR_setgroups32 206
-__SYSCALL(__NR_setgroups32, sys_setgroups)
-#define __NR_fchown32 207
-__SYSCALL(__NR_fchown32, sys_fchown)
-#define __NR_setresuid32 208
-__SYSCALL(__NR_setresuid32, sys_setresuid)
-#define __NR_getresuid32 209
-__SYSCALL(__NR_getresuid32, sys_getresuid)
-#define __NR_setresgid32 210
-__SYSCALL(__NR_setresgid32, sys_setresgid)
-#define __NR_getresgid32 211
-__SYSCALL(__NR_getresgid32, sys_getresgid)
-#define __NR_chown32 212
-__SYSCALL(__NR_chown32, sys_chown)
-#define __NR_setuid32 213
-__SYSCALL(__NR_setuid32, sys_setuid)
-#define __NR_setgid32 214
-__SYSCALL(__NR_setgid32, sys_setgid)
-#define __NR_setfsuid32 215
-__SYSCALL(__NR_setfsuid32, sys_setfsuid)
-#define __NR_setfsgid32 216
-__SYSCALL(__NR_setfsgid32, sys_setfsgid)
-#define __NR_getdents64 217
-__SYSCALL(__NR_getdents64, sys_getdents64)
-#define __NR_pivot_root 218
-__SYSCALL(__NR_pivot_root, sys_pivot_root)
-#define __NR_mincore 219
-__SYSCALL(__NR_mincore, sys_mincore)
-#define __NR_madvise 220
-__SYSCALL(__NR_madvise, sys_madvise)
-#define __NR_fcntl64 221
-__SYSCALL(__NR_fcntl64, compat_sys_fcntl64)
- /* 222 for tux */
-__SYSCALL(222, sys_ni_syscall)
- /* 223 is unused */
-__SYSCALL(223, sys_ni_syscall)
-#define __NR_gettid 224
-__SYSCALL(__NR_gettid, sys_gettid)
-#define __NR_readahead 225
-__SYSCALL(__NR_readahead, compat_sys_aarch32_readahead)
-#define __NR_setxattr 226
-__SYSCALL(__NR_setxattr, sys_setxattr)
-#define __NR_lsetxattr 227
-__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
-#define __NR_fsetxattr 228
-__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
-#define __NR_getxattr 229
-__SYSCALL(__NR_getxattr, sys_getxattr)
-#define __NR_lgetxattr 230
-__SYSCALL(__NR_lgetxattr, sys_lgetxattr)
-#define __NR_fgetxattr 231
-__SYSCALL(__NR_fgetxattr, sys_fgetxattr)
-#define __NR_listxattr 232
-__SYSCALL(__NR_listxattr, sys_listxattr)
-#define __NR_llistxattr 233
-__SYSCALL(__NR_llistxattr, sys_llistxattr)
-#define __NR_flistxattr 234
-__SYSCALL(__NR_flistxattr, sys_flistxattr)
-#define __NR_removexattr 235
-__SYSCALL(__NR_removexattr, sys_removexattr)
-#define __NR_lremovexattr 236
-__SYSCALL(__NR_lremovexattr, sys_lremovexattr)
-#define __NR_fremovexattr 237
-__SYSCALL(__NR_fremovexattr, sys_fremovexattr)
-#define __NR_tkill 238
-__SYSCALL(__NR_tkill, sys_tkill)
-#define __NR_sendfile64 239
-__SYSCALL(__NR_sendfile64, sys_sendfile64)
-#define __NR_futex 240
-__SYSCALL(__NR_futex, sys_futex_time32)
-#define __NR_sched_setaffinity 241
-__SYSCALL(__NR_sched_setaffinity, compat_sys_sched_setaffinity)
-#define __NR_sched_getaffinity 242
-__SYSCALL(__NR_sched_getaffinity, compat_sys_sched_getaffinity)
-#define __NR_io_setup 243
-__SYSCALL(__NR_io_setup, compat_sys_io_setup)
-#define __NR_io_destroy 244
-__SYSCALL(__NR_io_destroy, sys_io_destroy)
-#define __NR_io_getevents 245
-__SYSCALL(__NR_io_getevents, sys_io_getevents_time32)
-#define __NR_io_submit 246
-__SYSCALL(__NR_io_submit, compat_sys_io_submit)
-#define __NR_io_cancel 247
-__SYSCALL(__NR_io_cancel, sys_io_cancel)
-#define __NR_exit_group 248
-__SYSCALL(__NR_exit_group, sys_exit_group)
- /* 249 was lookup_dcookie */
-__SYSCALL(249, sys_ni_syscall)
-#define __NR_epoll_create 250
-__SYSCALL(__NR_epoll_create, sys_epoll_create)
-#define __NR_epoll_ctl 251
-__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl)
-#define __NR_epoll_wait 252
-__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
-#define __NR_remap_file_pages 253
-__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages)
- /* 254 for set_thread_area */
-__SYSCALL(254, sys_ni_syscall)
- /* 255 for get_thread_area */
-__SYSCALL(255, sys_ni_syscall)
-#define __NR_set_tid_address 256
-__SYSCALL(__NR_set_tid_address, sys_set_tid_address)
-#define __NR_timer_create 257
-__SYSCALL(__NR_timer_create, compat_sys_timer_create)
-#define __NR_timer_settime 258
-__SYSCALL(__NR_timer_settime, sys_timer_settime32)
-#define __NR_timer_gettime 259
-__SYSCALL(__NR_timer_gettime, sys_timer_gettime32)
-#define __NR_timer_getoverrun 260
-__SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun)
-#define __NR_timer_delete 261
-__SYSCALL(__NR_timer_delete, sys_timer_delete)
-#define __NR_clock_settime 262
-__SYSCALL(__NR_clock_settime, sys_clock_settime32)
-#define __NR_clock_gettime 263
-__SYSCALL(__NR_clock_gettime, sys_clock_gettime32)
-#define __NR_clock_getres 264
-__SYSCALL(__NR_clock_getres, sys_clock_getres_time32)
-#define __NR_clock_nanosleep 265
-__SYSCALL(__NR_clock_nanosleep, sys_clock_nanosleep_time32)
-#define __NR_statfs64 266
-__SYSCALL(__NR_statfs64, compat_sys_aarch32_statfs64)
-#define __NR_fstatfs64 267
-__SYSCALL(__NR_fstatfs64, compat_sys_aarch32_fstatfs64)
-#define __NR_tgkill 268
-__SYSCALL(__NR_tgkill, sys_tgkill)
-#define __NR_utimes 269
-__SYSCALL(__NR_utimes, sys_utimes_time32)
-#define __NR_arm_fadvise64_64 270
-__SYSCALL(__NR_arm_fadvise64_64, compat_sys_aarch32_fadvise64_64)
-#define __NR_pciconfig_iobase 271
-__SYSCALL(__NR_pciconfig_iobase, sys_pciconfig_iobase)
-#define __NR_pciconfig_read 272
-__SYSCALL(__NR_pciconfig_read, sys_pciconfig_read)
-#define __NR_pciconfig_write 273
-__SYSCALL(__NR_pciconfig_write, sys_pciconfig_write)
-#define __NR_mq_open 274
-__SYSCALL(__NR_mq_open, compat_sys_mq_open)
-#define __NR_mq_unlink 275
-__SYSCALL(__NR_mq_unlink, sys_mq_unlink)
-#define __NR_mq_timedsend 276
-__SYSCALL(__NR_mq_timedsend, sys_mq_timedsend_time32)
-#define __NR_mq_timedreceive 277
-__SYSCALL(__NR_mq_timedreceive, sys_mq_timedreceive_time32)
-#define __NR_mq_notify 278
-__SYSCALL(__NR_mq_notify, compat_sys_mq_notify)
-#define __NR_mq_getsetattr 279
-__SYSCALL(__NR_mq_getsetattr, compat_sys_mq_getsetattr)
-#define __NR_waitid 280
-__SYSCALL(__NR_waitid, compat_sys_waitid)
-#define __NR_socket 281
-__SYSCALL(__NR_socket, sys_socket)
-#define __NR_bind 282
-__SYSCALL(__NR_bind, sys_bind)
-#define __NR_connect 283
-__SYSCALL(__NR_connect, sys_connect)
-#define __NR_listen 284
-__SYSCALL(__NR_listen, sys_listen)
-#define __NR_accept 285
-__SYSCALL(__NR_accept, sys_accept)
-#define __NR_getsockname 286
-__SYSCALL(__NR_getsockname, sys_getsockname)
-#define __NR_getpeername 287
-__SYSCALL(__NR_getpeername, sys_getpeername)
-#define __NR_socketpair 288
-__SYSCALL(__NR_socketpair, sys_socketpair)
-#define __NR_send 289
-__SYSCALL(__NR_send, sys_send)
-#define __NR_sendto 290
-__SYSCALL(__NR_sendto, sys_sendto)
-#define __NR_recv 291
-__SYSCALL(__NR_recv, compat_sys_recv)
-#define __NR_recvfrom 292
-__SYSCALL(__NR_recvfrom, compat_sys_recvfrom)
-#define __NR_shutdown 293
-__SYSCALL(__NR_shutdown, sys_shutdown)
-#define __NR_setsockopt 294
-__SYSCALL(__NR_setsockopt, sys_setsockopt)
-#define __NR_getsockopt 295
-__SYSCALL(__NR_getsockopt, sys_getsockopt)
-#define __NR_sendmsg 296
-__SYSCALL(__NR_sendmsg, compat_sys_sendmsg)
-#define __NR_recvmsg 297
-__SYSCALL(__NR_recvmsg, compat_sys_recvmsg)
-#define __NR_semop 298
-__SYSCALL(__NR_semop, sys_semop)
-#define __NR_semget 299
-__SYSCALL(__NR_semget, sys_semget)
-#define __NR_semctl 300
-__SYSCALL(__NR_semctl, compat_sys_old_semctl)
-#define __NR_msgsnd 301
-__SYSCALL(__NR_msgsnd, compat_sys_msgsnd)
-#define __NR_msgrcv 302
-__SYSCALL(__NR_msgrcv, compat_sys_msgrcv)
-#define __NR_msgget 303
-__SYSCALL(__NR_msgget, sys_msgget)
-#define __NR_msgctl 304
-__SYSCALL(__NR_msgctl, compat_sys_old_msgctl)
-#define __NR_shmat 305
-__SYSCALL(__NR_shmat, compat_sys_shmat)
-#define __NR_shmdt 306
-__SYSCALL(__NR_shmdt, sys_shmdt)
-#define __NR_shmget 307
-__SYSCALL(__NR_shmget, sys_shmget)
-#define __NR_shmctl 308
-__SYSCALL(__NR_shmctl, compat_sys_old_shmctl)
-#define __NR_add_key 309
-__SYSCALL(__NR_add_key, sys_add_key)
-#define __NR_request_key 310
-__SYSCALL(__NR_request_key, sys_request_key)
-#define __NR_keyctl 311
-__SYSCALL(__NR_keyctl, compat_sys_keyctl)
-#define __NR_semtimedop 312
-__SYSCALL(__NR_semtimedop, sys_semtimedop_time32)
-#define __NR_vserver 313
-__SYSCALL(__NR_vserver, sys_ni_syscall)
-#define __NR_ioprio_set 314
-__SYSCALL(__NR_ioprio_set, sys_ioprio_set)
-#define __NR_ioprio_get 315
-__SYSCALL(__NR_ioprio_get, sys_ioprio_get)
-#define __NR_inotify_init 316
-__SYSCALL(__NR_inotify_init, sys_inotify_init)
-#define __NR_inotify_add_watch 317
-__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
-#define __NR_inotify_rm_watch 318
-__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
-#define __NR_mbind 319
-__SYSCALL(__NR_mbind, sys_mbind)
-#define __NR_get_mempolicy 320
-__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy)
-#define __NR_set_mempolicy 321
-__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy)
-#define __NR_openat 322
-__SYSCALL(__NR_openat, compat_sys_openat)
-#define __NR_mkdirat 323
-__SYSCALL(__NR_mkdirat, sys_mkdirat)
-#define __NR_mknodat 324
-__SYSCALL(__NR_mknodat, sys_mknodat)
-#define __NR_fchownat 325
-__SYSCALL(__NR_fchownat, sys_fchownat)
-#define __NR_futimesat 326
-__SYSCALL(__NR_futimesat, sys_futimesat_time32)
-#define __NR_fstatat64 327
-__SYSCALL(__NR_fstatat64, sys_fstatat64)
-#define __NR_unlinkat 328
-__SYSCALL(__NR_unlinkat, sys_unlinkat)
-#define __NR_renameat 329
-__SYSCALL(__NR_renameat, sys_renameat)
-#define __NR_linkat 330
-__SYSCALL(__NR_linkat, sys_linkat)
-#define __NR_symlinkat 331
-__SYSCALL(__NR_symlinkat, sys_symlinkat)
-#define __NR_readlinkat 332
-__SYSCALL(__NR_readlinkat, sys_readlinkat)
-#define __NR_fchmodat 333
-__SYSCALL(__NR_fchmodat, sys_fchmodat)
-#define __NR_faccessat 334
-__SYSCALL(__NR_faccessat, sys_faccessat)
-#define __NR_pselect6 335
-__SYSCALL(__NR_pselect6, compat_sys_pselect6_time32)
-#define __NR_ppoll 336
-__SYSCALL(__NR_ppoll, compat_sys_ppoll_time32)
-#define __NR_unshare 337
-__SYSCALL(__NR_unshare, sys_unshare)
-#define __NR_set_robust_list 338
-__SYSCALL(__NR_set_robust_list, compat_sys_set_robust_list)
-#define __NR_get_robust_list 339
-__SYSCALL(__NR_get_robust_list, compat_sys_get_robust_list)
-#define __NR_splice 340
-__SYSCALL(__NR_splice, sys_splice)
-#define __NR_sync_file_range2 341
-__SYSCALL(__NR_sync_file_range2, compat_sys_aarch32_sync_file_range2)
-#define __NR_tee 342
-__SYSCALL(__NR_tee, sys_tee)
-#define __NR_vmsplice 343
-__SYSCALL(__NR_vmsplice, sys_vmsplice)
-#define __NR_move_pages 344
-__SYSCALL(__NR_move_pages, sys_move_pages)
-#define __NR_getcpu 345
-__SYSCALL(__NR_getcpu, sys_getcpu)
-#define __NR_epoll_pwait 346
-__SYSCALL(__NR_epoll_pwait, compat_sys_epoll_pwait)
-#define __NR_kexec_load 347
-__SYSCALL(__NR_kexec_load, compat_sys_kexec_load)
-#define __NR_utimensat 348
-__SYSCALL(__NR_utimensat, sys_utimensat_time32)
-#define __NR_signalfd 349
-__SYSCALL(__NR_signalfd, compat_sys_signalfd)
-#define __NR_timerfd_create 350
-__SYSCALL(__NR_timerfd_create, sys_timerfd_create)
-#define __NR_eventfd 351
-__SYSCALL(__NR_eventfd, sys_eventfd)
-#define __NR_fallocate 352
-__SYSCALL(__NR_fallocate, compat_sys_aarch32_fallocate)
-#define __NR_timerfd_settime 353
-__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime32)
-#define __NR_timerfd_gettime 354
-__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime32)
-#define __NR_signalfd4 355
-__SYSCALL(__NR_signalfd4, compat_sys_signalfd4)
-#define __NR_eventfd2 356
-__SYSCALL(__NR_eventfd2, sys_eventfd2)
-#define __NR_epoll_create1 357
-__SYSCALL(__NR_epoll_create1, sys_epoll_create1)
-#define __NR_dup3 358
-__SYSCALL(__NR_dup3, sys_dup3)
-#define __NR_pipe2 359
-__SYSCALL(__NR_pipe2, sys_pipe2)
-#define __NR_inotify_init1 360
-__SYSCALL(__NR_inotify_init1, sys_inotify_init1)
-#define __NR_preadv 361
-__SYSCALL(__NR_preadv, compat_sys_preadv)
-#define __NR_pwritev 362
-__SYSCALL(__NR_pwritev, compat_sys_pwritev)
-#define __NR_rt_tgsigqueueinfo 363
-__SYSCALL(__NR_rt_tgsigqueueinfo, compat_sys_rt_tgsigqueueinfo)
-#define __NR_perf_event_open 364
-__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
-#define __NR_recvmmsg 365
-__SYSCALL(__NR_recvmmsg, compat_sys_recvmmsg_time32)
-#define __NR_accept4 366
-__SYSCALL(__NR_accept4, sys_accept4)
-#define __NR_fanotify_init 367
-__SYSCALL(__NR_fanotify_init, sys_fanotify_init)
-#define __NR_fanotify_mark 368
-__SYSCALL(__NR_fanotify_mark, compat_sys_fanotify_mark)
-#define __NR_prlimit64 369
-__SYSCALL(__NR_prlimit64, sys_prlimit64)
-#define __NR_name_to_handle_at 370
-__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
-#define __NR_open_by_handle_at 371
-__SYSCALL(__NR_open_by_handle_at, compat_sys_open_by_handle_at)
-#define __NR_clock_adjtime 372
-__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime32)
-#define __NR_syncfs 373
-__SYSCALL(__NR_syncfs, sys_syncfs)
-#define __NR_sendmmsg 374
-__SYSCALL(__NR_sendmmsg, compat_sys_sendmmsg)
-#define __NR_setns 375
-__SYSCALL(__NR_setns, sys_setns)
-#define __NR_process_vm_readv 376
-__SYSCALL(__NR_process_vm_readv, sys_process_vm_readv)
-#define __NR_process_vm_writev 377
-__SYSCALL(__NR_process_vm_writev, sys_process_vm_writev)
-#define __NR_kcmp 378
-__SYSCALL(__NR_kcmp, sys_kcmp)
-#define __NR_finit_module 379
-__SYSCALL(__NR_finit_module, sys_finit_module)
-#define __NR_sched_setattr 380
-__SYSCALL(__NR_sched_setattr, sys_sched_setattr)
-#define __NR_sched_getattr 381
-__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
-#define __NR_renameat2 382
-__SYSCALL(__NR_renameat2, sys_renameat2)
-#define __NR_seccomp 383
-__SYSCALL(__NR_seccomp, sys_seccomp)
-#define __NR_getrandom 384
-__SYSCALL(__NR_getrandom, sys_getrandom)
-#define __NR_memfd_create 385
-__SYSCALL(__NR_memfd_create, sys_memfd_create)
-#define __NR_bpf 386
-__SYSCALL(__NR_bpf, sys_bpf)
-#define __NR_execveat 387
-__SYSCALL(__NR_execveat, compat_sys_execveat)
-#define __NR_userfaultfd 388
-__SYSCALL(__NR_userfaultfd, sys_userfaultfd)
-#define __NR_membarrier 389
-__SYSCALL(__NR_membarrier, sys_membarrier)
-#define __NR_mlock2 390
-__SYSCALL(__NR_mlock2, sys_mlock2)
-#define __NR_copy_file_range 391
-__SYSCALL(__NR_copy_file_range, sys_copy_file_range)
-#define __NR_preadv2 392
-__SYSCALL(__NR_preadv2, compat_sys_preadv2)
-#define __NR_pwritev2 393
-__SYSCALL(__NR_pwritev2, compat_sys_pwritev2)
-#define __NR_pkey_mprotect 394
-__SYSCALL(__NR_pkey_mprotect, sys_pkey_mprotect)
-#define __NR_pkey_alloc 395
-__SYSCALL(__NR_pkey_alloc, sys_pkey_alloc)
-#define __NR_pkey_free 396
-__SYSCALL(__NR_pkey_free, sys_pkey_free)
-#define __NR_statx 397
-__SYSCALL(__NR_statx, sys_statx)
-#define __NR_rseq 398
-__SYSCALL(__NR_rseq, sys_rseq)
-#define __NR_io_pgetevents 399
-__SYSCALL(__NR_io_pgetevents, compat_sys_io_pgetevents)
-#define __NR_migrate_pages 400
-__SYSCALL(__NR_migrate_pages, sys_migrate_pages)
-#define __NR_kexec_file_load 401
-__SYSCALL(__NR_kexec_file_load, sys_kexec_file_load)
-/* 402 is unused */
-#define __NR_clock_gettime64 403
-__SYSCALL(__NR_clock_gettime64, sys_clock_gettime)
-#define __NR_clock_settime64 404
-__SYSCALL(__NR_clock_settime64, sys_clock_settime)
-#define __NR_clock_adjtime64 405
-__SYSCALL(__NR_clock_adjtime64, sys_clock_adjtime)
-#define __NR_clock_getres_time64 406
-__SYSCALL(__NR_clock_getres_time64, sys_clock_getres)
-#define __NR_clock_nanosleep_time64 407
-__SYSCALL(__NR_clock_nanosleep_time64, sys_clock_nanosleep)
-#define __NR_timer_gettime64 408
-__SYSCALL(__NR_timer_gettime64, sys_timer_gettime)
-#define __NR_timer_settime64 409
-__SYSCALL(__NR_timer_settime64, sys_timer_settime)
-#define __NR_timerfd_gettime64 410
-__SYSCALL(__NR_timerfd_gettime64, sys_timerfd_gettime)
-#define __NR_timerfd_settime64 411
-__SYSCALL(__NR_timerfd_settime64, sys_timerfd_settime)
-#define __NR_utimensat_time64 412
-__SYSCALL(__NR_utimensat_time64, sys_utimensat)
-#define __NR_pselect6_time64 413
-__SYSCALL(__NR_pselect6_time64, compat_sys_pselect6_time64)
-#define __NR_ppoll_time64 414
-__SYSCALL(__NR_ppoll_time64, compat_sys_ppoll_time64)
-#define __NR_io_pgetevents_time64 416
-__SYSCALL(__NR_io_pgetevents_time64, compat_sys_io_pgetevents_time64)
-#define __NR_recvmmsg_time64 417
-__SYSCALL(__NR_recvmmsg_time64, compat_sys_recvmmsg_time64)
-#define __NR_mq_timedsend_time64 418
-__SYSCALL(__NR_mq_timedsend_time64, sys_mq_timedsend)
-#define __NR_mq_timedreceive_time64 419
-__SYSCALL(__NR_mq_timedreceive_time64, sys_mq_timedreceive)
-#define __NR_semtimedop_time64 420
-__SYSCALL(__NR_semtimedop_time64, sys_semtimedop)
-#define __NR_rt_sigtimedwait_time64 421
-__SYSCALL(__NR_rt_sigtimedwait_time64, compat_sys_rt_sigtimedwait_time64)
-#define __NR_futex_time64 422
-__SYSCALL(__NR_futex_time64, sys_futex)
-#define __NR_sched_rr_get_interval_time64 423
-__SYSCALL(__NR_sched_rr_get_interval_time64, sys_sched_rr_get_interval)
-#define __NR_pidfd_send_signal 424
-__SYSCALL(__NR_pidfd_send_signal, sys_pidfd_send_signal)
-#define __NR_io_uring_setup 425
-__SYSCALL(__NR_io_uring_setup, sys_io_uring_setup)
-#define __NR_io_uring_enter 426
-__SYSCALL(__NR_io_uring_enter, sys_io_uring_enter)
-#define __NR_io_uring_register 427
-__SYSCALL(__NR_io_uring_register, sys_io_uring_register)
-#define __NR_open_tree 428
-__SYSCALL(__NR_open_tree, sys_open_tree)
-#define __NR_move_mount 429
-__SYSCALL(__NR_move_mount, sys_move_mount)
-#define __NR_fsopen 430
-__SYSCALL(__NR_fsopen, sys_fsopen)
-#define __NR_fsconfig 431
-__SYSCALL(__NR_fsconfig, sys_fsconfig)
-#define __NR_fsmount 432
-__SYSCALL(__NR_fsmount, sys_fsmount)
-#define __NR_fspick 433
-__SYSCALL(__NR_fspick, sys_fspick)
-#define __NR_pidfd_open 434
-__SYSCALL(__NR_pidfd_open, sys_pidfd_open)
-#define __NR_clone3 435
-__SYSCALL(__NR_clone3, sys_clone3)
-#define __NR_close_range 436
-__SYSCALL(__NR_close_range, sys_close_range)
-#define __NR_openat2 437
-__SYSCALL(__NR_openat2, sys_openat2)
-#define __NR_pidfd_getfd 438
-__SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
-#define __NR_faccessat2 439
-__SYSCALL(__NR_faccessat2, sys_faccessat2)
-#define __NR_process_madvise 440
-__SYSCALL(__NR_process_madvise, sys_process_madvise)
-#define __NR_epoll_pwait2 441
-__SYSCALL(__NR_epoll_pwait2, compat_sys_epoll_pwait2)
-#define __NR_mount_setattr 442
-__SYSCALL(__NR_mount_setattr, sys_mount_setattr)
-#define __NR_quotactl_fd 443
-__SYSCALL(__NR_quotactl_fd, sys_quotactl_fd)
-#define __NR_landlock_create_ruleset 444
-__SYSCALL(__NR_landlock_create_ruleset, sys_landlock_create_ruleset)
-#define __NR_landlock_add_rule 445
-__SYSCALL(__NR_landlock_add_rule, sys_landlock_add_rule)
-#define __NR_landlock_restrict_self 446
-__SYSCALL(__NR_landlock_restrict_self, sys_landlock_restrict_self)
-#define __NR_process_mrelease 448
-__SYSCALL(__NR_process_mrelease, sys_process_mrelease)
-#define __NR_futex_waitv 449
-__SYSCALL(__NR_futex_waitv, sys_futex_waitv)
-#define __NR_set_mempolicy_home_node 450
-__SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)
-#define __NR_cachestat 451
-__SYSCALL(__NR_cachestat, sys_cachestat)
-#define __NR_fchmodat2 452
-__SYSCALL(__NR_fchmodat2, sys_fchmodat2)
-#define __NR_map_shadow_stack 453
-__SYSCALL(__NR_map_shadow_stack, sys_map_shadow_stack)
-#define __NR_futex_wake 454
-__SYSCALL(__NR_futex_wake, sys_futex_wake)
-#define __NR_futex_wait 455
-__SYSCALL(__NR_futex_wait, sys_futex_wait)
-#define __NR_futex_requeue 456
-__SYSCALL(__NR_futex_requeue, sys_futex_requeue)
-#define __NR_statmount 457
-__SYSCALL(__NR_statmount, sys_statmount)
-#define __NR_listmount 458
-__SYSCALL(__NR_listmount, sys_listmount)
-#define __NR_lsm_get_self_attr 459
-__SYSCALL(__NR_lsm_get_self_attr, sys_lsm_get_self_attr)
-#define __NR_lsm_set_self_attr 460
-__SYSCALL(__NR_lsm_set_self_attr, sys_lsm_set_self_attr)
-#define __NR_lsm_list_modules 461
-__SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules)
-#define __NR_mseal 462
-__SYSCALL(__NR_mseal, sys_mseal)
+#define __NR_sync_file_range2 __NR_arm_sync_file_range
-/*
- * Please add new compat syscalls above this comment and update
- * __NR_compat_syscalls in asm/unistd.h.
- */
+#endif /* _UAPI__ASM_ARM_UNISTD_H */
diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
index ecb6fd4c3c64..778c1202bbbf 100644
--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -8,7 +8,7 @@
#ifndef __ASSEMBLY__
#include <asm/barrier.h>
-#include <asm/unistd.h>
+#include <asm/unistd_compat_32.h>
#include <asm/errno.h>
#include <asm/vdso/compat_barrier.h>
@@ -24,7 +24,7 @@ int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
register struct timezone *tz asm("r1") = _tz;
register struct __kernel_old_timeval *tv asm("r0") = _tv;
register long ret asm ("r0");
- register long nr asm("r7") = __NR_compat_gettimeofday;
+ register long nr asm("r7") = __NR_compat32_gettimeofday;
asm volatile(
" swi #0\n"
@@ -41,7 +41,7 @@ long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
register struct __kernel_timespec *ts asm("r1") = _ts;
register clockid_t clkid asm("r0") = _clkid;
register long ret asm ("r0");
- register long nr asm("r7") = __NR_compat_clock_gettime64;
+ register long nr asm("r7") = __NR_compat32_clock_gettime64;
asm volatile(
" swi #0\n"
@@ -58,7 +58,7 @@ long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
register struct old_timespec32 *ts asm("r1") = _ts;
register clockid_t clkid asm("r0") = _clkid;
register long ret asm ("r0");
- register long nr asm("r7") = __NR_compat_clock_gettime;
+ register long nr asm("r7") = __NR_compat32_clock_gettime;
asm volatile(
" swi #0\n"
@@ -75,7 +75,7 @@ int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
register struct __kernel_timespec *ts asm("r1") = _ts;
register clockid_t clkid asm("r0") = _clkid;
register long ret asm ("r0");
- register long nr asm("r7") = __NR_compat_clock_getres_time64;
+ register long nr asm("r7") = __NR_compat32_clock_getres_time64;
asm volatile(
" swi #0\n"
@@ -92,7 +92,7 @@ int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
register struct old_timespec32 *ts asm("r1") = _ts;
register clockid_t clkid asm("r0") = _clkid;
register long ret asm ("r0");
- register long nr asm("r7") = __NR_compat_clock_getres;
+ register long nr asm("r7") = __NR_compat32_clock_getres;
asm volatile(
" swi #0\n"
diff --git a/arch/arm64/include/asm/word-at-a-time.h b/arch/arm64/include/asm/word-at-a-time.h
index 14251abee23c..824ca6987a51 100644
--- a/arch/arm64/include/asm/word-at-a-time.h
+++ b/arch/arm64/include/asm/word-at-a-time.h
@@ -27,20 +27,15 @@ static inline unsigned long has_zero(unsigned long a, unsigned long *bits,
}
#define prep_zero_mask(a, bits, c) (bits)
+#define create_zero_mask(bits) (bits)
+#define find_zero(bits) (__ffs(bits) >> 3)
-static inline unsigned long create_zero_mask(unsigned long bits)
+static inline unsigned long zero_bytemask(unsigned long bits)
{
bits = (bits - 1) & ~bits;
return bits >> 7;
}
-static inline unsigned long find_zero(unsigned long mask)
-{
- return fls64(mask) >> 3;
-}
-
-#define zero_bytemask(mask) (mask)
-
#else /* __AARCH64EB__ */
#include <asm-generic/word-at-a-time.h>
#endif
diff --git a/arch/arm64/include/uapi/asm/Kbuild b/arch/arm64/include/uapi/asm/Kbuild
index 602d137932dc..c6d141d7b7d7 100644
--- a/arch/arm64/include/uapi/asm/Kbuild
+++ b/arch/arm64/include/uapi/asm/Kbuild
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += unistd_64.h
generic-y += kvm_para.h
diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h
index ce2ee8f1e361..df36f23876e8 100644
--- a/arch/arm64/include/uapi/asm/unistd.h
+++ b/arch/arm64/include/uapi/asm/unistd.h
@@ -1,25 +1,2 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define __ARCH_WANT_RENAMEAT
-#define __ARCH_WANT_NEW_STAT
-#define __ARCH_WANT_SET_GET_RLIMIT
-#define __ARCH_WANT_TIME32_SYSCALLS
-#define __ARCH_WANT_SYS_CLONE3
-#define __ARCH_WANT_MEMFD_SECRET
-
-#include <asm-generic/unistd.h>
+#include <asm/unistd_64.h>
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 763824963ed1..2b112f3b7510 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -46,7 +46,6 @@ obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
obj-$(CONFIG_HARDLOCKUP_DETECTOR_PERF) += watchdog_hld.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_EFI) += efi.o efi-rt-wrapper.o
diff --git a/arch/arm64/kernel/Makefile.syscalls b/arch/arm64/kernel/Makefile.syscalls
new file mode 100644
index 000000000000..3cfafd003b2d
--- /dev/null
+++ b/arch/arm64/kernel/Makefile.syscalls
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+syscall_abis_32 +=
+syscall_abis_64 += renameat newstat rlimit memfd_secret
+
+syscalltbl = arch/arm64/tools/syscall_%.tbl
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index e0e7b93c16cc..e6f66491fbe9 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -30,6 +30,7 @@
#include <linux/pgtable.h>
#include <acpi/ghes.h>
+#include <acpi/processor.h>
#include <asm/cputype.h>
#include <asm/cpu_ops.h>
#include <asm/daifflags.h>
@@ -45,6 +46,7 @@ EXPORT_SYMBOL(acpi_pci_disabled);
static bool param_acpi_off __initdata;
static bool param_acpi_on __initdata;
static bool param_acpi_force __initdata;
+static bool param_acpi_nospcr __initdata;
static int __init parse_acpi(char *arg)
{
@@ -58,6 +60,8 @@ static int __init parse_acpi(char *arg)
param_acpi_on = true;
else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */
param_acpi_force = true;
+ else if (strcmp(arg, "nospcr") == 0) /* disable SPCR as default console */
+ param_acpi_nospcr = true;
else
return -EINVAL; /* Core will print when we return error */
@@ -237,7 +241,20 @@ done:
acpi_put_table(facs);
}
#endif
- acpi_parse_spcr(earlycon_acpi_spcr_enable, true);
+
+ /*
+ * For varying privacy and security reasons, sometimes need
+ * to completely silence the serial console output, and only
+ * enable it when needed.
+ * But there are many existing systems that depend on this
+ * behaviour, use acpi=nospcr to disable console in ACPI SPCR
+ * table as default serial console.
+ */
+ acpi_parse_spcr(earlycon_acpi_spcr_enable,
+ !param_acpi_nospcr);
+ pr_info("Use ACPI SPCR as default console: %s\n",
+ param_acpi_nospcr ? "No" : "Yes");
+
if (IS_ENABLED(CONFIG_ACPI_BGRT))
acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
}
@@ -423,107 +440,23 @@ void arch_reserve_mem_area(acpi_physical_address addr, size_t size)
memblock_mark_nomap(addr, size);
}
-#ifdef CONFIG_ACPI_FFH
-/*
- * Implements ARM64 specific callbacks to support ACPI FFH Operation Region as
- * specified in https://developer.arm.com/docs/den0048/latest
- */
-struct acpi_ffh_data {
- struct acpi_ffh_info info;
- void (*invoke_ffh_fn)(unsigned long a0, unsigned long a1,
- unsigned long a2, unsigned long a3,
- unsigned long a4, unsigned long a5,
- unsigned long a6, unsigned long a7,
- struct arm_smccc_res *args,
- struct arm_smccc_quirk *res);
- void (*invoke_ffh64_fn)(const struct arm_smccc_1_2_regs *args,
- struct arm_smccc_1_2_regs *res);
-};
-
-int acpi_ffh_address_space_arch_setup(void *handler_ctxt, void **region_ctxt)
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 apci_id,
+ int *pcpu)
{
- enum arm_smccc_conduit conduit;
- struct acpi_ffh_data *ffh_ctxt;
-
- if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
- return -EOPNOTSUPP;
-
- conduit = arm_smccc_1_1_get_conduit();
- if (conduit == SMCCC_CONDUIT_NONE) {
- pr_err("%s: invalid SMCCC conduit\n", __func__);
- return -EOPNOTSUPP;
+ /* If an error code is passed in this stub can't fix it */
+ if (*pcpu < 0) {
+ pr_warn_once("Unable to map CPU to valid ID\n");
+ return *pcpu;
}
- ffh_ctxt = kzalloc(sizeof(*ffh_ctxt), GFP_KERNEL);
- if (!ffh_ctxt)
- return -ENOMEM;
-
- if (conduit == SMCCC_CONDUIT_SMC) {
- ffh_ctxt->invoke_ffh_fn = __arm_smccc_smc;
- ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_smc;
- } else {
- ffh_ctxt->invoke_ffh_fn = __arm_smccc_hvc;
- ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_hvc;
- }
-
- memcpy(ffh_ctxt, handler_ctxt, sizeof(ffh_ctxt->info));
-
- *region_ctxt = ffh_ctxt;
- return AE_OK;
-}
-
-static bool acpi_ffh_smccc_owner_allowed(u32 fid)
-{
- int owner = ARM_SMCCC_OWNER_NUM(fid);
-
- if (owner == ARM_SMCCC_OWNER_STANDARD ||
- owner == ARM_SMCCC_OWNER_SIP || owner == ARM_SMCCC_OWNER_OEM)
- return true;
-
- return false;
+ return 0;
}
+EXPORT_SYMBOL(acpi_map_cpu);
-int acpi_ffh_address_space_arch_handler(acpi_integer *value, void *region_context)
+int acpi_unmap_cpu(int cpu)
{
- int ret = 0;
- struct acpi_ffh_data *ffh_ctxt = region_context;
-
- if (ffh_ctxt->info.offset == 0) {
- /* SMC/HVC 32bit call */
- struct arm_smccc_res res;
- u32 a[8] = { 0 }, *ptr = (u32 *)value;
-
- if (!ARM_SMCCC_IS_FAST_CALL(*ptr) || ARM_SMCCC_IS_64(*ptr) ||
- !acpi_ffh_smccc_owner_allowed(*ptr) ||
- ffh_ctxt->info.length > 32) {
- ret = AE_ERROR;
- } else {
- int idx, len = ffh_ctxt->info.length >> 2;
-
- for (idx = 0; idx < len; idx++)
- a[idx] = *(ptr + idx);
-
- ffh_ctxt->invoke_ffh_fn(a[0], a[1], a[2], a[3], a[4],
- a[5], a[6], a[7], &res, NULL);
- memcpy(value, &res, sizeof(res));
- }
-
- } else if (ffh_ctxt->info.offset == 1) {
- /* SMC/HVC 64bit call */
- struct arm_smccc_1_2_regs *r = (struct arm_smccc_1_2_regs *)value;
-
- if (!ARM_SMCCC_IS_FAST_CALL(r->a0) || !ARM_SMCCC_IS_64(r->a0) ||
- !acpi_ffh_smccc_owner_allowed(r->a0) ||
- ffh_ctxt->info.length > sizeof(*r)) {
- ret = AE_ERROR;
- } else {
- ffh_ctxt->invoke_ffh64_fn(r, r);
- memcpy(value, r, ffh_ctxt->info.length);
- }
- } else {
- ret = AE_ERROR;
- }
-
- return ret;
+ return 0;
}
-#endif /* CONFIG_ACPI_FFH */
+EXPORT_SYMBOL(acpi_unmap_cpu);
+#endif /* CONFIG_ACPI_HOTPLUG_CPU */
diff --git a/arch/arm64/kernel/acpi_numa.c b/arch/arm64/kernel/acpi_numa.c
index e51535a5f939..0c036a9a3c33 100644
--- a/arch/arm64/kernel/acpi_numa.c
+++ b/arch/arm64/kernel/acpi_numa.c
@@ -34,17 +34,6 @@ int __init acpi_numa_get_nid(unsigned int cpu)
return acpi_early_node_map[cpu];
}
-static inline int get_cpu_for_acpi_id(u32 uid)
-{
- int cpu;
-
- for (cpu = 0; cpu < nr_cpu_ids; cpu++)
- if (uid == get_acpi_id_for_cpu(cpu))
- return cpu;
-
- return -EINVAL;
-}
-
static int __init acpi_parse_gicc_pxm(union acpi_subtable_headers *header,
const unsigned long end)
{
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 828be635e7e1..617424b73f8c 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -432,14 +432,17 @@ static const struct midr_range erratum_spec_unpriv_load_list[] = {
};
#endif
-#ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_SSBS
-static const struct midr_range erratum_spec_ssbs_list[] = {
#ifdef CONFIG_ARM64_ERRATUM_3194386
+static const struct midr_range erratum_spec_ssbs_list[] = {
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A720),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_X3),
MIDR_ALL_VERSIONS(MIDR_CORTEX_X4),
-#endif
-#ifdef CONFIG_ARM64_ERRATUM_3312417
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_X925),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3),
-#endif
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
{}
};
#endif
@@ -741,9 +744,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
MIDR_FIXED(MIDR_CPU_VAR_REV(1,1), BIT(25)),
},
#endif
-#ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_SSBS
+#ifdef CONFIG_ARM64_ERRATUM_3194386
{
- .desc = "ARM errata 3194386, 3312417",
+ .desc = "SSBS not fully self-synchronizing",
.capability = ARM64_WORKAROUND_SPECULATIVE_SSBS,
ERRATA_MIDR_RANGE_LIST(erratum_spec_ssbs_list),
},
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 48e7029f1054..646ecd3069fd 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -285,8 +285,8 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_FP_SHIFT, 4, ID_AA64PFR0_EL1_FP_NI),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL3_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL2_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL1_SHIFT, 4, ID_AA64PFR0_EL1_ELx_64BIT_ONLY),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL0_SHIFT, 4, ID_AA64PFR0_EL1_ELx_64BIT_ONLY),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL1_SHIFT, 4, ID_AA64PFR0_EL1_EL1_IMP),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL0_SHIFT, 4, ID_AA64PFR0_EL1_EL0_IMP),
ARM64_FTR_END,
};
@@ -429,6 +429,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
};
static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_ECBHB_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_TIDCP1_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_AFP_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_HCX_SHIFT, 4, 0),
diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index ba4f8f7d6a91..8f5422ed1b75 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -105,11 +105,6 @@ KVM_NVHE_ALIAS(__hyp_stub_vectors);
KVM_NVHE_ALIAS(vgic_v2_cpuif_trap);
KVM_NVHE_ALIAS(vgic_v3_cpuif_trap);
-#ifdef CONFIG_ARM64_PSEUDO_NMI
-/* Static key checked in GIC_PRIO_IRQOFF. */
-KVM_NVHE_ALIAS(gic_nonsecure_priorities);
-#endif
-
/* EL2 exception handling */
KVM_NVHE_ALIAS(__start___kvm_ex_table);
KVM_NVHE_ALIAS(__stop___kvm_ex_table);
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index dcdcccd40891..6174671be7c1 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -582,12 +582,9 @@ subsys_initcall(register_mte_tcf_preferred_sysctl);
size_t mte_probe_user_range(const char __user *uaddr, size_t size)
{
const char __user *end = uaddr + size;
- int err = 0;
char val;
- __raw_get_user(val, uaddr, err);
- if (err)
- return size;
+ __raw_get_user(val, uaddr, efault);
uaddr = PTR_ALIGN(uaddr, MTE_GRANULE_SIZE);
while (uaddr < end) {
@@ -595,12 +592,13 @@ size_t mte_probe_user_range(const char __user *uaddr, size_t size)
* A read is sufficient for mte, the caller should have probed
* for the pte write permission if required.
*/
- __raw_get_user(val, uaddr, err);
- if (err)
- return end - uaddr;
+ __raw_get_user(val, uaddr, efault);
uaddr += MTE_GRANULE_SIZE;
}
(void)val;
return 0;
+
+efault:
+ return end - uaddr;
}
diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c
index baca47bd443c..da53722f95d4 100644
--- a/arch/arm64/kernel/proton-pack.c
+++ b/arch/arm64/kernel/proton-pack.c
@@ -567,7 +567,7 @@ static enum mitigation_state spectre_v4_enable_hw_mitigation(void)
* Mitigate this with an unconditional speculation barrier, as CPUs
* could mis-speculate branches and bypass a conditional barrier.
*/
- if (IS_ENABLED(CONFIG_ARM64_WORKAROUND_SPECULATIVE_SSBS))
+ if (IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386))
spec_bar();
return SPECTRE_MITIGATED;
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 29a8e444db83..fabd732d0a2d 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -40,7 +40,7 @@ static int cpu_psci_cpu_boot(unsigned int cpu)
{
phys_addr_t pa_secondary_entry = __pa_symbol(secondary_entry);
int err = psci_ops.cpu_on(cpu_logical_map(cpu), pa_secondary_entry);
- if (err)
+ if (err && err != -EPERM)
pr_err("failed to boot CPU%d (%d)\n", cpu, err);
return err;
diff --git a/arch/arm64/kernel/reloc_test_core.c b/arch/arm64/kernel/reloc_test_core.c
index 99f2ffe9fc05..5b0891146054 100644
--- a/arch/arm64/kernel/reloc_test_core.c
+++ b/arch/arm64/kernel/reloc_test_core.c
@@ -74,4 +74,5 @@ static void __exit reloc_test_exit(void)
module_init(reloc_test_init);
module_exit(reloc_test_exit);
+MODULE_DESCRIPTION("Relocation testing module");
MODULE_LICENSE("GPL v2");
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index bbd542704730..81e798b6dada 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -17,7 +17,7 @@
#include <asm/signal32.h>
#include <asm/traps.h>
#include <linux/uaccess.h>
-#include <asm/unistd.h>
+#include <asm/unistd_compat_32.h>
#include <asm/vdso.h>
struct compat_vfp_sigframe {
@@ -451,7 +451,7 @@ int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
void compat_setup_restart_syscall(struct pt_regs *regs)
{
- regs->regs[7] = __NR_compat_restart_syscall;
+ regs->regs[7] = __NR_compat32_restart_syscall;
}
/*
diff --git a/arch/arm64/kernel/sigreturn32.S b/arch/arm64/kernel/sigreturn32.S
index ccbd4aab4ba4..6f486b95b413 100644
--- a/arch/arm64/kernel/sigreturn32.S
+++ b/arch/arm64/kernel/sigreturn32.S
@@ -13,7 +13,7 @@
* need two 16-bit instructions.
*/
-#include <asm/unistd.h>
+#include <asm/unistd_compat_32.h>
.section .rodata
.globl __aarch32_sigret_code_start
@@ -22,26 +22,26 @@ __aarch32_sigret_code_start:
/*
* ARM Code
*/
- .byte __NR_compat_sigreturn, 0x70, 0xa0, 0xe3 // mov r7, #__NR_compat_sigreturn
- .byte __NR_compat_sigreturn, 0x00, 0x00, 0xef // svc #__NR_compat_sigreturn
+ .byte __NR_compat32_sigreturn, 0x70, 0xa0, 0xe3 // mov r7, #__NR_compat32_sigreturn
+ .byte __NR_compat32_sigreturn, 0x00, 0x00, 0xef // svc #__NR_compat32_sigreturn
/*
* Thumb code
*/
- .byte __NR_compat_sigreturn, 0x27 // svc #__NR_compat_sigreturn
- .byte __NR_compat_sigreturn, 0xdf // mov r7, #__NR_compat_sigreturn
+ .byte __NR_compat32_sigreturn, 0x27 // svc #__NR_compat32_sigreturn
+ .byte __NR_compat32_sigreturn, 0xdf // mov r7, #__NR_compat32_sigreturn
/*
* ARM code
*/
- .byte __NR_compat_rt_sigreturn, 0x70, 0xa0, 0xe3 // mov r7, #__NR_compat_rt_sigreturn
- .byte __NR_compat_rt_sigreturn, 0x00, 0x00, 0xef // svc #__NR_compat_rt_sigreturn
+ .byte __NR_compat32_rt_sigreturn, 0x70, 0xa0, 0xe3 // mov r7, #__NR_compat32_rt_sigreturn
+ .byte __NR_compat32_rt_sigreturn, 0x00, 0x00, 0xef // svc #__NR_compat32_rt_sigreturn
/*
* Thumb code
*/
- .byte __NR_compat_rt_sigreturn, 0x27 // svc #__NR_compat_rt_sigreturn
- .byte __NR_compat_rt_sigreturn, 0xdf // mov r7, #__NR_compat_rt_sigreturn
+ .byte __NR_compat32_rt_sigreturn, 0x27 // svc #__NR_compat32_rt_sigreturn
+ .byte __NR_compat32_rt_sigreturn, 0xdf // mov r7, #__NR_compat32_rt_sigreturn
.globl __aarch32_sigret_code_end
__aarch32_sigret_code_end:
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 31c8b3094dd7..5e18fbcee9a2 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -55,9 +55,6 @@
#include <trace/events/ipi.h>
-DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number);
-EXPORT_PER_CPU_SYMBOL(cpu_number);
-
/*
* as from 2.5, kernels no longer have an init_tasks structure
* so we need some other way of telling a new secondary core
@@ -132,7 +129,8 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
/* Now bring the CPU into our world */
ret = boot_secondary(cpu, idle);
if (ret) {
- pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
+ if (ret != -EPERM)
+ pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
return ret;
}
@@ -510,6 +508,59 @@ static int __init smp_cpu_setup(int cpu)
static bool bootcpu_valid __initdata;
static unsigned int cpu_count = 1;
+int arch_register_cpu(int cpu)
+{
+ acpi_handle acpi_handle = acpi_get_processor_handle(cpu);
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+ if (!acpi_disabled && !acpi_handle &&
+ IS_ENABLED(CONFIG_ACPI_HOTPLUG_CPU))
+ return -EPROBE_DEFER;
+
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+ /* For now block anything that looks like physical CPU Hotplug */
+ if (invalid_logical_cpuid(cpu) || !cpu_present(cpu)) {
+ pr_err_once("Changing CPU present bit is not supported\n");
+ return -ENODEV;
+ }
+#endif
+
+ /*
+ * Availability of the acpi handle is sufficient to establish
+ * that _STA has aleady been checked. No need to recheck here.
+ */
+ c->hotpluggable = arch_cpu_is_hotpluggable(cpu);
+
+ return register_cpu(c, cpu);
+}
+
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+void arch_unregister_cpu(int cpu)
+{
+ acpi_handle acpi_handle = acpi_get_processor_handle(cpu);
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+ acpi_status status;
+ unsigned long long sta;
+
+ if (!acpi_handle) {
+ pr_err_once("Removing a CPU without associated ACPI handle\n");
+ return;
+ }
+
+ status = acpi_evaluate_integer(acpi_handle, "_STA", NULL, &sta);
+ if (ACPI_FAILURE(status))
+ return;
+
+ /* For now do not allow anything that looks like physical CPU HP */
+ if (cpu_present(cpu) && !(sta & ACPI_STA_DEVICE_PRESENT)) {
+ pr_err_once("Changing CPU present bit is not supported\n");
+ return;
+ }
+
+ unregister_cpu(c);
+}
+#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+
#ifdef CONFIG_ACPI
static struct acpi_madt_generic_interrupt cpu_madt_gicc[NR_CPUS];
@@ -530,7 +581,8 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
{
u64 hwid = processor->arm_mpidr;
- if (!acpi_gicc_is_usable(processor)) {
+ if (!(processor->flags &
+ (ACPI_MADT_ENABLED | ACPI_MADT_GICC_ONLINE_CAPABLE))) {
pr_debug("skipping disabled CPU entry with 0x%llx MPIDR\n", hwid);
return;
}
@@ -749,8 +801,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
*/
for_each_possible_cpu(cpu) {
- per_cpu(cpu_number, cpu) = cpu;
-
if (cpu == smp_processor_id())
continue;
@@ -767,13 +817,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
}
-static const char *ipi_types[NR_IPI] __tracepoint_string = {
+static const char *ipi_types[MAX_IPI] __tracepoint_string = {
[IPI_RESCHEDULE] = "Rescheduling interrupts",
[IPI_CALL_FUNC] = "Function call interrupts",
[IPI_CPU_STOP] = "CPU stop interrupts",
[IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts",
[IPI_TIMER] = "Timer broadcast interrupts",
[IPI_IRQ_WORK] = "IRQ work interrupts",
+ [IPI_CPU_BACKTRACE] = "CPU backtrace interrupts",
+ [IPI_KGDB_ROUNDUP] = "KGDB roundup interrupts",
};
static void smp_cross_call(const struct cpumask *target, unsigned int ipinr);
@@ -784,7 +836,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
{
unsigned int cpu, i;
- for (i = 0; i < NR_IPI; i++) {
+ for (i = 0; i < MAX_IPI; i++) {
seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
prec >= 4 ? " " : "");
for_each_online_cpu(cpu)
@@ -1028,12 +1080,12 @@ void __init set_smp_ipi_range(int ipi_base, int n)
if (ipi_should_be_nmi(i)) {
err = request_percpu_nmi(ipi_base + i, ipi_handler,
- "IPI", &cpu_number);
+ "IPI", &irq_stat);
WARN(err, "Could not request IPI %d as NMI, err=%d\n",
i, err);
} else {
err = request_percpu_irq(ipi_base + i, ipi_handler,
- "IPI", &cpu_number);
+ "IPI", &irq_stat);
WARN(err, "Could not request IPI %d as IRQ, err=%d\n",
i, err);
}
diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c
index d5ffaaab31a7..f08408b6e826 100644
--- a/arch/arm64/kernel/sys.c
+++ b/arch/arm64/kernel/sys.c
@@ -48,14 +48,16 @@ asmlinkage long __arm64_sys_ni_syscall(const struct pt_regs *__unused)
*/
#define __arm64_sys_personality __arm64_sys_arm64_personality
+#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
+
#undef __SYSCALL
#define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *);
-#include <asm/unistd.h>
+#include <asm/syscall_table_64.h>
#undef __SYSCALL
#define __SYSCALL(nr, sym) [nr] = __arm64_##sym,
const syscall_fn_t sys_call_table[__NR_syscalls] = {
[0 ... __NR_syscalls - 1] = __arm64_sys_ni_syscall,
-#include <asm/unistd.h>
+#include <asm/syscall_table_64.h>
};
diff --git a/arch/arm64/kernel/sys32.c b/arch/arm64/kernel/sys32.c
index fc40386afb1b..96bcfb907443 100644
--- a/arch/arm64/kernel/sys32.c
+++ b/arch/arm64/kernel/sys32.c
@@ -5,17 +5,12 @@
* Copyright (C) 2015 ARM Ltd.
*/
-/*
- * Needed to avoid conflicting __NR_* macros between uapi/asm/unistd.h and
- * asm/unistd32.h.
- */
-#define __COMPAT_SYSCALL_NR
-
#include <linux/compat.h>
#include <linux/compiler.h>
#include <linux/syscalls.h>
#include <asm/syscall.h>
+#include <asm/unistd_compat_32.h>
asmlinkage long compat_sys_sigreturn(void);
asmlinkage long compat_sys_rt_sigreturn(void);
@@ -122,14 +117,16 @@ COMPAT_SYSCALL_DEFINE6(aarch32_fallocate, int, fd, int, mode,
return ksys_fallocate(fd, mode, arg_u64(offset), arg_u64(len));
}
+#define __SYSCALL_WITH_COMPAT(nr, sym, compat) __SYSCALL(nr, compat)
+
#undef __SYSCALL
#define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *);
-#include <asm/unistd32.h>
+#include <asm/syscall_table_32.h>
#undef __SYSCALL
#define __SYSCALL(nr, sym) [nr] = __arm64_##sym,
-const syscall_fn_t compat_sys_call_table[__NR_compat_syscalls] = {
- [0 ... __NR_compat_syscalls - 1] = __arm64_sys_ni_syscall,
-#include <asm/unistd32.h>
+const syscall_fn_t compat_sys_call_table[__NR_compat32_syscalls] = {
+ [0 ... __NR_compat32_syscalls - 1] = __arm64_sys_ni_syscall,
+#include <asm/syscall_table_32.h>
};
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index 7230f6e20ab8..c442fcec6b9e 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -14,6 +14,7 @@
#include <asm/syscall.h>
#include <asm/thread_info.h>
#include <asm/unistd.h>
+#include <asm/unistd_compat_32.h>
long compat_arm_syscall(struct pt_regs *regs, int scno);
long sys_ni_syscall(void);
@@ -153,7 +154,7 @@ void do_el0_svc(struct pt_regs *regs)
#ifdef CONFIG_COMPAT
void do_el0_svc_compat(struct pt_regs *regs)
{
- el0_svc_common(regs, regs->regs[7], __NR_compat_syscalls,
+ el0_svc_common(regs, regs->regs[7], __NR_compat32_syscalls,
compat_sys_call_table);
}
#endif
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 755a22d4f840..55a8e310ea12 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -264,6 +264,9 @@ SECTIONS
EXIT_DATA
}
+ RUNTIME_CONST(shift, d_hash_shift)
+ RUNTIME_CONST(ptr, dentry_hashtable)
+
PERCPU_SECTION(L1_CACHE_BYTES)
HYPERVISOR_PERCPU_SECTION
diff --git a/arch/arm64/kvm/hyp/include/nvhe/fixed_config.h b/arch/arm64/kvm/hyp/include/nvhe/fixed_config.h
index 51f043649146..f957890c7e38 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/fixed_config.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/fixed_config.h
@@ -52,11 +52,11 @@
* Supported by KVM
*/
#define PVM_ID_AA64PFR0_RESTRICT_UNSIGNED (\
- FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0), ID_AA64PFR0_EL1_ELx_64BIT_ONLY) | \
- FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL1), ID_AA64PFR0_EL1_ELx_64BIT_ONLY) | \
- FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL2), ID_AA64PFR0_EL1_ELx_64BIT_ONLY) | \
- FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL3), ID_AA64PFR0_EL1_ELx_64BIT_ONLY) | \
- FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_RAS), ID_AA64PFR0_EL1_RAS_IMP) \
+ SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL0, IMP) | \
+ SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL1, IMP) | \
+ SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL2, IMP) | \
+ SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL3, IMP) | \
+ SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, RAS, IMP) \
)
/*
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 95cf18574251..187a5f4d56c0 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -33,9 +33,9 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
/* Protected KVM does not support AArch32 guests. */
BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
- PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) != ID_AA64PFR0_EL1_ELx_64BIT_ONLY);
+ PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) != ID_AA64PFR0_EL1_EL0_IMP);
BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL1),
- PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) != ID_AA64PFR0_EL1_ELx_64BIT_ONLY);
+ PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) != ID_AA64PFR0_EL1_EL1_IMP);
/*
* Linux guests assume support for floating-point and Advanced SIMD. Do
diff --git a/arch/arm64/kvm/hyp/nvhe/sys_regs.c b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
index edd969a1f36b..2860548d4250 100644
--- a/arch/arm64/kvm/hyp/nvhe/sys_regs.c
+++ b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
@@ -276,7 +276,7 @@ static bool pvm_access_id_aarch32(struct kvm_vcpu *vcpu,
* of AArch32 feature id registers.
*/
BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL1),
- PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) > ID_AA64PFR0_EL1_ELx_64BIT_ONLY);
+ PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) > ID_AA64PFR0_EL1_EL1_IMP);
return pvm_access_raz_wi(vcpu, p, r);
}
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index a35ce10e0a9f..d1a476b08f54 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -14,7 +14,6 @@
#include <asm/kvm_emulate.h>
#include <kvm/arm_pmu.h>
#include <kvm/arm_vgic.h>
-#include <asm/arm_pmuv3.h>
#define PERF_ATTR_CFG1_COUNTER_64BIT BIT(0)
diff --git a/arch/arm64/tools/Makefile b/arch/arm64/tools/Makefile
index fa2251d9762d..c2b34e761006 100644
--- a/arch/arm64/tools/Makefile
+++ b/arch/arm64/tools/Makefile
@@ -3,12 +3,16 @@
gen := arch/$(ARCH)/include/generated
kapi := $(gen)/asm
-kapi-hdrs-y := $(kapi)/cpucap-defs.h $(kapi)/sysreg-defs.h
+kapisyshdr-y := cpucap-defs.h sysreg-defs.h
+
+kapi-hdrs-y := $(addprefix $(kapi)/, $(kapisyshdr-y))
targets += $(addprefix ../../../, $(kapi-hdrs-y))
PHONY += kapi
+all: $(syscall64) kapi
+
kapi: $(kapi-hdrs-y)
quiet_cmd_gen_cpucaps = GEN $@
diff --git a/arch/arm64/tools/syscall_32.tbl b/arch/arm64/tools/syscall_32.tbl
new file mode 100644
index 000000000000..9a37930d4e26
--- /dev/null
+++ b/arch/arm64/tools/syscall_32.tbl
@@ -0,0 +1,476 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# AArch32 (compat) system call definitions.
+#
+# Copyright (C) 2001-2005 Russell King
+# Copyright (C) 2012 ARM Ltd.
+#
+# This file corresponds to arch/arm/tools/syscall.tbl
+# for the native EABI syscalls and should be kept in sync
+# Instead of the OABI syscalls, it contains pointers to
+# the compat entry points where they differ from the native
+# syscalls.
+#
+0 common restart_syscall sys_restart_syscall
+1 common exit sys_exit
+2 common fork sys_fork
+3 common read sys_read
+4 common write sys_write
+5 common open sys_open compat_sys_open
+6 common close sys_close
+# 7 was sys_waitpid
+8 common creat sys_creat
+9 common link sys_link
+10 common unlink sys_unlink
+11 common execve sys_execve compat_sys_execve
+12 common chdir sys_chdir
+# 13 was sys_time
+14 common mknod sys_mknod
+15 common chmod sys_chmod
+16 common lchown sys_lchown16
+# 17 was sys_break
+# 18 was sys_stat
+19 common lseek sys_lseek compat_sys_lseek
+20 common getpid sys_getpid
+21 common mount sys_mount
+# 22 was sys_umount
+23 common setuid sys_setuid16
+24 common getuid sys_getuid16
+# 25 was sys_stime
+26 common ptrace sys_ptrace compat_sys_ptrace
+# 27 was sys_alarm
+# 28 was sys_fstat
+29 common pause sys_pause
+# 30 was sys_utime
+# 31 was sys_stty
+# 32 was sys_gtty
+33 common access sys_access
+34 common nice sys_nice
+# 35 was sys_ftime
+36 common sync sys_sync
+37 common kill sys_kill
+38 common rename sys_rename
+39 common mkdir sys_mkdir
+40 common rmdir sys_rmdir
+41 common dup sys_dup
+42 common pipe sys_pipe
+43 common times sys_times compat_sys_times
+# 44 was sys_prof
+45 common brk sys_brk
+46 common setgid sys_setgid16
+47 common getgid sys_getgid16
+# 48 was sys_signal
+49 common geteuid sys_geteuid16
+50 common getegid sys_getegid16
+51 common acct sys_acct
+52 common umount2 sys_umount
+# 53 was sys_lock
+54 common ioctl sys_ioctl compat_sys_ioctl
+55 common fcntl sys_fcntl compat_sys_fcntl
+# 56 was sys_mpx
+57 common setpgid sys_setpgid
+# 58 was sys_ulimit
+# 59 was sys_olduname
+60 common umask sys_umask
+61 common chroot sys_chroot
+62 common ustat sys_ustat compat_sys_ustat
+63 common dup2 sys_dup2
+64 common getppid sys_getppid
+65 common getpgrp sys_getpgrp
+66 common setsid sys_setsid
+67 common sigaction sys_sigaction compat_sys_sigaction
+# 68 was sys_sgetmask
+# 69 was sys_ssetmask
+70 common setreuid sys_setreuid16
+71 common setregid sys_setregid16
+72 common sigsuspend sys_sigsuspend
+73 common sigpending sys_sigpending compat_sys_sigpending
+74 common sethostname sys_sethostname
+75 common setrlimit sys_setrlimit compat_sys_setrlimit
+# 76 was compat_sys_getrlimit
+77 common getrusage sys_getrusage compat_sys_getrusage
+78 common gettimeofday sys_gettimeofday compat_sys_gettimeofday
+79 common settimeofday sys_settimeofday compat_sys_settimeofday
+80 common getgroups sys_getgroups16
+81 common setgroups sys_setgroups16
+# 82 was compat_sys_select
+83 common symlink sys_symlink
+# 84 was sys_lstat
+85 common readlink sys_readlink
+86 common uselib sys_uselib
+87 common swapon sys_swapon
+88 common reboot sys_reboot
+# 89 was sys_readdir
+# 90 was sys_mmap
+91 common munmap sys_munmap
+92 common truncate sys_truncate compat_sys_truncate
+93 common ftruncate sys_ftruncate compat_sys_ftruncate
+94 common fchmod sys_fchmod
+95 common fchown sys_fchown16
+96 common getpriority sys_getpriority
+97 common setpriority sys_setpriority
+# 98 was sys_profil
+99 common statfs sys_statfs compat_sys_statfs
+100 common fstatfs sys_fstatfs compat_sys_fstatfs
+# 101 was sys_ioperm
+# 102 was sys_socketcall
+103 common syslog sys_syslog
+104 common setitimer sys_setitimer compat_sys_setitimer
+105 common getitimer sys_getitimer compat_sys_getitimer
+106 common stat sys_newstat compat_sys_newstat
+107 common lstat sys_newlstat compat_sys_newlstat
+108 common fstat sys_newfstat compat_sys_newfstat
+# 109 was sys_uname
+# 110 was sys_iopl
+111 common vhangup sys_vhangup
+# 112 was sys_idle
+# 113 was sys_syscall
+114 common wait4 sys_wait4 compat_sys_wait4
+115 common swapoff sys_swapoff
+116 common sysinfo sys_sysinfo compat_sys_sysinfo
+# 117 was sys_ipc
+118 common fsync sys_fsync
+119 common sigreturn sys_sigreturn_wrapper compat_sys_sigreturn
+120 common clone sys_clone
+121 common setdomainname sys_setdomainname
+122 common uname sys_newuname
+# 123 was sys_modify_ldt
+124 common adjtimex sys_adjtimex_time32
+125 common mprotect sys_mprotect
+126 common sigprocmask sys_sigprocmask compat_sys_sigprocmask
+# 127 was sys_create_module
+128 common init_module sys_init_module
+129 common delete_module sys_delete_module
+# 130 was sys_get_kernel_syms
+131 common quotactl sys_quotactl
+132 common getpgid sys_getpgid
+133 common fchdir sys_fchdir
+134 common bdflush sys_ni_syscall
+135 common sysfs sys_sysfs
+136 common personality sys_personality
+# 137 was sys_afs_syscall
+138 common setfsuid sys_setfsuid16
+139 common setfsgid sys_setfsgid16
+140 common _llseek sys_llseek
+141 common getdents sys_getdents compat_sys_getdents
+142 common _newselect sys_select compat_sys_select
+143 common flock sys_flock
+144 common msync sys_msync
+145 common readv sys_readv
+146 common writev sys_writev
+147 common getsid sys_getsid
+148 common fdatasync sys_fdatasync
+149 common _sysctl sys_ni_syscall
+150 common mlock sys_mlock
+151 common munlock sys_munlock
+152 common mlockall sys_mlockall
+153 common munlockall sys_munlockall
+154 common sched_setparam sys_sched_setparam
+155 common sched_getparam sys_sched_getparam
+156 common sched_setscheduler sys_sched_setscheduler
+157 common sched_getscheduler sys_sched_getscheduler
+158 common sched_yield sys_sched_yield
+159 common sched_get_priority_max sys_sched_get_priority_max
+160 common sched_get_priority_min sys_sched_get_priority_min
+161 common sched_rr_get_interval sys_sched_rr_get_interval_time32
+162 common nanosleep sys_nanosleep_time32
+163 common mremap sys_mremap
+164 common setresuid sys_setresuid16
+165 common getresuid sys_getresuid16
+# 166 was sys_vm86
+# 167 was sys_query_module
+168 common poll sys_poll
+169 common nfsservctl sys_ni_syscall
+170 common setresgid sys_setresgid16
+171 common getresgid sys_getresgid16
+172 common prctl sys_prctl
+173 common rt_sigreturn sys_rt_sigreturn_wrapper compat_sys_rt_sigreturn
+174 common rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction
+175 common rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask
+176 common rt_sigpending sys_rt_sigpending compat_sys_rt_sigpending
+177 common rt_sigtimedwait sys_rt_sigtimedwait_time32 compat_sys_rt_sigtimedwait_time32
+178 common rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo
+179 common rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend
+180 common pread64 sys_pread64 compat_sys_aarch32_pread64
+181 common pwrite64 sys_pwrite64 compat_sys_aarch32_pwrite64
+182 common chown sys_chown16
+183 common getcwd sys_getcwd
+184 common capget sys_capget
+185 common capset sys_capset
+186 common sigaltstack sys_sigaltstack compat_sys_sigaltstack
+187 common sendfile sys_sendfile compat_sys_sendfile
+# 188 reserved
+# 189 reserved
+190 common vfork sys_vfork
+# SuS compliant getrlimit
+191 common ugetrlimit sys_getrlimit compat_sys_getrlimit
+192 common mmap2 sys_mmap2 compat_sys_aarch32_mmap2
+193 common truncate64 sys_truncate64 compat_sys_aarch32_truncate64
+194 common ftruncate64 sys_ftruncate64 compat_sys_aarch32_ftruncate64
+195 common stat64 sys_stat64
+196 common lstat64 sys_lstat64
+197 common fstat64 sys_fstat64
+198 common lchown32 sys_lchown
+199 common getuid32 sys_getuid
+200 common getgid32 sys_getgid
+201 common geteuid32 sys_geteuid
+202 common getegid32 sys_getegid
+203 common setreuid32 sys_setreuid
+204 common setregid32 sys_setregid
+205 common getgroups32 sys_getgroups
+206 common setgroups32 sys_setgroups
+207 common fchown32 sys_fchown
+208 common setresuid32 sys_setresuid
+209 common getresuid32 sys_getresuid
+210 common setresgid32 sys_setresgid
+211 common getresgid32 sys_getresgid
+212 common chown32 sys_chown
+213 common setuid32 sys_setuid
+214 common setgid32 sys_setgid
+215 common setfsuid32 sys_setfsuid
+216 common setfsgid32 sys_setfsgid
+217 common getdents64 sys_getdents64
+218 common pivot_root sys_pivot_root
+219 common mincore sys_mincore
+220 common madvise sys_madvise
+221 common fcntl64 sys_fcntl64 compat_sys_fcntl64
+# 222 for tux
+# 223 is unused
+224 common gettid sys_gettid
+225 common readahead sys_readahead compat_sys_aarch32_readahead
+226 common setxattr sys_setxattr
+227 common lsetxattr sys_lsetxattr
+228 common fsetxattr sys_fsetxattr
+229 common getxattr sys_getxattr
+230 common lgetxattr sys_lgetxattr
+231 common fgetxattr sys_fgetxattr
+232 common listxattr sys_listxattr
+233 common llistxattr sys_llistxattr
+234 common flistxattr sys_flistxattr
+235 common removexattr sys_removexattr
+236 common lremovexattr sys_lremovexattr
+237 common fremovexattr sys_fremovexattr
+238 common tkill sys_tkill
+239 common sendfile64 sys_sendfile64
+240 common futex sys_futex_time32
+241 common sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity
+242 common sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity
+243 common io_setup sys_io_setup compat_sys_io_setup
+244 common io_destroy sys_io_destroy
+245 common io_getevents sys_io_getevents_time32
+246 common io_submit sys_io_submit compat_sys_io_submit
+247 common io_cancel sys_io_cancel
+248 common exit_group sys_exit_group
+249 common lookup_dcookie sys_ni_syscall
+250 common epoll_create sys_epoll_create
+251 common epoll_ctl sys_epoll_ctl
+252 common epoll_wait sys_epoll_wait
+253 common remap_file_pages sys_remap_file_pages
+# 254 for set_thread_area
+# 255 for get_thread_area
+256 common set_tid_address sys_set_tid_address
+257 common timer_create sys_timer_create compat_sys_timer_create
+258 common timer_settime sys_timer_settime32
+259 common timer_gettime sys_timer_gettime32
+260 common timer_getoverrun sys_timer_getoverrun
+261 common timer_delete sys_timer_delete
+262 common clock_settime sys_clock_settime32
+263 common clock_gettime sys_clock_gettime32
+264 common clock_getres sys_clock_getres_time32
+265 common clock_nanosleep sys_clock_nanosleep_time32
+266 common statfs64 sys_statfs64_wrapper compat_sys_aarch32_statfs64
+267 common fstatfs64 sys_fstatfs64_wrapper compat_sys_aarch32_fstatfs64
+268 common tgkill sys_tgkill
+269 common utimes sys_utimes_time32
+270 common arm_fadvise64_64 sys_arm_fadvise64_64 compat_sys_aarch32_fadvise64_64
+271 common pciconfig_iobase sys_pciconfig_iobase
+272 common pciconfig_read sys_pciconfig_read
+273 common pciconfig_write sys_pciconfig_write
+274 common mq_open sys_mq_open compat_sys_mq_open
+275 common mq_unlink sys_mq_unlink
+276 common mq_timedsend sys_mq_timedsend_time32
+277 common mq_timedreceive sys_mq_timedreceive_time32
+278 common mq_notify sys_mq_notify compat_sys_mq_notify
+279 common mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr
+280 common waitid sys_waitid compat_sys_waitid
+281 common socket sys_socket
+282 common bind sys_bind
+283 common connect sys_connect
+284 common listen sys_listen
+285 common accept sys_accept
+286 common getsockname sys_getsockname
+287 common getpeername sys_getpeername
+288 common socketpair sys_socketpair
+289 common send sys_send
+290 common sendto sys_sendto
+291 common recv sys_recv compat_sys_recv
+292 common recvfrom sys_recvfrom compat_sys_recvfrom
+293 common shutdown sys_shutdown
+294 common setsockopt sys_setsockopt
+295 common getsockopt sys_getsockopt
+296 common sendmsg sys_sendmsg compat_sys_sendmsg
+297 common recvmsg sys_recvmsg compat_sys_recvmsg
+298 common semop sys_semop
+299 common semget sys_semget
+300 common semctl sys_old_semctl compat_sys_old_semctl
+301 common msgsnd sys_msgsnd compat_sys_msgsnd
+302 common msgrcv sys_msgrcv compat_sys_msgrcv
+303 common msgget sys_msgget
+304 common msgctl sys_old_msgctl compat_sys_old_msgctl
+305 common shmat sys_shmat compat_sys_shmat
+306 common shmdt sys_shmdt
+307 common shmget sys_shmget
+308 common shmctl sys_old_shmctl compat_sys_old_shmctl
+309 common add_key sys_add_key
+310 common request_key sys_request_key
+311 common keyctl sys_keyctl compat_sys_keyctl
+312 common semtimedop sys_semtimedop_time32
+313 common vserver sys_ni_syscall
+314 common ioprio_set sys_ioprio_set
+315 common ioprio_get sys_ioprio_get
+316 common inotify_init sys_inotify_init
+317 common inotify_add_watch sys_inotify_add_watch
+318 common inotify_rm_watch sys_inotify_rm_watch
+319 common mbind sys_mbind
+320 common get_mempolicy sys_get_mempolicy
+321 common set_mempolicy sys_set_mempolicy
+322 common openat sys_openat compat_sys_openat
+323 common mkdirat sys_mkdirat
+324 common mknodat sys_mknodat
+325 common fchownat sys_fchownat
+326 common futimesat sys_futimesat_time32
+327 common fstatat64 sys_fstatat64
+328 common unlinkat sys_unlinkat
+329 common renameat sys_renameat
+330 common linkat sys_linkat
+331 common symlinkat sys_symlinkat
+332 common readlinkat sys_readlinkat
+333 common fchmodat sys_fchmodat
+334 common faccessat sys_faccessat
+335 common pselect6 sys_pselect6_time32 compat_sys_pselect6_time32
+336 common ppoll sys_ppoll_time32 compat_sys_ppoll_time32
+337 common unshare sys_unshare
+338 common set_robust_list sys_set_robust_list compat_sys_set_robust_list
+339 common get_robust_list sys_get_robust_list compat_sys_get_robust_list
+340 common splice sys_splice
+341 common arm_sync_file_range sys_sync_file_range2 compat_sys_aarch32_sync_file_range2
+342 common tee sys_tee
+343 common vmsplice sys_vmsplice
+344 common move_pages sys_move_pages
+345 common getcpu sys_getcpu
+346 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
+347 common kexec_load sys_kexec_load compat_sys_kexec_load
+348 common utimensat sys_utimensat_time32
+349 common signalfd sys_signalfd compat_sys_signalfd
+350 common timerfd_create sys_timerfd_create
+351 common eventfd sys_eventfd
+352 common fallocate sys_fallocate compat_sys_aarch32_fallocate
+353 common timerfd_settime sys_timerfd_settime32
+354 common timerfd_gettime sys_timerfd_gettime32
+355 common signalfd4 sys_signalfd4 compat_sys_signalfd4
+356 common eventfd2 sys_eventfd2
+357 common epoll_create1 sys_epoll_create1
+358 common dup3 sys_dup3
+359 common pipe2 sys_pipe2
+360 common inotify_init1 sys_inotify_init1
+361 common preadv sys_preadv compat_sys_preadv
+362 common pwritev sys_pwritev compat_sys_pwritev
+363 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
+364 common perf_event_open sys_perf_event_open
+365 common recvmmsg sys_recvmmsg_time32 compat_sys_recvmmsg_time32
+366 common accept4 sys_accept4
+367 common fanotify_init sys_fanotify_init
+368 common fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark
+369 common prlimit64 sys_prlimit64
+370 common name_to_handle_at sys_name_to_handle_at
+371 common open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at
+372 common clock_adjtime sys_clock_adjtime32
+373 common syncfs sys_syncfs
+374 common sendmmsg sys_sendmmsg compat_sys_sendmmsg
+375 common setns sys_setns
+376 common process_vm_readv sys_process_vm_readv
+377 common process_vm_writev sys_process_vm_writev
+378 common kcmp sys_kcmp
+379 common finit_module sys_finit_module
+380 common sched_setattr sys_sched_setattr
+381 common sched_getattr sys_sched_getattr
+382 common renameat2 sys_renameat2
+383 common seccomp sys_seccomp
+384 common getrandom sys_getrandom
+385 common memfd_create sys_memfd_create
+386 common bpf sys_bpf
+387 common execveat sys_execveat compat_sys_execveat
+388 common userfaultfd sys_userfaultfd
+389 common membarrier sys_membarrier
+390 common mlock2 sys_mlock2
+391 common copy_file_range sys_copy_file_range
+392 common preadv2 sys_preadv2 compat_sys_preadv2
+393 common pwritev2 sys_pwritev2 compat_sys_pwritev2
+394 common pkey_mprotect sys_pkey_mprotect
+395 common pkey_alloc sys_pkey_alloc
+396 common pkey_free sys_pkey_free
+397 common statx sys_statx
+398 common rseq sys_rseq
+399 common io_pgetevents sys_io_pgetevents_time32 compat_sys_io_pgetevents
+400 common migrate_pages sys_migrate_pages
+401 common kexec_file_load sys_kexec_file_load
+# 402 is unused
+403 common clock_gettime64 sys_clock_gettime
+404 common clock_settime64 sys_clock_settime
+405 common clock_adjtime64 sys_clock_adjtime
+406 common clock_getres_time64 sys_clock_getres
+407 common clock_nanosleep_time64 sys_clock_nanosleep
+408 common timer_gettime64 sys_timer_gettime
+409 common timer_settime64 sys_timer_settime
+410 common timerfd_gettime64 sys_timerfd_gettime
+411 common timerfd_settime64 sys_timerfd_settime
+412 common utimensat_time64 sys_utimensat
+413 common pselect6_time64 sys_pselect6 compat_sys_pselect6_time64
+414 common ppoll_time64 sys_ppoll compat_sys_ppoll_time64
+416 common io_pgetevents_time64 sys_io_pgetevents compat_sys_io_pgetevents_time64
+417 common recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64
+418 common mq_timedsend_time64 sys_mq_timedsend
+419 common mq_timedreceive_time64 sys_mq_timedreceive
+420 common semtimedop_time64 sys_semtimedop
+421 common rt_sigtimedwait_time64 sys_rt_sigtimedwait compat_sys_rt_sigtimedwait_time64
+422 common futex_time64 sys_futex
+423 common sched_rr_get_interval_time64 sys_sched_rr_get_interval
+424 common pidfd_send_signal sys_pidfd_send_signal
+425 common io_uring_setup sys_io_uring_setup
+426 common io_uring_enter sys_io_uring_enter
+427 common io_uring_register sys_io_uring_register
+428 common open_tree sys_open_tree
+429 common move_mount sys_move_mount
+430 common fsopen sys_fsopen
+431 common fsconfig sys_fsconfig
+432 common fsmount sys_fsmount
+433 common fspick sys_fspick
+434 common pidfd_open sys_pidfd_open
+435 common clone3 sys_clone3
+436 common close_range sys_close_range
+437 common openat2 sys_openat2
+438 common pidfd_getfd sys_pidfd_getfd
+439 common faccessat2 sys_faccessat2
+440 common process_madvise sys_process_madvise
+441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2
+442 common mount_setattr sys_mount_setattr
+443 common quotactl_fd sys_quotactl_fd
+444 common landlock_create_ruleset sys_landlock_create_ruleset
+445 common landlock_add_rule sys_landlock_add_rule
+446 common landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease
+449 common futex_waitv sys_futex_waitv
+450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common cachestat sys_cachestat
+452 common fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
+457 common statmount sys_statmount
+458 common listmount sys_listmount
+459 common lsm_get_self_attr sys_lsm_get_self_attr
+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
diff --git a/arch/arm64/tools/syscall_64.tbl b/arch/arm64/tools/syscall_64.tbl
new file mode 120000
index 000000000000..63135cf34b65
--- /dev/null
+++ b/arch/arm64/tools/syscall_64.tbl
@@ -0,0 +1 @@
+../../../scripts/syscall.tbl \ No newline at end of file
diff --git a/arch/csky/include/asm/Kbuild b/arch/csky/include/asm/Kbuild
index 1117c28cb7e8..9a9bc65b57a9 100644
--- a/arch/csky/include/asm/Kbuild
+++ b/arch/csky/include/asm/Kbuild
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y := syscall_table_32.h
+
generic-y += asm-offsets.h
generic-y += extable.h
-generic-y += gpio.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += qrwlock.h
diff --git a/arch/csky/include/asm/unistd.h b/arch/csky/include/asm/unistd.h
index 9cf97de9a26d..2c2c24de95d8 100644
--- a/arch/csky/include/asm/unistd.h
+++ b/arch/csky/include/asm/unistd.h
@@ -2,4 +2,7 @@
#include <uapi/asm/unistd.h>
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_CLONE
+
#define NR_syscalls (__NR_syscalls)
diff --git a/arch/csky/include/uapi/asm/Kbuild b/arch/csky/include/uapi/asm/Kbuild
index e78470141932..2501e82a1a0a 100644
--- a/arch/csky/include/uapi/asm/Kbuild
+++ b/arch/csky/include/uapi/asm/Kbuild
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += unistd_32.h
+
generic-y += ucontext.h
diff --git a/arch/csky/include/uapi/asm/unistd.h b/arch/csky/include/uapi/asm/unistd.h
index e0594b6370a6..44882179a6e1 100644
--- a/arch/csky/include/uapi/asm/unistd.h
+++ b/arch/csky/include/uapi/asm/unistd.h
@@ -1,15 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_NEW_STAT
-#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
-#define __ARCH_WANT_SET_GET_RLIMIT
-#define __ARCH_WANT_TIME32_SYSCALLS
-#define __ARCH_WANT_SYNC_FILE_RANGE2
-#include <asm-generic/unistd.h>
+#include <asm/unistd_32.h>
-#define __NR_set_thread_area (__NR_arch_specific_syscall + 0)
-__SYSCALL(__NR_set_thread_area, sys_set_thread_area)
-#define __NR_cacheflush (__NR_arch_specific_syscall + 1)
-__SYSCALL(__NR_cacheflush, sys_cacheflush)
+#define __NR_sync_file_range2 84
+#undef __NR_sync_file_range
diff --git a/arch/csky/kernel/Makefile.syscalls b/arch/csky/kernel/Makefile.syscalls
new file mode 100644
index 000000000000..3df3b5822fce
--- /dev/null
+++ b/arch/csky/kernel/Makefile.syscalls
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+syscall_abis_32 += csky time32 stat64 rlimit
+
diff --git a/arch/csky/kernel/syscall_table.c b/arch/csky/kernel/syscall_table.c
index a0c238c5377a..a6eb91a0e2f6 100644
--- a/arch/csky/kernel/syscall_table.c
+++ b/arch/csky/kernel/syscall_table.c
@@ -6,9 +6,11 @@
#undef __SYSCALL
#define __SYSCALL(nr, call)[nr] = (call),
+#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
#define sys_fadvise64_64 sys_csky_fadvise64_64
+#define sys_sync_file_range sys_sync_file_range2
void * const sys_call_table[__NR_syscalls] __page_aligned_data = {
[0 ... __NR_syscalls - 1] = sys_ni_syscall,
-#include <asm/unistd.h>
+#include <asm/syscall_table_32.h>
};
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 3ece3c93fe08..8c1a78c8f527 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += syscall_table_32.h
+
generic-y += extable.h
generic-y += iomap.h
generic-y += kvm_para.h
diff --git a/arch/hexagon/include/asm/unistd.h b/arch/hexagon/include/asm/unistd.h
new file mode 100644
index 000000000000..1f462bade75c
--- /dev/null
+++ b/arch/hexagon/include/asm/unistd.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_FORK
+
+#define __ARCH_BROKEN_SYS_CLONE3
+
+#include <uapi/asm/unistd.h>
diff --git a/arch/hexagon/include/uapi/asm/Kbuild b/arch/hexagon/include/uapi/asm/Kbuild
index e78470141932..2501e82a1a0a 100644
--- a/arch/hexagon/include/uapi/asm/Kbuild
+++ b/arch/hexagon/include/uapi/asm/Kbuild
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += unistd_32.h
+
generic-y += ucontext.h
diff --git a/arch/hexagon/include/uapi/asm/unistd.h b/arch/hexagon/include/uapi/asm/unistd.h
index 21ae22306b5d..a3b0cac25580 100644
--- a/arch/hexagon/include/uapi/asm/unistd.h
+++ b/arch/hexagon/include/uapi/asm/unistd.h
@@ -27,15 +27,7 @@
* See also: syscalltab.c
*/
-#define sys_mmap2 sys_mmap_pgoff
-#define __ARCH_WANT_RENAMEAT
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SET_GET_RLIMIT
-#define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_VFORK
-#define __ARCH_WANT_SYS_FORK
-#define __ARCH_WANT_TIME32_SYSCALLS
-#define __ARCH_WANT_SYNC_FILE_RANGE2
+#include <asm/unistd_32.h>
-#include <asm-generic/unistd.h>
+#define __NR_sync_file_range2 84
+#undef __NR_sync_file_range
diff --git a/arch/hexagon/kernel/Makefile.syscalls b/arch/hexagon/kernel/Makefile.syscalls
new file mode 100644
index 000000000000..d2b7c5d44d95
--- /dev/null
+++ b/arch/hexagon/kernel/Makefile.syscalls
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+syscall_abis_32 += hexagon time32 stat64 rlimit renameat
diff --git a/arch/hexagon/kernel/syscalltab.c b/arch/hexagon/kernel/syscalltab.c
index 5d98bdc494ec..b53e2eead4ac 100644
--- a/arch/hexagon/kernel/syscalltab.c
+++ b/arch/hexagon/kernel/syscalltab.c
@@ -11,8 +11,10 @@
#include <asm/syscall.h>
-#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = (call),
+#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
+
+#define sys_mmap2 sys_mmap_pgoff
SYSCALL_DEFINE6(hexagon_fadvise64_64, int, fd, int, advice,
SC_ARG64(offset), SC_ARG64(len))
@@ -21,6 +23,8 @@ SYSCALL_DEFINE6(hexagon_fadvise64_64, int, fd, int, advice,
}
#define sys_fadvise64_64 sys_hexagon_fadvise64_64
+#define sys_sync_file_range sys_sync_file_range2
+
void *sys_call_table[__NR_syscalls] = {
-#include <asm/unistd.h>
+#include <asm/syscall_table_32.h>
};
diff --git a/arch/loongarch/include/asm/Kbuild b/arch/loongarch/include/asm/Kbuild
index c862672ed953..2bb3676429c0 100644
--- a/arch/loongarch/include/asm/Kbuild
+++ b/arch/loongarch/include/asm/Kbuild
@@ -1,28 +1,13 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += syscall_table_64.h
generated-y += orc_hash.h
-generic-y += dma-contiguous.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += early_ioremap.h
generic-y += qrwlock.h
generic-y += qspinlock.h
-generic-y += rwsem.h
-generic-y += segment.h
generic-y += user.h
-generic-y += stat.h
-generic-y += fcntl.h
generic-y += ioctl.h
-generic-y += ioctls.h
-generic-y += mman.h
-generic-y += msgbuf.h
-generic-y += sembuf.h
-generic-y += shmbuf.h
generic-y += statfs.h
-generic-y += socket.h
-generic-y += sockios.h
-generic-y += termbits.h
-generic-y += poll.h
generic-y += param.h
-generic-y += posix_types.h
-generic-y += resource.h
diff --git a/arch/loongarch/include/asm/unistd.h b/arch/loongarch/include/asm/unistd.h
index cfddb0116a8c..fc0a481a7416 100644
--- a/arch/loongarch/include/asm/unistd.h
+++ b/arch/loongarch/include/asm/unistd.h
@@ -8,4 +8,6 @@
#include <uapi/asm/unistd.h>
+#define __ARCH_WANT_SYS_CLONE
+
#define NR_syscalls (__NR_syscalls)
diff --git a/arch/loongarch/include/uapi/asm/Kbuild b/arch/loongarch/include/uapi/asm/Kbuild
index 4aa680ca2e5f..c6d141d7b7d7 100644
--- a/arch/loongarch/include/uapi/asm/Kbuild
+++ b/arch/loongarch/include/uapi/asm/Kbuild
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += unistd_64.h
+
generic-y += kvm_para.h
diff --git a/arch/loongarch/include/uapi/asm/unistd.h b/arch/loongarch/include/uapi/asm/unistd.h
index fcb668984f03..1f01980f9c94 100644
--- a/arch/loongarch/include/uapi/asm/unistd.h
+++ b/arch/loongarch/include/uapi/asm/unistd.h
@@ -1,5 +1,3 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
-#include <asm-generic/unistd.h>
+#include <asm/unistd_64.h>
diff --git a/arch/loongarch/kernel/Makefile.syscalls b/arch/loongarch/kernel/Makefile.syscalls
new file mode 100644
index 000000000000..ab7d9baa2915
--- /dev/null
+++ b/arch/loongarch/kernel/Makefile.syscalls
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# No special ABIs on loongarch so far
+syscall_abis_64 +=
diff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c
index 8801611143ab..ec17cd5163b7 100644
--- a/arch/loongarch/kernel/syscall.c
+++ b/arch/loongarch/kernel/syscall.c
@@ -20,6 +20,7 @@
#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = (call),
+#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long,
prot, unsigned long, flags, unsigned long, fd, unsigned long, offset)
@@ -32,7 +33,7 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long,
void *sys_call_table[__NR_syscalls] = {
[0 ... __NR_syscalls - 1] = sys_ni_syscall,
-#include <asm/unistd.h>
+#include <asm/syscall_table_64.h>
};
typedef long (*sys_call_fn)(unsigned long, unsigned long,
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index d4b170c861bf..0147130dc34e 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -180,6 +180,15 @@ int __init amiga_parse_bootinfo(const struct bi_record *record)
dev->slotsize = be16_to_cpu(cd->cd_SlotSize);
dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr);
dev->boardsize = be32_to_cpu(cd->cd_BoardSize);
+
+ /* CS-LAB Warp 1260 workaround */
+ if (be16_to_cpu(dev->rom.er_Manufacturer) == ZORRO_MANUF(ZORRO_PROD_CSLAB_WARP_1260) &&
+ dev->rom.er_Product == ZORRO_PROD(ZORRO_PROD_CSLAB_WARP_1260)) {
+
+ /* turn off all interrupts */
+ pr_info("Warp 1260 card detected: applying interrupt storm workaround\n");
+ *(uint32_t *)(dev->boardaddr + 0x1000) = 0xfff;
+ }
} else
pr_warn("amiga_parse_bootinfo: too many AutoConfig devices\n");
#endif /* CONFIG_ZORRO */
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 23256434191c..0465444ceb21 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -301,11 +301,7 @@ void __init atari_init_IRQ(void)
if (ATARIHW_PRESENT(SCU)) {
/* init the SCU if present */
- tt_scu.sys_mask = 0x10; /* enable VBL (for the cursor) and
- * disable HSYNC interrupts (who
- * needs them?) MFP and SCC are
- * enabled in VME mask
- */
+ tt_scu.sys_mask = 0x0; /* disable all interrupts */
tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */
} else {
/* If no SCU and no Hades, the HSYNC interrupt needs to be
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 6bb202d03d34..9a084943a68a 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -373,6 +373,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 3598e0cc66b0..58ec725bf392 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -353,6 +353,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 3fbb8a9a307d..63ab7e892e59 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -368,6 +368,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index 9a2b0c7871ce..ca40744eec60 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -351,6 +351,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 2408785e0e48..77bcc6faf468 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -352,6 +352,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 6789d03b7b52..e73d4032b659 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -364,6 +364,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index b57af39db3b4..638df8442c98 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -407,6 +407,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index 29b70f27aedd..2248db426081 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -350,6 +350,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 757c582ffe84..2975b66521f6 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -351,6 +351,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index f15d1009108a..0a0e32344033 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -357,6 +357,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 5218c1e614b5..f16f1a99c2ba 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -347,6 +347,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index acdf4eb7af28..667bd61ae9b3 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -348,6 +348,7 @@ CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
+CONFIG_PFCP=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
diff --git a/arch/m68k/emu/nfblock.c b/arch/m68k/emu/nfblock.c
index 642fb80c5c4e..83410f8184ec 100644
--- a/arch/m68k/emu/nfblock.c
+++ b/arch/m68k/emu/nfblock.c
@@ -71,7 +71,7 @@ static void nfhd_submit_bio(struct bio *bio)
len = bvec.bv_len;
len >>= 9;
nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift,
- page_to_phys(bvec.bv_page) + bvec.bv_offset);
+ bvec_phys(&bvec));
sec += len;
}
bio_endio(bio);
@@ -98,6 +98,7 @@ static int __init nfhd_init_one(int id, u32 blocks, u32 bsize)
{
struct queue_limits lim = {
.logical_block_size = bsize,
+ .features = BLK_FEAT_ROTATIONAL,
};
struct nfhd_device *dev;
int dev_id = id - NFHD_DEV_OFFSET;
@@ -193,4 +194,5 @@ static void __exit nfhd_exit(void)
module_init(nfhd_init);
module_exit(nfhd_exit);
+MODULE_DESCRIPTION("Atari NatFeat block device driver");
MODULE_LICENSE("GPL");
diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c
index 17b2987c2bf5..d41260672e24 100644
--- a/arch/m68k/emu/nfcon.c
+++ b/arch/m68k/emu/nfcon.c
@@ -173,4 +173,5 @@ static void __exit nfcon_exit(void)
module_init(nfcon_init);
module_exit(nfcon_exit);
+MODULE_DESCRIPTION("Atari NatFeat console driver");
MODULE_LICENSE("GPL");
diff --git a/arch/m68k/include/asm/cmpxchg.h b/arch/m68k/include/asm/cmpxchg.h
index d7f3de9c5d6f..4ba14f3535fc 100644
--- a/arch/m68k/include/asm/cmpxchg.h
+++ b/arch/m68k/include/asm/cmpxchg.h
@@ -32,7 +32,7 @@ static inline unsigned long __arch_xchg(unsigned long x, volatile void * ptr, in
x = tmp;
break;
default:
- tmp = __invalid_xchg_size(x, ptr, size);
+ x = __invalid_xchg_size(x, ptr, size);
break;
}
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index 4ae52414cd9d..2e0047cf86f8 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -30,6 +30,5 @@
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_VFORK
-#define __ARCH_WANT_SYS_CLONE3
#endif /* _ASM_M68K_UNISTD_H_ */
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index 25a5253db7f4..ba83d3fb0a84 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -58,7 +58,6 @@
# endif
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
/* whitelists for checksyscalls */
#define __IGNORE_fadvise64_64
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index 7fe7437555fb..0d09829ed144 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += syscall_table_32.h
+
generic-y += cmpxchg.h
generic-y += extable.h
generic-y += kvm_para.h
diff --git a/arch/nios2/include/asm/unistd.h b/arch/nios2/include/asm/unistd.h
new file mode 100644
index 000000000000..1146e56473c5
--- /dev/null
+++ b/arch/nios2/include/asm/unistd.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __ASM_UNISTD_H
+#define __ASM_UNISTD_H
+
+#include <uapi/asm/unistd.h>
+
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SET_GET_RLIMIT
+
+#define __ARCH_BROKEN_SYS_CLONE3
+
+#endif
diff --git a/arch/nios2/include/uapi/asm/Kbuild b/arch/nios2/include/uapi/asm/Kbuild
index e78470141932..2501e82a1a0a 100644
--- a/arch/nios2/include/uapi/asm/Kbuild
+++ b/arch/nios2/include/uapi/asm/Kbuild
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += unistd_32.h
+
generic-y += ucontext.h
diff --git a/arch/nios2/include/uapi/asm/unistd.h b/arch/nios2/include/uapi/asm/unistd.h
index 0b4bb1d41b28..1f0e0f5538d9 100644
--- a/arch/nios2/include/uapi/asm/unistd.h
+++ b/arch/nios2/include/uapi/asm/unistd.h
@@ -16,16 +16,4 @@
*
*/
- #define sys_mmap2 sys_mmap_pgoff
-
-#define __ARCH_WANT_RENAMEAT
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SET_GET_RLIMIT
-#define __ARCH_WANT_TIME32_SYSCALLS
-
-/* Use the standard ABI for syscalls */
-#include <asm-generic/unistd.h>
-
-/* Additional Nios II specific syscalls. */
-#define __NR_cacheflush (__NR_arch_specific_syscall)
-__SYSCALL(__NR_cacheflush, sys_cacheflush)
+#include <asm/unistd_32.h>
diff --git a/arch/nios2/kernel/Makefile.syscalls b/arch/nios2/kernel/Makefile.syscalls
new file mode 100644
index 000000000000..579a9daec272
--- /dev/null
+++ b/arch/nios2/kernel/Makefile.syscalls
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+syscall_abis_32 += nios2 time32 stat64 renameat rlimit
diff --git a/arch/nios2/kernel/syscall_table.c b/arch/nios2/kernel/syscall_table.c
index c2875a6dd5a4..434694067d8f 100644
--- a/arch/nios2/kernel/syscall_table.c
+++ b/arch/nios2/kernel/syscall_table.c
@@ -9,10 +9,12 @@
#include <asm/syscalls.h>
-#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = (call),
+#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
+
+#define sys_mmap2 sys_mmap_pgoff
void *sys_call_table[__NR_syscalls] = {
[0 ... __NR_syscalls-1] = sys_ni_syscall,
-#include <asm/unistd.h>
+#include <asm/syscall_table_32.h>
};
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index c8c99b554ca4..cef49d60d74c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += syscall_table_32.h
+
generic-y += extable.h
generic-y += kvm_para.h
generic-y += parport.h
diff --git a/arch/openrisc/include/asm/syscalls.h b/arch/openrisc/include/asm/syscalls.h
index aa1c7e98722e..9f4c47961bea 100644
--- a/arch/openrisc/include/asm/syscalls.h
+++ b/arch/openrisc/include/asm/syscalls.h
@@ -25,8 +25,4 @@ asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
asmlinkage long __sys_clone3(struct clone_args __user *uargs, size_t size);
asmlinkage long __sys_fork(void);
-#define sys_clone __sys_clone
-#define sys_clone3 __sys_clone3
-#define sys_fork __sys_fork
-
#endif /* __ASM_OPENRISC_SYSCALLS_H */
diff --git a/arch/openrisc/include/asm/unistd.h b/arch/openrisc/include/asm/unistd.h
new file mode 100644
index 000000000000..c73f65e18d3b
--- /dev/null
+++ b/arch/openrisc/include/asm/unistd.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_TIME32_SYSCALLS
+
+#include <uapi/asm/unistd.h>
diff --git a/arch/openrisc/include/uapi/asm/Kbuild b/arch/openrisc/include/uapi/asm/Kbuild
index e78470141932..2501e82a1a0a 100644
--- a/arch/openrisc/include/uapi/asm/Kbuild
+++ b/arch/openrisc/include/uapi/asm/Kbuild
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += unistd_32.h
+
generic-y += ucontext.h
diff --git a/arch/openrisc/include/uapi/asm/unistd.h b/arch/openrisc/include/uapi/asm/unistd.h
index fae34c60fa88..46b94d454efd 100644
--- a/arch/openrisc/include/uapi/asm/unistd.h
+++ b/arch/openrisc/include/uapi/asm/unistd.h
@@ -17,17 +17,4 @@
* (at your option) any later version.
*/
-#define sys_mmap2 sys_mmap_pgoff
-
-#define __ARCH_WANT_RENAMEAT
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SET_GET_RLIMIT
-#define __ARCH_WANT_SYS_FORK
-#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
-#define __ARCH_WANT_TIME32_SYSCALLS
-
-#include <asm-generic/unistd.h>
-
-#define __NR_or1k_atomic __NR_arch_specific_syscall
-__SYSCALL(__NR_or1k_atomic, sys_or1k_atomic)
+#include <asm/unistd_32.h>
diff --git a/arch/openrisc/kernel/Makefile.syscalls b/arch/openrisc/kernel/Makefile.syscalls
new file mode 100644
index 000000000000..525a1e7e7fc9
--- /dev/null
+++ b/arch/openrisc/kernel/Makefile.syscalls
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+syscall_abis_32 += or1k time32 stat64 rlimit renameat
diff --git a/arch/openrisc/kernel/sys_call_table.c b/arch/openrisc/kernel/sys_call_table.c
index 3d18008310e4..b2f57e2538f7 100644
--- a/arch/openrisc/kernel/sys_call_table.c
+++ b/arch/openrisc/kernel/sys_call_table.c
@@ -16,9 +16,14 @@
#include <asm/syscalls.h>
-#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = (call),
+#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
+
+#define sys_mmap2 sys_mmap_pgoff
+#define sys_clone __sys_clone
+#define sys_clone3 __sys_clone3
+#define sys_fork __sys_fork
void *sys_call_table[__NR_syscalls] = {
-#include <asm/unistd.h>
+#include <asm/syscall_table_32.h>
};
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h
index e38f9a90ac15..98851ff7699a 100644
--- a/arch/parisc/include/asm/unistd.h
+++ b/arch/parisc/include/asm/unistd.h
@@ -160,7 +160,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_VFORK
#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
#define __ARCH_WANT_COMPAT_SYS_SENDFILE
#define __ARCH_WANT_COMPAT_STAT
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index 659a996c75aa..027ef94a12fb 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -51,7 +51,6 @@
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_VFORK
#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_UNISTD_H_ */
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c
index d1030bc52564..d283d281d28e 100644
--- a/arch/powerpc/kernel/eeh_pe.c
+++ b/arch/powerpc/kernel/eeh_pe.c
@@ -849,6 +849,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
{
struct eeh_dev *edev;
struct pci_dev *pdev;
+ struct pci_bus *bus = NULL;
if (pe->type & EEH_PE_PHB)
return pe->phb->bus;
@@ -859,9 +860,11 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
/* Retrieve the parent PCI bus of first (top) PCI device */
edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, entry);
+ pci_lock_rescan_remove();
pdev = eeh_dev_to_pci_dev(edev);
if (pdev)
- return pdev->bus;
+ bus = pdev->bus;
+ pci_unlock_rescan_remove();
- return NULL;
+ return bus;
}
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 4690c219bfa4..63432a33ec49 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -647,8 +647,9 @@ __after_prom_start:
* Note: This process overwrites the OF exception vectors.
*/
LOAD_REG_IMMEDIATE(r3, PAGE_OFFSET)
- mr. r4,r26 /* In some cases the loader may */
- beq 9f /* have already put us at zero */
+ mr r4,r26 /* Load the virtual source address into r4 */
+ cmpld r3,r4 /* Check if source == dest */
+ beq 9f /* If so skip the copy */
li r6,0x100 /* Start offset, the first 0x100 */
/* bytes were copied earlier. */
diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c
index 85050be08a23..72b12bc10f90 100644
--- a/arch/powerpc/kexec/core_64.c
+++ b/arch/powerpc/kexec/core_64.c
@@ -27,6 +27,7 @@
#include <asm/paca.h>
#include <asm/mmu.h>
#include <asm/sections.h> /* _end */
+#include <asm/setup.h>
#include <asm/smp.h>
#include <asm/hw_breakpoint.h>
#include <asm/svm.h>
@@ -317,6 +318,16 @@ void default_machine_kexec(struct kimage *image)
if (!kdump_in_progress())
kexec_prepare_cpus();
+#ifdef CONFIG_PPC_PSERIES
+ /*
+ * This must be done after other CPUs have shut down, otherwise they
+ * could execute the 'scv' instruction, which is not supported with
+ * reloc disabled (see configure_exceptions()).
+ */
+ if (firmware_has_feature(FW_FEATURE_SET_MODE))
+ pseries_disable_reloc_on_exc();
+#endif
+
printk("kexec: Starting switchover sequence.\n");
/* switch to a staticly allocated stack. Based on irq stack code.
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c
index 096d09ed89f6..431be156ca9b 100644
--- a/arch/powerpc/platforms/pseries/kexec.c
+++ b/arch/powerpc/platforms/pseries/kexec.c
@@ -61,11 +61,3 @@ void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
} else
xics_kexec_teardown_cpu(secondary);
}
-
-void pseries_machine_kexec(struct kimage *image)
-{
- if (firmware_has_feature(FW_FEATURE_SET_MODE))
- pseries_disable_reloc_on_exc();
-
- default_machine_kexec(image);
-}
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index bba4ad192b0f..3968a6970fa8 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -38,7 +38,6 @@ static inline void smp_init_pseries(void) { }
#endif
extern void pseries_kexec_cpu_down(int crash_shutdown, int secondary);
-void pseries_machine_kexec(struct kimage *image);
extern void pSeries_final_fixup(void);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 284a6fa04b0c..b10a25325238 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -343,8 +343,8 @@ static int alloc_dispatch_log_kmem_cache(void)
{
void (*ctor)(void *) = get_dtl_cache_ctor();
- dtl_cache = kmem_cache_create("dtl", DISPATCH_LOG_BYTES,
- DISPATCH_LOG_BYTES, 0, ctor);
+ dtl_cache = kmem_cache_create_usercopy("dtl", DISPATCH_LOG_BYTES,
+ DISPATCH_LOG_BYTES, 0, 0, DISPATCH_LOG_BYTES, ctor);
if (!dtl_cache) {
pr_warn("Failed to create dispatch trace log buffer cache\n");
pr_warn("Stolen time statistics will be unreliable\n");
@@ -1159,7 +1159,6 @@ define_machine(pseries) {
.machine_check_exception = pSeries_machine_check_exception,
.machine_check_log_err = pSeries_machine_check_log_err,
#ifdef CONFIG_KEXEC_CORE
- .machine_kexec = pseries_machine_kexec,
.kexec_cpu_down = pseries_kexec_cpu_down,
#endif
#ifdef CONFIG_MEMORY_HOTPLUG
diff --git a/arch/riscv/boot/dts/allwinner/Makefile b/arch/riscv/boot/dts/allwinner/Makefile
index 87f70b1af6b4..1c91be38ea16 100644
--- a/arch/riscv/boot/dts/allwinner/Makefile
+++ b/arch/riscv/boot/dts/allwinner/Makefile
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-clockworkpi-v3.14.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-devterm-v3.14.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-dongshan-nezha-stu.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-86-panel-480p.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun20i-d1-lichee-rv-86-panel-720p.dtb
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts
new file mode 100644
index 000000000000..750aec6cf2f2
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-clockworkpi-v3.14.dts
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Samuel Holland <[email protected]>
+
+#include <dt-bindings/gpio/gpio.h>
+
+/dts-v1/;
+
+#include "sun20i-d1.dtsi"
+#include "sun20i-common-regulators.dtsi"
+
+/ {
+ model = "ClockworkPi v3.14 (R-01)";
+ compatible = "clockwork,r-01-clockworkpi-v3.14", "allwinner,sun20i-d1";
+
+ aliases {
+ ethernet0 = &ap6256;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ /*
+ * This regulator is PWM-controlled, but the PWM controller is not
+ * yet supported, so fix the regulator to its default voltage.
+ */
+ reg_vdd_cpu: vdd-cpu {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-cpu";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&reg_vcc>;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&pio 6 11 GPIO_ACTIVE_LOW>; /* PG11/GPIO3 */
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&reg_vdd_cpu>;
+};
+
+&dcxo {
+ clock-frequency = <24000000>;
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-0 = <&i2c0_pb10_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ axp221: pmic@34 {
+ compatible = "x-powers,axp228", "x-powers,axp221";
+ reg = <0x34>;
+ interrupt-parent = <&pio>;
+ interrupts = <4 9 IRQ_TYPE_LEVEL_LOW>; /* PE9/GPIO2 */
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ ac_power_supply: ac-power {
+ compatible = "x-powers,axp221-ac-power-supply";
+ };
+
+ axp_adc: adc {
+ compatible = "x-powers,axp221-adc";
+ #io-channel-cells = <1>;
+ };
+
+ battery_power_supply: battery-power {
+ compatible = "x-powers,axp221-battery-power-supply";
+ };
+
+ axp_gpio: gpio {
+ compatible = "x-powers,axp221-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ regulators {
+ x-powers,dcdc-freq = <3000>;
+
+ reg_dcdc1: dcdc1 {
+ regulator-name = "sys-3v3";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_dcdc3: dcdc3 {
+ regulator-name = "sys-1v8";
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_aldo1: aldo1 {
+ regulator-name = "aud-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_aldo2: aldo2 {
+ regulator-name = "disp-3v3";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_aldo3: aldo3 {
+ regulator-name = "vdd-wifi";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ /* DLDO1 and ELDO1-3 are connected in parallel. */
+ reg_dldo1: dldo1 {
+ regulator-name = "vbat-wifi-a";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ /* DLDO2-DLDO4 are connected in parallel. */
+ reg_dldo2: dldo2 {
+ regulator-name = "vcc-3v3-ext-a";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_dldo3: dldo3 {
+ regulator-name = "vcc-3v3-ext-b";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_dldo4: dldo4 {
+ regulator-name = "vcc-3v3-ext-c";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_eldo1: eldo1 {
+ regulator-name = "vbat-wifi-b";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_eldo2: eldo2 {
+ regulator-name = "vbat-wifi-c";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_eldo3: eldo3 {
+ regulator-name = "vbat-wifi-d";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+
+ usb_power_supply: usb-power {
+ compatible = "x-powers,axp221-usb-power-supply";
+ status = "disabled";
+ };
+ };
+};
+
+&mmc0 {
+ broken-cd;
+ bus-width = <4>;
+ disable-wp;
+ vmmc-supply = <&reg_dcdc1>;
+ vqmmc-supply = <&reg_vcc_3v3>;
+ pinctrl-0 = <&mmc0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&mmc1 {
+ bus-width = <4>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ non-removable;
+ vmmc-supply = <&reg_dldo1>;
+ vqmmc-supply = <&reg_aldo3>;
+ pinctrl-0 = <&mmc1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ ap6256: wifi@1 {
+ compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac";
+ reg = <1>;
+ interrupt-parent = <&pio>;
+ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10/GPIO4 */
+ interrupt-names = "host-wake";
+ };
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&pio {
+ vcc-pg-supply = <&reg_ldoa>;
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pb8_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart1 {
+ uart-has-rtscts;
+ pinctrl-0 = <&uart1_pg6_pins>, <&uart1_pg8_rts_cts_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4345c5";
+ interrupt-parent = <&pio>;
+ interrupts = <6 17 IRQ_TYPE_LEVEL_HIGH>; /* PG17/GPIO6 */
+ device-wakeup-gpios = <&pio 6 16 GPIO_ACTIVE_HIGH>; /* PG16/GPIO7 */
+ shutdown-gpios = <&pio 6 18 GPIO_ACTIVE_HIGH>; /* PG18/GPIO5 */
+ max-speed = <1500000>;
+ vbat-supply = <&reg_dldo1>;
+ vddio-supply = <&reg_aldo3>;
+ };
+};
+
+&usb_otg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_vbus_power-supply = <&ac_power_supply>;
+ usb1_vbus-supply = <&reg_vcc>;
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts
new file mode 100644
index 000000000000..bc5c84f22762
--- /dev/null
+++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-devterm-v3.14.dts
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2022 Samuel Holland <[email protected]>
+
+#include "sun20i-d1-clockworkpi-v3.14.dts"
+
+/ {
+ model = "Clockwork DevTerm (R-01)";
+ compatible = "clockwork,r-01-devterm-v3.14",
+ "clockwork,r-01-clockworkpi-v3.14",
+ "allwinner,sun20i-d1";
+
+ fan {
+ compatible = "gpio-fan";
+ gpios = <&pio 3 10 GPIO_ACTIVE_HIGH>; /* PD10/GPIO41 */
+ gpio-fan,speed-map = <0 0>,
+ <6000 1>;
+ #cooling-cells = <2>;
+ };
+
+ i2c-gpio-0 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&pio 3 14 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; /* PD14/GPIO44 */
+ scl-gpios = <&pio 3 15 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; /* PD15/GPIO45 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@54 {
+ compatible = "ti,adc101c";
+ reg = <0x54>;
+ interrupt-parent = <&pio>;
+ interrupts = <4 12 IRQ_TYPE_LEVEL_LOW>; /* PE12/GPIO35 */
+ vref-supply = <&reg_dldo2>;
+ #io-channel-cells = <1>;
+ };
+ };
+};
diff --git a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi
index 5a9d7f5a75b4..e4175adb028d 100644
--- a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi
+++ b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi
@@ -396,6 +396,17 @@
ranges;
#address-cells = <1>;
#size-cells = <1>;
+
+ regulators@3000150 {
+ compatible = "allwinner,sun20i-d1-system-ldos";
+ reg = <0x3000150 0x4>;
+
+ reg_ldoa: ldoa {
+ };
+
+ reg_ldob: ldob {
+ };
+ };
};
dma: dma-controller@3002000 {
diff --git a/arch/riscv/boot/dts/canaan/canaan_kd233.dts b/arch/riscv/boot/dts/canaan/canaan_kd233.dts
index 8df4cf3656f2..a7d753b6fdfd 100644
--- a/arch/riscv/boot/dts/canaan/canaan_kd233.dts
+++ b/arch/riscv/boot/dts/canaan/canaan_kd233.dts
@@ -15,6 +15,10 @@
model = "Kendryte KD233";
compatible = "canaan,kendryte-kd233", "canaan,kendryte-k210";
+ aliases {
+ serial0 = &uarths0;
+ };
+
chosen {
bootargs = "earlycon console=ttySIF0";
stdout-path = "serial0:115200n8";
@@ -46,7 +50,6 @@
&fpioa {
pinctrl-0 = <&jtag_pinctrl>;
pinctrl-names = "default";
- status = "okay";
jtag_pinctrl: jtag-pinmux {
pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
@@ -118,6 +121,7 @@
#sound-dai-cells = <1>;
pinctrl-0 = <&i2s0_pinctrl>;
pinctrl-names = "default";
+ status = "okay";
};
&spi0 {
@@ -125,6 +129,7 @@
pinctrl-names = "default";
num-cs = <1>;
cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+ status = "okay";
panel@0 {
compatible = "canaan,kd233-tft", "ilitek,ili9341";
diff --git a/arch/riscv/boot/dts/canaan/k210.dtsi b/arch/riscv/boot/dts/canaan/k210.dtsi
index f87c5164d9cf..4f5d40fa1e77 100644
--- a/arch/riscv/boot/dts/canaan/k210.dtsi
+++ b/arch/riscv/boot/dts/canaan/k210.dtsi
@@ -16,13 +16,6 @@
#size-cells = <1>;
compatible = "canaan,kendryte-k210";
- aliases {
- serial0 = &uarths0;
- serial1 = &uart1;
- serial2 = &uart2;
- serial3 = &uart3;
- };
-
/*
* The K210 has an sv39 MMU following the privileged specification v1.9.
* Since this is a non-ratified draft specification, the kernel does not
@@ -137,6 +130,7 @@
reg = <0x38000000 0x1000>;
interrupts = <33>;
clocks = <&sysclk K210_CLK_CPU>;
+ status = "disabled";
};
gpio0: gpio-controller@38001000 {
@@ -152,6 +146,7 @@
<62>, <63>, <64>, <65>;
gpio-controller;
ngpios = <32>;
+ status = "disabled";
};
dmac0: dma-controller@50000000 {
@@ -187,6 +182,7 @@
<&sysclk K210_CLK_GPIO>;
clock-names = "bus", "db";
resets = <&sysrst K210_RST_GPIO>;
+ status = "disabled";
gpio1_0: gpio-port@0 {
#gpio-cells = <2>;
@@ -214,6 +210,7 @@
dsr-override;
cts-override;
ri-override;
+ status = "disabled";
};
uart2: serial@50220000 {
@@ -230,6 +227,7 @@
dsr-override;
cts-override;
ri-override;
+ status = "disabled";
};
uart3: serial@50230000 {
@@ -246,6 +244,7 @@
dsr-override;
cts-override;
ri-override;
+ status = "disabled";
};
spi2: spi@50240000 {
@@ -259,6 +258,7 @@
<&sysclk K210_CLK_APB0>;
clock-names = "ssi_clk", "pclk";
resets = <&sysrst K210_RST_SPI2>;
+ status = "disabled";
};
i2s0: i2s@50250000 {
@@ -268,6 +268,7 @@
clocks = <&sysclk K210_CLK_I2S0>;
clock-names = "i2sclk";
resets = <&sysrst K210_RST_I2S0>;
+ status = "disabled";
};
i2s1: i2s@50260000 {
@@ -277,6 +278,7 @@
clocks = <&sysclk K210_CLK_I2S1>;
clock-names = "i2sclk";
resets = <&sysrst K210_RST_I2S1>;
+ status = "disabled";
};
i2s2: i2s@50270000 {
@@ -286,6 +288,7 @@
clocks = <&sysclk K210_CLK_I2S2>;
clock-names = "i2sclk";
resets = <&sysrst K210_RST_I2S2>;
+ status = "disabled";
};
i2c0: i2c@50280000 {
@@ -296,6 +299,7 @@
<&sysclk K210_CLK_APB0>;
clock-names = "ref", "pclk";
resets = <&sysrst K210_RST_I2C0>;
+ status = "disabled";
};
i2c1: i2c@50290000 {
@@ -306,6 +310,7 @@
<&sysclk K210_CLK_APB0>;
clock-names = "ref", "pclk";
resets = <&sysrst K210_RST_I2C1>;
+ status = "disabled";
};
i2c2: i2c@502a0000 {
@@ -316,6 +321,7 @@
<&sysclk K210_CLK_APB0>;
clock-names = "ref", "pclk";
resets = <&sysrst K210_RST_I2C2>;
+ status = "disabled";
};
fpioa: pinmux@502b0000 {
@@ -464,6 +470,7 @@
reset-names = "spi";
num-cs = <4>;
reg-io-width = <4>;
+ status = "disabled";
};
spi1: spi@53000000 {
@@ -479,6 +486,7 @@
reset-names = "spi";
num-cs = <4>;
reg-io-width = <4>;
+ status = "disabled";
};
spi3: spi@54000000 {
@@ -495,6 +503,7 @@
num-cs = <4>;
reg-io-width = <4>;
+ status = "disabled";
};
};
};
diff --git a/arch/riscv/boot/dts/canaan/k210_generic.dts b/arch/riscv/boot/dts/canaan/k210_generic.dts
index 396c8ca4d24d..5734cc03753b 100644
--- a/arch/riscv/boot/dts/canaan/k210_generic.dts
+++ b/arch/riscv/boot/dts/canaan/k210_generic.dts
@@ -15,6 +15,10 @@
model = "Kendryte K210 generic";
compatible = "canaan,kendryte-k210";
+ aliases {
+ serial0 = &uarths0;
+ };
+
chosen {
bootargs = "earlycon console=ttySIF0";
stdout-path = "serial0:115200n8";
@@ -24,7 +28,6 @@
&fpioa {
pinctrl-0 = <&jtag_pins>;
pinctrl-names = "default";
- status = "okay";
jtag_pins: jtag-pinmux {
pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
diff --git a/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts b/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
index 6d25bf07481a..2ab376d609d2 100644
--- a/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
+++ b/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
@@ -17,6 +17,10 @@
compatible = "sipeed,maix-bit", "sipeed,maix-bitm",
"canaan,kendryte-k210";
+ aliases {
+ serial0 = &uarths0;
+ };
+
chosen {
bootargs = "earlycon console=ttySIF0";
stdout-path = "serial0:115200n8";
@@ -58,7 +62,6 @@
&fpioa {
pinctrl-names = "default";
pinctrl-0 = <&jtag_pinctrl>;
- status = "okay";
jtag_pinctrl: jtag-pinmux {
pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
@@ -156,6 +159,7 @@
#sound-dai-cells = <1>;
pinctrl-0 = <&i2s0_pinctrl>;
pinctrl-names = "default";
+ status = "okay";
};
&i2c1 {
@@ -170,6 +174,7 @@
pinctrl-names = "default";
num-cs = <1>;
cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+ status = "okay";
panel@0 {
compatible = "sitronix,st7789v";
@@ -199,6 +204,8 @@
};
&spi3 {
+ status = "okay";
+
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
diff --git a/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts b/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
index f4f4d8d5e8b8..d98e20775c07 100644
--- a/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
+++ b/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
@@ -17,6 +17,10 @@
compatible = "sipeed,maix-dock-m1", "sipeed,maix-dock-m1w",
"canaan,kendryte-k210";
+ aliases {
+ serial0 = &uarths0;
+ };
+
chosen {
bootargs = "earlycon console=ttySIF0";
stdout-path = "serial0:115200n8";
@@ -63,7 +67,6 @@
&fpioa {
pinctrl-0 = <&jtag_pinctrl>;
pinctrl-names = "default";
- status = "okay";
jtag_pinctrl: jtag-pinmux {
pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
@@ -159,6 +162,7 @@
#sound-dai-cells = <1>;
pinctrl-0 = <&i2s0_pinctrl>;
pinctrl-names = "default";
+ status = "okay";
};
&i2c1 {
@@ -173,6 +177,7 @@
pinctrl-names = "default";
num-cs = <1>;
cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+ status = "okay";
panel@0 {
compatible = "sitronix,st7789v";
diff --git a/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts b/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
index 0d86df47e1ed..79ecd549700a 100644
--- a/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
+++ b/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
@@ -16,6 +16,10 @@
model = "SiPeed MAIX GO";
compatible = "sipeed,maix-go", "canaan,kendryte-k210";
+ aliases {
+ serial0 = &uarths0;
+ };
+
chosen {
bootargs = "earlycon console=ttySIF0";
stdout-path = "serial0:115200n8";
@@ -69,7 +73,6 @@
&fpioa {
pinctrl-0 = <&jtag_pinctrl>;
pinctrl-names = "default";
- status = "okay";
jtag_pinctrl: jtag-pinmux {
pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
@@ -167,6 +170,7 @@
#sound-dai-cells = <1>;
pinctrl-0 = <&i2s0_pinctrl>;
pinctrl-names = "default";
+ status = "okay";
};
&i2c1 {
@@ -181,6 +185,7 @@
pinctrl-names = "default";
num-cs = <1>;
cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+ status = "okay";
panel@0 {
compatible = "sitronix,st7789v";
@@ -209,6 +214,8 @@
};
&spi3 {
+ status = "okay";
+
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
diff --git a/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts b/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
index 5c05c498e2b8..019c03ae51f6 100644
--- a/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
+++ b/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
@@ -15,6 +15,10 @@
model = "SiPeed MAIXDUINO";
compatible = "sipeed,maixduino", "canaan,kendryte-k210";
+ aliases {
+ serial0 = &uarths0;
+ };
+
chosen {
bootargs = "earlycon console=ttySIF0";
stdout-path = "serial0:115200n8";
@@ -39,8 +43,6 @@
};
&fpioa {
- status = "okay";
-
uarths_pinctrl: uarths-pinmux {
pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>, /* Header "0" */
<K210_FPIOA(5, K210_PCF_UARTHS_TX)>; /* Header "1" */
@@ -132,6 +134,7 @@
#sound-dai-cells = <1>;
pinctrl-0 = <&i2s0_pinctrl>;
pinctrl-names = "default";
+ status = "okay";
};
&i2c1 {
@@ -146,6 +149,7 @@
pinctrl-names = "default";
num-cs = <1>;
cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+ status = "okay";
panel@0 {
compatible = "sitronix,st7789v";
@@ -174,6 +178,8 @@
};
&spi3 {
+ status = "okay";
+
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
diff --git a/arch/riscv/boot/dts/microchip/Makefile b/arch/riscv/boot/dts/microchip/Makefile
index e177815bf1a2..f51aeeb9fd3b 100644
--- a/arch/riscv/boot/dts/microchip/Makefile
+++ b/arch/riscv/boot/dts/microchip/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-beaglev-fire.dtb
dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-icicle-kit.dtb
dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-m100pfsevp.dtb
dtb-$(CONFIG_ARCH_MICROCHIP_POLARFIRE) += mpfs-polarberry.dtb
diff --git a/arch/riscv/boot/dts/microchip/mpfs-beaglev-fire-fabric.dtsi b/arch/riscv/boot/dts/microchip/mpfs-beaglev-fire-fabric.dtsi
new file mode 100644
index 000000000000..e153eaf9b90e
--- /dev/null
+++ b/arch/riscv/boot/dts/microchip/mpfs-beaglev-fire-fabric.dtsi
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/ {
+ fabric_clk3: fabric-clk3 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
+ };
+
+ fabric_clk1: fabric-clk1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <125000000>;
+ };
+
+ fabric-bus@40000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x40000000 0x0 0x40000000 0x0 0x20000000>, /* FIC3-FAB */
+ <0x0 0x60000000 0x0 0x60000000 0x0 0x20000000>, /* FIC0, LO */
+ <0x0 0xe0000000 0x0 0xe0000000 0x0 0x20000000>, /* FIC1, LO */
+ <0x20 0x0 0x20 0x0 0x10 0x0>, /* FIC0,HI */
+ <0x30 0x0 0x30 0x0 0x10 0x0>; /* FIC1,HI */
+
+ cape_gpios_p8: gpio@41100000 {
+ compatible = "microchip,coregpio-rtl-v3";
+ reg = <0x0 0x41100000 0x0 0x1000>;
+ clocks = <&fabric_clk3>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <16>;
+ gpio-line-names = "P8_PIN31", "P8_PIN32", "P8_PIN33", "P8_PIN34",
+ "P8_PIN35", "P8_PIN36", "P8_PIN37", "P8_PIN38",
+ "P8_PIN39", "P8_PIN40", "P8_PIN41", "P8_PIN42",
+ "P8_PIN43", "P8_PIN44", "P8_PIN45", "P8_PIN46";
+ };
+
+ cape_gpios_p9: gpio@41200000 {
+ compatible = "microchip,coregpio-rtl-v3";
+ reg = <0x0 0x41200000 0x0 0x1000>;
+ clocks = <&fabric_clk3>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <20>;
+ gpio-line-names = "P9_PIN11", "P9_PIN12", "P9_PIN13", "P9_PIN14",
+ "P9_PIN15", "P9_PIN16", "P9_PIN17", "P9_PIN18",
+ "P9_PIN21", "P9_PIN22", "P9_PIN23", "P9_PIN24",
+ "P9_PIN25", "P9_PIN26", "P9_PIN27", "P9_PIN28",
+ "P9_PIN29", "P9_PIN31", "P9_PIN41", "P9_PIN42";
+ };
+
+ hsi_gpios: gpio@44000000 {
+ compatible = "microchip,coregpio-rtl-v3";
+ reg = <0x0 0x44000000 0x0 0x1000>;
+ clocks = <&fabric_clk3>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <20>;
+ gpio-line-names = "B0_HSIO70N", "B0_HSIO71N", "B0_HSIO83N",
+ "B0_HSIO73N_C2P_CLKN", "B0_HSIO70P", "B0_HSIO71P",
+ "B0_HSIO83P", "B0_HSIO73N_C2P_CLKP", "XCVR1_RX_VALID",
+ "XCVR1_LOCK", "XCVR1_ERROR", "XCVR2_RX_VALID",
+ "XCVR2_LOCK", "XCVR2_ERROR", "XCVR3_RX_VALID",
+ "XCVR3_LOCK", "XCVR3_ERROR", "XCVR_0B_REF_CLK_PLL_LOCK",
+ "XCVR_0C_REF_CLK_PLL_LOCK", "B0_HSIO81N";
+ };
+ };
+
+ refclk_ccc: cccrefclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+};
+
+&ccc_nw {
+ clocks = <&refclk_ccc>, <&refclk_ccc>, <&refclk_ccc>, <&refclk_ccc>,
+ <&refclk_ccc>, <&refclk_ccc>;
+ clock-names = "pll0_ref0", "pll0_ref1", "pll1_ref0", "pll1_ref1",
+ "dll0_ref", "dll1_ref";
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/microchip/mpfs-beaglev-fire.dts b/arch/riscv/boot/dts/microchip/mpfs-beaglev-fire.dts
new file mode 100644
index 000000000000..47cf693beb68
--- /dev/null
+++ b/arch/riscv/boot/dts/microchip/mpfs-beaglev-fire.dts
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2020-2021 Microchip Technology Inc */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "mpfs.dtsi"
+#include "mpfs-beaglev-fire-fabric.dtsi"
+
+/* Clock frequency (in Hz) of MTIMER */
+#define MTIMER_FREQ 1000000
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "BeagleBoard BeagleV-Fire";
+ compatible = "beagle,beaglev-fire", "microchip,mpfs";
+
+ aliases {
+ serial0 = &mmuart0;
+ serial1 = &mmuart1;
+ serial2 = &mmuart2;
+ serial3 = &mmuart3;
+ serial4 = &mmuart4;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ cpus {
+ timebase-frequency = <MTIMER_FREQ>;
+ };
+
+ ddrc_cache_lo: memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x40000000>;
+ status = "okay";
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ hss: hss-buffer@103fc00000 {
+ compatible = "shared-dma-pool";
+ reg = <0x10 0x3fc00000 0x0 0x400000>;
+ no-map;
+ };
+ };
+
+ imx219_clk: camera-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ };
+
+ imx219_vana: fixedregulator-0 {
+ compatible = "regulator-fixed";
+ regulator-name = "imx219_vana";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ imx219_vdig: fixedregulator-1 {
+ compatible = "regulator-fixed";
+ regulator-name = "imx219_vdig";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ imx219_vddl: fixedregulator-2 {
+ compatible = "regulator-fixed";
+ regulator-name = "imx219_vddl";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+};
+
+&gpio2 {
+ interrupts = <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>,
+ <53>, <53>, <53>, <53>;
+ ngpios=<32>;
+ gpio-line-names = "P8_PIN3_USER_LED_0", "P8_PIN4_USER_LED_1", "P8_PIN5_USER_LED_2",
+ "P8_PIN6_USER_LED_3", "P8_PIN7_USER_LED_4", "P8_PIN8_USER_LED_5",
+ "P8_PIN9_USER_LED_6", "P8_PIN10_USER_LED_7", "P8_PIN11_USER_LED_8",
+ "P8_PIN12_USER_LED_9", "P8_PIN13_USER_LED_10", "P8_PIN14_USER_LED_11",
+ "P8_PIN15", "P8_PIN16", "P8_PIN17", "P8_PIN18", "P8_PIN19", "P8_PIN20",
+ "P8_PIN21", "P8_PIN22", "P8_PIN23", "P8_PIN24", "P8_PIN25", "P8_PIN26",
+ "P8_PIN27", "P8_PIN28", "P8_PIN29", "P8_PIN30", "M2_W_DISABLE1",
+ "M2_W_DISABLE2", "VIO_ENABLE", "SD_DET";
+ status = "okay";
+
+ vio-enable-hog {
+ gpio-hog;
+ gpios = <30 30>;
+ output-high;
+ line-name = "VIO_ENABLE";
+ };
+
+ sd-det-hog {
+ gpio-hog;
+ gpios = <31 31>;
+ input;
+ line-name = "SD_DET";
+ };
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ eeprom: eeprom@50 {
+ compatible = "atmel,24c32";
+ reg = <0x50>;
+ };
+
+ imx219: sensor@10 {
+ compatible = "sony,imx219";
+ reg = <0x10>;
+ clocks = <&imx219_clk>;
+ VANA-supply = <&imx219_vana>; /* 2.8v */
+ VDIG-supply = <&imx219_vdig>; /* 1.8v */
+ VDDL-supply = <&imx219_vddl>; /* 1.2v */
+
+ port {
+ imx219_0: endpoint {
+ data-lanes = <1 2>;
+ clock-noncontinuous;
+ link-frequencies = /bits/ 64 <456000000>;
+ };
+ };
+ };
+};
+
+&mac0 {
+ status = "okay";
+ phy-mode = "sgmii";
+ phy-handle = <&phy0>;
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+};
+
+&mbox {
+ status = "okay";
+};
+
+&mmc {
+ bus-width = <4>;
+ disable-wp;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ status = "okay";
+};
+
+&mmuart0 {
+ status = "okay";
+};
+
+&mmuart1 {
+ status = "okay";
+};
+
+&refclk {
+ clock-frequency = <125000000>;
+};
+
+&refclk_ccc {
+ clock-frequency = <50000000>;
+};
+
+&rtc {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+};
+
+&spi1 {
+ status = "okay";
+};
+
+&syscontroller {
+ microchip,bitstream-flash = <&sys_ctrl_flash>;
+ status = "okay";
+};
+
+&syscontroller_qspi {
+ status = "okay";
+
+ sys_ctrl_flash: flash@0 { // MT25QL01GBBB8ESF-0SIT
+ compatible = "jedec,spi-nor";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <20000000>;
+ spi-rx-bus-width = <1>;
+ reg = <0>;
+ };
+};
+
+&usb {
+ status = "okay";
+ dr_mode = "otg";
+};
diff --git a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
index 49b4b9c2c101..80cb017974d8 100644
--- a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
+++ b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
@@ -14,6 +14,18 @@
};
};
+&cgi_main {
+ clock-frequency = <25000000>;
+};
+
+&cgi_dpll0 {
+ clock-frequency = <25000000>;
+};
+
+&cgi_dpll1 {
+ clock-frequency = <25000000>;
+};
+
&uart0 {
status = "okay";
};
diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi
index 81fda312f988..34c802bd3f9b 100644
--- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi
+++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi
@@ -4,8 +4,10 @@
*/
/dts-v1/;
+#include <dt-bindings/clock/sophgo,sg2042-clkgen.h>
+#include <dt-bindings/clock/sophgo,sg2042-pll.h>
+#include <dt-bindings/clock/sophgo,sg2042-rpgate.h>
#include <dt-bindings/interrupt-controller/irq.h>
-
#include <dt-bindings/reset/sophgo,sg2042-reset.h>
#include "sg2042-cpus.dtsi"
@@ -20,12 +22,60 @@
serial0 = &uart0;
};
+ cgi_main: oscillator0 {
+ compatible = "fixed-clock";
+ clock-output-names = "cgi_main";
+ #clock-cells = <0>;
+ };
+
+ cgi_dpll0: oscillator1 {
+ compatible = "fixed-clock";
+ clock-output-names = "cgi_dpll0";
+ #clock-cells = <0>;
+ };
+
+ cgi_dpll1: oscillator2 {
+ compatible = "fixed-clock";
+ clock-output-names = "cgi_dpll1";
+ #clock-cells = <0>;
+ };
+
soc: soc {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ pllclk: clock-controller@70300100c0 {
+ compatible = "sophgo,sg2042-pll";
+ reg = <0x70 0x300100c0 0x0 0x40>;
+ clocks = <&cgi_main>, <&cgi_dpll0>, <&cgi_dpll1>;
+ clock-names = "cgi_main", "cgi_dpll0", "cgi_dpll1";
+ #clock-cells = <1>;
+ };
+
+ rpgate: clock-controller@7030010368 {
+ compatible = "sophgo,sg2042-rpgate";
+ reg = <0x70 0x30010368 0x0 0x98>;
+ clocks = <&clkgen GATE_CLK_RP_CPU_NORMAL>;
+ clock-names = "rpgate";
+ #clock-cells = <1>;
+ };
+
+ clkgen: clock-controller@7030012000 {
+ compatible = "sophgo,sg2042-clkgen";
+ reg = <0x70 0x30012000 0x0 0x1000>;
+ clocks = <&pllclk MPLL_CLK>,
+ <&pllclk FPLL_CLK>,
+ <&pllclk DPLL0_CLK>,
+ <&pllclk DPLL1_CLK>;
+ clock-names = "mpll",
+ "fpll",
+ "dpll0",
+ "dpll1";
+ #clock-cells = <1>;
+ };
+
clint_mswi: interrupt-controller@7094000000 {
compatible = "sophgo,sg2042-aclint-mswi", "thead,c900-aclint-mswi";
reg = <0x00000070 0x94000000 0x00000000 0x00004000>;
@@ -341,6 +391,9 @@
interrupt-parent = <&intc>;
interrupts = <112 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <500000000>;
+ clocks = <&clkgen GATE_CLK_UART_500M>,
+ <&clkgen GATE_CLK_APB_UART>;
+ clock-names = "baudclk", "apb_pclk";
reg-shift = <2>;
reg-io-width = <4>;
resets = <&rstgen RST_UART0>;
diff --git a/arch/riscv/boot/dts/starfive/Makefile b/arch/riscv/boot/dts/starfive/Makefile
index 2fa0cd7f31c3..7a163a7d6ba3 100644
--- a/arch/riscv/boot/dts/starfive/Makefile
+++ b/arch/riscv/boot/dts/starfive/Makefile
@@ -9,5 +9,6 @@ dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-beaglev-starlight.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-starfive-visionfive-v1.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
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb
diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
index 8ff6ea64f048..ca2d44d59d48 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
@@ -244,7 +244,7 @@
regulator-boot-on;
regulator-always-on;
regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
regulator-name = "emmc_vdd";
};
};
@@ -294,6 +294,20 @@
status = "okay";
};
+&pcie0 {
+ perst-gpios = <&sysgpio 26 GPIO_ACTIVE_LOW>;
+ phys = <&pciephy0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_pins>;
+};
+
+&pcie1 {
+ perst-gpios = <&sysgpio 28 GPIO_ACTIVE_LOW>;
+ phys = <&pciephy1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_pins>;
+};
+
&pwmdac {
pinctrl-names = "default";
pinctrl-0 = <&pwmdac_pins>;
@@ -321,16 +335,13 @@
#size-cells = <1>;
spl@0 {
- reg = <0x0 0x80000>;
+ reg = <0x0 0xf0000>;
};
uboot-env@f0000 {
reg = <0xf0000 0x10000>;
};
uboot@100000 {
- reg = <0x100000 0x400000>;
- };
- reserved-data@600000 {
- reg = <0x600000 0xa00000>;
+ reg = <0x100000 0xf00000>;
};
};
};
@@ -476,6 +487,54 @@
};
};
+ pcie0_pins: pcie0-0 {
+ clkreq-pins {
+ pinmux = <GPIOMUX(27, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-down;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ wake-pins {
+ pinmux = <GPIOMUX(32, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-up;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
+ pcie1_pins: pcie1-0 {
+ clkreq-pins {
+ pinmux = <GPIOMUX(29, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-down;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ wake-pins {
+ pinmux = <GPIOMUX(21, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-up;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
pwmdac_pins: pwmdac-0 {
pwmdac-pins {
pinmux = <GPIOMUX(33, GPOUT_SYS_PWMDAC_LEFT,
diff --git a/arch/riscv/boot/dts/starfive/jh7110-milkv-mars.dts b/arch/riscv/boot/dts/starfive/jh7110-milkv-mars.dts
index fa0eac78e0ba..5cb9e99e1dac 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-milkv-mars.dts
+++ b/arch/riscv/boot/dts/starfive/jh7110-milkv-mars.dts
@@ -17,6 +17,13 @@
assigned-clock-parents = <&aoncrg JH7110_AONCLK_GMAC0_RMII_RTX>;
};
+&pcie0 {
+ status = "okay";
+};
+
+&pcie1 {
+ status = "okay";
+};
&phy0 {
motorcomm,tx-clk-adj-enabled;
diff --git a/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts b/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts
new file mode 100644
index 000000000000..b720cdd15ed6
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2024 Henry Bell <[email protected]>
+ */
+
+/dts-v1/;
+#include "jh7110-common.dtsi"
+
+/ {
+ model = "Pine64 Star64";
+ compatible = "pine64,star64", "starfive,jh7110";
+ aliases {
+ ethernet1 = &gmac1;
+ };
+};
+
+&gmac0 {
+ starfive,tx-use-rgmii-clk;
+ assigned-clocks = <&aoncrg JH7110_AONCLK_GMAC0_TX>;
+ assigned-clock-parents = <&aoncrg JH7110_AONCLK_GMAC0_RMII_RTX>;
+};
+
+&gmac1 {
+ phy-handle = <&phy1>;
+ phy-mode = "rgmii-id";
+ starfive,tx-use-rgmii-clk;
+ assigned-clocks = <&syscrg JH7110_SYSCLK_GMAC1_TX>;
+ assigned-clock-parents = <&syscrg JH7110_SYSCLK_GMAC1_RMII_RTX>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+};
+
+&pcie1 {
+ status = "okay";
+};
+
+&phy0 {
+ rx-internal-delay-ps = <1900>;
+ tx-internal-delay-ps = <1500>;
+ motorcomm,rx-clk-drv-microamp = <2910>;
+ motorcomm,rx-data-drv-microamp = <2910>;
+ motorcomm,tx-clk-adj-enabled;
+ motorcomm,tx-clk-10-inverted;
+ motorcomm,tx-clk-100-inverted;
+ motorcomm,tx-clk-1000-inverted;
+};
+
+&phy1 {
+ rx-internal-delay-ps = <0>;
+ tx-internal-delay-ps = <300>;
+ motorcomm,rx-clk-drv-microamp = <2910>;
+ motorcomm,rx-data-drv-microamp = <2910>;
+ motorcomm,tx-clk-adj-enabled;
+ motorcomm,tx-clk-10-inverted;
+ motorcomm,tx-clk-100-inverted;
+};
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 9d70f21c86fc..18f38fc790a4 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
@@ -32,3 +32,11 @@
&mmc0 {
non-removable;
};
+
+&pcie0 {
+ status = "okay";
+};
+
+&pcie1 {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index 18047195c600..5ac70759e0ab 100644
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -1214,5 +1214,91 @@
#reset-cells = <1>;
power-domains = <&pwrc JH7110_PD_VOUT>;
};
+
+ pcie0: pcie@940000000 {
+ compatible = "starfive,jh7110-pcie";
+ reg = <0x9 0x40000000 0x0 0x1000000>,
+ <0x0 0x2b000000 0x0 0x100000>;
+ reg-names = "cfg", "apb";
+ linux,pci-domain = <0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0x0 0x30000000 0x0 0x30000000 0x0 0x08000000>,
+ <0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>;
+ interrupts = <56>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc0 0x1>,
+ <0x0 0x0 0x0 0x2 &pcie_intc0 0x2>,
+ <0x0 0x0 0x0 0x3 &pcie_intc0 0x3>,
+ <0x0 0x0 0x0 0x4 &pcie_intc0 0x4>;
+ msi-controller;
+ device_type = "pci";
+ starfive,stg-syscon = <&stg_syscon>;
+ bus-range = <0x0 0xff>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
+ <&stgcrg JH7110_STGCLK_PCIE0_TL>,
+ <&stgcrg JH7110_STGCLK_PCIE0_AXI_MST0>,
+ <&stgcrg JH7110_STGCLK_PCIE0_APB>;
+ clock-names = "noc", "tl", "axi_mst0", "apb";
+ resets = <&stgcrg JH7110_STGRST_PCIE0_AXI_MST0>,
+ <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV0>,
+ <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV>,
+ <&stgcrg JH7110_STGRST_PCIE0_BRG>,
+ <&stgcrg JH7110_STGRST_PCIE0_CORE>,
+ <&stgcrg JH7110_STGRST_PCIE0_APB>;
+ reset-names = "mst0", "slv0", "slv", "brg",
+ "core", "apb";
+ status = "disabled";
+
+ pcie_intc0: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+
+ pcie1: pcie@9c0000000 {
+ compatible = "starfive,jh7110-pcie";
+ reg = <0x9 0xc0000000 0x0 0x1000000>,
+ <0x0 0x2c000000 0x0 0x100000>;
+ reg-names = "cfg", "apb";
+ linux,pci-domain = <1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0x0 0x38000000 0x0 0x38000000 0x0 0x08000000>,
+ <0xc3000000 0x9 0x80000000 0x9 0x80000000 0x0 0x40000000>;
+ interrupts = <57>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc1 0x1>,
+ <0x0 0x0 0x0 0x2 &pcie_intc1 0x2>,
+ <0x0 0x0 0x0 0x3 &pcie_intc1 0x3>,
+ <0x0 0x0 0x0 0x4 &pcie_intc1 0x4>;
+ msi-controller;
+ device_type = "pci";
+ starfive,stg-syscon = <&stg_syscon>;
+ bus-range = <0x0 0xff>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
+ <&stgcrg JH7110_STGCLK_PCIE1_TL>,
+ <&stgcrg JH7110_STGCLK_PCIE1_AXI_MST0>,
+ <&stgcrg JH7110_STGCLK_PCIE1_APB>;
+ clock-names = "noc", "tl", "axi_mst0", "apb";
+ resets = <&stgcrg JH7110_STGRST_PCIE1_AXI_MST0>,
+ <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV0>,
+ <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV>,
+ <&stgcrg JH7110_STGRST_PCIE1_BRG>,
+ <&stgcrg JH7110_STGRST_PCIE1_CORE>,
+ <&stgcrg JH7110_STGRST_PCIE1_APB>;
+ reset-names = "mst0", "slv0", "slv", "brg",
+ "core", "apb";
+ status = "disabled";
+
+ pcie_intc1: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
};
};
diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/thead/th1520.dtsi
index d2fa25839012..3c9974062c20 100644
--- a/arch/riscv/boot/dts/thead/th1520.dtsi
+++ b/arch/riscv/boot/dts/thead/th1520.dtsi
@@ -122,6 +122,87 @@
};
};
+ pmu {
+ compatible = "riscv,pmu";
+ riscv,event-to-mhpmcounters =
+ <0x00003 0x00003 0x0007fff8>,
+ <0x00004 0x00004 0x0007fff8>,
+ <0x00005 0x00005 0x0007fff8>,
+ <0x00006 0x00006 0x0007fff8>,
+ <0x00007 0x00007 0x0007fff8>,
+ <0x00008 0x00008 0x0007fff8>,
+ <0x00009 0x00009 0x0007fff8>,
+ <0x0000a 0x0000a 0x0007fff8>,
+ <0x10000 0x10000 0x0007fff8>,
+ <0x10001 0x10001 0x0007fff8>,
+ <0x10002 0x10002 0x0007fff8>,
+ <0x10003 0x10003 0x0007fff8>,
+ <0x10010 0x10010 0x0007fff8>,
+ <0x10011 0x10011 0x0007fff8>,
+ <0x10012 0x10012 0x0007fff8>,
+ <0x10013 0x10013 0x0007fff8>;
+ riscv,event-to-mhpmevent =
+ <0x00003 0x00000000 0x00000001>,
+ <0x00004 0x00000000 0x00000002>,
+ <0x00006 0x00000000 0x00000006>,
+ <0x00005 0x00000000 0x00000007>,
+ <0x00007 0x00000000 0x00000008>,
+ <0x00008 0x00000000 0x00000009>,
+ <0x00009 0x00000000 0x0000000a>,
+ <0x0000a 0x00000000 0x0000000b>,
+ <0x10000 0x00000000 0x0000000c>,
+ <0x10001 0x00000000 0x0000000d>,
+ <0x10002 0x00000000 0x0000000e>,
+ <0x10003 0x00000000 0x0000000f>,
+ <0x10010 0x00000000 0x00000010>,
+ <0x10011 0x00000000 0x00000011>,
+ <0x10012 0x00000000 0x00000012>,
+ <0x10013 0x00000000 0x00000013>;
+ riscv,raw-event-to-mhpmcounters =
+ <0x00000000 0x00000001 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000002 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000003 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000004 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000005 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000006 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000007 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000008 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000009 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000000a 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000000b 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000000c 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000000d 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000000e 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000000f 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000010 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000011 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000012 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000013 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000014 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000015 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000016 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000017 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000018 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000019 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000001a 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000001b 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000001c 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000001d 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000001e 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000001f 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000020 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000021 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000022 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000023 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000024 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000025 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000026 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000027 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000028 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x00000029 0xffffffff 0xffffffff 0x0007fff8>,
+ <0x00000000 0x0000002a 0xffffffff 0xffffffff 0x0007fff8>;
+ };
+
osc: oscillator {
compatible = "fixed-clock";
clock-output-names = "osc_24m";
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 12dc8c73a8ac..3f1f055866af 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -110,8 +110,10 @@ CONFIG_PCIEPORTBUS=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCIE_XILINX=y
CONFIG_PCIE_FU740=y
+CONFIG_PCIE_STARFIVE_HOST=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_SIFIVE_CCACHE=y
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
@@ -143,6 +145,7 @@ CONFIG_RAVB=y
CONFIG_STMMAC_ETH=m
CONFIG_MICREL_PHY=y
CONFIG_MICROSEMI_PHY=y
+CONFIG_MOTORCOMM_PHY=y
CONFIG_CAN_RCAR_CANFD=m
CONFIG_INPUT_MOUSEDEV=y
CONFIG_KEYBOARD_SUN4I_LRADC=m
@@ -155,24 +158,35 @@ CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
+CONFIG_HW_RANDOM_JH7110=m
+CONFIG_I2C=y
CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_I2C_MV64XXX=m
CONFIG_I2C_RIIC=y
CONFIG_SPI=y
+CONFIG_SPI_CADENCE_QUADSPI=m
+CONFIG_SPI_PL022=m
CONFIG_SPI_RSPI=m
CONFIG_SPI_SIFIVE=y
CONFIG_SPI_SUN6I=y
# CONFIG_PTP_1588_CLOCK is not set
CONFIG_GPIO_SIFIVE=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_SENSORS_SFCTEMP=m
CONFIG_CPU_THERMAL=y
CONFIG_DEVFREQ_THERMAL=y
CONFIG_RZG2L_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=y
CONFIG_RENESAS_RZG2LWDT=y
+CONFIG_MFD_AXP20X_I2C=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_GPIO=y
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_VIDEO_CADENCE_CSI2RX=m
CONFIG_DRM=m
CONFIG_DRM_RADEON=m
CONFIG_DRM_NOUVEAU=m
@@ -184,6 +198,10 @@ CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_RZ=m
+CONFIG_SND_DESIGNWARE_I2S=m
+CONFIG_SND_SOC_STARFIVE=m
+CONFIG_SND_SOC_JH7110_PWMDAC=m
+CONFIG_SND_SOC_JH7110_TDM=m
CONFIG_SND_SOC_WM8978=m
CONFIG_SND_SIMPLE_CARD=m
CONFIG_USB=y
@@ -197,6 +215,11 @@ CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_RENESAS_USBHS=m
CONFIG_USB_STORAGE=y
CONFIG_USB_UAS=y
+CONFIG_USB_CDNS_SUPPORT=m
+CONFIG_USB_CDNS3=m
+CONFIG_USB_CDNS3_GADGET=y
+CONFIG_USB_CDNS3_HOST=y
+CONFIG_USB_CDNS3_STARFIVE=m
CONFIG_USB_MUSB_HDRC=m
CONFIG_USB_MUSB_SUNXI=m
CONFIG_NOP_USB_XCEIV=m
@@ -246,6 +269,9 @@ CONFIG_RZG2L_ADC=m
CONFIG_RESET_RZG2L_USBPHY_CTRL=y
CONFIG_PHY_SUN4I_USB=m
CONFIG_PHY_RCAR_GEN3_USB2=y
+CONFIG_PHY_STARFIVE_JH7110_DPHY_RX=m
+CONFIG_PHY_STARFIVE_JH7110_PCIE=m
+CONFIG_PHY_STARFIVE_JH7110_USB=m
CONFIG_LIBNVDIMM=y
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_EXT4_FS=y
diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild
index 504f8b7e72d4..5c589770f2a8 100644
--- a/arch/riscv/include/asm/Kbuild
+++ b/arch/riscv/include/asm/Kbuild
@@ -1,4 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += syscall_table_32.h
+syscall-y += syscall_table_64.h
+
generic-y += early_ioremap.h
generic-y += flat.h
generic-y += kvm_para.h
diff --git a/arch/riscv/include/asm/syscall_table.h b/arch/riscv/include/asm/syscall_table.h
new file mode 100644
index 000000000000..0c2d61782813
--- /dev/null
+++ b/arch/riscv/include/asm/syscall_table.h
@@ -0,0 +1,7 @@
+#include <asm/bitsperlong.h>
+
+#if __BITS_PER_LONG == 64
+#include <asm/syscall_table_64.h>
+#else
+#include <asm/syscall_table_32.h>
+#endif
diff --git a/arch/riscv/include/asm/unistd.h b/arch/riscv/include/asm/unistd.h
index 221630bdbd07..e6d904fa67c5 100644
--- a/arch/riscv/include/asm/unistd.h
+++ b/arch/riscv/include/asm/unistd.h
@@ -3,11 +3,6 @@
* Copyright (C) 2012 Regents of the University of California
*/
-/*
- * There is explicitly no include guard here because this file is expected to
- * be included multiple times.
- */
-
#define __ARCH_WANT_SYS_CLONE
#ifdef CONFIG_COMPAT
@@ -21,6 +16,14 @@
#define __ARCH_WANT_COMPAT_FADVISE64_64
#endif
+#if defined(__LP64__) && !defined(__SYSCALL_COMPAT)
+#define __ARCH_WANT_NEW_STAT
+#define __ARCH_WANT_SET_GET_RLIMIT
+#endif /* __LP64__ */
+
+#define __ARCH_WANT_MEMFD_SECRET
+
+
#include <uapi/asm/unistd.h>
#define NR_syscalls (__NR_syscalls)
diff --git a/arch/riscv/include/uapi/asm/Kbuild b/arch/riscv/include/uapi/asm/Kbuild
index f66554cd5c45..89ac01faa5ae 100644
--- a/arch/riscv/include/uapi/asm/Kbuild
+++ b/arch/riscv/include/uapi/asm/Kbuild
@@ -1 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
+syscall-y += unistd_32.h
+syscall-y += unistd_64.h
diff --git a/arch/riscv/include/uapi/asm/unistd.h b/arch/riscv/include/uapi/asm/unistd.h
index 950ab3fd4409..81896bbbf727 100644
--- a/arch/riscv/include/uapi/asm/unistd.h
+++ b/arch/riscv/include/uapi/asm/unistd.h
@@ -14,41 +14,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include <asm/bitsperlong.h>
-#if defined(__LP64__) && !defined(__SYSCALL_COMPAT)
-#define __ARCH_WANT_NEW_STAT
-#define __ARCH_WANT_SET_GET_RLIMIT
-#endif /* __LP64__ */
-
-#define __ARCH_WANT_SYS_CLONE3
-#define __ARCH_WANT_MEMFD_SECRET
-
-#include <asm-generic/unistd.h>
-
-/*
- * Allows the instruction cache to be flushed from userspace. Despite RISC-V
- * having a direct 'fence.i' instruction available to userspace (which we
- * can't trap!), that's not actually viable when running on Linux because the
- * kernel might schedule a process on another hart. There is no way for
- * userspace to handle this without invoking the kernel (as it doesn't know the
- * thread->hart mappings), so we've defined a RISC-V specific system call to
- * flush the instruction cache.
- *
- * __NR_riscv_flush_icache is defined to flush the instruction cache over an
- * address range, with the flush applying to either all threads or just the
- * caller. We don't currently do anything with the address range, that's just
- * in there for forwards compatibility.
- */
-#ifndef __NR_riscv_flush_icache
-#define __NR_riscv_flush_icache (__NR_arch_specific_syscall + 15)
-#endif
-__SYSCALL(__NR_riscv_flush_icache, sys_riscv_flush_icache)
-
-/*
- * Allows userspace to query the kernel for CPU architecture and
- * microarchitecture details across a given set of CPUs.
- */
-#ifndef __NR_riscv_hwprobe
-#define __NR_riscv_hwprobe (__NR_arch_specific_syscall + 14)
+#if __BITS_PER_LONG == 64
+#include <asm/unistd_64.h>
+#else
+#include <asm/unistd_32.h>
#endif
-__SYSCALL(__NR_riscv_hwprobe, sys_riscv_hwprobe)
diff --git a/arch/riscv/kernel/Makefile.syscalls b/arch/riscv/kernel/Makefile.syscalls
new file mode 100644
index 000000000000..52087a023b3d
--- /dev/null
+++ b/arch/riscv/kernel/Makefile.syscalls
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+syscall_abis_32 += riscv memfd_secret
+syscall_abis_64 += riscv newstat rlimit memfd_secret
diff --git a/arch/riscv/kernel/compat_syscall_table.c b/arch/riscv/kernel/compat_syscall_table.c
index ad7f2d712f5f..e884c069e88f 100644
--- a/arch/riscv/kernel/compat_syscall_table.c
+++ b/arch/riscv/kernel/compat_syscall_table.c
@@ -8,9 +8,11 @@
#include <asm-generic/syscalls.h>
#include <asm/syscall.h>
+#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, compat)
+
#undef __SYSCALL
#define __SYSCALL(nr, call) asmlinkage long __riscv_##call(const struct pt_regs *);
-#include <asm/unistd.h>
+#include <asm/syscall_table_32.h>
#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = __riscv_##call,
@@ -19,5 +21,5 @@ asmlinkage long compat_sys_rt_sigreturn(void);
void * const compat_sys_call_table[__NR_syscalls] = {
[0 ... __NR_syscalls - 1] = __riscv_sys_ni_syscall,
-#include <asm/unistd.h>
+#include <asm/syscall_table_32.h>
};
diff --git a/arch/riscv/kernel/machine_kexec.c b/arch/riscv/kernel/machine_kexec.c
index ed9cad20c039..3c830a6f7ef4 100644
--- a/arch/riscv/kernel/machine_kexec.c
+++ b/arch/riscv/kernel/machine_kexec.c
@@ -121,20 +121,12 @@ static void machine_kexec_mask_interrupts(void)
for_each_irq_desc(i, desc) {
struct irq_chip *chip;
- int ret;
chip = irq_desc_get_chip(desc);
if (!chip)
continue;
- /*
- * First try to remove the active state. If this
- * fails, try to EOI the interrupt.
- */
- ret = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false);
-
- if (ret && irqd_irq_inprogress(&desc->irq_data) &&
- chip->irq_eoi)
+ if (chip->irq_eoi && irqd_irq_inprogress(&desc->irq_data))
chip->irq_eoi(&desc->irq_data);
if (chip->irq_mask)
diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c
index 0d3f00eb0bae..10e311b2759d 100644
--- a/arch/riscv/kernel/stacktrace.c
+++ b/arch/riscv/kernel/stacktrace.c
@@ -32,6 +32,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
bool (*fn)(void *, unsigned long), void *arg)
{
unsigned long fp, sp, pc;
+ int graph_idx = 0;
int level = 0;
if (regs) {
@@ -68,7 +69,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
pc = regs->ra;
} else {
fp = frame->fp;
- pc = ftrace_graph_ret_addr(current, NULL, frame->ra,
+ pc = ftrace_graph_ret_addr(current, &graph_idx, frame->ra,
&frame->ra);
if (pc == (unsigned long)ret_from_exception) {
if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc)))
diff --git a/arch/riscv/kernel/syscall_table.c b/arch/riscv/kernel/syscall_table.c
index dda913764903..6f1a36cb0f3f 100644
--- a/arch/riscv/kernel/syscall_table.c
+++ b/arch/riscv/kernel/syscall_table.c
@@ -9,14 +9,16 @@
#include <asm-generic/syscalls.h>
#include <asm/syscall.h>
+#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
+
#undef __SYSCALL
#define __SYSCALL(nr, call) asmlinkage long __riscv_##call(const struct pt_regs *);
-#include <asm/unistd.h>
+#include <asm/syscall_table.h>
#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = __riscv_##call,
void * const sys_call_table[__NR_syscalls] = {
[0 ... __NR_syscalls - 1] = __riscv_sys_ni_syscall,
-#include <asm/unistd.h>
+#include <asm/syscall_table.h>
};
diff --git a/arch/riscv/kvm/vcpu_pmu.c b/arch/riscv/kvm/vcpu_pmu.c
index 04db1f993c47..bcf41d6e0df0 100644
--- a/arch/riscv/kvm/vcpu_pmu.c
+++ b/arch/riscv/kvm/vcpu_pmu.c
@@ -327,7 +327,7 @@ static long kvm_pmu_create_perf_event(struct kvm_pmc *pmc, struct perf_event_att
event = perf_event_create_kernel_counter(attr, -1, current, kvm_riscv_pmu_overflow, pmc);
if (IS_ERR(event)) {
- pr_err("kvm pmu event creation failed for eidx %lx: %ld\n", eidx, PTR_ERR(event));
+ pr_debug("kvm pmu event creation failed for eidx %lx: %ld\n", eidx, PTR_ERR(event));
return PTR_ERR(event);
}
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig
index 8c4adece8911..f3602414a961 100644
--- a/arch/s390/configs/debug_defconfig
+++ b/arch/s390/configs/debug_defconfig
@@ -601,17 +601,16 @@ CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_SOFT_WATCHDOG=m
CONFIG_DIAG288_WATCHDOG=m
+CONFIG_DRM=m
+CONFIG_DRM_VIRTIO_GPU=m
CONFIG_FB=y
# CONFIG_FB_DEVICE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_INFINIBAND=m
CONFIG_INFINIBAND_USER_ACCESS=m
CONFIG_MLX4_INFINIBAND=m
CONFIG_MLX5_INFINIBAND=m
-CONFIG_SYNC_FILE=y
CONFIG_VFIO=m
CONFIG_VFIO_PCI=m
CONFIG_MLX5_VFIO_PCI=m
diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig
index 6dd11d3b6aaa..d0d8925fdf09 100644
--- a/arch/s390/configs/defconfig
+++ b/arch/s390/configs/defconfig
@@ -592,17 +592,16 @@ CONFIG_WATCHDOG_CORE=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_SOFT_WATCHDOG=m
CONFIG_DIAG288_WATCHDOG=m
+CONFIG_DRM=m
+CONFIG_DRM_VIRTIO_GPU=m
CONFIG_FB=y
# CONFIG_FB_DEVICE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_INFINIBAND=m
CONFIG_INFINIBAND_USER_ACCESS=m
CONFIG_MLX4_INFINIBAND=m
CONFIG_MLX5_INFINIBAND=m
-CONFIG_SYNC_FILE=y
CONFIG_VFIO=m
CONFIG_VFIO_PCI=m
CONFIG_MLX5_VFIO_PCI=m
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 95990461888f..9281063636a7 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -427,6 +427,7 @@ struct kvm_vcpu_stat {
u64 instruction_io_other;
u64 instruction_lpsw;
u64 instruction_lpswe;
+ u64 instruction_lpswey;
u64 instruction_pfmf;
u64 instruction_ptff;
u64 instruction_sck;
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h
index 4260bc5ce7f8..70fc671397da 100644
--- a/arch/s390/include/asm/unistd.h
+++ b/arch/s390/include/asm/unistd.h
@@ -35,6 +35,5 @@
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_VFORK
#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
#endif /* _ASM_S390_UNISTD_H_ */
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 82e9631cd9ef..54b5b2565df8 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -132,6 +132,7 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
STATS_DESC_COUNTER(VCPU, instruction_io_other),
STATS_DESC_COUNTER(VCPU, instruction_lpsw),
STATS_DESC_COUNTER(VCPU, instruction_lpswe),
+ STATS_DESC_COUNTER(VCPU, instruction_lpswey),
STATS_DESC_COUNTER(VCPU, instruction_pfmf),
STATS_DESC_COUNTER(VCPU, instruction_ptff),
STATS_DESC_COUNTER(VCPU, instruction_sck),
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 111eb5c74784..bf8534218af3 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -138,6 +138,21 @@ static inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu, u8 *ar)
return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
}
+static inline u64 kvm_s390_get_base_disp_siy(struct kvm_vcpu *vcpu, u8 *ar)
+{
+ u32 base1 = vcpu->arch.sie_block->ipb >> 28;
+ s64 disp1;
+
+ /* The displacement is a 20bit _SIGNED_ value */
+ disp1 = sign_extend64(((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
+ ((vcpu->arch.sie_block->ipb & 0xff00) << 4), 19);
+
+ if (ar)
+ *ar = base1;
+
+ return (base1 ? vcpu->run->s.regs.gprs[base1] : 0) + disp1;
+}
+
static inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu,
u64 *address1, u64 *address2,
u8 *ar_b1, u8 *ar_b2)
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 1be19cc9d73c..1a49b89706f8 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -797,6 +797,36 @@ static int handle_lpswe(struct kvm_vcpu *vcpu)
return 0;
}
+static int handle_lpswey(struct kvm_vcpu *vcpu)
+{
+ psw_t new_psw;
+ u64 addr;
+ int rc;
+ u8 ar;
+
+ vcpu->stat.instruction_lpswey++;
+
+ if (!test_kvm_facility(vcpu->kvm, 193))
+ return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
+
+ if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
+ return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
+
+ addr = kvm_s390_get_base_disp_siy(vcpu, &ar);
+ if (addr & 7)
+ return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+ rc = read_guest(vcpu, addr, ar, &new_psw, sizeof(new_psw));
+ if (rc)
+ return kvm_s390_inject_prog_cond(vcpu, rc);
+
+ vcpu->arch.sie_block->gpsw = new_psw;
+ if (!is_valid_psw(&vcpu->arch.sie_block->gpsw))
+ return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+ return 0;
+}
+
static int handle_stidp(struct kvm_vcpu *vcpu)
{
u64 stidp_data = vcpu->kvm->arch.model.cpuid;
@@ -1462,6 +1492,8 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu)
case 0x61:
case 0x62:
return handle_ri(vcpu);
+ case 0x71:
+ return handle_lpswey(vcpu);
default:
return -EOPNOTSUPP;
}
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index abb629d7e131..7e3e767ab87d 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -55,6 +55,8 @@ unsigned long *crst_table_alloc(struct mm_struct *mm)
void crst_table_free(struct mm_struct *mm, unsigned long *table)
{
+ if (!table)
+ return;
pagetable_free(virt_to_ptdesc(table));
}
@@ -262,6 +264,8 @@ static unsigned long *base_crst_alloc(unsigned long val)
static void base_crst_free(unsigned long *table)
{
+ if (!table)
+ return;
pagetable_free(virt_to_ptdesc(table));
}
diff --git a/arch/sh/include/asm/unistd.h b/arch/sh/include/asm/unistd.h
index d6e126250136..3d7f35650a13 100644
--- a/arch/sh/include/asm/unistd.h
+++ b/arch/sh/include/asm/unistd.h
@@ -28,4 +28,6 @@
# define __ARCH_WANT_SYS_VFORK
# define __ARCH_WANT_SYS_CLONE
+#define __ARCH_BROKEN_SYS_CLONE3
+
#include <uapi/asm/unistd.h>
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h
index d6bc76706a7a..3380411a4537 100644
--- a/arch/sparc/include/asm/unistd.h
+++ b/arch/sparc/include/asm/unistd.h
@@ -49,6 +49,8 @@
#define __ARCH_WANT_COMPAT_STAT
#endif
+#define __ARCH_BROKEN_SYS_CLONE3
+
#ifdef __32bit_syscall_numbers__
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
* it never had the plain ones and there is no value to adding those
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index ef805eaa9e01..9f1e76ddda5a 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -447,43 +447,31 @@ static int bulk_req_safe_read(
return n;
}
-/* Called without dev->lock held, and only in interrupt context. */
-static void ubd_handler(void)
+static void ubd_end_request(struct io_thread_req *io_req)
{
- int n;
- int count;
-
- while(1){
- n = bulk_req_safe_read(
- thread_fd,
- irq_req_buffer,
- &irq_remainder,
- &irq_remainder_size,
- UBD_REQ_BUFFER_SIZE
- );
- if (n < 0) {
- if(n == -EAGAIN)
- break;
- printk(KERN_ERR "spurious interrupt in ubd_handler, "
- "err = %d\n", -n);
- return;
- }
- for (count = 0; count < n/sizeof(struct io_thread_req *); count++) {
- struct io_thread_req *io_req = (*irq_req_buffer)[count];
-
- if ((io_req->error == BLK_STS_NOTSUPP) && (req_op(io_req->req) == REQ_OP_DISCARD)) {
- blk_queue_max_discard_sectors(io_req->req->q, 0);
- blk_queue_max_write_zeroes_sectors(io_req->req->q, 0);
- }
- blk_mq_end_request(io_req->req, io_req->error);
- kfree(io_req);
- }
+ if (io_req->error == BLK_STS_NOTSUPP) {
+ if (req_op(io_req->req) == REQ_OP_DISCARD)
+ blk_queue_disable_discard(io_req->req->q);
+ else if (req_op(io_req->req) == REQ_OP_WRITE_ZEROES)
+ blk_queue_disable_write_zeroes(io_req->req->q);
}
+ blk_mq_end_request(io_req->req, io_req->error);
+ kfree(io_req);
}
static irqreturn_t ubd_intr(int irq, void *dev)
{
- ubd_handler();
+ int len, i;
+
+ while ((len = bulk_req_safe_read(thread_fd, irq_req_buffer,
+ &irq_remainder, &irq_remainder_size,
+ UBD_REQ_BUFFER_SIZE)) >= 0) {
+ for (i = 0; i < len / sizeof(struct io_thread_req *); i++)
+ ubd_end_request((*irq_req_buffer)[i]);
+ }
+
+ if (len < 0 && len != -EAGAIN)
+ pr_err("spurious interrupt in %s, err = %d\n", __func__, len);
return IRQ_HANDLED;
}
@@ -847,6 +835,7 @@ static int ubd_add(int n, char **error_out)
struct queue_limits lim = {
.max_segments = MAX_SG,
.seg_boundary_mask = PAGE_SIZE - 1,
+ .features = BLK_FEAT_WRITE_CACHE,
};
struct gendisk *disk;
int err = 0;
@@ -893,8 +882,6 @@ static int ubd_add(int n, char **error_out)
goto out_cleanup_tags;
}
- blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
- blk_queue_write_cache(disk->queue, true, false);
disk->major = UBD_MAJOR;
disk->first_minor = n << UBD_SHIFT;
disk->minors = 1 << UBD_SHIFT;
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 6fe34779291a..6c583040537c 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -1,5 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-generic-y += bpf_perf_event.h
generic-y += bug.h
generic-y += compat.h
generic-y += current.h
diff --git a/arch/um/include/asm/bpf_perf_event.h b/arch/um/include/asm/bpf_perf_event.h
new file mode 100644
index 000000000000..287221342d2c
--- /dev/null
+++ b/arch/um/include/asm/bpf_perf_event.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * asm-generic/bpf_perf_event.h is part of the uapi headers, but since
+ * arch/um has no uapi of its on, we can't use the "generic-y"
+ * Kbuild rule to generate the wrapper
+ */
+
+#include <asm-generic/bpf_perf_event.h>
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 1d7122a1883e..9778234cf111 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1118,6 +1118,13 @@ config X86_LOCAL_APIC
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI
select IRQ_DOMAIN_HIERARCHY
+config ACPI_MADT_WAKEUP
+ def_bool y
+ depends on X86_64
+ depends on ACPI
+ depends on SMP
+ depends on X86_LOCAL_APIC
+
config X86_IO_APIC
def_bool y
depends on X86_LOCAL_APIC || X86_UP_IOAPIC
@@ -2038,26 +2045,6 @@ config EFI_MIXED
If unsure, say N.
-config EFI_FAKE_MEMMAP
- bool "Enable EFI fake memory map"
- depends on EFI
- help
- Saying Y here will enable "efi_fake_mem" boot option. By specifying
- this parameter, you can add arbitrary attribute to specific memory
- range by updating original (firmware provided) EFI memmap. This is
- useful for debugging of EFI memmap related feature, e.g., Address
- Range Mirroring feature.
-
-config EFI_MAX_FAKE_MEM
- int "maximum allowable number of ranges in efi_fake_mem boot option"
- depends on EFI_FAKE_MEMMAP
- range 1 128
- default 8
- help
- Maximum allowable number of ranges in efi_fake_mem boot option.
- Ranges can be set up to this value using comma-separated list.
- The default value is 8.
-
config EFI_RUNTIME_MAP
bool "Export EFI runtime maps to sysfs" if EXPERT
depends on EFI
diff --git a/arch/x86/Kconfig.assembler b/arch/x86/Kconfig.assembler
index 59aedf32c4ea..6d20a6ce0507 100644
--- a/arch/x86/Kconfig.assembler
+++ b/arch/x86/Kconfig.assembler
@@ -36,6 +36,6 @@ config AS_VPCLMULQDQ
Supported by binutils >= 2.30 and LLVM integrated assembler
config AS_WRUSS
- def_bool $(as-instr,wrussq %rax$(comma)(%rbx))
+ def_bool $(as-instr64,wrussq %rax$(comma)(%rbx))
help
Supported by binutils >= 2.31 and LLVM integrated assembler
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index dec961c6d16a..f4d82379bf44 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -119,13 +119,8 @@ char *skip_spaces(const char *str)
#include "../../../../lib/ctype.c"
#include "../../../../lib/cmdline.c"
-enum parse_mode {
- PARSE_MEMMAP,
- PARSE_EFI,
-};
-
static int
-parse_memmap(char *p, u64 *start, u64 *size, enum parse_mode mode)
+parse_memmap(char *p, u64 *start, u64 *size)
{
char *oldp;
@@ -148,29 +143,11 @@ parse_memmap(char *p, u64 *start, u64 *size, enum parse_mode mode)
*start = memparse(p + 1, &p);
return 0;
case '@':
- if (mode == PARSE_MEMMAP) {
- /*
- * memmap=nn@ss specifies usable region, should
- * be skipped
- */
- *size = 0;
- } else {
- u64 flags;
-
- /*
- * efi_fake_mem=nn@ss:attr the attr specifies
- * flags that might imply a soft-reservation.
- */
- *start = memparse(p + 1, &p);
- if (p && *p == ':') {
- p++;
- if (kstrtoull(p, 0, &flags) < 0)
- *size = 0;
- else if (flags & EFI_MEMORY_SP)
- return 0;
- }
- *size = 0;
- }
+ /*
+ * memmap=nn@ss specifies usable region, should
+ * be skipped
+ */
+ *size = 0;
fallthrough;
default:
/*
@@ -185,7 +162,7 @@ parse_memmap(char *p, u64 *start, u64 *size, enum parse_mode mode)
return -EINVAL;
}
-static void mem_avoid_memmap(enum parse_mode mode, char *str)
+static void mem_avoid_memmap(char *str)
{
static int i;
@@ -200,7 +177,7 @@ static void mem_avoid_memmap(enum parse_mode mode, char *str)
if (k)
*k++ = 0;
- rc = parse_memmap(str, &start, &size, mode);
+ rc = parse_memmap(str, &start, &size);
if (rc < 0)
break;
str = k;
@@ -281,7 +258,7 @@ static void handle_mem_options(void)
break;
if (!strcmp(param, "memmap")) {
- mem_avoid_memmap(PARSE_MEMMAP, val);
+ mem_avoid_memmap(val);
} else if (IS_ENABLED(CONFIG_X86_64) && strstr(param, "hugepages")) {
parse_gb_huge_pages(param, val);
} else if (!strcmp(param, "mem")) {
@@ -295,8 +272,6 @@ static void handle_mem_options(void)
if (mem_size < mem_limit)
mem_limit = mem_size;
- } else if (!strcmp(param, "efi_fake_mem")) {
- mem_avoid_memmap(PARSE_EFI, val);
}
}
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index b70e4a21c15f..944454306ef4 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -531,8 +531,3 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
return output + entry_offset;
}
-
-void __fortify_panic(const u8 reason, size_t avail, size_t size)
-{
- error("detected buffer overflow");
-}
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index 0457a9d7e515..cd44e120fe53 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -127,7 +127,35 @@ static bool fault_in_kernel_space(unsigned long address)
#include "../../lib/insn.c"
/* Include code for early handlers */
-#include "../../kernel/sev-shared.c"
+#include "../../coco/sev/shared.c"
+
+static struct svsm_ca *svsm_get_caa(void)
+{
+ return boot_svsm_caa;
+}
+
+static u64 svsm_get_caa_pa(void)
+{
+ return boot_svsm_caa_pa;
+}
+
+static int svsm_perform_call_protocol(struct svsm_call *call)
+{
+ struct ghcb *ghcb;
+ int ret;
+
+ if (boot_ghcb)
+ ghcb = boot_ghcb;
+ else
+ ghcb = NULL;
+
+ do {
+ ret = ghcb ? svsm_perform_ghcb_protocol(ghcb, call)
+ : svsm_perform_msr_protocol(call);
+ } while (ret == -EAGAIN);
+
+ return ret;
+}
bool sev_snp_enabled(void)
{
@@ -145,8 +173,8 @@ static void __page_state_change(unsigned long paddr, enum psc_op op)
* If private -> shared then invalidate the page before requesting the
* state change in the RMP table.
*/
- if (op == SNP_PAGE_STATE_SHARED && pvalidate(paddr, RMP_PG_SIZE_4K, 0))
- sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE);
+ if (op == SNP_PAGE_STATE_SHARED)
+ pvalidate_4k_page(paddr, paddr, false);
/* Issue VMGEXIT to change the page state in RMP table. */
sev_es_wr_ghcb_msr(GHCB_MSR_PSC_REQ_GFN(paddr >> PAGE_SHIFT, op));
@@ -161,8 +189,8 @@ static void __page_state_change(unsigned long paddr, enum psc_op op)
* Now that page state is changed in the RMP table, validate it so that it is
* consistent with the RMP entry.
*/
- if (op == SNP_PAGE_STATE_PRIVATE && pvalidate(paddr, RMP_PG_SIZE_4K, 1))
- sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE);
+ if (op == SNP_PAGE_STATE_PRIVATE)
+ pvalidate_4k_page(paddr, paddr, true);
}
void snp_set_page_private(unsigned long paddr)
@@ -256,6 +284,16 @@ void sev_es_shutdown_ghcb(void)
error("SEV-ES CPU Features missing.");
/*
+ * This denotes whether to use the GHCB MSR protocol or the GHCB
+ * shared page to perform a GHCB request. Since the GHCB page is
+ * being changed to encrypted, it can't be used to perform GHCB
+ * requests. Clear the boot_ghcb variable so that the GHCB MSR
+ * protocol is used to change the GHCB page over to an encrypted
+ * page.
+ */
+ boot_ghcb = NULL;
+
+ /*
* GHCB Page must be flushed from the cache and mapped encrypted again.
* Otherwise the running kernel will see strange cache effects when
* trying to use that page.
@@ -463,6 +501,13 @@ static bool early_snp_init(struct boot_params *bp)
setup_cpuid_table(cc_info);
/*
+ * Record the SVSM Calling Area (CA) address if the guest is not
+ * running at VMPL0. The CA will be used to communicate with the
+ * SVSM and request its services.
+ */
+ svsm_setup_ca(cc_info);
+
+ /*
* Pass run-time kernel a pointer to CC info via boot_params so EFI
* config table doesn't need to be searched again during early startup
* phase.
@@ -565,22 +610,31 @@ void sev_enable(struct boot_params *bp)
* features.
*/
if (sev_status & MSR_AMD64_SEV_SNP_ENABLED) {
- if (!(get_hv_features() & GHCB_HV_FT_SNP))
+ u64 hv_features;
+ int ret;
+
+ hv_features = get_hv_features();
+ if (!(hv_features & GHCB_HV_FT_SNP))
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
/*
- * Enforce running at VMPL0.
- *
- * RMPADJUST modifies RMP permissions of a lesser-privileged (numerically
- * higher) privilege level. Here, clear the VMPL1 permission mask of the
- * GHCB page. If the guest is not running at VMPL0, this will fail.
+ * Enforce running at VMPL0 or with an SVSM.
*
- * If the guest is running at VMPL0, it will succeed. Even if that operation
- * modifies permission bits, it is still ok to do so currently because Linux
- * SNP guests running at VMPL0 only run at VMPL0, so VMPL1 or higher
- * permission mask changes are a don't-care.
+ * Use RMPADJUST (see the rmpadjust() function for a description of
+ * what the instruction does) to update the VMPL1 permissions of a
+ * page. If the guest is running at VMPL0, this will succeed. If the
+ * guest is running at any other VMPL, this will fail. Linux SNP guests
+ * only ever run at a single VMPL level so permission mask changes of a
+ * lesser-privileged VMPL are a don't-care.
+ */
+ ret = rmpadjust((unsigned long)&boot_ghcb_page, RMP_PG_SIZE_4K, 1);
+
+ /*
+ * Running at VMPL0 is not required if an SVSM is present and the hypervisor
+ * supports the required SVSM GHCB events.
*/
- if (rmpadjust((unsigned long)&boot_ghcb_page, RMP_PG_SIZE_4K, 1))
+ if (ret &&
+ !(snp_vmpl && (hv_features & GHCB_HV_FT_SNP_MULTI_VMPL)))
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NOT_VMPL0);
}
diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
index fed8d13ce252..0aae4d4ed615 100644
--- a/arch/x86/boot/cpucheck.c
+++ b/arch/x86/boot/cpucheck.c
@@ -203,7 +203,7 @@ int check_knl_erratum(void)
*/
if (!is_intel() ||
cpu.family != 6 ||
- cpu.model != INTEL_FAM6_XEON_PHI_KNL)
+ cpu.model != 0x57 /*INTEL_XEON_PHI_KNL*/)
return 0;
/*
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index 9049f390d834..9d0fea18d3c8 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -27,34 +27,32 @@ char *heap_end = _end; /* Default end of heap = no heap */
* screws up the old-style command line protocol, adjust by
* filling in the new-style command line pointer instead.
*/
-
static void copy_boot_params(void)
{
struct old_cmdline {
u16 cl_magic;
u16 cl_offset;
};
- const struct old_cmdline * const oldcmd =
- absolute_pointer(OLD_CL_ADDRESS);
+ const struct old_cmdline * const oldcmd = absolute_pointer(OLD_CL_ADDRESS);
BUILD_BUG_ON(sizeof(boot_params) != 4096);
memcpy(&boot_params.hdr, &hdr, sizeof(hdr));
- if (!boot_params.hdr.cmd_line_ptr &&
- oldcmd->cl_magic == OLD_CL_MAGIC) {
- /* Old-style command line protocol. */
+ if (!boot_params.hdr.cmd_line_ptr && oldcmd->cl_magic == OLD_CL_MAGIC) {
+ /* Old-style command line protocol */
u16 cmdline_seg;
- /* Figure out if the command line falls in the region
- of memory that an old kernel would have copied up
- to 0x90000... */
+ /*
+ * Figure out if the command line falls in the region
+ * of memory that an old kernel would have copied up
+ * to 0x90000...
+ */
if (oldcmd->cl_offset < boot_params.hdr.setup_move_size)
cmdline_seg = ds();
else
cmdline_seg = 0x9000;
- boot_params.hdr.cmd_line_ptr =
- (cmdline_seg << 4) + oldcmd->cl_offset;
+ boot_params.hdr.cmd_line_ptr = (cmdline_seg << 4) + oldcmd->cl_offset;
}
}
@@ -66,6 +64,7 @@ static void copy_boot_params(void)
static void keyboard_init(void)
{
struct biosregs ireg, oreg;
+
initregs(&ireg);
ireg.ah = 0x02; /* Get keyboard status */
@@ -83,8 +82,10 @@ static void query_ist(void)
{
struct biosregs ireg, oreg;
- /* Some older BIOSes apparently crash on this call, so filter
- it from machines too old to have SpeedStep at all. */
+ /*
+ * Some older BIOSes apparently crash on this call, so filter
+ * it from machines too old to have SpeedStep at all.
+ */
if (cpu.level < 6)
return;
@@ -119,17 +120,13 @@ static void init_heap(void)
char *stack_end;
if (boot_params.hdr.loadflags & CAN_USE_HEAP) {
- asm("leal %n1(%%esp),%0"
- : "=r" (stack_end) : "i" (STACK_SIZE));
-
- heap_end = (char *)
- ((size_t)boot_params.hdr.heap_end_ptr + 0x200);
+ stack_end = (char *) (current_stack_pointer - STACK_SIZE);
+ heap_end = (char *) ((size_t)boot_params.hdr.heap_end_ptr + 0x200);
if (heap_end > stack_end)
heap_end = stack_end;
} else {
/* Boot protocol 2.00 only, no heap available */
- puts("WARNING: Ancient bootloader, some functionality "
- "may be limited!\n");
+ puts("WARNING: Ancient bootloader, some functionality may be limited!\n");
}
}
@@ -150,12 +147,11 @@ void main(void)
/* Make sure we have all the proper CPU support */
if (validate_cpu()) {
- puts("Unable to boot - please use a kernel appropriate "
- "for your CPU.\n");
+ puts("Unable to boot - please use a kernel appropriate for your CPU.\n");
die();
}
- /* Tell the BIOS what CPU mode we intend to run in. */
+ /* Tell the BIOS what CPU mode we intend to run in */
set_bios_mode();
/* Detect memory layout */
diff --git a/arch/x86/coco/Makefile b/arch/x86/coco/Makefile
index c816acf78b6a..eabdc7486538 100644
--- a/arch/x86/coco/Makefile
+++ b/arch/x86/coco/Makefile
@@ -6,3 +6,4 @@ CFLAGS_core.o += -fno-stack-protector
obj-y += core.o
obj-$(CONFIG_INTEL_TDX_GUEST) += tdx/
+obj-$(CONFIG_AMD_MEM_ENCRYPT) += sev/
diff --git a/arch/x86/coco/core.c b/arch/x86/coco/core.c
index b31ef2424d19..0f81f70aca82 100644
--- a/arch/x86/coco/core.c
+++ b/arch/x86/coco/core.c
@@ -29,7 +29,6 @@ static bool noinstr intel_cc_platform_has(enum cc_attr attr)
{
switch (attr) {
case CC_ATTR_GUEST_UNROLL_STRING_IO:
- case CC_ATTR_HOTPLUG_DISABLED:
case CC_ATTR_GUEST_MEM_ENCRYPT:
case CC_ATTR_MEM_ENCRYPT:
return true;
diff --git a/arch/x86/coco/sev/Makefile b/arch/x86/coco/sev/Makefile
new file mode 100644
index 000000000000..4e375e7305ac
--- /dev/null
+++ b/arch/x86/coco/sev/Makefile
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += core.o
+
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_core.o = -pg
+endif
+
+KASAN_SANITIZE_core.o := n
+KMSAN_SANITIZE_core.o := n
+KCOV_INSTRUMENT_core.o := n
+
+# With some compiler versions the generated code results in boot hangs, caused
+# by several compilation units. To be safe, disable all instrumentation.
+KCSAN_SANITIZE := n
diff --git a/arch/x86/kernel/sev.c b/arch/x86/coco/sev/core.c
index 3342ed58e168..082d61d85dfc 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/coco/sev/core.c
@@ -133,16 +133,20 @@ struct ghcb_state {
struct ghcb *ghcb;
};
+/* For early boot SVSM communication */
+static struct svsm_ca boot_svsm_ca_page __aligned(PAGE_SIZE);
+
static DEFINE_PER_CPU(struct sev_es_runtime_data*, runtime_data);
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,
/*
- * A flag used by __set_pages_state() that 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.
+ * 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
@@ -150,6 +154,15 @@ struct sev_config {
*/
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 : 62;
};
@@ -572,8 +585,61 @@ fault:
return ES_EXCEPTION;
}
+static __always_inline void vc_forward_exception(struct es_em_ctxt *ctxt)
+{
+ long error_code = ctxt->fi.error_code;
+ int trapnr = ctxt->fi.vector;
+
+ ctxt->regs->orig_ax = ctxt->fi.error_code;
+
+ switch (trapnr) {
+ case X86_TRAP_GP:
+ exc_general_protection(ctxt->regs, error_code);
+ break;
+ case X86_TRAP_UD:
+ exc_invalid_op(ctxt->regs);
+ break;
+ case X86_TRAP_PF:
+ write_cr2(ctxt->fi.cr2);
+ exc_page_fault(ctxt->regs, error_code);
+ break;
+ case X86_TRAP_AC:
+ exc_alignment_check(ctxt->regs, error_code);
+ break;
+ default:
+ pr_emerg("Unsupported exception in #VC instruction emulation - can't continue\n");
+ BUG();
+ }
+}
+
/* Include code shared with pre-decompression boot stage */
-#include "sev-shared.c"
+#include "shared.c"
+
+static inline struct svsm_ca *svsm_get_caa(void)
+{
+ /*
+ * Use rIP-relative references when called early in the boot. If
+ * ->use_cas is set, then it is late in the boot and no need
+ * to worry about rIP-relative references.
+ */
+ if (RIP_REL_REF(sev_cfg).use_cas)
+ return this_cpu_read(svsm_caa);
+ else
+ return RIP_REL_REF(boot_svsm_caa);
+}
+
+static u64 svsm_get_caa_pa(void)
+{
+ /*
+ * Use rIP-relative references when called early in the boot. If
+ * ->use_cas is set, then it is late in the boot and no need
+ * to worry about rIP-relative references.
+ */
+ if (RIP_REL_REF(sev_cfg).use_cas)
+ return this_cpu_read(svsm_caa_pa);
+ else
+ return RIP_REL_REF(boot_svsm_caa_pa);
+}
static noinstr void __sev_put_ghcb(struct ghcb_state *state)
{
@@ -600,6 +666,44 @@ static noinstr void __sev_put_ghcb(struct ghcb_state *state)
}
}
+static int svsm_perform_call_protocol(struct svsm_call *call)
+{
+ struct ghcb_state state;
+ unsigned long flags;
+ struct ghcb *ghcb;
+ int ret;
+
+ /*
+ * This can be called very early in the boot, use native functions in
+ * order to avoid paravirt issues.
+ */
+ flags = native_local_irq_save();
+
+ /*
+ * Use rip-relative references when called early in the boot. If
+ * ghcbs_initialized is set, then it is late in the boot and no need
+ * to worry about rip-relative references in called functions.
+ */
+ if (RIP_REL_REF(sev_cfg).ghcbs_initialized)
+ ghcb = __sev_get_ghcb(&state);
+ else if (RIP_REL_REF(boot_ghcb))
+ ghcb = RIP_REL_REF(boot_ghcb);
+ else
+ ghcb = NULL;
+
+ do {
+ ret = ghcb ? svsm_perform_ghcb_protocol(ghcb, call)
+ : svsm_perform_msr_protocol(call);
+ } while (ret == -EAGAIN);
+
+ if (RIP_REL_REF(sev_cfg).ghcbs_initialized)
+ __sev_put_ghcb(&state);
+
+ native_local_irq_restore(flags);
+
+ return ret;
+}
+
void noinstr __sev_es_nmi_complete(void)
{
struct ghcb_state state;
@@ -709,7 +813,6 @@ early_set_pages_state(unsigned long vaddr, unsigned long paddr,
{
unsigned long paddr_end;
u64 val;
- int ret;
vaddr = vaddr & PAGE_MASK;
@@ -717,12 +820,9 @@ early_set_pages_state(unsigned long vaddr, unsigned long paddr,
paddr_end = paddr + (npages << PAGE_SHIFT);
while (paddr < paddr_end) {
- if (op == SNP_PAGE_STATE_SHARED) {
- /* Page validation must be rescinded before changing to shared */
- ret = pvalidate(vaddr, RMP_PG_SIZE_4K, false);
- if (WARN(ret, "Failed to validate address 0x%lx ret %d", paddr, ret))
- goto e_term;
- }
+ /* Page validation must be rescinded before changing to shared */
+ if (op == SNP_PAGE_STATE_SHARED)
+ pvalidate_4k_page(vaddr, paddr, false);
/*
* Use the MSR protocol because this function can be called before
@@ -744,12 +844,9 @@ early_set_pages_state(unsigned long vaddr, unsigned long paddr,
paddr, GHCB_MSR_PSC_RESP_VAL(val)))
goto e_term;
- if (op == SNP_PAGE_STATE_PRIVATE) {
- /* Page validation must be performed after changing to private */
- ret = pvalidate(vaddr, RMP_PG_SIZE_4K, true);
- if (WARN(ret, "Failed to validate address 0x%lx ret %d", paddr, ret))
- goto e_term;
- }
+ /* Page validation must be performed after changing to private */
+ if (op == SNP_PAGE_STATE_PRIVATE)
+ pvalidate_4k_page(vaddr, paddr, true);
vaddr += PAGE_SIZE;
paddr += PAGE_SIZE;
@@ -913,22 +1010,49 @@ void snp_accept_memory(phys_addr_t start, phys_addr_t end)
set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE);
}
-static int snp_set_vmsa(void *va, bool vmsa)
+static int snp_set_vmsa(void *va, void *caa, int apic_id, bool make_vmsa)
{
- u64 attrs;
+ int ret;
- /*
- * Running at VMPL0 allows the kernel to change the VMSA bit for a page
- * using the RMPADJUST instruction. However, for the instruction to
- * succeed it must target the permissions of a lesser privileged
- * (higher numbered) VMPL level, so use VMPL1 (refer to the RMPADJUST
- * instruction in the AMD64 APM Volume 3).
- */
- attrs = 1;
- if (vmsa)
- attrs |= RMPADJUST_VMSA_PAGE_BIT;
+ if (snp_vmpl) {
+ struct svsm_call call = {};
+ unsigned long flags;
+
+ local_irq_save(flags);
- return rmpadjust((unsigned long)va, RMP_PG_SIZE_4K, attrs);
+ call.caa = this_cpu_read(svsm_caa);
+ call.rcx = __pa(va);
+
+ if (make_vmsa) {
+ /* Protocol 0, Call ID 2 */
+ call.rax = SVSM_CORE_CALL(SVSM_CORE_CREATE_VCPU);
+ call.rdx = __pa(caa);
+ call.r8 = apic_id;
+ } else {
+ /* Protocol 0, Call ID 3 */
+ call.rax = SVSM_CORE_CALL(SVSM_CORE_DELETE_VCPU);
+ }
+
+ ret = svsm_perform_call_protocol(&call);
+
+ local_irq_restore(flags);
+ } else {
+ /*
+ * If the kernel runs at VMPL0, it can change the VMSA
+ * bit for a page using the RMPADJUST instruction.
+ * However, for the instruction to succeed it must
+ * target the permissions of a lesser privileged (higher
+ * numbered) VMPL level, so use VMPL1.
+ */
+ u64 attrs = 1;
+
+ if (make_vmsa)
+ attrs |= RMPADJUST_VMSA_PAGE_BIT;
+
+ ret = rmpadjust((unsigned long)va, RMP_PG_SIZE_4K, attrs);
+ }
+
+ return ret;
}
#define __ATTR_BASE (SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK)
@@ -962,11 +1086,11 @@ static void *snp_alloc_vmsa_page(int cpu)
return page_address(p + 1);
}
-static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa)
+static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa, int apic_id)
{
int err;
- err = snp_set_vmsa(vmsa, false);
+ err = snp_set_vmsa(vmsa, NULL, apic_id, false);
if (err)
pr_err("clear VMSA page failed (%u), leaking page\n", err);
else
@@ -977,6 +1101,7 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
{
struct sev_es_save_area *cur_vmsa, *vmsa;
struct ghcb_state state;
+ struct svsm_ca *caa;
unsigned long flags;
struct ghcb *ghcb;
u8 sipi_vector;
@@ -1023,6 +1148,9 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
if (!vmsa)
return -ENOMEM;
+ /* If an SVSM is present, the SVSM per-CPU CAA will be !NULL */
+ caa = per_cpu(svsm_caa, cpu);
+
/* CR4 should maintain the MCE value */
cr4 = native_read_cr4() & X86_CR4_MCE;
@@ -1070,11 +1198,11 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
* VMPL level
* SEV_FEATURES (matches the SEV STATUS MSR right shifted 2 bits)
*/
- vmsa->vmpl = 0;
+ vmsa->vmpl = snp_vmpl;
vmsa->sev_features = sev_status >> 2;
/* Switch the page over to a VMSA page now that it is initialized */
- ret = snp_set_vmsa(vmsa, true);
+ ret = snp_set_vmsa(vmsa, caa, apic_id, true);
if (ret) {
pr_err("set VMSA page failed (%u)\n", ret);
free_page((unsigned long)vmsa);
@@ -1090,7 +1218,10 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
vc_ghcb_invalidate(ghcb);
ghcb_set_rax(ghcb, vmsa->sev_features);
ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_AP_CREATION);
- ghcb_set_sw_exit_info_1(ghcb, ((u64)apic_id << 32) | SVM_VMGEXIT_AP_CREATE);
+ ghcb_set_sw_exit_info_1(ghcb,
+ ((u64)apic_id << 32) |
+ ((u64)snp_vmpl << 16) |
+ SVM_VMGEXIT_AP_CREATE);
ghcb_set_sw_exit_info_2(ghcb, __pa(vmsa));
sev_es_wr_ghcb_msr(__pa(ghcb));
@@ -1108,13 +1239,13 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
/* Perform cleanup if there was an error */
if (ret) {
- snp_cleanup_vmsa(vmsa);
+ snp_cleanup_vmsa(vmsa, apic_id);
vmsa = NULL;
}
/* Free up any previous VMSA page */
if (cur_vmsa)
- snp_cleanup_vmsa(cur_vmsa);
+ snp_cleanup_vmsa(cur_vmsa, apic_id);
/* Record the current VMSA page */
per_cpu(sev_vmsa, cpu) = vmsa;
@@ -1209,6 +1340,17 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
/* Is it a WRMSR? */
exit_info_1 = (ctxt->insn.opcode.bytes[1] == 0x30) ? 1 : 0;
+ 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;
+ }
+
ghcb_set_rcx(ghcb, regs->cx);
if (exit_info_1) {
ghcb_set_rax(ghcb, regs->ax);
@@ -1346,6 +1488,18 @@ static void __init alloc_runtime_data(int cpu)
panic("Can't allocate SEV-ES runtime data");
per_cpu(runtime_data, cpu) = data;
+
+ if (snp_vmpl) {
+ struct svsm_ca *caa;
+
+ /* Allocate the SVSM CA page if an SVSM is present */
+ caa = memblock_alloc(sizeof(*caa), PAGE_SIZE);
+ if (!caa)
+ panic("Can't allocate SVSM CA page\n");
+
+ per_cpu(svsm_caa, cpu) = caa;
+ per_cpu(svsm_caa_pa, cpu) = __pa(caa);
+ }
}
static void __init init_ghcb(int cpu)
@@ -1395,6 +1549,32 @@ void __init sev_es_init_vc_handling(void)
init_ghcb(cpu);
}
+ /* If running under an SVSM, switch to the per-cpu CA */
+ if (snp_vmpl) {
+ struct svsm_call call = {};
+ unsigned long flags;
+ int ret;
+
+ local_irq_save(flags);
+
+ /*
+ * SVSM_CORE_REMAP_CA call:
+ * RAX = 0 (Protocol=0, CallID=0)
+ * RCX = New CA GPA
+ */
+ call.caa = svsm_get_caa();
+ call.rax = SVSM_CORE_CALL(SVSM_CORE_REMAP_CA);
+ call.rcx = this_cpu_read(svsm_caa_pa);
+ ret = svsm_perform_call_protocol(&call);
+ if (ret)
+ panic("Can't remap the SVSM CA, ret=%d, rax_out=0x%llx\n",
+ ret, call.rax_out);
+
+ sev_cfg.use_cas = true;
+
+ local_irq_restore(flags);
+ }
+
sev_es_setup_play_dead();
/* Secondary CPUs use the runtime #VC handler */
@@ -1819,33 +1999,6 @@ static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt,
return result;
}
-static __always_inline void vc_forward_exception(struct es_em_ctxt *ctxt)
-{
- long error_code = ctxt->fi.error_code;
- int trapnr = ctxt->fi.vector;
-
- ctxt->regs->orig_ax = ctxt->fi.error_code;
-
- switch (trapnr) {
- case X86_TRAP_GP:
- exc_general_protection(ctxt->regs, error_code);
- break;
- case X86_TRAP_UD:
- exc_invalid_op(ctxt->regs);
- break;
- case X86_TRAP_PF:
- write_cr2(ctxt->fi.cr2);
- exc_page_fault(ctxt->regs, error_code);
- break;
- case X86_TRAP_AC:
- exc_alignment_check(ctxt->regs, error_code);
- break;
- default:
- pr_emerg("Unsupported exception in #VC instruction emulation - can't continue\n");
- BUG();
- }
-}
-
static __always_inline bool is_vc2_stack(unsigned long sp)
{
return (sp >= __this_cpu_ist_bottom_va(VC2) && sp < __this_cpu_ist_top_va(VC2));
@@ -2095,6 +2248,47 @@ found_cc_info:
return cc_info;
}
+static __head void svsm_setup(struct cc_blob_sev_info *cc_info)
+{
+ struct svsm_call call = {};
+ int ret;
+ u64 pa;
+
+ /*
+ * Record the SVSM Calling Area address (CAA) if the guest is not
+ * running at VMPL0. The CA will be used to communicate with the
+ * SVSM to perform the SVSM services.
+ */
+ if (!svsm_setup_ca(cc_info))
+ return;
+
+ /*
+ * It is very early in the boot and the kernel is running identity
+ * mapped but without having adjusted the pagetables to where the
+ * kernel was loaded (physbase), so the get the CA address using
+ * RIP-relative addressing.
+ */
+ pa = (u64)&RIP_REL_REF(boot_svsm_ca_page);
+
+ /*
+ * Switch over to the boot SVSM CA while the current CA is still
+ * addressable. There is no GHCB at this point so use the MSR protocol.
+ *
+ * SVSM_CORE_REMAP_CA call:
+ * RAX = 0 (Protocol=0, CallID=0)
+ * RCX = New CA GPA
+ */
+ call.caa = svsm_get_caa();
+ call.rax = SVSM_CORE_CALL(SVSM_CORE_REMAP_CA);
+ call.rcx = pa;
+ ret = svsm_perform_call_protocol(&call);
+ if (ret)
+ panic("Can't remap the SVSM CA, ret=%d, rax_out=0x%llx\n", ret, call.rax_out);
+
+ RIP_REL_REF(boot_svsm_caa) = (struct svsm_ca *)pa;
+ RIP_REL_REF(boot_svsm_caa_pa) = pa;
+}
+
bool __head snp_init(struct boot_params *bp)
{
struct cc_blob_sev_info *cc_info;
@@ -2108,6 +2302,8 @@ bool __head snp_init(struct boot_params *bp)
setup_cpuid_table(cc_info);
+ svsm_setup(cc_info);
+
/*
* The CC blob will be used later to access the secrets page. Cache
* it here like the boot kernel does.
@@ -2156,23 +2352,27 @@ static void dump_cpuid_table(void)
* expected, but that initialization happens too early in boot to print any
* sort of indicator, and there's not really any other good place to do it,
* so do it here.
+ *
+ * If running as an SNP guest, report the current VM privilege level (VMPL).
*/
-static int __init report_cpuid_table(void)
+static int __init report_snp_info(void)
{
const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
- if (!cpuid_table->count)
- return 0;
+ if (cpuid_table->count) {
+ pr_info("Using SNP CPUID table, %d entries present.\n",
+ cpuid_table->count);
- pr_info("Using SNP CPUID table, %d entries present.\n",
- cpuid_table->count);
+ if (sev_cfg.debug)
+ dump_cpuid_table();
+ }
- if (sev_cfg.debug)
- dump_cpuid_table();
+ if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+ pr_info("SNP running at VMPL%u.\n", snp_vmpl);
return 0;
}
-arch_initcall(report_cpuid_table);
+arch_initcall(report_snp_info);
static int __init init_sev_config(char *str)
{
@@ -2191,6 +2391,56 @@ static int __init init_sev_config(char *str)
}
__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 */
+ if (call->rcx_out != call->rcx)
+ input->manifest_buf.len = call->rcx_out;
+
+ if (call->rdx_out != call->rdx)
+ input->certificates_buf.len = call->rdx_out;
+
+ if (call->r8_out != call->r8)
+ input->report_buf.len = call->r8_out;
+}
+
+int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call,
+ struct svsm_attest_call *input)
+{
+ struct svsm_attest_call *ac;
+ unsigned long flags;
+ u64 attest_call_pa;
+ int ret;
+
+ if (!snp_vmpl)
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ call->caa = svsm_get_caa();
+
+ ac = (struct svsm_attest_call *)call->caa->svsm_buffer;
+ attest_call_pa = svsm_get_caa_pa() + offsetof(struct svsm_ca, svsm_buffer);
+
+ *ac = *input;
+
+ /*
+ * Set input registers for the request and set RDX and R8 to known
+ * values in order to detect length values being returned in them.
+ */
+ call->rax = call_id;
+ call->rcx = attest_call_pa;
+ call->rdx = -1;
+ call->r8 = -1;
+ ret = svsm_perform_call_protocol(call);
+ update_attest_input(call, input);
+
+ local_irq_restore(flags);
+
+ return ret;
+}
+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)
{
struct ghcb_state state;
@@ -2299,3 +2549,58 @@ void sev_show_status(void)
}
pr_cont("\n");
}
+
+void __init snp_update_svsm_ca(void)
+{
+ if (!snp_vmpl)
+ return;
+
+ /* Update the CAA to a proper kernel address */
+ boot_svsm_caa = &boot_svsm_ca_page;
+}
+
+#ifdef CONFIG_SYSFS
+static ssize_t vmpl_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", snp_vmpl);
+}
+
+static struct kobj_attribute vmpl_attr = __ATTR_RO(vmpl);
+
+static struct attribute *vmpl_attrs[] = {
+ &vmpl_attr.attr,
+ NULL
+};
+
+static struct attribute_group sev_attr_group = {
+ .attrs = vmpl_attrs,
+};
+
+static int __init sev_sysfs_init(void)
+{
+ struct kobject *sev_kobj;
+ struct device *dev_root;
+ int ret;
+
+ if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+ return -ENODEV;
+
+ dev_root = bus_get_dev_root(&cpu_subsys);
+ if (!dev_root)
+ return -ENODEV;
+
+ sev_kobj = kobject_create_and_add("sev", &dev_root->kobj);
+ put_device(dev_root);
+
+ if (!sev_kobj)
+ return -ENOMEM;
+
+ ret = sysfs_create_group(sev_kobj, &sev_attr_group);
+ if (ret)
+ kobject_put(sev_kobj);
+
+ return ret;
+}
+arch_initcall(sev_sysfs_init);
+#endif // CONFIG_SYSFS
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/coco/sev/shared.c
index b4f8fa0f722c..71de53194089 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/coco/sev/shared.c
@@ -21,8 +21,30 @@
#define WARN(condition, format...) (!!(condition))
#define sev_printk(fmt, ...)
#define sev_printk_rtl(fmt, ...)
+#undef vc_forward_exception
+#define vc_forward_exception(c) panic("SNP: Hypervisor requested exception\n")
#endif
+/*
+ * SVSM related information:
+ * When running under an SVSM, the VMPL that Linux is executing at must be
+ * non-zero. The VMPL is therefore used to indicate the presence of an SVSM.
+ *
+ * During boot, the page tables are set up as identity mapped and later
+ * changed to use kernel virtual addresses. Maintain separate virtual and
+ * physical addresses for the CAA to allow SVSM functions to be used during
+ * early boot, both with identity mapped virtual addresses and proper kernel
+ * virtual addresses.
+ */
+u8 snp_vmpl __ro_after_init;
+EXPORT_SYMBOL_GPL(snp_vmpl);
+static struct svsm_ca *boot_svsm_caa __ro_after_init;
+static u64 boot_svsm_caa_pa __ro_after_init;
+
+static struct svsm_ca *svsm_get_caa(void);
+static u64 svsm_get_caa_pa(void);
+static int svsm_perform_call_protocol(struct svsm_call *call);
+
/* I/O parameters for CPUID-related helpers */
struct cpuid_leaf {
u32 fn;
@@ -229,6 +251,126 @@ static enum es_result verify_exception_info(struct ghcb *ghcb, struct es_em_ctxt
return ES_VMM_ERROR;
}
+static inline int svsm_process_result_codes(struct svsm_call *call)
+{
+ switch (call->rax_out) {
+ case SVSM_SUCCESS:
+ return 0;
+ case SVSM_ERR_INCOMPLETE:
+ case SVSM_ERR_BUSY:
+ return -EAGAIN;
+ default:
+ return -EINVAL;
+ }
+}
+
+/*
+ * Issue a VMGEXIT to call the SVSM:
+ * - Load the SVSM register state (RAX, RCX, RDX, R8 and R9)
+ * - Set the CA call pending field to 1
+ * - Issue VMGEXIT
+ * - Save the SVSM return register state (RAX, RCX, RDX, R8 and R9)
+ * - Perform atomic exchange of the CA call pending field
+ *
+ * - See the "Secure VM Service Module for SEV-SNP Guests" specification for
+ * details on the calling convention.
+ * - The calling convention loosely follows the Microsoft X64 calling
+ * convention by putting arguments in RCX, RDX, R8 and R9.
+ * - RAX specifies the SVSM protocol/callid as input and the return code
+ * as output.
+ */
+static __always_inline void svsm_issue_call(struct svsm_call *call, u8 *pending)
+{
+ register unsigned long rax asm("rax") = call->rax;
+ register unsigned long rcx asm("rcx") = call->rcx;
+ register unsigned long rdx asm("rdx") = call->rdx;
+ register unsigned long r8 asm("r8") = call->r8;
+ register unsigned long r9 asm("r9") = call->r9;
+
+ call->caa->call_pending = 1;
+
+ asm volatile("rep; vmmcall\n\t"
+ : "+r" (rax), "+r" (rcx), "+r" (rdx), "+r" (r8), "+r" (r9)
+ : : "memory");
+
+ *pending = xchg(&call->caa->call_pending, *pending);
+
+ call->rax_out = rax;
+ call->rcx_out = rcx;
+ call->rdx_out = rdx;
+ call->r8_out = r8;
+ call->r9_out = r9;
+}
+
+static int svsm_perform_msr_protocol(struct svsm_call *call)
+{
+ u8 pending = 0;
+ u64 val, resp;
+
+ /*
+ * When using the MSR protocol, be sure to save and restore
+ * the current MSR value.
+ */
+ val = sev_es_rd_ghcb_msr();
+
+ sev_es_wr_ghcb_msr(GHCB_MSR_VMPL_REQ_LEVEL(0));
+
+ svsm_issue_call(call, &pending);
+
+ resp = sev_es_rd_ghcb_msr();
+
+ sev_es_wr_ghcb_msr(val);
+
+ if (pending)
+ return -EINVAL;
+
+ if (GHCB_RESP_CODE(resp) != GHCB_MSR_VMPL_RESP)
+ return -EINVAL;
+
+ if (GHCB_MSR_VMPL_RESP_VAL(resp))
+ return -EINVAL;
+
+ return svsm_process_result_codes(call);
+}
+
+static int svsm_perform_ghcb_protocol(struct ghcb *ghcb, struct svsm_call *call)
+{
+ struct es_em_ctxt ctxt;
+ u8 pending = 0;
+
+ vc_ghcb_invalidate(ghcb);
+
+ /*
+ * Fill in protocol and format specifiers. This can be called very early
+ * in the boot, so use rip-relative references as needed.
+ */
+ ghcb->protocol_version = RIP_REL_REF(ghcb_version);
+ ghcb->ghcb_usage = GHCB_DEFAULT_USAGE;
+
+ ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_SNP_RUN_VMPL);
+ ghcb_set_sw_exit_info_1(ghcb, 0);
+ ghcb_set_sw_exit_info_2(ghcb, 0);
+
+ sev_es_wr_ghcb_msr(__pa(ghcb));
+
+ svsm_issue_call(call, &pending);
+
+ if (pending)
+ return -EINVAL;
+
+ switch (verify_exception_info(ghcb, &ctxt)) {
+ case ES_OK:
+ break;
+ case ES_EXCEPTION:
+ vc_forward_exception(&ctxt);
+ fallthrough;
+ default:
+ return -EINVAL;
+ }
+
+ return svsm_process_result_codes(call);
+}
+
static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
struct es_em_ctxt *ctxt,
u64 exit_code, u64 exit_info_1,
@@ -1079,38 +1221,268 @@ static void __head setup_cpuid_table(const struct cc_blob_sev_info *cc_info)
}
}
-static void pvalidate_pages(struct snp_psc_desc *desc)
+static inline void __pval_terminate(u64 pfn, bool action, unsigned int page_size,
+ int ret, u64 svsm_ret)
+{
+ WARN(1, "PVALIDATE failure: pfn: 0x%llx, action: %u, size: %u, ret: %d, svsm_ret: 0x%llx\n",
+ pfn, action, page_size, ret, svsm_ret);
+
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE);
+}
+
+static void svsm_pval_terminate(struct svsm_pvalidate_call *pc, int ret, u64 svsm_ret)
+{
+ unsigned int page_size;
+ bool action;
+ u64 pfn;
+
+ pfn = pc->entry[pc->cur_index].pfn;
+ action = pc->entry[pc->cur_index].action;
+ page_size = pc->entry[pc->cur_index].page_size;
+
+ __pval_terminate(pfn, action, page_size, ret, svsm_ret);
+}
+
+static void svsm_pval_4k_page(unsigned long paddr, bool validate)
+{
+ struct svsm_pvalidate_call *pc;
+ struct svsm_call call = {};
+ unsigned long flags;
+ u64 pc_pa;
+ int ret;
+
+ /*
+ * This can be called very early in the boot, use native functions in
+ * order to avoid paravirt issues.
+ */
+ flags = native_local_irq_save();
+
+ call.caa = svsm_get_caa();
+
+ pc = (struct svsm_pvalidate_call *)call.caa->svsm_buffer;
+ pc_pa = svsm_get_caa_pa() + offsetof(struct svsm_ca, svsm_buffer);
+
+ pc->num_entries = 1;
+ pc->cur_index = 0;
+ pc->entry[0].page_size = RMP_PG_SIZE_4K;
+ pc->entry[0].action = validate;
+ pc->entry[0].ignore_cf = 0;
+ pc->entry[0].pfn = paddr >> PAGE_SHIFT;
+
+ /* Protocol 0, Call ID 1 */
+ call.rax = SVSM_CORE_CALL(SVSM_CORE_PVALIDATE);
+ call.rcx = pc_pa;
+
+ ret = svsm_perform_call_protocol(&call);
+ if (ret)
+ svsm_pval_terminate(pc, ret, call.rax_out);
+
+ native_local_irq_restore(flags);
+}
+
+static void pvalidate_4k_page(unsigned long vaddr, unsigned long paddr, bool validate)
+{
+ int ret;
+
+ /*
+ * This can be called very early during boot, so use rIP-relative
+ * references as needed.
+ */
+ if (RIP_REL_REF(snp_vmpl)) {
+ svsm_pval_4k_page(paddr, validate);
+ } else {
+ ret = pvalidate(vaddr, RMP_PG_SIZE_4K, validate);
+ if (ret)
+ __pval_terminate(PHYS_PFN(paddr), validate, RMP_PG_SIZE_4K, ret, 0);
+ }
+}
+
+static void pval_pages(struct snp_psc_desc *desc)
{
struct psc_entry *e;
unsigned long vaddr;
unsigned int size;
unsigned int i;
bool validate;
+ u64 pfn;
int rc;
for (i = 0; i <= desc->hdr.end_entry; i++) {
e = &desc->entries[i];
- vaddr = (unsigned long)pfn_to_kaddr(e->gfn);
+ pfn = e->gfn;
+ vaddr = (unsigned long)pfn_to_kaddr(pfn);
size = e->pagesize ? RMP_PG_SIZE_2M : RMP_PG_SIZE_4K;
validate = e->operation == SNP_PAGE_STATE_PRIVATE;
rc = pvalidate(vaddr, size, validate);
+ if (!rc)
+ continue;
+
if (rc == PVALIDATE_FAIL_SIZEMISMATCH && size == RMP_PG_SIZE_2M) {
unsigned long vaddr_end = vaddr + PMD_SIZE;
- for (; vaddr < vaddr_end; vaddr += PAGE_SIZE) {
+ for (; vaddr < vaddr_end; vaddr += PAGE_SIZE, pfn++) {
rc = pvalidate(vaddr, RMP_PG_SIZE_4K, validate);
if (rc)
- break;
+ __pval_terminate(pfn, validate, RMP_PG_SIZE_4K, rc, 0);
}
+ } else {
+ __pval_terminate(pfn, validate, size, rc, 0);
}
+ }
+}
+
+static u64 svsm_build_ca_from_pfn_range(u64 pfn, u64 pfn_end, bool action,
+ struct svsm_pvalidate_call *pc)
+{
+ struct svsm_pvalidate_entry *pe;
+
+ /* Nothing in the CA yet */
+ pc->num_entries = 0;
+ pc->cur_index = 0;
+
+ pe = &pc->entry[0];
+
+ while (pfn < pfn_end) {
+ pe->page_size = RMP_PG_SIZE_4K;
+ pe->action = action;
+ pe->ignore_cf = 0;
+ pe->pfn = pfn;
+
+ pe++;
+ pfn++;
+
+ pc->num_entries++;
+ if (pc->num_entries == SVSM_PVALIDATE_MAX_COUNT)
+ break;
+ }
+
+ return pfn;
+}
+
+static int svsm_build_ca_from_psc_desc(struct snp_psc_desc *desc, unsigned int desc_entry,
+ struct svsm_pvalidate_call *pc)
+{
+ struct svsm_pvalidate_entry *pe;
+ struct psc_entry *e;
+
+ /* Nothing in the CA yet */
+ pc->num_entries = 0;
+ pc->cur_index = 0;
+
+ pe = &pc->entry[0];
+ e = &desc->entries[desc_entry];
+
+ while (desc_entry <= desc->hdr.end_entry) {
+ pe->page_size = e->pagesize ? RMP_PG_SIZE_2M : RMP_PG_SIZE_4K;
+ pe->action = e->operation == SNP_PAGE_STATE_PRIVATE;
+ pe->ignore_cf = 0;
+ pe->pfn = e->gfn;
+
+ pe++;
+ e++;
+
+ desc_entry++;
+ pc->num_entries++;
+ if (pc->num_entries == SVSM_PVALIDATE_MAX_COUNT)
+ break;
+ }
+
+ return desc_entry;
+}
+
+static void svsm_pval_pages(struct snp_psc_desc *desc)
+{
+ struct svsm_pvalidate_entry pv_4k[VMGEXIT_PSC_MAX_ENTRY];
+ unsigned int i, pv_4k_count = 0;
+ struct svsm_pvalidate_call *pc;
+ struct svsm_call call = {};
+ unsigned long flags;
+ bool action;
+ u64 pc_pa;
+ int ret;
+
+ /*
+ * This can be called very early in the boot, use native functions in
+ * order to avoid paravirt issues.
+ */
+ flags = native_local_irq_save();
+
+ /*
+ * The SVSM calling area (CA) can support processing 510 entries at a
+ * time. Loop through the Page State Change descriptor until the CA is
+ * full or the last entry in the descriptor is reached, at which time
+ * the SVSM is invoked. This repeats until all entries in the descriptor
+ * are processed.
+ */
+ call.caa = svsm_get_caa();
+
+ pc = (struct svsm_pvalidate_call *)call.caa->svsm_buffer;
+ pc_pa = svsm_get_caa_pa() + offsetof(struct svsm_ca, svsm_buffer);
+
+ /* Protocol 0, Call ID 1 */
+ call.rax = SVSM_CORE_CALL(SVSM_CORE_PVALIDATE);
+ call.rcx = pc_pa;
+
+ for (i = 0; i <= desc->hdr.end_entry;) {
+ i = svsm_build_ca_from_psc_desc(desc, i, pc);
+
+ do {
+ ret = svsm_perform_call_protocol(&call);
+ if (!ret)
+ continue;
+
+ /*
+ * Check if the entry failed because of an RMP mismatch (a
+ * PVALIDATE at 2M was requested, but the page is mapped in
+ * the RMP as 4K).
+ */
- if (rc) {
- WARN(1, "Failed to validate address 0x%lx ret %d", vaddr, rc);
- sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE);
+ if (call.rax_out == SVSM_PVALIDATE_FAIL_SIZEMISMATCH &&
+ pc->entry[pc->cur_index].page_size == RMP_PG_SIZE_2M) {
+ /* Save this entry for post-processing at 4K */
+ pv_4k[pv_4k_count++] = pc->entry[pc->cur_index];
+
+ /* Skip to the next one unless at the end of the list */
+ pc->cur_index++;
+ if (pc->cur_index < pc->num_entries)
+ ret = -EAGAIN;
+ else
+ ret = 0;
+ }
+ } while (ret == -EAGAIN);
+
+ if (ret)
+ svsm_pval_terminate(pc, ret, call.rax_out);
+ }
+
+ /* Process any entries that failed to be validated at 2M and validate them at 4K */
+ for (i = 0; i < pv_4k_count; i++) {
+ u64 pfn, pfn_end;
+
+ action = pv_4k[i].action;
+ pfn = pv_4k[i].pfn;
+ pfn_end = pfn + 512;
+
+ while (pfn < pfn_end) {
+ pfn = svsm_build_ca_from_pfn_range(pfn, pfn_end, action, pc);
+
+ ret = svsm_perform_call_protocol(&call);
+ if (ret)
+ svsm_pval_terminate(pc, ret, call.rax_out);
}
}
+
+ native_local_irq_restore(flags);
+}
+
+static void pvalidate_pages(struct snp_psc_desc *desc)
+{
+ if (snp_vmpl)
+ svsm_pval_pages(desc);
+ else
+ pval_pages(desc);
}
static int vmgexit_psc(struct ghcb *ghcb, struct snp_psc_desc *desc)
@@ -1269,3 +1641,77 @@ static enum es_result vc_check_opcode_bytes(struct es_em_ctxt *ctxt,
return ES_UNSUPPORTED;
}
+
+/*
+ * Maintain the GPA of the SVSM Calling Area (CA) in order to utilize the SVSM
+ * services needed when not running in VMPL0.
+ */
+static bool __head svsm_setup_ca(const struct cc_blob_sev_info *cc_info)
+{
+ struct snp_secrets_page *secrets_page;
+ struct snp_cpuid_table *cpuid_table;
+ unsigned int i;
+ u64 caa;
+
+ BUILD_BUG_ON(sizeof(*secrets_page) != PAGE_SIZE);
+
+ /*
+ * Check if running at VMPL0.
+ *
+ * Use RMPADJUST (see the rmpadjust() function for a description of what
+ * the instruction does) to update the VMPL1 permissions of a page. If
+ * the guest is running at VMPL0, this will succeed and implies there is
+ * no SVSM. If the guest is running at any other VMPL, this will fail.
+ * Linux SNP guests only ever run at a single VMPL level so permission mask
+ * changes of a lesser-privileged VMPL are a don't-care.
+ *
+ * Use a rip-relative reference to obtain the proper address, since this
+ * routine is running identity mapped when called, both by the decompressor
+ * code and the early kernel code.
+ */
+ if (!rmpadjust((unsigned long)&RIP_REL_REF(boot_ghcb_page), RMP_PG_SIZE_4K, 1))
+ return false;
+
+ /*
+ * Not running at VMPL0, ensure everything has been properly supplied
+ * for running under an SVSM.
+ */
+ if (!cc_info || !cc_info->secrets_phys || cc_info->secrets_len != PAGE_SIZE)
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SECRETS_PAGE);
+
+ secrets_page = (struct snp_secrets_page *)cc_info->secrets_phys;
+ if (!secrets_page->svsm_size)
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NO_SVSM);
+
+ if (!secrets_page->svsm_guest_vmpl)
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SVSM_VMPL0);
+
+ RIP_REL_REF(snp_vmpl) = secrets_page->svsm_guest_vmpl;
+
+ caa = secrets_page->svsm_caa;
+
+ /*
+ * An open-coded PAGE_ALIGNED() in order to avoid including
+ * kernel-proper headers into the decompressor.
+ */
+ if (caa & (PAGE_SIZE - 1))
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SVSM_CAA);
+
+ /*
+ * The CA is identity mapped when this routine is called, both by the
+ * decompressor code and the early kernel code.
+ */
+ RIP_REL_REF(boot_svsm_caa) = (struct svsm_ca *)caa;
+ RIP_REL_REF(boot_svsm_caa_pa) = caa;
+
+ /* Advertise the SVSM presence via CPUID. */
+ cpuid_table = (struct snp_cpuid_table *)snp_cpuid_get_table();
+ for (i = 0; i < cpuid_table->count; i++) {
+ struct snp_cpuid_fn *fn = &cpuid_table->fn[i];
+
+ if (fn->eax_in == 0x8000001f)
+ fn->eax |= BIT(28);
+ }
+
+ return true;
+}
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index c1cb90369915..078e2bac2553 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -7,6 +7,7 @@
#include <linux/cpufeature.h>
#include <linux/export.h>
#include <linux/io.h>
+#include <linux/kexec.h>
#include <asm/coco.h>
#include <asm/tdx.h>
#include <asm/vmx.h>
@@ -14,6 +15,7 @@
#include <asm/insn.h>
#include <asm/insn-eval.h>
#include <asm/pgtable.h>
+#include <asm/set_memory.h>
/* MMIO direction */
#define EPT_READ 0
@@ -38,6 +40,8 @@
#define TDREPORT_SUBTYPE_0 0
+static atomic_long_t nr_shared;
+
/* Called from __tdx_hypercall() for unrecoverable failure */
noinstr void __noreturn __tdx_hypercall_failed(void)
{
@@ -798,28 +802,124 @@ static bool tdx_enc_status_changed(unsigned long vaddr, int numpages, bool enc)
return true;
}
-static bool tdx_enc_status_change_prepare(unsigned long vaddr, int numpages,
- bool enc)
+static int tdx_enc_status_change_prepare(unsigned long vaddr, int numpages,
+ bool enc)
{
/*
* Only handle shared->private conversion here.
* See the comment in tdx_early_init().
*/
- if (enc)
- return tdx_enc_status_changed(vaddr, numpages, enc);
- return true;
+ if (enc && !tdx_enc_status_changed(vaddr, numpages, enc))
+ return -EIO;
+
+ return 0;
}
-static bool tdx_enc_status_change_finish(unsigned long vaddr, int numpages,
+static int tdx_enc_status_change_finish(unsigned long vaddr, int numpages,
bool enc)
{
/*
* Only handle private->shared conversion here.
* See the comment in tdx_early_init().
*/
- if (!enc)
- return tdx_enc_status_changed(vaddr, numpages, enc);
- return true;
+ if (!enc && !tdx_enc_status_changed(vaddr, numpages, enc))
+ return -EIO;
+
+ if (enc)
+ atomic_long_sub(numpages, &nr_shared);
+ else
+ atomic_long_add(numpages, &nr_shared);
+
+ return 0;
+}
+
+/* Stop new private<->shared conversions */
+static void tdx_kexec_begin(void)
+{
+ if (!IS_ENABLED(CONFIG_KEXEC_CORE))
+ return;
+
+ /*
+ * Crash kernel reaches 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");
+}
+
+/* Walk direct mapping and convert all shared memory back to private */
+static void tdx_kexec_finish(void)
+{
+ unsigned long addr, end;
+ long found = 0, shared;
+
+ if (!IS_ENABLED(CONFIG_KEXEC_CORE))
+ return;
+
+ lockdep_assert_irqs_disabled();
+
+ addr = PAGE_OFFSET;
+ end = PAGE_OFFSET + get_max_mapped();
+
+ while (addr < end) {
+ unsigned long size;
+ unsigned int level;
+ pte_t *pte;
+
+ pte = lookup_address(addr, &level);
+ size = page_level_size(level);
+
+ if (pte && pte_decrypted(*pte)) {
+ int pages = size / PAGE_SIZE;
+
+ /*
+ * Touching memory with shared bit set triggers implicit
+ * conversion to shared.
+ *
+ * Make sure nobody touches the shared range from
+ * now on.
+ */
+ set_pte(pte, __pte(0));
+
+ /*
+ * Memory encryption state persists across kexec.
+ * If tdx_enc_status_changed() fails in the first
+ * kernel, it leaves memory in an unknown state.
+ *
+ * If that memory remains shared, accessing it in the
+ * *next* kernel through a private mapping will result
+ * in an unrecoverable guest shutdown.
+ *
+ * The kdump kernel boot is not impacted as it uses
+ * a pre-reserved memory range that is always private.
+ * However, gathering crash information could lead to
+ * a crash if it accesses unconverted memory through
+ * a private mapping which is possible when accessing
+ * that memory through /proc/vmcore, for example.
+ *
+ * In all cases, print error info in order to leave
+ * enough bread crumbs for debugging.
+ */
+ if (!tdx_enc_status_changed(addr, pages, true)) {
+ pr_err("Failed to unshare range %#lx-%#lx\n",
+ addr, addr + size);
+ }
+
+ found += pages;
+ }
+
+ addr += size;
+ }
+
+ __flush_tlb_all();
+
+ shared = atomic_long_read(&nr_shared);
+ if (shared != found) {
+ pr_err("shared page accounting is off\n");
+ pr_err("nr_shared = %ld, nr_found = %ld\n", shared, found);
+ }
}
void __init tdx_early_init(void)
@@ -881,6 +981,9 @@ void __init tdx_early_init(void)
x86_platform.guest.enc_cache_flush_required = tdx_cache_flush_required;
x86_platform.guest.enc_tlb_flush_required = tdx_tlb_flush_required;
+ x86_platform.guest.enc_kexec_begin = tdx_kexec_begin;
+ x86_platform.guest.enc_kexec_finish = tdx_kexec_finish;
+
/*
* TDX intercepts the RDMSR to read the X2APIC ID in the parallel
* bringup low level code. That raises #VE which cannot be handled
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 11c9b8efdc4c..ed0a5f2dc129 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -89,10 +89,6 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL)
cld
- IBRS_ENTER
- UNTRAIN_RET
- CLEAR_BRANCH_HISTORY
-
/*
* SYSENTER doesn't filter flags, so we need to clear NT and AC
* ourselves. To save a few cycles, we can check whether
@@ -116,6 +112,16 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL)
jnz .Lsysenter_fix_flags
.Lsysenter_flags_fixed:
+ /*
+ * CPU bugs mitigations mechanisms can call other functions. They
+ * should be invoked after making sure TF is cleared because
+ * single-step is ignored only for instructions inside the
+ * entry_SYSENTER_compat function.
+ */
+ IBRS_ENTER
+ UNTRAIN_RET
+ CLEAR_BRANCH_HISTORY
+
movq %rsp, %rdi
call do_SYSENTER_32
jmp sysret32_from_system_call
diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c
index c2235bae17ef..8cc9950d7104 100644
--- a/arch/x86/entry/syscall_32.c
+++ b/arch/x86/entry/syscall_32.c
@@ -14,9 +14,12 @@
#endif
#define __SYSCALL(nr, sym) extern long __ia32_##sym(const struct pt_regs *);
-
+#define __SYSCALL_NORETURN(nr, sym) extern long __noreturn __ia32_##sym(const struct pt_regs *);
#include <asm/syscalls_32.h>
-#undef __SYSCALL
+#undef __SYSCALL
+
+#undef __SYSCALL_NORETURN
+#define __SYSCALL_NORETURN __SYSCALL
/*
* The sys_call_table[] is no longer used for system calls, but
@@ -28,11 +31,10 @@
const sys_call_ptr_t sys_call_table[] = {
#include <asm/syscalls_32.h>
};
-#undef __SYSCALL
+#undef __SYSCALL
#endif
#define __SYSCALL(nr, sym) case nr: return __ia32_##sym(regs);
-
long ia32_sys_call(const struct pt_regs *regs, unsigned int nr)
{
switch (nr) {
diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
index 33b3f09e6f15..ba8354424860 100644
--- a/arch/x86/entry/syscall_64.c
+++ b/arch/x86/entry/syscall_64.c
@@ -8,8 +8,12 @@
#include <asm/syscall.h>
#define __SYSCALL(nr, sym) extern long __x64_##sym(const struct pt_regs *);
+#define __SYSCALL_NORETURN(nr, sym) extern long __noreturn __x64_##sym(const struct pt_regs *);
#include <asm/syscalls_64.h>
-#undef __SYSCALL
+#undef __SYSCALL
+
+#undef __SYSCALL_NORETURN
+#define __SYSCALL_NORETURN __SYSCALL
/*
* The sys_call_table[] is no longer used for system calls, but
@@ -20,10 +24,9 @@
const sys_call_ptr_t sys_call_table[] = {
#include <asm/syscalls_64.h>
};
-#undef __SYSCALL
+#undef __SYSCALL
#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
-
long x64_sys_call(const struct pt_regs *regs, unsigned int nr)
{
switch (nr) {
diff --git a/arch/x86/entry/syscall_x32.c b/arch/x86/entry/syscall_x32.c
index 03de4a932131..fb77908f44f3 100644
--- a/arch/x86/entry/syscall_x32.c
+++ b/arch/x86/entry/syscall_x32.c
@@ -8,11 +8,14 @@
#include <asm/syscall.h>
#define __SYSCALL(nr, sym) extern long __x64_##sym(const struct pt_regs *);
+#define __SYSCALL_NORETURN(nr, sym) extern long __noreturn __x64_##sym(const struct pt_regs *);
#include <asm/syscalls_x32.h>
-#undef __SYSCALL
+#undef __SYSCALL
-#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
+#undef __SYSCALL_NORETURN
+#define __SYSCALL_NORETURN __SYSCALL
+#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
long x32_sys_call(const struct pt_regs *regs, unsigned int nr)
{
switch (nr) {
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index d6ebcab1d8b2..534c74b14fab 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -1,8 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
#
# 32-bit system call numbers and entry vectors
#
# The format is:
-# <number> <abi> <name> <entry point> <compat entry point>
+# <number> <abi> <name> <entry point> [<compat entry point> [noreturn]]
#
# The __ia32_sys and __ia32_compat_sys stubs are created on-the-fly for
# sys_*() system calls and compat_sys_*() compat system calls if
@@ -12,7 +13,7 @@
# The abi is always "i386" for this file.
#
0 i386 restart_syscall sys_restart_syscall
-1 i386 exit sys_exit
+1 i386 exit sys_exit - noreturn
2 i386 fork sys_fork
3 i386 read sys_read
4 i386 write sys_write
@@ -263,7 +264,7 @@
249 i386 io_cancel sys_io_cancel
250 i386 fadvise64 sys_ia32_fadvise64
# 251 is available for reuse (was briefly sys_set_zone_reclaim)
-252 i386 exit_group sys_exit_group
+252 i386 exit_group sys_exit_group - noreturn
253 i386 lookup_dcookie
254 i386 epoll_create sys_epoll_create
255 i386 epoll_ctl sys_epoll_ctl
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index a396f6e6ab5b..097e5a18db52 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -1,8 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
#
# 64-bit system call numbers and entry vectors
#
# The format is:
-# <number> <abi> <name> <entry point>
+# <number> <abi> <name> <entry point> [<compat entry point> [noreturn]]
#
# The __x64_sys_*() stubs are created on-the-fly for sys_*() system calls
#
@@ -68,7 +69,7 @@
57 common fork sys_fork
58 common vfork sys_vfork
59 64 execve sys_execve
-60 common exit sys_exit
+60 common exit sys_exit - noreturn
61 common wait4 sys_wait4
62 common kill sys_kill
63 common uname sys_newuname
@@ -239,7 +240,7 @@
228 common clock_gettime sys_clock_gettime
229 common clock_getres sys_clock_getres
230 common clock_nanosleep sys_clock_nanosleep
-231 common exit_group sys_exit_group
+231 common exit_group sys_exit_group - noreturn
232 common epoll_wait sys_epoll_wait
233 common epoll_ctl sys_epoll_ctl
234 common tgkill sys_tgkill
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 38c1b1f1deaa..0e835dc134a5 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -4698,8 +4698,8 @@ static void intel_pmu_check_extra_regs(struct extra_reg *extra_regs);
static inline bool intel_pmu_broken_perf_cap(void)
{
/* The Perf Metric (Bit 15) is always cleared */
- if ((boot_cpu_data.x86_model == INTEL_FAM6_METEORLAKE) ||
- (boot_cpu_data.x86_model == INTEL_FAM6_METEORLAKE_L))
+ if (boot_cpu_data.x86_vfm == INTEL_METEORLAKE ||
+ boot_cpu_data.x86_vfm == INTEL_METEORLAKE_L)
return true;
return false;
@@ -5187,35 +5187,35 @@ static __init void intel_clovertown_quirk(void)
}
static const struct x86_cpu_desc isolation_ucodes[] = {
- INTEL_CPU_DESC(INTEL_FAM6_HASWELL, 3, 0x0000001f),
- INTEL_CPU_DESC(INTEL_FAM6_HASWELL_L, 1, 0x0000001e),
- INTEL_CPU_DESC(INTEL_FAM6_HASWELL_G, 1, 0x00000015),
- INTEL_CPU_DESC(INTEL_FAM6_HASWELL_X, 2, 0x00000037),
- INTEL_CPU_DESC(INTEL_FAM6_HASWELL_X, 4, 0x0000000a),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL, 4, 0x00000023),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_G, 1, 0x00000014),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D, 2, 0x00000010),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D, 3, 0x07000009),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D, 4, 0x0f000009),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D, 5, 0x0e000002),
- INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_X, 1, 0x0b000014),
- INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 3, 0x00000021),
- INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 4, 0x00000000),
- INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 5, 0x00000000),
- INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 6, 0x00000000),
- INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 7, 0x00000000),
- INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 11, 0x00000000),
- INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_L, 3, 0x0000007c),
- INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE, 3, 0x0000007c),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 9, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_L, 9, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_L, 10, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_L, 11, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_L, 12, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 10, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 11, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 12, 0x0000004e),
- INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 13, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_HASWELL, 3, 0x0000001f),
+ INTEL_CPU_DESC(INTEL_HASWELL_L, 1, 0x0000001e),
+ INTEL_CPU_DESC(INTEL_HASWELL_G, 1, 0x00000015),
+ INTEL_CPU_DESC(INTEL_HASWELL_X, 2, 0x00000037),
+ INTEL_CPU_DESC(INTEL_HASWELL_X, 4, 0x0000000a),
+ INTEL_CPU_DESC(INTEL_BROADWELL, 4, 0x00000023),
+ INTEL_CPU_DESC(INTEL_BROADWELL_G, 1, 0x00000014),
+ INTEL_CPU_DESC(INTEL_BROADWELL_D, 2, 0x00000010),
+ INTEL_CPU_DESC(INTEL_BROADWELL_D, 3, 0x07000009),
+ INTEL_CPU_DESC(INTEL_BROADWELL_D, 4, 0x0f000009),
+ INTEL_CPU_DESC(INTEL_BROADWELL_D, 5, 0x0e000002),
+ INTEL_CPU_DESC(INTEL_BROADWELL_X, 1, 0x0b000014),
+ INTEL_CPU_DESC(INTEL_SKYLAKE_X, 3, 0x00000021),
+ INTEL_CPU_DESC(INTEL_SKYLAKE_X, 4, 0x00000000),
+ INTEL_CPU_DESC(INTEL_SKYLAKE_X, 5, 0x00000000),
+ INTEL_CPU_DESC(INTEL_SKYLAKE_X, 6, 0x00000000),
+ INTEL_CPU_DESC(INTEL_SKYLAKE_X, 7, 0x00000000),
+ INTEL_CPU_DESC(INTEL_SKYLAKE_X, 11, 0x00000000),
+ INTEL_CPU_DESC(INTEL_SKYLAKE_L, 3, 0x0000007c),
+ INTEL_CPU_DESC(INTEL_SKYLAKE, 3, 0x0000007c),
+ INTEL_CPU_DESC(INTEL_KABYLAKE, 9, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_KABYLAKE_L, 9, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_KABYLAKE_L, 10, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_KABYLAKE_L, 11, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_KABYLAKE_L, 12, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_KABYLAKE, 10, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_KABYLAKE, 11, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_KABYLAKE, 12, 0x0000004e),
+ INTEL_CPU_DESC(INTEL_KABYLAKE, 13, 0x0000004e),
{}
};
@@ -5232,9 +5232,9 @@ static __init void intel_pebs_isolation_quirk(void)
}
static const struct x86_cpu_desc pebs_ucodes[] = {
- INTEL_CPU_DESC(INTEL_FAM6_SANDYBRIDGE, 7, 0x00000028),
- INTEL_CPU_DESC(INTEL_FAM6_SANDYBRIDGE_X, 6, 0x00000618),
- INTEL_CPU_DESC(INTEL_FAM6_SANDYBRIDGE_X, 7, 0x0000070c),
+ INTEL_CPU_DESC(INTEL_SANDYBRIDGE, 7, 0x00000028),
+ INTEL_CPU_DESC(INTEL_SANDYBRIDGE_X, 6, 0x00000618),
+ INTEL_CPU_DESC(INTEL_SANDYBRIDGE_X, 7, 0x0000070c),
{}
};
@@ -6238,19 +6238,19 @@ __init int intel_pmu_init(void)
/*
* Install the hw-cache-events table:
*/
- switch (boot_cpu_data.x86_model) {
- case INTEL_FAM6_CORE_YONAH:
+ switch (boot_cpu_data.x86_vfm) {
+ case INTEL_CORE_YONAH:
pr_cont("Core events, ");
name = "core";
break;
- case INTEL_FAM6_CORE2_MEROM:
+ case INTEL_CORE2_MEROM:
x86_add_quirk(intel_clovertown_quirk);
fallthrough;
- case INTEL_FAM6_CORE2_MEROM_L:
- case INTEL_FAM6_CORE2_PENRYN:
- case INTEL_FAM6_CORE2_DUNNINGTON:
+ case INTEL_CORE2_MEROM_L:
+ case INTEL_CORE2_PENRYN:
+ case INTEL_CORE2_DUNNINGTON:
memcpy(hw_cache_event_ids, core2_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
@@ -6262,9 +6262,9 @@ __init int intel_pmu_init(void)
name = "core2";
break;
- case INTEL_FAM6_NEHALEM:
- case INTEL_FAM6_NEHALEM_EP:
- case INTEL_FAM6_NEHALEM_EX:
+ case INTEL_NEHALEM:
+ case INTEL_NEHALEM_EP:
+ case INTEL_NEHALEM_EX:
memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
@@ -6296,11 +6296,11 @@ __init int intel_pmu_init(void)
name = "nehalem";
break;
- case INTEL_FAM6_ATOM_BONNELL:
- case INTEL_FAM6_ATOM_BONNELL_MID:
- case INTEL_FAM6_ATOM_SALTWELL:
- case INTEL_FAM6_ATOM_SALTWELL_MID:
- case INTEL_FAM6_ATOM_SALTWELL_TABLET:
+ case INTEL_ATOM_BONNELL:
+ case INTEL_ATOM_BONNELL_MID:
+ case INTEL_ATOM_SALTWELL:
+ case INTEL_ATOM_SALTWELL_MID:
+ case INTEL_ATOM_SALTWELL_TABLET:
memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
@@ -6313,11 +6313,11 @@ __init int intel_pmu_init(void)
name = "bonnell";
break;
- case INTEL_FAM6_ATOM_SILVERMONT:
- case INTEL_FAM6_ATOM_SILVERMONT_D:
- case INTEL_FAM6_ATOM_SILVERMONT_MID:
- case INTEL_FAM6_ATOM_AIRMONT:
- case INTEL_FAM6_ATOM_AIRMONT_MID:
+ case INTEL_ATOM_SILVERMONT:
+ case INTEL_ATOM_SILVERMONT_D:
+ case INTEL_ATOM_SILVERMONT_MID:
+ case INTEL_ATOM_AIRMONT:
+ case INTEL_ATOM_AIRMONT_MID:
memcpy(hw_cache_event_ids, slm_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
@@ -6335,8 +6335,8 @@ __init int intel_pmu_init(void)
name = "silvermont";
break;
- case INTEL_FAM6_ATOM_GOLDMONT:
- case INTEL_FAM6_ATOM_GOLDMONT_D:
+ case INTEL_ATOM_GOLDMONT:
+ case INTEL_ATOM_GOLDMONT_D:
memcpy(hw_cache_event_ids, glm_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
memcpy(hw_cache_extra_regs, glm_hw_cache_extra_regs,
@@ -6362,7 +6362,7 @@ __init int intel_pmu_init(void)
name = "goldmont";
break;
- case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
+ case INTEL_ATOM_GOLDMONT_PLUS:
memcpy(hw_cache_event_ids, glp_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
memcpy(hw_cache_extra_regs, glp_hw_cache_extra_regs,
@@ -6391,9 +6391,9 @@ __init int intel_pmu_init(void)
name = "goldmont_plus";
break;
- case INTEL_FAM6_ATOM_TREMONT_D:
- case INTEL_FAM6_ATOM_TREMONT:
- case INTEL_FAM6_ATOM_TREMONT_L:
+ case INTEL_ATOM_TREMONT_D:
+ case INTEL_ATOM_TREMONT:
+ case INTEL_ATOM_TREMONT_L:
x86_pmu.late_ack = true;
memcpy(hw_cache_event_ids, glp_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
@@ -6420,7 +6420,7 @@ __init int intel_pmu_init(void)
name = "Tremont";
break;
- case INTEL_FAM6_ATOM_GRACEMONT:
+ case INTEL_ATOM_GRACEMONT:
intel_pmu_init_grt(NULL);
intel_pmu_pebs_data_source_grt();
x86_pmu.pebs_latency_data = adl_latency_data_small;
@@ -6432,8 +6432,8 @@ __init int intel_pmu_init(void)
name = "gracemont";
break;
- case INTEL_FAM6_ATOM_CRESTMONT:
- case INTEL_FAM6_ATOM_CRESTMONT_X:
+ case INTEL_ATOM_CRESTMONT:
+ case INTEL_ATOM_CRESTMONT_X:
intel_pmu_init_grt(NULL);
x86_pmu.extra_regs = intel_cmt_extra_regs;
intel_pmu_pebs_data_source_cmt();
@@ -6446,9 +6446,9 @@ __init int intel_pmu_init(void)
name = "crestmont";
break;
- case INTEL_FAM6_WESTMERE:
- case INTEL_FAM6_WESTMERE_EP:
- case INTEL_FAM6_WESTMERE_EX:
+ case INTEL_WESTMERE:
+ case INTEL_WESTMERE_EP:
+ case INTEL_WESTMERE_EX:
memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
@@ -6477,8 +6477,8 @@ __init int intel_pmu_init(void)
name = "westmere";
break;
- case INTEL_FAM6_SANDYBRIDGE:
- case INTEL_FAM6_SANDYBRIDGE_X:
+ case INTEL_SANDYBRIDGE:
+ case INTEL_SANDYBRIDGE_X:
x86_add_quirk(intel_sandybridge_quirk);
x86_add_quirk(intel_ht_bug);
memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
@@ -6491,7 +6491,7 @@ __init int intel_pmu_init(void)
x86_pmu.event_constraints = intel_snb_event_constraints;
x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints;
x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
- if (boot_cpu_data.x86_model == INTEL_FAM6_SANDYBRIDGE_X)
+ if (boot_cpu_data.x86_vfm == INTEL_SANDYBRIDGE_X)
x86_pmu.extra_regs = intel_snbep_extra_regs;
else
x86_pmu.extra_regs = intel_snb_extra_regs;
@@ -6517,8 +6517,8 @@ __init int intel_pmu_init(void)
name = "sandybridge";
break;
- case INTEL_FAM6_IVYBRIDGE:
- case INTEL_FAM6_IVYBRIDGE_X:
+ case INTEL_IVYBRIDGE:
+ case INTEL_IVYBRIDGE_X:
x86_add_quirk(intel_ht_bug);
memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
@@ -6534,7 +6534,7 @@ __init int intel_pmu_init(void)
x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints;
x86_pmu.pebs_aliases = intel_pebs_aliases_ivb;
x86_pmu.pebs_prec_dist = true;
- if (boot_cpu_data.x86_model == INTEL_FAM6_IVYBRIDGE_X)
+ if (boot_cpu_data.x86_vfm == INTEL_IVYBRIDGE_X)
x86_pmu.extra_regs = intel_snbep_extra_regs;
else
x86_pmu.extra_regs = intel_snb_extra_regs;
@@ -6556,10 +6556,10 @@ __init int intel_pmu_init(void)
break;
- case INTEL_FAM6_HASWELL:
- case INTEL_FAM6_HASWELL_X:
- case INTEL_FAM6_HASWELL_L:
- case INTEL_FAM6_HASWELL_G:
+ case INTEL_HASWELL:
+ case INTEL_HASWELL_X:
+ case INTEL_HASWELL_L:
+ case INTEL_HASWELL_G:
x86_add_quirk(intel_ht_bug);
x86_add_quirk(intel_pebs_isolation_quirk);
x86_pmu.late_ack = true;
@@ -6589,10 +6589,10 @@ __init int intel_pmu_init(void)
name = "haswell";
break;
- case INTEL_FAM6_BROADWELL:
- case INTEL_FAM6_BROADWELL_D:
- case INTEL_FAM6_BROADWELL_G:
- case INTEL_FAM6_BROADWELL_X:
+ case INTEL_BROADWELL:
+ case INTEL_BROADWELL_D:
+ case INTEL_BROADWELL_G:
+ case INTEL_BROADWELL_X:
x86_add_quirk(intel_pebs_isolation_quirk);
x86_pmu.late_ack = true;
memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
@@ -6631,8 +6631,8 @@ __init int intel_pmu_init(void)
name = "broadwell";
break;
- case INTEL_FAM6_XEON_PHI_KNL:
- case INTEL_FAM6_XEON_PHI_KNM:
+ case INTEL_XEON_PHI_KNL:
+ case INTEL_XEON_PHI_KNM:
memcpy(hw_cache_event_ids,
slm_hw_cache_event_ids, sizeof(hw_cache_event_ids));
memcpy(hw_cache_extra_regs,
@@ -6651,15 +6651,15 @@ __init int intel_pmu_init(void)
name = "knights-landing";
break;
- case INTEL_FAM6_SKYLAKE_X:
+ case INTEL_SKYLAKE_X:
pmem = true;
fallthrough;
- case INTEL_FAM6_SKYLAKE_L:
- case INTEL_FAM6_SKYLAKE:
- case INTEL_FAM6_KABYLAKE_L:
- case INTEL_FAM6_KABYLAKE:
- case INTEL_FAM6_COMETLAKE_L:
- case INTEL_FAM6_COMETLAKE:
+ case INTEL_SKYLAKE_L:
+ case INTEL_SKYLAKE:
+ case INTEL_KABYLAKE_L:
+ case INTEL_KABYLAKE:
+ case INTEL_COMETLAKE_L:
+ case INTEL_COMETLAKE:
x86_add_quirk(intel_pebs_isolation_quirk);
x86_pmu.late_ack = true;
memcpy(hw_cache_event_ids, skl_hw_cache_event_ids, sizeof(hw_cache_event_ids));
@@ -6708,16 +6708,16 @@ __init int intel_pmu_init(void)
name = "skylake";
break;
- case INTEL_FAM6_ICELAKE_X:
- case INTEL_FAM6_ICELAKE_D:
+ case INTEL_ICELAKE_X:
+ case INTEL_ICELAKE_D:
x86_pmu.pebs_ept = 1;
pmem = true;
fallthrough;
- case INTEL_FAM6_ICELAKE_L:
- case INTEL_FAM6_ICELAKE:
- case INTEL_FAM6_TIGERLAKE_L:
- case INTEL_FAM6_TIGERLAKE:
- case INTEL_FAM6_ROCKETLAKE:
+ case INTEL_ICELAKE_L:
+ case INTEL_ICELAKE:
+ case INTEL_TIGERLAKE_L:
+ case INTEL_TIGERLAKE:
+ case INTEL_ROCKETLAKE:
x86_pmu.late_ack = true;
memcpy(hw_cache_event_ids, skl_hw_cache_event_ids, sizeof(hw_cache_event_ids));
memcpy(hw_cache_extra_regs, skl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
@@ -6752,13 +6752,13 @@ __init int intel_pmu_init(void)
name = "icelake";
break;
- case INTEL_FAM6_SAPPHIRERAPIDS_X:
- case INTEL_FAM6_EMERALDRAPIDS_X:
+ case INTEL_SAPPHIRERAPIDS_X:
+ case INTEL_EMERALDRAPIDS_X:
x86_pmu.flags |= PMU_FL_MEM_LOADS_AUX;
x86_pmu.extra_regs = intel_glc_extra_regs;
fallthrough;
- case INTEL_FAM6_GRANITERAPIDS_X:
- case INTEL_FAM6_GRANITERAPIDS_D:
+ case INTEL_GRANITERAPIDS_X:
+ case INTEL_GRANITERAPIDS_D:
intel_pmu_init_glc(NULL);
if (!x86_pmu.extra_regs)
x86_pmu.extra_regs = intel_rwc_extra_regs;
@@ -6776,11 +6776,11 @@ __init int intel_pmu_init(void)
name = "sapphire_rapids";
break;
- case INTEL_FAM6_ALDERLAKE:
- case INTEL_FAM6_ALDERLAKE_L:
- case INTEL_FAM6_RAPTORLAKE:
- case INTEL_FAM6_RAPTORLAKE_P:
- case INTEL_FAM6_RAPTORLAKE_S:
+ case INTEL_ALDERLAKE:
+ case INTEL_ALDERLAKE_L:
+ case INTEL_RAPTORLAKE:
+ case INTEL_RAPTORLAKE_P:
+ case INTEL_RAPTORLAKE_S:
/*
* Alder Lake has 2 types of CPU, core and atom.
*
@@ -6838,8 +6838,8 @@ __init int intel_pmu_init(void)
name = "alderlake_hybrid";
break;
- case INTEL_FAM6_METEORLAKE:
- case INTEL_FAM6_METEORLAKE_L:
+ case INTEL_METEORLAKE:
+ case INTEL_METEORLAKE_L:
intel_pmu_init_hybrid(hybrid_big_small);
x86_pmu.pebs_latency_data = mtl_latency_data_small;
diff --git a/arch/x86/events/rapl.c b/arch/x86/events/rapl.c
index 0c5e7a7c43ac..b985ca79cf97 100644
--- a/arch/x86/events/rapl.c
+++ b/arch/x86/events/rapl.c
@@ -765,51 +765,51 @@ static struct rapl_model model_amd_hygon = {
};
static const struct x86_cpu_id rapl_model_match[] __initconst = {
- X86_MATCH_FEATURE(X86_FEATURE_RAPL, &model_amd_hygon),
- X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE, &model_snb),
- X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, &model_snbep),
- X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE, &model_snb),
- X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X, &model_snbep),
- X86_MATCH_INTEL_FAM6_MODEL(HASWELL, &model_hsw),
- X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X, &model_hsx),
- X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L, &model_hsw),
- X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G, &model_hsw),
- X86_MATCH_INTEL_FAM6_MODEL(BROADWELL, &model_hsw),
- X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G, &model_hsw),
- X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X, &model_hsx),
- X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D, &model_hsx),
- X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &model_knl),
- X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &model_knl),
- X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X, &model_hsx),
- X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(CANNONLAKE_L, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &model_hsw),
- X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D, &model_hsw),
- X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS, &model_hsw),
- X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(ICELAKE, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, &model_hsx),
- X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, &model_hsx),
- X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, &model_spr),
- X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X, &model_spr),
- X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(ARROWLAKE_H, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(ARROWLAKE, &model_skl),
- X86_MATCH_INTEL_FAM6_MODEL(LUNARLAKE_M, &model_skl),
+ X86_MATCH_FEATURE(X86_FEATURE_RAPL, &model_amd_hygon),
+ X86_MATCH_VFM(INTEL_SANDYBRIDGE, &model_snb),
+ X86_MATCH_VFM(INTEL_SANDYBRIDGE_X, &model_snbep),
+ X86_MATCH_VFM(INTEL_IVYBRIDGE, &model_snb),
+ X86_MATCH_VFM(INTEL_IVYBRIDGE_X, &model_snbep),
+ X86_MATCH_VFM(INTEL_HASWELL, &model_hsw),
+ X86_MATCH_VFM(INTEL_HASWELL_X, &model_hsx),
+ X86_MATCH_VFM(INTEL_HASWELL_L, &model_hsw),
+ X86_MATCH_VFM(INTEL_HASWELL_G, &model_hsw),
+ X86_MATCH_VFM(INTEL_BROADWELL, &model_hsw),
+ X86_MATCH_VFM(INTEL_BROADWELL_G, &model_hsw),
+ X86_MATCH_VFM(INTEL_BROADWELL_X, &model_hsx),
+ X86_MATCH_VFM(INTEL_BROADWELL_D, &model_hsx),
+ X86_MATCH_VFM(INTEL_XEON_PHI_KNL, &model_knl),
+ X86_MATCH_VFM(INTEL_XEON_PHI_KNM, &model_knl),
+ X86_MATCH_VFM(INTEL_SKYLAKE_L, &model_skl),
+ X86_MATCH_VFM(INTEL_SKYLAKE, &model_skl),
+ X86_MATCH_VFM(INTEL_SKYLAKE_X, &model_hsx),
+ X86_MATCH_VFM(INTEL_KABYLAKE_L, &model_skl),
+ X86_MATCH_VFM(INTEL_KABYLAKE, &model_skl),
+ X86_MATCH_VFM(INTEL_CANNONLAKE_L, &model_skl),
+ X86_MATCH_VFM(INTEL_ATOM_GOLDMONT, &model_hsw),
+ X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_D, &model_hsw),
+ X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_PLUS, &model_hsw),
+ X86_MATCH_VFM(INTEL_ICELAKE_L, &model_skl),
+ X86_MATCH_VFM(INTEL_ICELAKE, &model_skl),
+ X86_MATCH_VFM(INTEL_ICELAKE_D, &model_hsx),
+ X86_MATCH_VFM(INTEL_ICELAKE_X, &model_hsx),
+ X86_MATCH_VFM(INTEL_COMETLAKE_L, &model_skl),
+ X86_MATCH_VFM(INTEL_COMETLAKE, &model_skl),
+ X86_MATCH_VFM(INTEL_TIGERLAKE_L, &model_skl),
+ X86_MATCH_VFM(INTEL_TIGERLAKE, &model_skl),
+ X86_MATCH_VFM(INTEL_ALDERLAKE, &model_skl),
+ X86_MATCH_VFM(INTEL_ALDERLAKE_L, &model_skl),
+ X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, &model_skl),
+ X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, &model_spr),
+ X86_MATCH_VFM(INTEL_EMERALDRAPIDS_X, &model_spr),
+ X86_MATCH_VFM(INTEL_RAPTORLAKE, &model_skl),
+ X86_MATCH_VFM(INTEL_RAPTORLAKE_P, &model_skl),
+ X86_MATCH_VFM(INTEL_RAPTORLAKE_S, &model_skl),
+ X86_MATCH_VFM(INTEL_METEORLAKE, &model_skl),
+ X86_MATCH_VFM(INTEL_METEORLAKE_L, &model_skl),
+ X86_MATCH_VFM(INTEL_ARROWLAKE_H, &model_skl),
+ X86_MATCH_VFM(INTEL_ARROWLAKE, &model_skl),
+ X86_MATCH_VFM(INTEL_LUNARLAKE_M, &model_skl),
{},
};
MODULE_DEVICE_TABLE(x86cpu, rapl_model_match);
diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
index 768d73de0d09..b4a851d27c7c 100644
--- a/arch/x86/hyperv/ivm.c
+++ b/arch/x86/hyperv/ivm.c
@@ -523,9 +523,9 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
* transition is complete, hv_vtom_set_host_visibility() marks the pages
* as "present" again.
*/
-static bool hv_vtom_clear_present(unsigned long kbuffer, int pagecount, bool enc)
+static int hv_vtom_clear_present(unsigned long kbuffer, int pagecount, bool enc)
{
- return !set_memory_np(kbuffer, pagecount);
+ return set_memory_np(kbuffer, pagecount);
}
/*
@@ -536,20 +536,19 @@ static bool hv_vtom_clear_present(unsigned long kbuffer, int pagecount, bool enc
* with host. This function works as wrap of hv_mark_gpa_visibility()
* with memory base and size.
*/
-static bool hv_vtom_set_host_visibility(unsigned long kbuffer, int pagecount, bool enc)
+static int hv_vtom_set_host_visibility(unsigned long kbuffer, int pagecount, bool enc)
{
enum hv_mem_host_visibility visibility = enc ?
VMBUS_PAGE_NOT_VISIBLE : VMBUS_PAGE_VISIBLE_READ_WRITE;
u64 *pfn_array;
phys_addr_t paddr;
+ int i, pfn, err;
void *vaddr;
int ret = 0;
- bool result = true;
- int i, pfn;
pfn_array = kmalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL);
if (!pfn_array) {
- result = false;
+ ret = -ENOMEM;
goto err_set_memory_p;
}
@@ -568,10 +567,8 @@ static bool hv_vtom_set_host_visibility(unsigned long kbuffer, int pagecount, bo
if (pfn == HV_MAX_MODIFY_GPA_REP_COUNT || i == pagecount - 1) {
ret = hv_mark_gpa_visibility(pfn, pfn_array,
visibility);
- if (ret) {
- result = false;
+ if (ret)
goto err_free_pfn_array;
- }
pfn = 0;
}
}
@@ -586,10 +583,11 @@ err_set_memory_p:
* order to avoid leaving the memory range in a "broken" state. Setting
* the PRESENT bits shouldn't fail, but return an error if it does.
*/
- if (set_memory_p(kbuffer, pagecount))
- result = false;
+ err = set_memory_p(kbuffer, pagecount);
+ if (err && !ret)
+ ret = err;
- return result;
+ return ret;
}
static bool hv_vtom_tlb_flush_required(bool private)
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 5af926c050f0..21bc53f5ed0c 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -78,6 +78,13 @@ static inline bool acpi_skip_set_wakeup_address(void)
#define acpi_skip_set_wakeup_address acpi_skip_set_wakeup_address
+union acpi_subtable_headers;
+
+int __init acpi_parse_mp_wake(union acpi_subtable_headers *header,
+ const unsigned long end);
+
+void asm_acpi_mp_play_dead(u64 reset_vector, u64 pgd_pa);
+
/*
* Check if the CPU can handle C2 and deeper
*/
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index ba99ef75f56c..ca9ae606aab9 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -156,102 +156,50 @@ static inline int alternatives_text_reserved(void *start, void *end)
#define ALT_CALL_INSTR "call BUG_func"
-#define b_replacement(num) "664"#num
-#define e_replacement(num) "665"#num
+#define alt_slen "772b-771b"
+#define alt_total_slen "773b-771b"
+#define alt_rlen "775f-774f"
-#define alt_end_marker "663"
-#define alt_slen "662b-661b"
-#define alt_total_slen alt_end_marker"b-661b"
-#define alt_rlen(num) e_replacement(num)"f-"b_replacement(num)"f"
-
-#define OLDINSTR(oldinstr, num) \
- "# ALT: oldnstr\n" \
- "661:\n\t" oldinstr "\n662:\n" \
+#define OLDINSTR(oldinstr) \
+ "# ALT: oldinstr\n" \
+ "771:\n\t" oldinstr "\n772:\n" \
"# ALT: padding\n" \
- ".skip -(((" alt_rlen(num) ")-(" alt_slen ")) > 0) * " \
- "((" alt_rlen(num) ")-(" alt_slen ")),0x90\n" \
- alt_end_marker ":\n"
-
-/*
- * gas compatible max based on the idea from:
- * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
- *
- * The additional "-" is needed because gas uses a "true" value of -1.
- */
-#define alt_max_short(a, b) "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") < (" b ")))))"
-
-/*
- * Pad the second replacement alternative with additional NOPs if it is
- * additionally longer than the first replacement alternative.
- */
-#define OLDINSTR_2(oldinstr, num1, num2) \
- "# ALT: oldinstr2\n" \
- "661:\n\t" oldinstr "\n662:\n" \
- "# ALT: padding2\n" \
- ".skip -((" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")) > 0) * " \
- "(" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")), 0x90\n" \
- alt_end_marker ":\n"
-
-#define OLDINSTR_3(oldinsn, n1, n2, n3) \
- "# ALT: oldinstr3\n" \
- "661:\n\t" oldinsn "\n662:\n" \
- "# ALT: padding3\n" \
- ".skip -((" alt_max_short(alt_max_short(alt_rlen(n1), alt_rlen(n2)), alt_rlen(n3)) \
- " - (" alt_slen ")) > 0) * " \
- "(" alt_max_short(alt_max_short(alt_rlen(n1), alt_rlen(n2)), alt_rlen(n3)) \
- " - (" alt_slen ")), 0x90\n" \
- alt_end_marker ":\n"
-
-#define ALTINSTR_ENTRY(ft_flags, num) \
- " .long 661b - .\n" /* label */ \
- " .long " b_replacement(num)"f - .\n" /* new instruction */ \
+ ".skip -(((" alt_rlen ")-(" alt_slen ")) > 0) * " \
+ "((" alt_rlen ")-(" alt_slen ")),0x90\n" \
+ "773:\n"
+
+#define ALTINSTR_ENTRY(ft_flags) \
+ ".pushsection .altinstructions,\"a\"\n" \
+ " .long 771b - .\n" /* label */ \
+ " .long 774f - .\n" /* new instruction */ \
" .4byte " __stringify(ft_flags) "\n" /* feature + flags */ \
" .byte " alt_total_slen "\n" /* source len */ \
- " .byte " alt_rlen(num) "\n" /* replacement len */
+ " .byte " alt_rlen "\n" /* replacement len */ \
+ ".popsection\n"
-#define ALTINSTR_REPLACEMENT(newinstr, num) /* replacement */ \
- "# ALT: replacement " #num "\n" \
- b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n"
+#define ALTINSTR_REPLACEMENT(newinstr) /* replacement */ \
+ ".pushsection .altinstr_replacement, \"ax\"\n" \
+ "# ALT: replacement\n" \
+ "774:\n\t" newinstr "\n775:\n" \
+ ".popsection\n"
/* alternative assembly primitive: */
#define ALTERNATIVE(oldinstr, newinstr, ft_flags) \
- OLDINSTR(oldinstr, 1) \
- ".pushsection .altinstructions,\"a\"\n" \
- ALTINSTR_ENTRY(ft_flags, 1) \
- ".popsection\n" \
- ".pushsection .altinstr_replacement, \"ax\"\n" \
- ALTINSTR_REPLACEMENT(newinstr, 1) \
- ".popsection\n"
+ OLDINSTR(oldinstr) \
+ ALTINSTR_ENTRY(ft_flags) \
+ ALTINSTR_REPLACEMENT(newinstr)
#define ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) \
- OLDINSTR_2(oldinstr, 1, 2) \
- ".pushsection .altinstructions,\"a\"\n" \
- ALTINSTR_ENTRY(ft_flags1, 1) \
- ALTINSTR_ENTRY(ft_flags2, 2) \
- ".popsection\n" \
- ".pushsection .altinstr_replacement, \"ax\"\n" \
- ALTINSTR_REPLACEMENT(newinstr1, 1) \
- ALTINSTR_REPLACEMENT(newinstr2, 2) \
- ".popsection\n"
+ ALTERNATIVE(ALTERNATIVE(oldinstr, newinstr1, ft_flags1), newinstr2, ft_flags2)
/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
#define ALTERNATIVE_TERNARY(oldinstr, ft_flags, newinstr_yes, newinstr_no) \
- ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \
- newinstr_yes, ft_flags)
-
-#define ALTERNATIVE_3(oldinsn, newinsn1, ft_flags1, newinsn2, ft_flags2, \
- newinsn3, ft_flags3) \
- OLDINSTR_3(oldinsn, 1, 2, 3) \
- ".pushsection .altinstructions,\"a\"\n" \
- ALTINSTR_ENTRY(ft_flags1, 1) \
- ALTINSTR_ENTRY(ft_flags2, 2) \
- ALTINSTR_ENTRY(ft_flags3, 3) \
- ".popsection\n" \
- ".pushsection .altinstr_replacement, \"ax\"\n" \
- ALTINSTR_REPLACEMENT(newinsn1, 1) \
- ALTINSTR_REPLACEMENT(newinsn2, 2) \
- ALTINSTR_REPLACEMENT(newinsn3, 3) \
- ".popsection\n"
+ ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, newinstr_yes, ft_flags)
+
+#define ALTERNATIVE_3(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2, \
+ newinstr3, ft_flags3) \
+ ALTERNATIVE(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2), \
+ newinstr3, ft_flags3)
/*
* Alternative instructions for different CPU types or capabilities.
@@ -266,14 +214,11 @@ static inline int alternatives_text_reserved(void *start, void *end)
* without volatile and memory clobber.
*/
#define alternative(oldinstr, newinstr, ft_flags) \
- asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, ft_flags) : : : "memory")
+ asm_inline volatile(ALTERNATIVE(oldinstr, newinstr, ft_flags) : : : "memory")
#define alternative_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) \
asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) ::: "memory")
-#define alternative_ternary(oldinstr, ft_flags, newinstr_yes, newinstr_no) \
- asm_inline volatile(ALTERNATIVE_TERNARY(oldinstr, ft_flags, newinstr_yes, newinstr_no) ::: "memory")
-
/*
* Alternative inline assembly with input.
*
@@ -283,18 +228,28 @@ static inline int alternatives_text_reserved(void *start, void *end)
* Leaving an unused argument 0 to keep API compatibility.
*/
#define alternative_input(oldinstr, newinstr, ft_flags, input...) \
- asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, ft_flags) \
+ asm_inline volatile(ALTERNATIVE(oldinstr, newinstr, ft_flags) \
: : "i" (0), ## input)
/* Like alternative_input, but with a single output argument */
#define alternative_io(oldinstr, newinstr, ft_flags, output, input...) \
- asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, ft_flags) \
+ asm_inline volatile(ALTERNATIVE(oldinstr, newinstr, ft_flags) \
: output : "i" (0), ## input)
-/* Like alternative_io, but for replacing a direct call with another one. */
-#define alternative_call(oldfunc, newfunc, ft_flags, output, input...) \
- asm_inline volatile (ALTERNATIVE("call %c[old]", "call %c[new]", ft_flags) \
- : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)
+/*
+ * Like alternative_io, but for replacing a direct call with another one.
+ *
+ * Use the %c operand modifier which is the generic way to print a bare
+ * constant expression with all syntax-specific punctuation omitted. %P
+ * is the x86-specific variant which can handle constants too, for
+ * historical reasons, but it should be used primarily for PIC
+ * references: i.e., if used for a function, it would add the PLT
+ * suffix.
+ */
+#define alternative_call(oldfunc, newfunc, ft_flags, output, input...) \
+ asm_inline volatile(ALTERNATIVE("call %c[old]", "call %c[new]", ft_flags) \
+ : ALT_OUTPUT_SP(output) \
+ : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)
/*
* Like alternative_call, but there are two features and respective functions.
@@ -302,12 +257,12 @@ static inline int alternatives_text_reserved(void *start, void *end)
* Otherwise, if CPU has feature1, function1 is used.
* Otherwise, old function is used.
*/
-#define alternative_call_2(oldfunc, newfunc1, ft_flags1, newfunc2, ft_flags2, \
- output, input...) \
- asm_inline volatile (ALTERNATIVE_2("call %c[old]", "call %c[new1]", ft_flags1, \
- "call %c[new2]", ft_flags2) \
- : output, ASM_CALL_CONSTRAINT \
- : [old] "i" (oldfunc), [new1] "i" (newfunc1), \
+#define alternative_call_2(oldfunc, newfunc1, ft_flags1, newfunc2, ft_flags2, \
+ output, input...) \
+ asm_inline volatile(ALTERNATIVE_2("call %c[old]", "call %c[new1]", ft_flags1, \
+ "call %c[new2]", ft_flags2) \
+ : ALT_OUTPUT_SP(output) \
+ : [old] "i" (oldfunc), [new1] "i" (newfunc1), \
[new2] "i" (newfunc2), ## input)
/*
@@ -322,6 +277,8 @@ static inline int alternatives_text_reserved(void *start, void *end)
*/
#define ASM_NO_INPUT_CLOBBER(clbr...) "i" (0) : clbr
+#define ALT_OUTPUT_SP(...) ASM_CALL_CONSTRAINT, ## __VA_ARGS__
+
/* Macro for creating assembler functions avoiding any C magic. */
#define DEFINE_ASM_FUNC(func, instr, sec) \
asm (".pushsection " #sec ", \"ax\"\n" \
@@ -388,22 +345,23 @@ void nop_func(void);
* @newinstr. ".skip" directive takes care of proper instruction padding
* in case @newinstr is longer than @oldinstr.
*/
-.macro ALTERNATIVE oldinstr, newinstr, ft_flags
-140:
- \oldinstr
-141:
- .skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x90
-142:
-
- .pushsection .altinstructions,"a"
- altinstr_entry 140b,143f,\ft_flags,142b-140b,144f-143f
- .popsection
+#define __ALTERNATIVE(oldinst, newinst, flag) \
+740: \
+ oldinst ; \
+741: \
+ .skip -(((744f-743f)-(741b-740b)) > 0) * ((744f-743f)-(741b-740b)),0x90 ;\
+742: \
+ .pushsection .altinstructions,"a" ; \
+ altinstr_entry 740b,743f,flag,742b-740b,744f-743f ; \
+ .popsection ; \
+ .pushsection .altinstr_replacement,"ax" ; \
+743: \
+ newinst ; \
+744: \
+ .popsection ;
- .pushsection .altinstr_replacement,"ax"
-143:
- \newinstr
-144:
- .popsection
+.macro ALTERNATIVE oldinstr, newinstr, ft_flags
+ __ALTERNATIVE(\oldinstr, \newinstr, \ft_flags)
.endm
#define old_len 141b-140b
@@ -412,65 +370,18 @@ void nop_func(void);
#define new_len3 146f-145f
/*
- * gas compatible max based on the idea from:
- * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
- *
- * The additional "-" is needed because gas uses a "true" value of -1.
- */
-#define alt_max_2(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
-#define alt_max_3(a, b, c) (alt_max_2(alt_max_2(a, b), c))
-
-
-/*
* Same as ALTERNATIVE macro above but for two alternatives. If CPU
* has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
* @feature2, it replaces @oldinstr with @feature2.
*/
.macro ALTERNATIVE_2 oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2
-140:
- \oldinstr
-141:
- .skip -((alt_max_2(new_len1, new_len2) - (old_len)) > 0) * \
- (alt_max_2(new_len1, new_len2) - (old_len)),0x90
-142:
-
- .pushsection .altinstructions,"a"
- altinstr_entry 140b,143f,\ft_flags1,142b-140b,144f-143f
- altinstr_entry 140b,144f,\ft_flags2,142b-140b,145f-144f
- .popsection
-
- .pushsection .altinstr_replacement,"ax"
-143:
- \newinstr1
-144:
- \newinstr2
-145:
- .popsection
+ __ALTERNATIVE(__ALTERNATIVE(\oldinstr, \newinstr1, \ft_flags1),
+ \newinstr2, \ft_flags2)
.endm
.macro ALTERNATIVE_3 oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2, newinstr3, ft_flags3
-140:
- \oldinstr
-141:
- .skip -((alt_max_3(new_len1, new_len2, new_len3) - (old_len)) > 0) * \
- (alt_max_3(new_len1, new_len2, new_len3) - (old_len)),0x90
-142:
-
- .pushsection .altinstructions,"a"
- altinstr_entry 140b,143f,\ft_flags1,142b-140b,144f-143f
- altinstr_entry 140b,144f,\ft_flags2,142b-140b,145f-144f
- altinstr_entry 140b,145f,\ft_flags3,142b-140b,146f-145f
- .popsection
-
- .pushsection .altinstr_replacement,"ax"
-143:
- \newinstr1
-144:
- \newinstr2
-145:
- \newinstr3
-146:
- .popsection
+ __ALTERNATIVE(ALTERNATIVE_2(\oldinstr, \newinstr1, \ft_flags1, \newinstr2, \ft_flags2),
+ \newinstr3, \ft_flags3)
.endm
/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
index 5c37944c8a5e..6f3b6aef47ba 100644
--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -21,8 +21,8 @@ extern int amd_numa_init(void);
extern int amd_get_subcaches(int);
extern int amd_set_subcaches(int, unsigned long);
-extern int amd_smn_read(u16 node, u32 address, u32 *value);
-extern int amd_smn_write(u16 node, u32 address, u32 value);
+int __must_check amd_smn_read(u16 node, u32 address, u32 *value);
+int __must_check amd_smn_write(u16 node, u32 address, u32 value);
struct amd_l3_cache {
unsigned indices;
diff --git a/arch/x86/include/asm/cpu_device_id.h b/arch/x86/include/asm/cpu_device_id.h
index b6325ee30871..3831f612e89c 100644
--- a/arch/x86/include/asm/cpu_device_id.h
+++ b/arch/x86/include/asm/cpu_device_id.h
@@ -280,10 +280,10 @@ struct x86_cpu_desc {
u32 x86_microcode_rev;
};
-#define INTEL_CPU_DESC(model, stepping, revision) { \
- .x86_family = 6, \
- .x86_vendor = X86_VENDOR_INTEL, \
- .x86_model = (model), \
+#define INTEL_CPU_DESC(vfm, stepping, revision) { \
+ .x86_family = VFM_FAMILY(vfm), \
+ .x86_vendor = VFM_VENDOR(vfm), \
+ .x86_model = VFM_MODEL(vfm), \
.x86_stepping = (stepping), \
.x86_microcode_rev = (revision), \
}
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 3c7434329661..b51e88d01b21 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -18,170 +18,170 @@
/*
* Note: If the comment begins with a quoted string, that string is used
- * in /proc/cpuinfo instead of the macro name. If the string is "",
- * this feature bit is not displayed in /proc/cpuinfo at all.
+ * in /proc/cpuinfo instead of the macro name. Otherwise, this feature
+ * bit is not displayed in /proc/cpuinfo at all.
*
* When adding new features here that depend on other features,
* please update the table in kernel/cpu/cpuid-deps.c as well.
*/
/* Intel-defined CPU features, CPUID level 0x00000001 (EDX), word 0 */
-#define X86_FEATURE_FPU ( 0*32+ 0) /* Onboard FPU */
-#define X86_FEATURE_VME ( 0*32+ 1) /* Virtual Mode Extensions */
-#define X86_FEATURE_DE ( 0*32+ 2) /* Debugging Extensions */
-#define X86_FEATURE_PSE ( 0*32+ 3) /* Page Size Extensions */
-#define X86_FEATURE_TSC ( 0*32+ 4) /* Time Stamp Counter */
-#define X86_FEATURE_MSR ( 0*32+ 5) /* Model-Specific Registers */
-#define X86_FEATURE_PAE ( 0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE ( 0*32+ 7) /* Machine Check Exception */
-#define X86_FEATURE_CX8 ( 0*32+ 8) /* CMPXCHG8 instruction */
-#define X86_FEATURE_APIC ( 0*32+ 9) /* Onboard APIC */
-#define X86_FEATURE_SEP ( 0*32+11) /* SYSENTER/SYSEXIT */
-#define X86_FEATURE_MTRR ( 0*32+12) /* Memory Type Range Registers */
-#define X86_FEATURE_PGE ( 0*32+13) /* Page Global Enable */
-#define X86_FEATURE_MCA ( 0*32+14) /* Machine Check Architecture */
-#define X86_FEATURE_CMOV ( 0*32+15) /* CMOV instructions (plus FCMOVcc, FCOMI with FPU) */
-#define X86_FEATURE_PAT ( 0*32+16) /* Page Attribute Table */
-#define X86_FEATURE_PSE36 ( 0*32+17) /* 36-bit PSEs */
-#define X86_FEATURE_PN ( 0*32+18) /* Processor serial number */
-#define X86_FEATURE_CLFLUSH ( 0*32+19) /* CLFLUSH instruction */
+#define X86_FEATURE_FPU ( 0*32+ 0) /* "fpu" Onboard FPU */
+#define X86_FEATURE_VME ( 0*32+ 1) /* "vme" Virtual Mode Extensions */
+#define X86_FEATURE_DE ( 0*32+ 2) /* "de" Debugging Extensions */
+#define X86_FEATURE_PSE ( 0*32+ 3) /* "pse" Page Size Extensions */
+#define X86_FEATURE_TSC ( 0*32+ 4) /* "tsc" Time Stamp Counter */
+#define X86_FEATURE_MSR ( 0*32+ 5) /* "msr" Model-Specific Registers */
+#define X86_FEATURE_PAE ( 0*32+ 6) /* "pae" Physical Address Extensions */
+#define X86_FEATURE_MCE ( 0*32+ 7) /* "mce" Machine Check Exception */
+#define X86_FEATURE_CX8 ( 0*32+ 8) /* "cx8" CMPXCHG8 instruction */
+#define X86_FEATURE_APIC ( 0*32+ 9) /* "apic" Onboard APIC */
+#define X86_FEATURE_SEP ( 0*32+11) /* "sep" SYSENTER/SYSEXIT */
+#define X86_FEATURE_MTRR ( 0*32+12) /* "mtrr" Memory Type Range Registers */
+#define X86_FEATURE_PGE ( 0*32+13) /* "pge" Page Global Enable */
+#define X86_FEATURE_MCA ( 0*32+14) /* "mca" Machine Check Architecture */
+#define X86_FEATURE_CMOV ( 0*32+15) /* "cmov" CMOV instructions (plus FCMOVcc, FCOMI with FPU) */
+#define X86_FEATURE_PAT ( 0*32+16) /* "pat" Page Attribute Table */
+#define X86_FEATURE_PSE36 ( 0*32+17) /* "pse36" 36-bit PSEs */
+#define X86_FEATURE_PN ( 0*32+18) /* "pn" Processor serial number */
+#define X86_FEATURE_CLFLUSH ( 0*32+19) /* "clflush" CLFLUSH instruction */
#define X86_FEATURE_DS ( 0*32+21) /* "dts" Debug Store */
-#define X86_FEATURE_ACPI ( 0*32+22) /* ACPI via MSR */
-#define X86_FEATURE_MMX ( 0*32+23) /* Multimedia Extensions */
-#define X86_FEATURE_FXSR ( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */
+#define X86_FEATURE_ACPI ( 0*32+22) /* "acpi" ACPI via MSR */
+#define X86_FEATURE_MMX ( 0*32+23) /* "mmx" Multimedia Extensions */
+#define X86_FEATURE_FXSR ( 0*32+24) /* "fxsr" FXSAVE/FXRSTOR, CR4.OSFXSR */
#define X86_FEATURE_XMM ( 0*32+25) /* "sse" */
#define X86_FEATURE_XMM2 ( 0*32+26) /* "sse2" */
#define X86_FEATURE_SELFSNOOP ( 0*32+27) /* "ss" CPU self snoop */
-#define X86_FEATURE_HT ( 0*32+28) /* Hyper-Threading */
+#define X86_FEATURE_HT ( 0*32+28) /* "ht" Hyper-Threading */
#define X86_FEATURE_ACC ( 0*32+29) /* "tm" Automatic clock control */
-#define X86_FEATURE_IA64 ( 0*32+30) /* IA-64 processor */
-#define X86_FEATURE_PBE ( 0*32+31) /* Pending Break Enable */
+#define X86_FEATURE_IA64 ( 0*32+30) /* "ia64" IA-64 processor */
+#define X86_FEATURE_PBE ( 0*32+31) /* "pbe" Pending Break Enable */
/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
/* Don't duplicate feature flags which are redundant with Intel! */
-#define X86_FEATURE_SYSCALL ( 1*32+11) /* SYSCALL/SYSRET */
-#define X86_FEATURE_MP ( 1*32+19) /* MP Capable */
-#define X86_FEATURE_NX ( 1*32+20) /* Execute Disable */
-#define X86_FEATURE_MMXEXT ( 1*32+22) /* AMD MMX extensions */
-#define X86_FEATURE_FXSR_OPT ( 1*32+25) /* FXSAVE/FXRSTOR optimizations */
+#define X86_FEATURE_SYSCALL ( 1*32+11) /* "syscall" SYSCALL/SYSRET */
+#define X86_FEATURE_MP ( 1*32+19) /* "mp" MP Capable */
+#define X86_FEATURE_NX ( 1*32+20) /* "nx" Execute Disable */
+#define X86_FEATURE_MMXEXT ( 1*32+22) /* "mmxext" AMD MMX extensions */
+#define X86_FEATURE_FXSR_OPT ( 1*32+25) /* "fxsr_opt" FXSAVE/FXRSTOR optimizations */
#define X86_FEATURE_GBPAGES ( 1*32+26) /* "pdpe1gb" GB pages */
-#define X86_FEATURE_RDTSCP ( 1*32+27) /* RDTSCP */
-#define X86_FEATURE_LM ( 1*32+29) /* Long Mode (x86-64, 64-bit support) */
-#define X86_FEATURE_3DNOWEXT ( 1*32+30) /* AMD 3DNow extensions */
-#define X86_FEATURE_3DNOW ( 1*32+31) /* 3DNow */
+#define X86_FEATURE_RDTSCP ( 1*32+27) /* "rdtscp" RDTSCP */
+#define X86_FEATURE_LM ( 1*32+29) /* "lm" Long Mode (x86-64, 64-bit support) */
+#define X86_FEATURE_3DNOWEXT ( 1*32+30) /* "3dnowext" AMD 3DNow extensions */
+#define X86_FEATURE_3DNOW ( 1*32+31) /* "3dnow" 3DNow */
/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
-#define X86_FEATURE_RECOVERY ( 2*32+ 0) /* CPU in recovery mode */
-#define X86_FEATURE_LONGRUN ( 2*32+ 1) /* Longrun power control */
-#define X86_FEATURE_LRTI ( 2*32+ 3) /* LongRun table interface */
+#define X86_FEATURE_RECOVERY ( 2*32+ 0) /* "recovery" CPU in recovery mode */
+#define X86_FEATURE_LONGRUN ( 2*32+ 1) /* "longrun" Longrun power control */
+#define X86_FEATURE_LRTI ( 2*32+ 3) /* "lrti" LongRun table interface */
/* Other features, Linux-defined mapping, word 3 */
/* This range is used for feature bits which conflict or are synthesized */
-#define X86_FEATURE_CXMMX ( 3*32+ 0) /* Cyrix MMX extensions */
-#define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */
-#define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */
-#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */
-#define X86_FEATURE_K8 ( 3*32+ 4) /* "" Opteron, Athlon64 */
-#define X86_FEATURE_ZEN5 ( 3*32+ 5) /* "" CPU based on Zen5 microarchitecture */
-#define X86_FEATURE_P3 ( 3*32+ 6) /* "" P3 */
-#define X86_FEATURE_P4 ( 3*32+ 7) /* "" P4 */
-#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */
-#define X86_FEATURE_UP ( 3*32+ 9) /* SMP kernel running on UP */
-#define X86_FEATURE_ART ( 3*32+10) /* Always running timer (ART) */
-#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */
-#define X86_FEATURE_PEBS ( 3*32+12) /* Precise-Event Based Sampling */
-#define X86_FEATURE_BTS ( 3*32+13) /* Branch Trace Store */
-#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in IA32 userspace */
-#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in IA32 userspace */
-#define X86_FEATURE_REP_GOOD ( 3*32+16) /* REP microcode works well */
-#define X86_FEATURE_AMD_LBR_V2 ( 3*32+17) /* AMD Last Branch Record Extension Version 2 */
-#define X86_FEATURE_CLEAR_CPU_BUF ( 3*32+18) /* "" Clear CPU buffers using VERW */
-#define X86_FEATURE_ACC_POWER ( 3*32+19) /* AMD Accumulated Power Mechanism */
-#define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */
-#define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */
-#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* CPU topology enum extensions */
-#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
-#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */
-#define X86_FEATURE_CPUID ( 3*32+25) /* CPU has CPUID instruction itself */
-#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* Extended APICID (8 bits) */
-#define X86_FEATURE_AMD_DCM ( 3*32+27) /* AMD multi-node processor */
-#define X86_FEATURE_APERFMPERF ( 3*32+28) /* P-State hardware coordination feedback capability (APERF/MPERF MSRs) */
-#define X86_FEATURE_RAPL ( 3*32+29) /* AMD/Hygon RAPL interface */
-#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
-#define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* TSC has known frequency */
+#define X86_FEATURE_CXMMX ( 3*32+ 0) /* "cxmmx" Cyrix MMX extensions */
+#define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* "k6_mtrr" AMD K6 nonstandard MTRRs */
+#define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* "cyrix_arr" Cyrix ARRs (= MTRRs) */
+#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* "centaur_mcr" Centaur MCRs (= MTRRs) */
+#define X86_FEATURE_K8 ( 3*32+ 4) /* Opteron, Athlon64 */
+#define X86_FEATURE_ZEN5 ( 3*32+ 5) /* CPU based on Zen5 microarchitecture */
+#define X86_FEATURE_P3 ( 3*32+ 6) /* P3 */
+#define X86_FEATURE_P4 ( 3*32+ 7) /* P4 */
+#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* "constant_tsc" TSC ticks at a constant rate */
+#define X86_FEATURE_UP ( 3*32+ 9) /* "up" SMP kernel running on UP */
+#define X86_FEATURE_ART ( 3*32+10) /* "art" Always running timer (ART) */
+#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* "arch_perfmon" Intel Architectural PerfMon */
+#define X86_FEATURE_PEBS ( 3*32+12) /* "pebs" Precise-Event Based Sampling */
+#define X86_FEATURE_BTS ( 3*32+13) /* "bts" Branch Trace Store */
+#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* syscall in IA32 userspace */
+#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* sysenter in IA32 userspace */
+#define X86_FEATURE_REP_GOOD ( 3*32+16) /* "rep_good" REP microcode works well */
+#define X86_FEATURE_AMD_LBR_V2 ( 3*32+17) /* "amd_lbr_v2" AMD Last Branch Record Extension Version 2 */
+#define X86_FEATURE_CLEAR_CPU_BUF ( 3*32+18) /* Clear CPU buffers using VERW */
+#define X86_FEATURE_ACC_POWER ( 3*32+19) /* "acc_power" AMD Accumulated Power Mechanism */
+#define X86_FEATURE_NOPL ( 3*32+20) /* "nopl" The NOPL (0F 1F) instructions */
+#define X86_FEATURE_ALWAYS ( 3*32+21) /* Always-present feature */
+#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* "xtopology" CPU topology enum extensions */
+#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* "tsc_reliable" TSC is known to be reliable */
+#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* "nonstop_tsc" TSC does not stop in C states */
+#define X86_FEATURE_CPUID ( 3*32+25) /* "cpuid" CPU has CPUID instruction itself */
+#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* "extd_apicid" Extended APICID (8 bits) */
+#define X86_FEATURE_AMD_DCM ( 3*32+27) /* "amd_dcm" AMD multi-node processor */
+#define X86_FEATURE_APERFMPERF ( 3*32+28) /* "aperfmperf" P-State hardware coordination feedback capability (APERF/MPERF MSRs) */
+#define X86_FEATURE_RAPL ( 3*32+29) /* "rapl" AMD/Hygon RAPL interface */
+#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* "nonstop_tsc_s3" TSC doesn't stop in S3 state */
+#define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* "tsc_known_freq" TSC has known frequency */
/* Intel-defined CPU features, CPUID level 0x00000001 (ECX), word 4 */
#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */
-#define X86_FEATURE_PCLMULQDQ ( 4*32+ 1) /* PCLMULQDQ instruction */
-#define X86_FEATURE_DTES64 ( 4*32+ 2) /* 64-bit Debug Store */
+#define X86_FEATURE_PCLMULQDQ ( 4*32+ 1) /* "pclmulqdq" PCLMULQDQ instruction */
+#define X86_FEATURE_DTES64 ( 4*32+ 2) /* "dtes64" 64-bit Debug Store */
#define X86_FEATURE_MWAIT ( 4*32+ 3) /* "monitor" MONITOR/MWAIT support */
#define X86_FEATURE_DSCPL ( 4*32+ 4) /* "ds_cpl" CPL-qualified (filtered) Debug Store */
-#define X86_FEATURE_VMX ( 4*32+ 5) /* Hardware virtualization */
-#define X86_FEATURE_SMX ( 4*32+ 6) /* Safer Mode eXtensions */
-#define X86_FEATURE_EST ( 4*32+ 7) /* Enhanced SpeedStep */
-#define X86_FEATURE_TM2 ( 4*32+ 8) /* Thermal Monitor 2 */
-#define X86_FEATURE_SSSE3 ( 4*32+ 9) /* Supplemental SSE-3 */
-#define X86_FEATURE_CID ( 4*32+10) /* Context ID */
-#define X86_FEATURE_SDBG ( 4*32+11) /* Silicon Debug */
-#define X86_FEATURE_FMA ( 4*32+12) /* Fused multiply-add */
-#define X86_FEATURE_CX16 ( 4*32+13) /* CMPXCHG16B instruction */
-#define X86_FEATURE_XTPR ( 4*32+14) /* Send Task Priority Messages */
-#define X86_FEATURE_PDCM ( 4*32+15) /* Perf/Debug Capabilities MSR */
-#define X86_FEATURE_PCID ( 4*32+17) /* Process Context Identifiers */
-#define X86_FEATURE_DCA ( 4*32+18) /* Direct Cache Access */
+#define X86_FEATURE_VMX ( 4*32+ 5) /* "vmx" Hardware virtualization */
+#define X86_FEATURE_SMX ( 4*32+ 6) /* "smx" Safer Mode eXtensions */
+#define X86_FEATURE_EST ( 4*32+ 7) /* "est" Enhanced SpeedStep */
+#define X86_FEATURE_TM2 ( 4*32+ 8) /* "tm2" Thermal Monitor 2 */
+#define X86_FEATURE_SSSE3 ( 4*32+ 9) /* "ssse3" Supplemental SSE-3 */
+#define X86_FEATURE_CID ( 4*32+10) /* "cid" Context ID */
+#define X86_FEATURE_SDBG ( 4*32+11) /* "sdbg" Silicon Debug */
+#define X86_FEATURE_FMA ( 4*32+12) /* "fma" Fused multiply-add */
+#define X86_FEATURE_CX16 ( 4*32+13) /* "cx16" CMPXCHG16B instruction */
+#define X86_FEATURE_XTPR ( 4*32+14) /* "xtpr" Send Task Priority Messages */
+#define X86_FEATURE_PDCM ( 4*32+15) /* "pdcm" Perf/Debug Capabilities MSR */
+#define X86_FEATURE_PCID ( 4*32+17) /* "pcid" Process Context Identifiers */
+#define X86_FEATURE_DCA ( 4*32+18) /* "dca" Direct Cache Access */
#define X86_FEATURE_XMM4_1 ( 4*32+19) /* "sse4_1" SSE-4.1 */
#define X86_FEATURE_XMM4_2 ( 4*32+20) /* "sse4_2" SSE-4.2 */
-#define X86_FEATURE_X2APIC ( 4*32+21) /* X2APIC */
-#define X86_FEATURE_MOVBE ( 4*32+22) /* MOVBE instruction */
-#define X86_FEATURE_POPCNT ( 4*32+23) /* POPCNT instruction */
-#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* TSC deadline timer */
-#define X86_FEATURE_AES ( 4*32+25) /* AES instructions */
-#define X86_FEATURE_XSAVE ( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV instructions */
-#define X86_FEATURE_OSXSAVE ( 4*32+27) /* "" XSAVE instruction enabled in the OS */
-#define X86_FEATURE_AVX ( 4*32+28) /* Advanced Vector Extensions */
-#define X86_FEATURE_F16C ( 4*32+29) /* 16-bit FP conversions */
-#define X86_FEATURE_RDRAND ( 4*32+30) /* RDRAND instruction */
-#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */
+#define X86_FEATURE_X2APIC ( 4*32+21) /* "x2apic" X2APIC */
+#define X86_FEATURE_MOVBE ( 4*32+22) /* "movbe" MOVBE instruction */
+#define X86_FEATURE_POPCNT ( 4*32+23) /* "popcnt" POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* "tsc_deadline_timer" TSC deadline timer */
+#define X86_FEATURE_AES ( 4*32+25) /* "aes" AES instructions */
+#define X86_FEATURE_XSAVE ( 4*32+26) /* "xsave" XSAVE/XRSTOR/XSETBV/XGETBV instructions */
+#define X86_FEATURE_OSXSAVE ( 4*32+27) /* XSAVE instruction enabled in the OS */
+#define X86_FEATURE_AVX ( 4*32+28) /* "avx" Advanced Vector Extensions */
+#define X86_FEATURE_F16C ( 4*32+29) /* "f16c" 16-bit FP conversions */
+#define X86_FEATURE_RDRAND ( 4*32+30) /* "rdrand" RDRAND instruction */
+#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* "hypervisor" Running on a hypervisor */
/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
#define X86_FEATURE_XSTORE ( 5*32+ 2) /* "rng" RNG present (xstore) */
#define X86_FEATURE_XSTORE_EN ( 5*32+ 3) /* "rng_en" RNG enabled */
#define X86_FEATURE_XCRYPT ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */
#define X86_FEATURE_XCRYPT_EN ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */
-#define X86_FEATURE_ACE2 ( 5*32+ 8) /* Advanced Cryptography Engine v2 */
-#define X86_FEATURE_ACE2_EN ( 5*32+ 9) /* ACE v2 enabled */
-#define X86_FEATURE_PHE ( 5*32+10) /* PadLock Hash Engine */
-#define X86_FEATURE_PHE_EN ( 5*32+11) /* PHE enabled */
-#define X86_FEATURE_PMM ( 5*32+12) /* PadLock Montgomery Multiplier */
-#define X86_FEATURE_PMM_EN ( 5*32+13) /* PMM enabled */
+#define X86_FEATURE_ACE2 ( 5*32+ 8) /* "ace2" Advanced Cryptography Engine v2 */
+#define X86_FEATURE_ACE2_EN ( 5*32+ 9) /* "ace2_en" ACE v2 enabled */
+#define X86_FEATURE_PHE ( 5*32+10) /* "phe" PadLock Hash Engine */
+#define X86_FEATURE_PHE_EN ( 5*32+11) /* "phe_en" PHE enabled */
+#define X86_FEATURE_PMM ( 5*32+12) /* "pmm" PadLock Montgomery Multiplier */
+#define X86_FEATURE_PMM_EN ( 5*32+13) /* "pmm_en" PMM enabled */
/* More extended AMD flags: CPUID level 0x80000001, ECX, word 6 */
-#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* LAHF/SAHF in long mode */
-#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* If yes HyperThreading not valid */
-#define X86_FEATURE_SVM ( 6*32+ 2) /* Secure Virtual Machine */
-#define X86_FEATURE_EXTAPIC ( 6*32+ 3) /* Extended APIC space */
-#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* CR8 in 32-bit mode */
-#define X86_FEATURE_ABM ( 6*32+ 5) /* Advanced bit manipulation */
-#define X86_FEATURE_SSE4A ( 6*32+ 6) /* SSE-4A */
-#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */
-#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */
-#define X86_FEATURE_OSVW ( 6*32+ 9) /* OS Visible Workaround */
-#define X86_FEATURE_IBS ( 6*32+10) /* Instruction Based Sampling */
-#define X86_FEATURE_XOP ( 6*32+11) /* extended AVX instructions */
-#define X86_FEATURE_SKINIT ( 6*32+12) /* SKINIT/STGI instructions */
-#define X86_FEATURE_WDT ( 6*32+13) /* Watchdog timer */
-#define X86_FEATURE_LWP ( 6*32+15) /* Light Weight Profiling */
-#define X86_FEATURE_FMA4 ( 6*32+16) /* 4 operands MAC instructions */
-#define X86_FEATURE_TCE ( 6*32+17) /* Translation Cache Extension */
-#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* NodeId MSR */
-#define X86_FEATURE_TBM ( 6*32+21) /* Trailing Bit Manipulations */
-#define X86_FEATURE_TOPOEXT ( 6*32+22) /* Topology extensions CPUID leafs */
-#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* Core performance counter extensions */
-#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */
-#define X86_FEATURE_BPEXT ( 6*32+26) /* Data breakpoint extension */
-#define X86_FEATURE_PTSC ( 6*32+27) /* Performance time-stamp counter */
-#define X86_FEATURE_PERFCTR_LLC ( 6*32+28) /* Last Level Cache performance counter extensions */
-#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX instructions) */
+#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* "lahf_lm" LAHF/SAHF in long mode */
+#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* "cmp_legacy" If yes HyperThreading not valid */
+#define X86_FEATURE_SVM ( 6*32+ 2) /* "svm" Secure Virtual Machine */
+#define X86_FEATURE_EXTAPIC ( 6*32+ 3) /* "extapic" Extended APIC space */
+#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* "cr8_legacy" CR8 in 32-bit mode */
+#define X86_FEATURE_ABM ( 6*32+ 5) /* "abm" Advanced bit manipulation */
+#define X86_FEATURE_SSE4A ( 6*32+ 6) /* "sse4a" SSE-4A */
+#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* "misalignsse" Misaligned SSE mode */
+#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* "3dnowprefetch" 3DNow prefetch instructions */
+#define X86_FEATURE_OSVW ( 6*32+ 9) /* "osvw" OS Visible Workaround */
+#define X86_FEATURE_IBS ( 6*32+10) /* "ibs" Instruction Based Sampling */
+#define X86_FEATURE_XOP ( 6*32+11) /* "xop" Extended AVX instructions */
+#define X86_FEATURE_SKINIT ( 6*32+12) /* "skinit" SKINIT/STGI instructions */
+#define X86_FEATURE_WDT ( 6*32+13) /* "wdt" Watchdog timer */
+#define X86_FEATURE_LWP ( 6*32+15) /* "lwp" Light Weight Profiling */
+#define X86_FEATURE_FMA4 ( 6*32+16) /* "fma4" 4 operands MAC instructions */
+#define X86_FEATURE_TCE ( 6*32+17) /* "tce" Translation Cache Extension */
+#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* "nodeid_msr" NodeId MSR */
+#define X86_FEATURE_TBM ( 6*32+21) /* "tbm" Trailing Bit Manipulations */
+#define X86_FEATURE_TOPOEXT ( 6*32+22) /* "topoext" Topology extensions CPUID leafs */
+#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* "perfctr_core" Core performance counter extensions */
+#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* "perfctr_nb" NB performance counter extensions */
+#define X86_FEATURE_BPEXT ( 6*32+26) /* "bpext" Data breakpoint extension */
+#define X86_FEATURE_PTSC ( 6*32+27) /* "ptsc" Performance time-stamp counter */
+#define X86_FEATURE_PERFCTR_LLC ( 6*32+28) /* "perfctr_llc" Last Level Cache performance counter extensions */
+#define X86_FEATURE_MWAITX ( 6*32+29) /* "mwaitx" MWAIT extension (MONITORX/MWAITX instructions) */
/*
* Auxiliary flags: Linux defined - For features scattered in various
@@ -189,93 +189,93 @@
*
* Reuse free bits when adding new feature flags!
*/
-#define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT instructions */
-#define X86_FEATURE_CPUID_FAULT ( 7*32+ 1) /* Intel CPUID faulting */
-#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */
-#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
-#define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */
-#define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* Cache Allocation Technology L2 */
-#define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* Code and Data Prioritization L3 */
-#define X86_FEATURE_TDX_HOST_PLATFORM ( 7*32+ 7) /* Platform supports being a TDX host */
-#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
-#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
-#define X86_FEATURE_XCOMPACTED ( 7*32+10) /* "" Use compacted XSTATE (XSAVES or XSAVEC) */
-#define X86_FEATURE_PTI ( 7*32+11) /* Kernel Page Table Isolation enabled */
-#define X86_FEATURE_KERNEL_IBRS ( 7*32+12) /* "" Set/clear IBRS on kernel entry/exit */
-#define X86_FEATURE_RSB_VMEXIT ( 7*32+13) /* "" Fill RSB on VM-Exit */
-#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */
-#define X86_FEATURE_CDP_L2 ( 7*32+15) /* Code and Data Prioritization L2 */
-#define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16) /* "" MSR SPEC_CTRL is implemented */
-#define X86_FEATURE_SSBD ( 7*32+17) /* Speculative Store Bypass Disable */
-#define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */
-#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* "" Fill RSB on context switches */
-#define X86_FEATURE_PERFMON_V2 ( 7*32+20) /* AMD Performance Monitoring Version 2 */
-#define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */
-#define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* "" Use IBRS during runtime firmware calls */
-#define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* "" Disable Speculative Store Bypass. */
-#define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* "" AMD SSBD implementation via LS_CFG MSR */
-#define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */
-#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */
-#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */
-#define X86_FEATURE_ZEN ( 7*32+28) /* "" Generic flag for all Zen and newer */
-#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */
-#define X86_FEATURE_IBRS_ENHANCED ( 7*32+30) /* Enhanced IBRS */
-#define X86_FEATURE_MSR_IA32_FEAT_CTL ( 7*32+31) /* "" MSR IA32_FEAT_CTL configured */
+#define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* "ring3mwait" Ring 3 MONITOR/MWAIT instructions */
+#define X86_FEATURE_CPUID_FAULT ( 7*32+ 1) /* "cpuid_fault" Intel CPUID faulting */
+#define X86_FEATURE_CPB ( 7*32+ 2) /* "cpb" AMD Core Performance Boost */
+#define X86_FEATURE_EPB ( 7*32+ 3) /* "epb" IA32_ENERGY_PERF_BIAS support */
+#define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* "cat_l3" Cache Allocation Technology L3 */
+#define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* "cat_l2" Cache Allocation Technology L2 */
+#define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* "cdp_l3" Code and Data Prioritization L3 */
+#define X86_FEATURE_TDX_HOST_PLATFORM ( 7*32+ 7) /* "tdx_host_platform" Platform supports being a TDX host */
+#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* "hw_pstate" AMD HW-PState */
+#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* "proc_feedback" AMD ProcFeedbackInterface */
+#define X86_FEATURE_XCOMPACTED ( 7*32+10) /* Use compacted XSTATE (XSAVES or XSAVEC) */
+#define X86_FEATURE_PTI ( 7*32+11) /* "pti" Kernel Page Table Isolation enabled */
+#define X86_FEATURE_KERNEL_IBRS ( 7*32+12) /* Set/clear IBRS on kernel entry/exit */
+#define X86_FEATURE_RSB_VMEXIT ( 7*32+13) /* Fill RSB on VM-Exit */
+#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* "intel_ppin" Intel Processor Inventory Number */
+#define X86_FEATURE_CDP_L2 ( 7*32+15) /* "cdp_l2" Code and Data Prioritization L2 */
+#define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16) /* MSR SPEC_CTRL is implemented */
+#define X86_FEATURE_SSBD ( 7*32+17) /* "ssbd" Speculative Store Bypass Disable */
+#define X86_FEATURE_MBA ( 7*32+18) /* "mba" Memory Bandwidth Allocation */
+#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* Fill RSB on context switches */
+#define X86_FEATURE_PERFMON_V2 ( 7*32+20) /* "perfmon_v2" AMD Performance Monitoring Version 2 */
+#define X86_FEATURE_USE_IBPB ( 7*32+21) /* Indirect Branch Prediction Barrier enabled */
+#define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* Use IBRS during runtime firmware calls */
+#define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* Disable Speculative Store Bypass. */
+#define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* AMD SSBD implementation via LS_CFG MSR */
+#define X86_FEATURE_IBRS ( 7*32+25) /* "ibrs" Indirect Branch Restricted Speculation */
+#define X86_FEATURE_IBPB ( 7*32+26) /* "ibpb" Indirect Branch Prediction Barrier */
+#define X86_FEATURE_STIBP ( 7*32+27) /* "stibp" Single Thread Indirect Branch Predictors */
+#define X86_FEATURE_ZEN ( 7*32+28) /* Generic flag for all Zen and newer */
+#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* L1TF workaround PTE inversion */
+#define X86_FEATURE_IBRS_ENHANCED ( 7*32+30) /* "ibrs_enhanced" Enhanced IBRS */
+#define X86_FEATURE_MSR_IA32_FEAT_CTL ( 7*32+31) /* MSR IA32_FEAT_CTL configured */
/* Virtualization flags: Linux defined, word 8 */
-#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
-#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 1) /* Intel FlexPriority */
-#define X86_FEATURE_EPT ( 8*32+ 2) /* Intel Extended Page Table */
-#define X86_FEATURE_VPID ( 8*32+ 3) /* Intel Virtual Processor ID */
+#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* "tpr_shadow" Intel TPR Shadow */
+#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 1) /* "flexpriority" Intel FlexPriority */
+#define X86_FEATURE_EPT ( 8*32+ 2) /* "ept" Intel Extended Page Table */
+#define X86_FEATURE_VPID ( 8*32+ 3) /* "vpid" Intel Virtual Processor ID */
-#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */
-#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */
-#define X86_FEATURE_EPT_AD ( 8*32+17) /* Intel Extended Page Table access-dirty bit */
-#define X86_FEATURE_VMCALL ( 8*32+18) /* "" Hypervisor supports the VMCALL instruction */
-#define X86_FEATURE_VMW_VMMCALL ( 8*32+19) /* "" VMware prefers VMMCALL hypercall instruction */
-#define X86_FEATURE_PVUNLOCK ( 8*32+20) /* "" PV unlock function */
-#define X86_FEATURE_VCPUPREEMPT ( 8*32+21) /* "" PV vcpu_is_preempted function */
-#define X86_FEATURE_TDX_GUEST ( 8*32+22) /* Intel Trust Domain Extensions Guest */
+#define X86_FEATURE_VMMCALL ( 8*32+15) /* "vmmcall" Prefer VMMCALL to VMCALL */
+#define X86_FEATURE_XENPV ( 8*32+16) /* Xen paravirtual guest */
+#define X86_FEATURE_EPT_AD ( 8*32+17) /* "ept_ad" Intel Extended Page Table access-dirty bit */
+#define X86_FEATURE_VMCALL ( 8*32+18) /* Hypervisor supports the VMCALL instruction */
+#define X86_FEATURE_VMW_VMMCALL ( 8*32+19) /* VMware prefers VMMCALL hypercall instruction */
+#define X86_FEATURE_PVUNLOCK ( 8*32+20) /* PV unlock function */
+#define X86_FEATURE_VCPUPREEMPT ( 8*32+21) /* PV vcpu_is_preempted function */
+#define X86_FEATURE_TDX_GUEST ( 8*32+22) /* "tdx_guest" Intel Trust Domain Extensions Guest */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */
-#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/
-#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3B */
-#define X86_FEATURE_SGX ( 9*32+ 2) /* Software Guard Extensions */
-#define X86_FEATURE_BMI1 ( 9*32+ 3) /* 1st group bit manipulation extensions */
-#define X86_FEATURE_HLE ( 9*32+ 4) /* Hardware Lock Elision */
-#define X86_FEATURE_AVX2 ( 9*32+ 5) /* AVX2 instructions */
-#define X86_FEATURE_FDP_EXCPTN_ONLY ( 9*32+ 6) /* "" FPU data pointer updated only on x87 exceptions */
-#define X86_FEATURE_SMEP ( 9*32+ 7) /* Supervisor Mode Execution Protection */
-#define X86_FEATURE_BMI2 ( 9*32+ 8) /* 2nd group bit manipulation extensions */
-#define X86_FEATURE_ERMS ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB instructions */
-#define X86_FEATURE_INVPCID ( 9*32+10) /* Invalidate Processor Context ID */
-#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */
-#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */
-#define X86_FEATURE_ZERO_FCS_FDS ( 9*32+13) /* "" Zero out FPU CS and FPU DS */
-#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */
-#define X86_FEATURE_RDT_A ( 9*32+15) /* Resource Director Technology Allocation */
-#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */
-#define X86_FEATURE_AVX512DQ ( 9*32+17) /* AVX-512 DQ (Double/Quad granular) Instructions */
-#define X86_FEATURE_RDSEED ( 9*32+18) /* RDSEED instruction */
-#define X86_FEATURE_ADX ( 9*32+19) /* ADCX and ADOX instructions */
-#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */
-#define X86_FEATURE_AVX512IFMA ( 9*32+21) /* AVX-512 Integer Fused Multiply-Add instructions */
-#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
-#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */
-#define X86_FEATURE_INTEL_PT ( 9*32+25) /* Intel Processor Trace */
-#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */
-#define X86_FEATURE_AVX512ER ( 9*32+27) /* AVX-512 Exponential and Reciprocal */
-#define X86_FEATURE_AVX512CD ( 9*32+28) /* AVX-512 Conflict Detection */
-#define X86_FEATURE_SHA_NI ( 9*32+29) /* SHA1/SHA256 Instruction Extensions */
-#define X86_FEATURE_AVX512BW ( 9*32+30) /* AVX-512 BW (Byte/Word granular) Instructions */
-#define X86_FEATURE_AVX512VL ( 9*32+31) /* AVX-512 VL (128/256 Vector Length) Extensions */
+#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* "fsgsbase" RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/
+#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* "tsc_adjust" TSC adjustment MSR 0x3B */
+#define X86_FEATURE_SGX ( 9*32+ 2) /* "sgx" Software Guard Extensions */
+#define X86_FEATURE_BMI1 ( 9*32+ 3) /* "bmi1" 1st group bit manipulation extensions */
+#define X86_FEATURE_HLE ( 9*32+ 4) /* "hle" Hardware Lock Elision */
+#define X86_FEATURE_AVX2 ( 9*32+ 5) /* "avx2" AVX2 instructions */
+#define X86_FEATURE_FDP_EXCPTN_ONLY ( 9*32+ 6) /* FPU data pointer updated only on x87 exceptions */
+#define X86_FEATURE_SMEP ( 9*32+ 7) /* "smep" Supervisor Mode Execution Protection */
+#define X86_FEATURE_BMI2 ( 9*32+ 8) /* "bmi2" 2nd group bit manipulation extensions */
+#define X86_FEATURE_ERMS ( 9*32+ 9) /* "erms" Enhanced REP MOVSB/STOSB instructions */
+#define X86_FEATURE_INVPCID ( 9*32+10) /* "invpcid" Invalidate Processor Context ID */
+#define X86_FEATURE_RTM ( 9*32+11) /* "rtm" Restricted Transactional Memory */
+#define X86_FEATURE_CQM ( 9*32+12) /* "cqm" Cache QoS Monitoring */
+#define X86_FEATURE_ZERO_FCS_FDS ( 9*32+13) /* Zero out FPU CS and FPU DS */
+#define X86_FEATURE_MPX ( 9*32+14) /* "mpx" Memory Protection Extension */
+#define X86_FEATURE_RDT_A ( 9*32+15) /* "rdt_a" Resource Director Technology Allocation */
+#define X86_FEATURE_AVX512F ( 9*32+16) /* "avx512f" AVX-512 Foundation */
+#define X86_FEATURE_AVX512DQ ( 9*32+17) /* "avx512dq" AVX-512 DQ (Double/Quad granular) Instructions */
+#define X86_FEATURE_RDSEED ( 9*32+18) /* "rdseed" RDSEED instruction */
+#define X86_FEATURE_ADX ( 9*32+19) /* "adx" ADCX and ADOX instructions */
+#define X86_FEATURE_SMAP ( 9*32+20) /* "smap" Supervisor Mode Access Prevention */
+#define X86_FEATURE_AVX512IFMA ( 9*32+21) /* "avx512ifma" AVX-512 Integer Fused Multiply-Add instructions */
+#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* "clflushopt" CLFLUSHOPT instruction */
+#define X86_FEATURE_CLWB ( 9*32+24) /* "clwb" CLWB instruction */
+#define X86_FEATURE_INTEL_PT ( 9*32+25) /* "intel_pt" Intel Processor Trace */
+#define X86_FEATURE_AVX512PF ( 9*32+26) /* "avx512pf" AVX-512 Prefetch */
+#define X86_FEATURE_AVX512ER ( 9*32+27) /* "avx512er" AVX-512 Exponential and Reciprocal */
+#define X86_FEATURE_AVX512CD ( 9*32+28) /* "avx512cd" AVX-512 Conflict Detection */
+#define X86_FEATURE_SHA_NI ( 9*32+29) /* "sha_ni" SHA1/SHA256 Instruction Extensions */
+#define X86_FEATURE_AVX512BW ( 9*32+30) /* "avx512bw" AVX-512 BW (Byte/Word granular) Instructions */
+#define X86_FEATURE_AVX512VL ( 9*32+31) /* "avx512vl" AVX-512 VL (128/256 Vector Length) Extensions */
/* Extended state features, CPUID level 0x0000000d:1 (EAX), word 10 */
-#define X86_FEATURE_XSAVEOPT (10*32+ 0) /* XSAVEOPT instruction */
-#define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC instruction */
-#define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 instruction */
-#define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS instructions */
-#define X86_FEATURE_XFD (10*32+ 4) /* "" eXtended Feature Disabling */
+#define X86_FEATURE_XSAVEOPT (10*32+ 0) /* "xsaveopt" XSAVEOPT instruction */
+#define X86_FEATURE_XSAVEC (10*32+ 1) /* "xsavec" XSAVEC instruction */
+#define X86_FEATURE_XGETBV1 (10*32+ 2) /* "xgetbv1" XGETBV with ECX = 1 instruction */
+#define X86_FEATURE_XSAVES (10*32+ 3) /* "xsaves" XSAVES/XRSTORS instructions */
+#define X86_FEATURE_XFD (10*32+ 4) /* eXtended Feature Disabling */
/*
* Extended auxiliary flags: Linux defined - for features scattered in various
@@ -283,181 +283,182 @@
*
* Reuse free bits when adding new feature flags!
*/
-#define X86_FEATURE_CQM_LLC (11*32+ 0) /* LLC QoS if 1 */
-#define X86_FEATURE_CQM_OCCUP_LLC (11*32+ 1) /* LLC occupancy monitoring */
-#define X86_FEATURE_CQM_MBM_TOTAL (11*32+ 2) /* LLC Total MBM monitoring */
-#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* LLC Local MBM monitoring */
-#define X86_FEATURE_FENCE_SWAPGS_USER (11*32+ 4) /* "" LFENCE in user entry SWAPGS path */
-#define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */
-#define X86_FEATURE_SPLIT_LOCK_DETECT (11*32+ 6) /* #AC for split lock */
-#define X86_FEATURE_PER_THREAD_MBA (11*32+ 7) /* "" Per-thread Memory Bandwidth Allocation */
-#define X86_FEATURE_SGX1 (11*32+ 8) /* "" Basic SGX */
-#define X86_FEATURE_SGX2 (11*32+ 9) /* "" SGX Enclave Dynamic Memory Management (EDMM) */
-#define X86_FEATURE_ENTRY_IBPB (11*32+10) /* "" Issue an IBPB on kernel entry */
-#define X86_FEATURE_RRSBA_CTRL (11*32+11) /* "" RET prediction control */
-#define X86_FEATURE_RETPOLINE (11*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */
-#define X86_FEATURE_RETPOLINE_LFENCE (11*32+13) /* "" Use LFENCE for Spectre variant 2 */
-#define X86_FEATURE_RETHUNK (11*32+14) /* "" Use REturn THUNK */
-#define X86_FEATURE_UNRET (11*32+15) /* "" AMD BTB untrain return */
-#define X86_FEATURE_USE_IBPB_FW (11*32+16) /* "" Use IBPB during runtime firmware calls */
-#define X86_FEATURE_RSB_VMEXIT_LITE (11*32+17) /* "" Fill RSB on VM exit when EIBRS is enabled */
-#define X86_FEATURE_SGX_EDECCSSA (11*32+18) /* "" SGX EDECCSSA user leaf function */
-#define X86_FEATURE_CALL_DEPTH (11*32+19) /* "" Call depth tracking for RSB stuffing */
-#define X86_FEATURE_MSR_TSX_CTRL (11*32+20) /* "" MSR IA32_TSX_CTRL (Intel) implemented */
-#define X86_FEATURE_SMBA (11*32+21) /* "" Slow Memory Bandwidth Allocation */
-#define X86_FEATURE_BMEC (11*32+22) /* "" Bandwidth Monitoring Event Configuration */
-#define X86_FEATURE_USER_SHSTK (11*32+23) /* Shadow stack support for user mode applications */
-#define X86_FEATURE_SRSO (11*32+24) /* "" AMD BTB untrain RETs */
-#define X86_FEATURE_SRSO_ALIAS (11*32+25) /* "" AMD BTB untrain RETs through aliasing */
-#define X86_FEATURE_IBPB_ON_VMEXIT (11*32+26) /* "" Issue an IBPB only on VMEXIT */
-#define X86_FEATURE_APIC_MSRS_FENCE (11*32+27) /* "" IA32_TSC_DEADLINE and X2APIC MSRs need fencing */
-#define X86_FEATURE_ZEN2 (11*32+28) /* "" CPU based on Zen2 microarchitecture */
-#define X86_FEATURE_ZEN3 (11*32+29) /* "" CPU based on Zen3 microarchitecture */
-#define X86_FEATURE_ZEN4 (11*32+30) /* "" CPU based on Zen4 microarchitecture */
-#define X86_FEATURE_ZEN1 (11*32+31) /* "" CPU based on Zen1 microarchitecture */
+#define X86_FEATURE_CQM_LLC (11*32+ 0) /* "cqm_llc" LLC QoS if 1 */
+#define X86_FEATURE_CQM_OCCUP_LLC (11*32+ 1) /* "cqm_occup_llc" LLC occupancy monitoring */
+#define X86_FEATURE_CQM_MBM_TOTAL (11*32+ 2) /* "cqm_mbm_total" LLC Total MBM monitoring */
+#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* "cqm_mbm_local" LLC Local MBM monitoring */
+#define X86_FEATURE_FENCE_SWAPGS_USER (11*32+ 4) /* LFENCE in user entry SWAPGS path */
+#define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5) /* LFENCE in kernel entry SWAPGS path */
+#define X86_FEATURE_SPLIT_LOCK_DETECT (11*32+ 6) /* "split_lock_detect" #AC for split lock */
+#define X86_FEATURE_PER_THREAD_MBA (11*32+ 7) /* Per-thread Memory Bandwidth Allocation */
+#define X86_FEATURE_SGX1 (11*32+ 8) /* Basic SGX */
+#define X86_FEATURE_SGX2 (11*32+ 9) /* SGX Enclave Dynamic Memory Management (EDMM) */
+#define X86_FEATURE_ENTRY_IBPB (11*32+10) /* Issue an IBPB on kernel entry */
+#define X86_FEATURE_RRSBA_CTRL (11*32+11) /* RET prediction control */
+#define X86_FEATURE_RETPOLINE (11*32+12) /* Generic Retpoline mitigation for Spectre variant 2 */
+#define X86_FEATURE_RETPOLINE_LFENCE (11*32+13) /* Use LFENCE for Spectre variant 2 */
+#define X86_FEATURE_RETHUNK (11*32+14) /* Use REturn THUNK */
+#define X86_FEATURE_UNRET (11*32+15) /* AMD BTB untrain return */
+#define X86_FEATURE_USE_IBPB_FW (11*32+16) /* Use IBPB during runtime firmware calls */
+#define X86_FEATURE_RSB_VMEXIT_LITE (11*32+17) /* Fill RSB on VM exit when EIBRS is enabled */
+#define X86_FEATURE_SGX_EDECCSSA (11*32+18) /* SGX EDECCSSA user leaf function */
+#define X86_FEATURE_CALL_DEPTH (11*32+19) /* Call depth tracking for RSB stuffing */
+#define X86_FEATURE_MSR_TSX_CTRL (11*32+20) /* MSR IA32_TSX_CTRL (Intel) implemented */
+#define X86_FEATURE_SMBA (11*32+21) /* Slow Memory Bandwidth Allocation */
+#define X86_FEATURE_BMEC (11*32+22) /* Bandwidth Monitoring Event Configuration */
+#define X86_FEATURE_USER_SHSTK (11*32+23) /* "user_shstk" Shadow stack support for user mode applications */
+#define X86_FEATURE_SRSO (11*32+24) /* AMD BTB untrain RETs */
+#define X86_FEATURE_SRSO_ALIAS (11*32+25) /* AMD BTB untrain RETs through aliasing */
+#define X86_FEATURE_IBPB_ON_VMEXIT (11*32+26) /* Issue an IBPB only on VMEXIT */
+#define X86_FEATURE_APIC_MSRS_FENCE (11*32+27) /* IA32_TSC_DEADLINE and X2APIC MSRs need fencing */
+#define X86_FEATURE_ZEN2 (11*32+28) /* CPU based on Zen2 microarchitecture */
+#define X86_FEATURE_ZEN3 (11*32+29) /* CPU based on Zen3 microarchitecture */
+#define X86_FEATURE_ZEN4 (11*32+30) /* CPU based on Zen4 microarchitecture */
+#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_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */
-#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */
-#define X86_FEATURE_CMPCCXADD (12*32+ 7) /* "" CMPccXADD instructions */
-#define X86_FEATURE_ARCH_PERFMON_EXT (12*32+ 8) /* "" Intel Architectural PerfMon Extension */
-#define X86_FEATURE_FZRM (12*32+10) /* "" Fast zero-length REP MOVSB */
-#define X86_FEATURE_FSRS (12*32+11) /* "" Fast short REP STOSB */
-#define X86_FEATURE_FSRC (12*32+12) /* "" Fast short REP {CMPSB,SCASB} */
-#define X86_FEATURE_FRED (12*32+17) /* Flexible Return and Event Delivery */
-#define X86_FEATURE_LKGS (12*32+18) /* "" Load "kernel" (userspace) GS */
-#define X86_FEATURE_WRMSRNS (12*32+19) /* "" Non-serializing WRMSR */
-#define X86_FEATURE_AMX_FP16 (12*32+21) /* "" AMX fp16 Support */
-#define X86_FEATURE_AVX_IFMA (12*32+23) /* "" Support for VPMADD52[H,L]UQ */
-#define X86_FEATURE_LAM (12*32+26) /* Linear Address Masking */
+#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 */
+#define X86_FEATURE_ARCH_PERFMON_EXT (12*32+ 8) /* Intel Architectural PerfMon Extension */
+#define X86_FEATURE_FZRM (12*32+10) /* Fast zero-length REP MOVSB */
+#define X86_FEATURE_FSRS (12*32+11) /* Fast short REP STOSB */
+#define X86_FEATURE_FSRC (12*32+12) /* Fast short REP {CMPSB,SCASB} */
+#define X86_FEATURE_FRED (12*32+17) /* "fred" Flexible Return and Event Delivery */
+#define X86_FEATURE_LKGS (12*32+18) /* Load "kernel" (userspace) GS */
+#define X86_FEATURE_WRMSRNS (12*32+19) /* Non-serializing WRMSR */
+#define X86_FEATURE_AMX_FP16 (12*32+21) /* AMX fp16 Support */
+#define X86_FEATURE_AVX_IFMA (12*32+23) /* Support for VPMADD52[H,L]UQ */
+#define X86_FEATURE_LAM (12*32+26) /* "lam" Linear Address Masking */
/* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */
-#define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */
-#define X86_FEATURE_IRPERF (13*32+ 1) /* Instructions Retired Count */
-#define X86_FEATURE_XSAVEERPTR (13*32+ 2) /* Always save/restore FP error pointers */
-#define X86_FEATURE_RDPRU (13*32+ 4) /* Read processor register at user level */
-#define X86_FEATURE_WBNOINVD (13*32+ 9) /* WBNOINVD instruction */
-#define X86_FEATURE_AMD_IBPB (13*32+12) /* "" Indirect Branch Prediction Barrier */
-#define X86_FEATURE_AMD_IBRS (13*32+14) /* "" Indirect Branch Restricted Speculation */
-#define X86_FEATURE_AMD_STIBP (13*32+15) /* "" Single Thread Indirect Branch Predictors */
-#define X86_FEATURE_AMD_STIBP_ALWAYS_ON (13*32+17) /* "" Single Thread Indirect Branch Predictors always-on preferred */
-#define X86_FEATURE_AMD_PPIN (13*32+23) /* Protected Processor Inventory Number */
-#define X86_FEATURE_AMD_SSBD (13*32+24) /* "" Speculative Store Bypass Disable */
-#define X86_FEATURE_VIRT_SSBD (13*32+25) /* Virtualized Speculative Store Bypass Disable */
-#define X86_FEATURE_AMD_SSB_NO (13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */
-#define X86_FEATURE_CPPC (13*32+27) /* Collaborative Processor Performance Control */
-#define X86_FEATURE_AMD_PSFD (13*32+28) /* "" Predictive Store Forwarding Disable */
-#define X86_FEATURE_BTC_NO (13*32+29) /* "" Not vulnerable to Branch Type Confusion */
-#define X86_FEATURE_BRS (13*32+31) /* Branch Sampling available */
+#define X86_FEATURE_CLZERO (13*32+ 0) /* "clzero" CLZERO instruction */
+#define X86_FEATURE_IRPERF (13*32+ 1) /* "irperf" Instructions Retired Count */
+#define X86_FEATURE_XSAVEERPTR (13*32+ 2) /* "xsaveerptr" Always save/restore FP error pointers */
+#define X86_FEATURE_RDPRU (13*32+ 4) /* "rdpru" Read processor register at user level */
+#define X86_FEATURE_WBNOINVD (13*32+ 9) /* "wbnoinvd" WBNOINVD instruction */
+#define X86_FEATURE_AMD_IBPB (13*32+12) /* Indirect Branch Prediction Barrier */
+#define X86_FEATURE_AMD_IBRS (13*32+14) /* Indirect Branch Restricted Speculation */
+#define X86_FEATURE_AMD_STIBP (13*32+15) /* Single Thread Indirect Branch Predictors */
+#define X86_FEATURE_AMD_STIBP_ALWAYS_ON (13*32+17) /* Single Thread Indirect Branch Predictors always-on preferred */
+#define X86_FEATURE_AMD_PPIN (13*32+23) /* "amd_ppin" Protected Processor Inventory Number */
+#define X86_FEATURE_AMD_SSBD (13*32+24) /* Speculative Store Bypass Disable */
+#define X86_FEATURE_VIRT_SSBD (13*32+25) /* "virt_ssbd" Virtualized Speculative Store Bypass Disable */
+#define X86_FEATURE_AMD_SSB_NO (13*32+26) /* Speculative Store Bypass is fixed in hardware. */
+#define X86_FEATURE_CPPC (13*32+27) /* "cppc" Collaborative Processor Performance Control */
+#define X86_FEATURE_AMD_PSFD (13*32+28) /* Predictive Store Forwarding Disable */
+#define X86_FEATURE_BTC_NO (13*32+29) /* Not vulnerable to Branch Type Confusion */
+#define X86_FEATURE_BRS (13*32+31) /* "brs" Branch Sampling available */
/* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */
-#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */
-#define X86_FEATURE_IDA (14*32+ 1) /* Intel Dynamic Acceleration */
-#define X86_FEATURE_ARAT (14*32+ 2) /* Always Running APIC Timer */
-#define X86_FEATURE_PLN (14*32+ 4) /* Intel Power Limit Notification */
-#define X86_FEATURE_PTS (14*32+ 6) /* Intel Package Thermal Status */
-#define X86_FEATURE_HWP (14*32+ 7) /* Intel Hardware P-states */
-#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* HWP Notification */
-#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */
-#define X86_FEATURE_HWP_EPP (14*32+10) /* HWP Energy Perf. Preference */
-#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */
-#define X86_FEATURE_HFI (14*32+19) /* Hardware Feedback Interface */
+#define X86_FEATURE_DTHERM (14*32+ 0) /* "dtherm" Digital Thermal Sensor */
+#define X86_FEATURE_IDA (14*32+ 1) /* "ida" Intel Dynamic Acceleration */
+#define X86_FEATURE_ARAT (14*32+ 2) /* "arat" Always Running APIC Timer */
+#define X86_FEATURE_PLN (14*32+ 4) /* "pln" Intel Power Limit Notification */
+#define X86_FEATURE_PTS (14*32+ 6) /* "pts" Intel Package Thermal Status */
+#define X86_FEATURE_HWP (14*32+ 7) /* "hwp" Intel Hardware P-states */
+#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* "hwp_notify" HWP Notification */
+#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* "hwp_act_window" HWP Activity Window */
+#define X86_FEATURE_HWP_EPP (14*32+10) /* "hwp_epp" HWP Energy Perf. Preference */
+#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* "hwp_pkg_req" HWP Package Level Request */
+#define X86_FEATURE_HFI (14*32+19) /* "hfi" Hardware Feedback Interface */
/* AMD SVM Feature Identification, CPUID level 0x8000000a (EDX), word 15 */
-#define X86_FEATURE_NPT (15*32+ 0) /* Nested Page Table support */
-#define X86_FEATURE_LBRV (15*32+ 1) /* LBR Virtualization support */
+#define X86_FEATURE_NPT (15*32+ 0) /* "npt" Nested Page Table support */
+#define X86_FEATURE_LBRV (15*32+ 1) /* "lbrv" LBR Virtualization support */
#define X86_FEATURE_SVML (15*32+ 2) /* "svm_lock" SVM locking MSR */
#define X86_FEATURE_NRIPS (15*32+ 3) /* "nrip_save" SVM next_rip save */
#define X86_FEATURE_TSCRATEMSR (15*32+ 4) /* "tsc_scale" TSC scaling support */
#define X86_FEATURE_VMCBCLEAN (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */
-#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */
-#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */
-#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */
-#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */
-#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
-#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */
-#define X86_FEATURE_VGIF (15*32+16) /* Virtual GIF */
-#define X86_FEATURE_X2AVIC (15*32+18) /* Virtual x2apic */
-#define X86_FEATURE_V_SPEC_CTRL (15*32+20) /* Virtual SPEC_CTRL */
-#define X86_FEATURE_VNMI (15*32+25) /* Virtual NMI */
-#define X86_FEATURE_SVME_ADDR_CHK (15*32+28) /* "" SVME addr check */
+#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* "flushbyasid" Flush-by-ASID support */
+#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* "decodeassists" Decode Assists support */
+#define X86_FEATURE_PAUSEFILTER (15*32+10) /* "pausefilter" Filtered pause intercept */
+#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* "pfthreshold" Pause filter threshold */
+#define X86_FEATURE_AVIC (15*32+13) /* "avic" Virtual Interrupt Controller */
+#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* "v_vmsave_vmload" Virtual VMSAVE VMLOAD */
+#define X86_FEATURE_VGIF (15*32+16) /* "vgif" Virtual GIF */
+#define X86_FEATURE_X2AVIC (15*32+18) /* "x2avic" Virtual x2apic */
+#define X86_FEATURE_V_SPEC_CTRL (15*32+20) /* "v_spec_ctrl" Virtual SPEC_CTRL */
+#define X86_FEATURE_VNMI (15*32+25) /* "vnmi" Virtual NMI */
+#define X86_FEATURE_SVME_ADDR_CHK (15*32+28) /* SVME addr check */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ECX), word 16 */
-#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
-#define X86_FEATURE_UMIP (16*32+ 2) /* User Mode Instruction Protection */
-#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */
-#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */
-#define X86_FEATURE_WAITPKG (16*32+ 5) /* UMONITOR/UMWAIT/TPAUSE Instructions */
-#define X86_FEATURE_AVX512_VBMI2 (16*32+ 6) /* Additional AVX512 Vector Bit Manipulation Instructions */
-#define X86_FEATURE_SHSTK (16*32+ 7) /* "" Shadow stack */
-#define X86_FEATURE_GFNI (16*32+ 8) /* Galois Field New Instructions */
-#define X86_FEATURE_VAES (16*32+ 9) /* Vector AES */
-#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */
-#define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */
-#define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */
-#define X86_FEATURE_TME (16*32+13) /* Intel Total Memory Encryption */
-#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */
-#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */
-#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */
-#define X86_FEATURE_BUS_LOCK_DETECT (16*32+24) /* Bus Lock detect */
-#define X86_FEATURE_CLDEMOTE (16*32+25) /* CLDEMOTE instruction */
-#define X86_FEATURE_MOVDIRI (16*32+27) /* MOVDIRI instruction */
-#define X86_FEATURE_MOVDIR64B (16*32+28) /* MOVDIR64B instruction */
-#define X86_FEATURE_ENQCMD (16*32+29) /* ENQCMD and ENQCMDS instructions */
-#define X86_FEATURE_SGX_LC (16*32+30) /* Software Guard Extensions Launch Control */
+#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* "avx512vbmi" AVX512 Vector Bit Manipulation instructions*/
+#define X86_FEATURE_UMIP (16*32+ 2) /* "umip" User Mode Instruction Protection */
+#define X86_FEATURE_PKU (16*32+ 3) /* "pku" Protection Keys for Userspace */
+#define X86_FEATURE_OSPKE (16*32+ 4) /* "ospke" OS Protection Keys Enable */
+#define X86_FEATURE_WAITPKG (16*32+ 5) /* "waitpkg" UMONITOR/UMWAIT/TPAUSE Instructions */
+#define X86_FEATURE_AVX512_VBMI2 (16*32+ 6) /* "avx512_vbmi2" Additional AVX512 Vector Bit Manipulation Instructions */
+#define X86_FEATURE_SHSTK (16*32+ 7) /* Shadow stack */
+#define X86_FEATURE_GFNI (16*32+ 8) /* "gfni" Galois Field New Instructions */
+#define X86_FEATURE_VAES (16*32+ 9) /* "vaes" Vector AES */
+#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* "vpclmulqdq" Carry-Less Multiplication Double Quadword */
+#define X86_FEATURE_AVX512_VNNI (16*32+11) /* "avx512_vnni" Vector Neural Network Instructions */
+#define X86_FEATURE_AVX512_BITALG (16*32+12) /* "avx512_bitalg" Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */
+#define X86_FEATURE_TME (16*32+13) /* "tme" Intel Total Memory Encryption */
+#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* "avx512_vpopcntdq" POPCNT for vectors of DW/QW */
+#define X86_FEATURE_LA57 (16*32+16) /* "la57" 5-level page tables */
+#define X86_FEATURE_RDPID (16*32+22) /* "rdpid" RDPID instruction */
+#define X86_FEATURE_BUS_LOCK_DETECT (16*32+24) /* "bus_lock_detect" Bus Lock detect */
+#define X86_FEATURE_CLDEMOTE (16*32+25) /* "cldemote" CLDEMOTE instruction */
+#define X86_FEATURE_MOVDIRI (16*32+27) /* "movdiri" MOVDIRI instruction */
+#define X86_FEATURE_MOVDIR64B (16*32+28) /* "movdir64b" MOVDIR64B instruction */
+#define X86_FEATURE_ENQCMD (16*32+29) /* "enqcmd" ENQCMD and ENQCMDS instructions */
+#define X86_FEATURE_SGX_LC (16*32+30) /* "sgx_lc" Software Guard Extensions Launch Control */
/* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */
-#define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* MCA overflow recovery support */
-#define X86_FEATURE_SUCCOR (17*32+ 1) /* Uncorrectable error containment and recovery */
-#define X86_FEATURE_SMCA (17*32+ 3) /* Scalable MCA */
+#define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* "overflow_recov" MCA overflow recovery support */
+#define X86_FEATURE_SUCCOR (17*32+ 1) /* "succor" Uncorrectable error containment and recovery */
+#define X86_FEATURE_SMCA (17*32+ 3) /* "smca" Scalable MCA */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
-#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */
-#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
-#define X86_FEATURE_FSRM (18*32+ 4) /* Fast Short Rep Mov */
-#define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */
-#define X86_FEATURE_SRBDS_CTRL (18*32+ 9) /* "" SRBDS mitigation MSR available */
-#define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */
-#define X86_FEATURE_RTM_ALWAYS_ABORT (18*32+11) /* "" RTM transaction always aborts */
-#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */
-#define X86_FEATURE_SERIALIZE (18*32+14) /* SERIALIZE instruction */
-#define X86_FEATURE_HYBRID_CPU (18*32+15) /* "" This part has CPUs of more than one type */
-#define X86_FEATURE_TSXLDTRK (18*32+16) /* TSX Suspend Load Address Tracking */
-#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
-#define X86_FEATURE_ARCH_LBR (18*32+19) /* Intel ARCH LBR */
-#define X86_FEATURE_IBT (18*32+20) /* Indirect Branch Tracking */
-#define X86_FEATURE_AMX_BF16 (18*32+22) /* AMX bf16 Support */
-#define X86_FEATURE_AVX512_FP16 (18*32+23) /* AVX512 FP16 */
-#define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */
-#define X86_FEATURE_AMX_INT8 (18*32+25) /* AMX int8 Support */
-#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */
-#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */
-#define X86_FEATURE_FLUSH_L1D (18*32+28) /* Flush L1D cache */
-#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
-#define X86_FEATURE_CORE_CAPABILITIES (18*32+30) /* "" IA32_CORE_CAPABILITIES MSR */
-#define X86_FEATURE_SPEC_CTRL_SSBD (18*32+31) /* "" Speculative Store Bypass Disable */
+#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* "avx512_4vnniw" AVX-512 Neural Network Instructions */
+#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* "avx512_4fmaps" AVX-512 Multiply Accumulation Single precision */
+#define X86_FEATURE_FSRM (18*32+ 4) /* "fsrm" Fast Short Rep Mov */
+#define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* "avx512_vp2intersect" AVX-512 Intersect for D/Q */
+#define X86_FEATURE_SRBDS_CTRL (18*32+ 9) /* SRBDS mitigation MSR available */
+#define X86_FEATURE_MD_CLEAR (18*32+10) /* "md_clear" VERW clears CPU buffers */
+#define X86_FEATURE_RTM_ALWAYS_ABORT (18*32+11) /* RTM transaction always aborts */
+#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* TSX_FORCE_ABORT */
+#define X86_FEATURE_SERIALIZE (18*32+14) /* "serialize" SERIALIZE instruction */
+#define X86_FEATURE_HYBRID_CPU (18*32+15) /* This part has CPUs of more than one type */
+#define X86_FEATURE_TSXLDTRK (18*32+16) /* "tsxldtrk" TSX Suspend Load Address Tracking */
+#define X86_FEATURE_PCONFIG (18*32+18) /* "pconfig" Intel PCONFIG */
+#define X86_FEATURE_ARCH_LBR (18*32+19) /* "arch_lbr" Intel ARCH LBR */
+#define X86_FEATURE_IBT (18*32+20) /* "ibt" Indirect Branch Tracking */
+#define X86_FEATURE_AMX_BF16 (18*32+22) /* "amx_bf16" AMX bf16 Support */
+#define X86_FEATURE_AVX512_FP16 (18*32+23) /* "avx512_fp16" AVX512 FP16 */
+#define X86_FEATURE_AMX_TILE (18*32+24) /* "amx_tile" AMX tile Support */
+#define X86_FEATURE_AMX_INT8 (18*32+25) /* "amx_int8" AMX int8 Support */
+#define X86_FEATURE_SPEC_CTRL (18*32+26) /* Speculation Control (IBRS + IBPB) */
+#define X86_FEATURE_INTEL_STIBP (18*32+27) /* Single Thread Indirect Branch Predictors */
+#define X86_FEATURE_FLUSH_L1D (18*32+28) /* "flush_l1d" Flush L1D cache */
+#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* "arch_capabilities" IA32_ARCH_CAPABILITIES MSR (Intel) */
+#define X86_FEATURE_CORE_CAPABILITIES (18*32+30) /* IA32_CORE_CAPABILITIES MSR */
+#define X86_FEATURE_SPEC_CTRL_SSBD (18*32+31) /* Speculative Store Bypass Disable */
/* AMD-defined memory encryption features, CPUID level 0x8000001f (EAX), word 19 */
-#define X86_FEATURE_SME (19*32+ 0) /* AMD Secure Memory Encryption */
-#define X86_FEATURE_SEV (19*32+ 1) /* AMD Secure Encrypted Virtualization */
-#define X86_FEATURE_VM_PAGE_FLUSH (19*32+ 2) /* "" VM Page Flush MSR is supported */
-#define X86_FEATURE_SEV_ES (19*32+ 3) /* AMD Secure Encrypted Virtualization - Encrypted State */
-#define X86_FEATURE_SEV_SNP (19*32+ 4) /* AMD Secure Encrypted Virtualization - Secure Nested Paging */
-#define X86_FEATURE_V_TSC_AUX (19*32+ 9) /* "" Virtual TSC_AUX */
-#define X86_FEATURE_SME_COHERENT (19*32+10) /* "" AMD hardware-enforced cache coherency */
-#define X86_FEATURE_DEBUG_SWAP (19*32+14) /* AMD SEV-ES full debug state swap support */
+#define X86_FEATURE_SME (19*32+ 0) /* "sme" AMD Secure Memory Encryption */
+#define X86_FEATURE_SEV (19*32+ 1) /* "sev" AMD Secure Encrypted Virtualization */
+#define X86_FEATURE_VM_PAGE_FLUSH (19*32+ 2) /* VM Page Flush MSR is supported */
+#define X86_FEATURE_SEV_ES (19*32+ 3) /* "sev_es" AMD Secure Encrypted Virtualization - Encrypted State */
+#define X86_FEATURE_SEV_SNP (19*32+ 4) /* "sev_snp" AMD Secure Encrypted Virtualization - Secure Nested Paging */
+#define X86_FEATURE_V_TSC_AUX (19*32+ 9) /* Virtual TSC_AUX */
+#define X86_FEATURE_SME_COHERENT (19*32+10) /* AMD hardware-enforced cache coherency */
+#define X86_FEATURE_DEBUG_SWAP (19*32+14) /* "debug_swap" AMD SEV-ES full debug state swap support */
+#define X86_FEATURE_SVSM (19*32+28) /* "svsm" SVSM present */
/* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */
-#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* "" No Nested Data Breakpoints */
-#define X86_FEATURE_WRMSR_XX_BASE_NS (20*32+ 1) /* "" WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing */
-#define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* "" LFENCE always serializing / synchronizes RDTSC */
-#define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* "" Null Selector Clears Base */
-#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */
-#define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* "" SMM_CTL MSR is not present */
+#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* No Nested Data Breakpoints */
+#define X86_FEATURE_WRMSR_XX_BASE_NS (20*32+ 1) /* WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing */
+#define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* LFENCE always serializing / synchronizes RDTSC */
+#define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* Null Selector Clears Base */
+#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* Automatic IBRS */
+#define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* SMM_CTL MSR is not present */
-#define X86_FEATURE_SBPB (20*32+27) /* "" Selective Branch Prediction Barrier */
-#define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */
-#define X86_FEATURE_SRSO_NO (20*32+29) /* "" CPU is not affected by SRSO */
+#define X86_FEATURE_SBPB (20*32+27) /* Selective Branch Prediction Barrier */
+#define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* MSR_PRED_CMD[IBPB] flushes all branch type predictions */
+#define X86_FEATURE_SRSO_NO (20*32+29) /* CPU is not affected by SRSO */
/*
* Extended auxiliary flags: Linux defined - for features scattered in various
@@ -465,59 +466,59 @@
*
* Reuse free bits when adding new feature flags!
*/
-#define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */
-#define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */
-#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_AMD_LBR_PMC_FREEZE (21*32+ 0) /* "amd_lbr_pmc_freeze" AMD LBR and PMC Freeze */
+#define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* Clear branch history at syscall entry using SW loop */
+#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 */
/*
* BUG word(s)
*/
#define X86_BUG(x) (NCAPINTS*32 + (x))
-#define X86_BUG_F00F X86_BUG(0) /* Intel F00F */
-#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */
-#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */
+#define X86_BUG_F00F X86_BUG(0) /* "f00f" Intel F00F */
+#define X86_BUG_FDIV X86_BUG(1) /* "fdiv" FPU FDIV */
+#define X86_BUG_COMA X86_BUG(2) /* "coma" Cyrix 6x86 coma */
#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */
#define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */
-#define X86_BUG_11AP X86_BUG(5) /* Bad local APIC aka 11AP */
-#define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */
-#define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
-#define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
+#define X86_BUG_11AP X86_BUG(5) /* "11ap" Bad local APIC aka 11AP */
+#define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* "fxsave_leak" FXSAVE leaks FOP/FIP/FOP */
+#define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* "clflush_monitor" AAI65, CLFLUSH required before MONITOR */
+#define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* "sysret_ss_attrs" SYSRET doesn't fix up SS attrs */
#ifdef CONFIG_X86_32
/*
* 64-bit kernels don't use X86_BUG_ESPFIX. Make the define conditional
* to avoid confusion.
*/
-#define X86_BUG_ESPFIX X86_BUG(9) /* "" IRET to 16-bit SS corrupts ESP/RSP high bits */
+#define X86_BUG_ESPFIX X86_BUG(9) /* IRET to 16-bit SS corrupts ESP/RSP high bits */
#endif
-#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */
-#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */
-#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */
-#define X86_BUG_AMD_E400 X86_BUG(13) /* CPU is among the affected by Erratum 400 */
-#define X86_BUG_CPU_MELTDOWN X86_BUG(14) /* CPU is affected by meltdown attack and needs kernel page table isolation */
-#define X86_BUG_SPECTRE_V1 X86_BUG(15) /* CPU is affected by Spectre variant 1 attack with conditional branches */
-#define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */
-#define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* CPU is affected by speculative store bypass attack */
-#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */
-#define X86_BUG_MDS X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
-#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* CPU is only affected by the MSDBS variant of BUG_MDS */
-#define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
-#define X86_BUG_TAA X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
-#define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
-#define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
-#define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
-#define X86_BUG_MMIO_UNKNOWN X86_BUG(26) /* CPU is too old and its MMIO Stale Data status is unknown */
-#define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */
-#define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
-#define X86_BUG_SMT_RSB X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */
-#define X86_BUG_GDS X86_BUG(30) /* CPU is affected by Gather Data Sampling */
-#define X86_BUG_TDX_PW_MCE X86_BUG(31) /* CPU may incur #MC if non-TD software does partial write to TDX private memory */
+#define X86_BUG_NULL_SEG X86_BUG(10) /* "null_seg" Nulling a selector preserves the base */
+#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* "swapgs_fence" SWAPGS without input dep on GS */
+#define X86_BUG_MONITOR X86_BUG(12) /* "monitor" IPI required to wake up remote CPU */
+#define X86_BUG_AMD_E400 X86_BUG(13) /* "amd_e400" CPU is among the affected by Erratum 400 */
+#define X86_BUG_CPU_MELTDOWN X86_BUG(14) /* "cpu_meltdown" CPU is affected by meltdown attack and needs kernel page table isolation */
+#define X86_BUG_SPECTRE_V1 X86_BUG(15) /* "spectre_v1" CPU is affected by Spectre variant 1 attack with conditional branches */
+#define X86_BUG_SPECTRE_V2 X86_BUG(16) /* "spectre_v2" CPU is affected by Spectre variant 2 attack with indirect branches */
+#define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* "spec_store_bypass" CPU is affected by speculative store bypass attack */
+#define X86_BUG_L1TF X86_BUG(18) /* "l1tf" CPU is affected by L1 Terminal Fault */
+#define X86_BUG_MDS X86_BUG(19) /* "mds" CPU is affected by Microarchitectural data sampling */
+#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* "msbds_only" CPU is only affected by the MSDBS variant of BUG_MDS */
+#define X86_BUG_SWAPGS X86_BUG(21) /* "swapgs" CPU is affected by speculation through SWAPGS */
+#define X86_BUG_TAA X86_BUG(22) /* "taa" CPU is affected by TSX Async Abort(TAA) */
+#define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* "itlb_multihit" CPU may incur MCE during certain page attribute changes */
+#define X86_BUG_SRBDS X86_BUG(24) /* "srbds" CPU may leak RNG bits if not mitigated */
+#define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* "mmio_stale_data" CPU is affected by Processor MMIO Stale Data vulnerabilities */
+#define X86_BUG_MMIO_UNKNOWN X86_BUG(26) /* "mmio_unknown" CPU is too old and its MMIO Stale Data status is unknown */
+#define X86_BUG_RETBLEED X86_BUG(27) /* "retbleed" CPU is affected by RETBleed */
+#define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* "eibrs_pbrsb" EIBRS is vulnerable to Post Barrier RSB Predictions */
+#define X86_BUG_SMT_RSB X86_BUG(29) /* "smt_rsb" CPU is vulnerable to Cross-Thread Return Address Predictions */
+#define X86_BUG_GDS X86_BUG(30) /* "gds" CPU is affected by Gather Data Sampling */
+#define X86_BUG_TDX_PW_MCE X86_BUG(31) /* "tdx_pw_mce" CPU may incur #MC if non-TD software does partial write to TDX private memory */
/* BUG word 2 */
-#define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */
-#define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */
-#define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */
-#define X86_BUG_BHI X86_BUG(1*32 + 3) /* CPU is affected by Branch History Injection */
+#define X86_BUG_SRSO X86_BUG(1*32 + 0) /* "srso" AMD SRSO bug */
+#define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* "div0" AMD DIV0 speculation bug */
+#define X86_BUG_RFDS X86_BUG(1*32 + 2) /* "rfds" CPU is vulnerable to Register File Data Sampling */
+#define X86_BUG_BHI X86_BUG(1*32 + 3) /* "bhi" CPU is affected by Branch History Injection */
#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 481096177500..521aad70e41b 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -229,7 +229,8 @@ static inline bool efi_is_native(void)
static inline void *efi64_zero_upper(void *p)
{
- ((u32 *)p)[1] = 0;
+ if (p)
+ ((u32 *)p)[1] = 0;
return p;
}
@@ -315,6 +316,10 @@ static inline u32 efi64_convert_status(efi_status_t status)
#define __efi64_argmap_clear_memory_attributes(protocol, phys, size, flags) \
((protocol), __efi64_split(phys), __efi64_split(size), __efi64_split(flags))
+/* EFI SMBIOS protocol */
+#define __efi64_argmap_get_next(protocol, smbioshandle, type, record, phandle) \
+ ((protocol), (smbioshandle), (type), efi64_zero_upper(record), \
+ efi64_zero_upper(phandle))
/*
* The macros below handle the plumbing for the argument mapping. To add a
* mapping for a specific EFI method, simply define a macro
@@ -384,23 +389,8 @@ static inline void efi_reserve_boot_services(void)
}
#endif /* CONFIG_EFI */
-#ifdef CONFIG_EFI_FAKE_MEMMAP
-extern void __init efi_fake_memmap_early(void);
-extern void __init efi_fake_memmap(void);
-#else
-static inline void efi_fake_memmap_early(void)
-{
-}
-
-static inline void efi_fake_memmap(void)
-{
-}
-#endif
-
extern int __init efi_memmap_alloc(unsigned int num_entries,
struct efi_memory_map_data *data);
-extern void __efi_memmap_free(u64 phys, unsigned long size,
- unsigned long flags);
extern int __init efi_memmap_install(struct efi_memory_map_data *data);
extern int __init efi_memmap_split_count(efi_memory_desc_t *md,
diff --git a/arch/x86/include/asm/init.h b/arch/x86/include/asm/init.h
index cc9ccf61b6bd..14d72727d7ee 100644
--- a/arch/x86/include/asm/init.h
+++ b/arch/x86/include/asm/init.h
@@ -6,6 +6,7 @@
struct x86_mapping_info {
void *(*alloc_pgt_page)(void *); /* allocate buf for page table */
+ void (*free_pgt_page)(void *, void *); /* free buf for page table */
void *context; /* context for alloc_pgt_page */
unsigned long page_flag; /* page flag for PMD or PUD entry */
unsigned long offset; /* ident mapping offset */
@@ -16,4 +17,6 @@ struct x86_mapping_info {
int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
unsigned long pstart, unsigned long pend);
+void kernel_ident_mapping_free(struct x86_mapping_info *info, pgd_t *pgd);
+
#endif /* _ASM_X86_INIT_H */
diff --git a/arch/x86/include/asm/intel_pconfig.h b/arch/x86/include/asm/intel_pconfig.h
deleted file mode 100644
index 994638ef171b..000000000000
--- a/arch/x86/include/asm/intel_pconfig.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _ASM_X86_INTEL_PCONFIG_H
-#define _ASM_X86_INTEL_PCONFIG_H
-
-#include <asm/asm.h>
-#include <asm/processor.h>
-
-enum pconfig_target {
- INVALID_TARGET = 0,
- MKTME_TARGET = 1,
- PCONFIG_TARGET_NR
-};
-
-int pconfig_target_supported(enum pconfig_target target);
-
-enum pconfig_leaf {
- MKTME_KEY_PROGRAM = 0,
- PCONFIG_LEAF_INVALID,
-};
-
-#define PCONFIG ".byte 0x0f, 0x01, 0xc5"
-
-/* Defines and structure for MKTME_KEY_PROGRAM of PCONFIG instruction */
-
-/* mktme_key_program::keyid_ctrl COMMAND, bits [7:0] */
-#define MKTME_KEYID_SET_KEY_DIRECT 0
-#define MKTME_KEYID_SET_KEY_RANDOM 1
-#define MKTME_KEYID_CLEAR_KEY 2
-#define MKTME_KEYID_NO_ENCRYPT 3
-
-/* mktme_key_program::keyid_ctrl ENC_ALG, bits [23:8] */
-#define MKTME_AES_XTS_128 (1 << 8)
-
-/* Return codes from the PCONFIG MKTME_KEY_PROGRAM */
-#define MKTME_PROG_SUCCESS 0
-#define MKTME_INVALID_PROG_CMD 1
-#define MKTME_ENTROPY_ERROR 2
-#define MKTME_INVALID_KEYID 3
-#define MKTME_INVALID_ENC_ALG 4
-#define MKTME_DEVICE_BUSY 5
-
-/* Hardware requires the structure to be 256 byte aligned. Otherwise #GP(0). */
-struct mktme_key_program {
- u16 keyid;
- u32 keyid_ctrl;
- u8 __rsvd[58];
- u8 key_field_1[64];
- u8 key_field_2[64];
-} __packed __aligned(256);
-
-static inline int mktme_key_program(struct mktme_key_program *key_program)
-{
- unsigned long rax = MKTME_KEY_PROGRAM;
-
- if (!pconfig_target_supported(MKTME_TARGET))
- return -ENXIO;
-
- asm volatile(PCONFIG
- : "=a" (rax), "=b" (key_program)
- : "0" (rax), "1" (key_program)
- : "memory", "cc");
-
- return rax;
-}
-
-#endif /* _ASM_X86_INTEL_PCONFIG_H */
diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h
index 8c5ae649d2df..cf7fc2b8e3ce 100644
--- a/arch/x86/include/asm/irqflags.h
+++ b/arch/x86/include/asm/irqflags.h
@@ -54,6 +54,26 @@ static __always_inline void native_halt(void)
asm volatile("hlt": : :"memory");
}
+static __always_inline int native_irqs_disabled_flags(unsigned long flags)
+{
+ return !(flags & X86_EFLAGS_IF);
+}
+
+static __always_inline unsigned long native_local_irq_save(void)
+{
+ unsigned long flags = native_save_fl();
+
+ native_irq_disable();
+
+ return flags;
+}
+
+static __always_inline void native_local_irq_restore(unsigned long flags)
+{
+ if (!native_irqs_disabled_flags(flags))
+ native_irq_enable();
+}
+
#endif
#ifdef CONFIG_PARAVIRT_XXL
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index dfd2e9699bd7..3ad29b128943 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -261,7 +261,8 @@ enum mcp_flags {
MCP_DONTLOG = BIT(2), /* only clear, don't log */
MCP_QUEUE_LOG = BIT(3), /* only queue to genpool */
};
-bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b);
+
+void machine_check_poll(enum mcp_flags flags, mce_banks_t *b);
int mce_notify_irq(void);
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index e022e6eb766c..01342963011e 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -660,6 +660,8 @@
#define MSR_AMD64_RMP_BASE 0xc0010132
#define MSR_AMD64_RMP_END 0xc0010133
+#define MSR_SVSM_CAA 0xc001f000
+
/* AMD Collaborative Processor Performance Control MSRs */
#define MSR_AMD_CPPC_CAP1 0xc00102b0
#define MSR_AMD_CPPC_ENABLE 0xc00102b1
@@ -1164,6 +1166,7 @@
#define MSR_IA32_QM_CTR 0xc8e
#define MSR_IA32_PQR_ASSOC 0xc8f
#define MSR_IA32_L3_CBM_BASE 0xc90
+#define MSR_RMID_SNC_CONFIG 0xca0
#define MSR_IA32_L2_CBM_BASE 0xd10
#define MSR_IA32_MBA_THRTL_BASE 0xd50
diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h
index cc6b8e087192..af4302d79b59 100644
--- a/arch/x86/include/asm/page_64.h
+++ b/arch/x86/include/asm/page_64.h
@@ -54,7 +54,7 @@ static inline void clear_page(void *page)
clear_page_rep, X86_FEATURE_REP_GOOD,
clear_page_erms, X86_FEATURE_ERMS,
"=D" (page),
- "0" (page)
+ "D" (page)
: "cc", "memory", "rax", "rcx");
}
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 65b8e5bb902c..e39311a89bf4 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -140,6 +140,11 @@ static inline int pte_young(pte_t pte)
return pte_flags(pte) & _PAGE_ACCESSED;
}
+static inline bool pte_decrypted(pte_t pte)
+{
+ return cc_mkdec(pte_val(pte)) == pte_val(pte);
+}
+
#define pmd_dirty pmd_dirty
static inline bool pmd_dirty(pmd_t pmd)
{
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index b78644962626..2f321137736c 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -549,6 +549,7 @@ enum pg_level {
PG_LEVEL_2M,
PG_LEVEL_1G,
PG_LEVEL_512G,
+ PG_LEVEL_256T,
PG_LEVEL_NUM
};
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index cb4f6c513c48..a75a07f4931f 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -692,7 +692,17 @@ static inline u32 per_cpu_l2c_id(unsigned int cpu)
#ifdef CONFIG_CPU_SUP_AMD
extern u32 amd_get_highest_perf(void);
-extern void amd_clear_divider(void);
+
+/*
+ * Issue a DIV 0/1 insn to clear any division data from previous DIV
+ * operations.
+ */
+static __always_inline void amd_clear_divider(void)
+{
+ asm volatile(ALTERNATIVE("", "div %2\n\t", X86_BUG_DIV0)
+ :: "a" (0), "d" (0), "r" (1));
+}
+
extern void amd_check_microcode(void);
#else
static inline u32 amd_get_highest_perf(void) { return 0; }
diff --git a/arch/x86/include/asm/runtime-const.h b/arch/x86/include/asm/runtime-const.h
new file mode 100644
index 000000000000..24e3a53ca255
--- /dev/null
+++ b/arch/x86/include/asm/runtime-const.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RUNTIME_CONST_H
+#define _ASM_RUNTIME_CONST_H
+
+#define runtime_const_ptr(sym) ({ \
+ typeof(sym) __ret; \
+ asm_inline("mov %1,%0\n1:\n" \
+ ".pushsection runtime_ptr_" #sym ",\"a\"\n\t" \
+ ".long 1b - %c2 - .\n\t" \
+ ".popsection" \
+ :"=r" (__ret) \
+ :"i" ((unsigned long)0x0123456789abcdefull), \
+ "i" (sizeof(long))); \
+ __ret; })
+
+// The 'typeof' will create at _least_ a 32-bit type, but
+// will happily also take a bigger type and the 'shrl' will
+// clear the upper bits
+#define runtime_const_shift_right_32(val, sym) ({ \
+ typeof(0u+(val)) __ret = (val); \
+ asm_inline("shrl $12,%k0\n1:\n" \
+ ".pushsection runtime_shift_" #sym ",\"a\"\n\t" \
+ ".long 1b - 1 - .\n\t" \
+ ".popsection" \
+ :"+r" (__ret)); \
+ __ret; })
+
+#define runtime_const_init(type, sym) do { \
+ extern s32 __start_runtime_##type##_##sym[]; \
+ extern s32 __stop_runtime_##type##_##sym[]; \
+ runtime_const_fixup(__runtime_fixup_##type, \
+ (unsigned long)(sym), \
+ __start_runtime_##type##_##sym, \
+ __stop_runtime_##type##_##sym); \
+} while (0)
+
+/*
+ * The text patching is trivial - you can only do this at init time,
+ * when the text section hasn't been marked RO, and before the text
+ * has ever been executed.
+ */
+static inline void __runtime_fixup_ptr(void *where, unsigned long val)
+{
+ *(unsigned long *)where = val;
+}
+
+static inline void __runtime_fixup_shift(void *where, unsigned long val)
+{
+ *(unsigned char *)where = val;
+}
+
+static inline void runtime_const_fixup(void (*fn)(void *, unsigned long),
+ unsigned long val, s32 *start, s32 *end)
+{
+ while (start < end) {
+ fn(*start + (void *)start, val);
+ start++;
+ }
+}
+
+#endif
diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h
index 9aee31862b4a..4b2abce2e3e7 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -49,8 +49,11 @@ int set_memory_wb(unsigned long addr, int numpages);
int set_memory_np(unsigned long addr, int numpages);
int set_memory_p(unsigned long addr, int numpages);
int set_memory_4k(unsigned long addr, int numpages);
+
+bool set_memory_enc_stop_conversion(void);
int set_memory_encrypted(unsigned long addr, int numpages);
int set_memory_decrypted(unsigned long addr, int numpages);
+
int set_memory_np_noalias(unsigned long addr, int numpages);
int set_memory_nonglobal(unsigned long addr, int numpages);
int set_memory_global(unsigned long addr, int numpages);
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index e61e68d71cba..0667b2a88614 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -28,6 +28,8 @@
#define NEW_CL_POINTER 0x228 /* Relative to real mode data */
#ifndef __ASSEMBLY__
+#include <linux/cache.h>
+
#include <asm/bootparam.h>
#include <asm/x86_init.h>
@@ -133,6 +135,12 @@ asmlinkage void __init __noreturn x86_64_start_reservations(char *real_mode_data
#endif /* __i386__ */
#endif /* _SETUP */
+#ifdef CONFIG_CMDLINE_BOOL
+extern bool builtin_cmdline_added __ro_after_init;
+#else
+#define builtin_cmdline_added 0
+#endif
+
#else /* __ASSEMBLY */
.macro __RESERVE_BRK name, size
diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
index 5a8246dd532f..e90d403f2068 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -98,6 +98,19 @@ enum psc_op {
/* GHCBData[63:32] */ \
(((u64)(val) & GENMASK_ULL(63, 32)) >> 32)
+/* GHCB Run at VMPL Request/Response */
+#define GHCB_MSR_VMPL_REQ 0x016
+#define GHCB_MSR_VMPL_REQ_LEVEL(v) \
+ /* GHCBData[39:32] */ \
+ (((u64)(v) & GENMASK_ULL(7, 0) << 32) | \
+ /* GHCBDdata[11:0] */ \
+ GHCB_MSR_VMPL_REQ)
+
+#define GHCB_MSR_VMPL_RESP 0x017
+#define GHCB_MSR_VMPL_RESP_VAL(v) \
+ /* GHCBData[63:32] */ \
+ (((u64)(v) & GENMASK_ULL(63, 32)) >> 32)
+
/* GHCB Hypervisor Feature Request/Response */
#define GHCB_MSR_HV_FT_REQ 0x080
#define GHCB_MSR_HV_FT_RESP 0x081
@@ -109,6 +122,7 @@ enum psc_op {
#define GHCB_HV_FT_SNP BIT_ULL(0)
#define GHCB_HV_FT_SNP_AP_CREATION BIT_ULL(1)
+#define GHCB_HV_FT_SNP_MULTI_VMPL BIT_ULL(5)
/*
* SNP Page State Change NAE event
@@ -163,6 +177,10 @@ struct snp_psc_desc {
#define GHCB_TERM_NOT_VMPL0 3 /* SNP guest is not running at VMPL-0 */
#define GHCB_TERM_CPUID 4 /* CPUID-validation failure */
#define GHCB_TERM_CPUID_HV 5 /* CPUID failure during hypervisor fallback */
+#define GHCB_TERM_SECRETS_PAGE 6 /* Secrets page failure */
+#define GHCB_TERM_NO_SVSM 7 /* SVSM is not advertised in the secrets page */
+#define GHCB_TERM_SVSM_VMPL0 8 /* SVSM is present but has set VMPL to 0 */
+#define GHCB_TERM_SVSM_CAA 9 /* SVSM is present but CAA is not page aligned */
#define GHCB_RESP_CODE(v) ((v) & GHCB_MSR_INFO_MASK)
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index ca20cc4e5826..ac5886ce252e 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -152,10 +152,119 @@ struct snp_secrets_page {
u8 vmpck2[VMPCK_KEY_LEN];
u8 vmpck3[VMPCK_KEY_LEN];
struct secrets_os_area os_area;
- u8 rsvd3[3840];
+
+ u8 vmsa_tweak_bitmap[64];
+
+ /* SVSM fields */
+ u64 svsm_base;
+ u64 svsm_size;
+ u64 svsm_caa;
+ u32 svsm_max_version;
+ u8 svsm_guest_vmpl;
+ u8 rsvd3[3];
+
+ /* Remainder of page */
+ u8 rsvd4[3744];
} __packed;
+/*
+ * The SVSM Calling Area (CA) related structures.
+ */
+struct svsm_ca {
+ u8 call_pending;
+ u8 mem_available;
+ u8 rsvd1[6];
+
+ u8 svsm_buffer[PAGE_SIZE - 8];
+};
+
+#define SVSM_SUCCESS 0
+#define SVSM_ERR_INCOMPLETE 0x80000000
+#define SVSM_ERR_UNSUPPORTED_PROTOCOL 0x80000001
+#define SVSM_ERR_UNSUPPORTED_CALL 0x80000002
+#define SVSM_ERR_INVALID_ADDRESS 0x80000003
+#define SVSM_ERR_INVALID_FORMAT 0x80000004
+#define SVSM_ERR_INVALID_PARAMETER 0x80000005
+#define SVSM_ERR_INVALID_REQUEST 0x80000006
+#define SVSM_ERR_BUSY 0x80000007
+#define SVSM_PVALIDATE_FAIL_SIZEMISMATCH 0x80001006
+
+/*
+ * The SVSM PVALIDATE related structures
+ */
+struct svsm_pvalidate_entry {
+ u64 page_size : 2,
+ action : 1,
+ ignore_cf : 1,
+ rsvd : 8,
+ pfn : 52;
+};
+
+struct svsm_pvalidate_call {
+ u16 num_entries;
+ u16 cur_index;
+
+ u8 rsvd1[4];
+
+ struct svsm_pvalidate_entry entry[];
+};
+
+#define SVSM_PVALIDATE_MAX_COUNT ((sizeof_field(struct svsm_ca, svsm_buffer) - \
+ offsetof(struct svsm_pvalidate_call, entry)) / \
+ sizeof(struct svsm_pvalidate_entry))
+
+/*
+ * The SVSM Attestation related structures
+ */
+struct svsm_loc_entry {
+ u64 pa;
+ u32 len;
+ u8 rsvd[4];
+};
+
+struct svsm_attest_call {
+ struct svsm_loc_entry report_buf;
+ struct svsm_loc_entry nonce;
+ struct svsm_loc_entry manifest_buf;
+ struct svsm_loc_entry certificates_buf;
+
+ /* For attesting a single service */
+ u8 service_guid[16];
+ u32 service_manifest_ver;
+ u8 rsvd[4];
+};
+
+/*
+ * SVSM protocol structure
+ */
+struct svsm_call {
+ struct svsm_ca *caa;
+ u64 rax;
+ u64 rcx;
+ u64 rdx;
+ u64 r8;
+ u64 r9;
+ u64 rax_out;
+ u64 rcx_out;
+ u64 rdx_out;
+ u64 r8_out;
+ u64 r9_out;
+};
+
+#define SVSM_CORE_CALL(x) ((0ULL << 32) | (x))
+#define SVSM_CORE_REMAP_CA 0
+#define SVSM_CORE_PVALIDATE 1
+#define SVSM_CORE_CREATE_VCPU 2
+#define SVSM_CORE_DELETE_VCPU 3
+
+#define SVSM_ATTEST_CALL(x) ((1ULL << 32) | (x))
+#define SVSM_ATTEST_SERVICES 0
+#define SVSM_ATTEST_SINGLE_SERVICE 1
+
#ifdef CONFIG_AMD_MEM_ENCRYPT
+
+extern u8 snp_vmpl;
+
extern void __sev_es_ist_enter(struct pt_regs *regs);
extern void __sev_es_ist_exit(void);
static __always_inline void sev_es_ist_enter(struct pt_regs *regs)
@@ -181,6 +290,14 @@ static __always_inline void sev_es_nmi_complete(void)
extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
extern void sev_enable(struct boot_params *bp);
+/*
+ * RMPADJUST modifies the RMP permissions of a page of a lesser-
+ * privileged (numerically higher) VMPL.
+ *
+ * If the guest is running at a higher-privilege than the privilege
+ * level the instruction is targeting, the instruction will succeed,
+ * otherwise, it will fail.
+ */
static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs)
{
int rc;
@@ -225,11 +342,16 @@ 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_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);
-#else
+void snp_update_svsm_ca(void);
+
+#else /* !CONFIG_AMD_MEM_ENCRYPT */
+
+#define snp_vmpl 0
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
static inline void sev_es_ist_exit(void) { }
static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; }
@@ -253,12 +375,17 @@ static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *in
{
return -ENOTTY;
}
-
+static inline int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call, struct svsm_attest_call *input)
+{
+ return -ENOTTY;
+}
static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
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) { }
-#endif
+static inline void snp_update_svsm_ca(void) { }
+
+#endif /* CONFIG_AMD_MEM_ENCRYPT */
#ifdef CONFIG_KVM_AMD_SEV
bool snp_probe_rmptable_info(void);
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index a35936b512fe..ca073f40698f 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -35,6 +35,7 @@ struct smp_ops {
int (*cpu_disable)(void);
void (*cpu_die)(unsigned int cpu);
void (*play_dead)(void);
+ void (*stop_this_cpu)(void);
void (*send_call_func_ipi)(const struct cpumask *mask);
void (*send_call_func_single_ipi)(int cpu);
diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
index 405efb3e4996..94408a784c8e 100644
--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -28,9 +28,6 @@ static inline cycles_t get_cycles(void)
}
#define get_cycles get_cycles
-extern struct system_counterval_t convert_art_to_tsc(u64 art);
-extern struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns);
-
extern void tsc_early_init(void);
extern void tsc_init(void);
extern void mark_tsc_unstable(char *reason);
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h
index 761173ccc33c..6c9e5bdd3916 100644
--- a/arch/x86/include/asm/unistd.h
+++ b/arch/x86/include/asm/unistd.h
@@ -56,6 +56,5 @@
# define __ARCH_WANT_SYS_FORK
# define __ARCH_WANT_SYS_VFORK
# define __ARCH_WANT_SYS_CLONE
-# define __ARCH_WANT_SYS_CLONE3
#endif /* _ASM_X86_UNISTD_H */
diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h
index 0ef36190abe6..b2d2df026f6e 100644
--- a/arch/x86/include/asm/vdso/gettimeofday.h
+++ b/arch/x86/include/asm/vdso/gettimeofday.h
@@ -328,9 +328,8 @@ static __always_inline u64 vdso_calc_ns(const struct vdso_data *vd, u64 cycles,
* due to unsigned comparison.
*
* Due to the MSB/Sign-bit being used as invalid marker (see
- * arch_vdso_cycles_valid() above), the effective mask is S64_MAX,
- * but that case is also unlikely and will also take the unlikely path
- * here.
+ * arch_vdso_cycles_ok() above), the effective mask is S64_MAX, but that
+ * case is also unlikely and will also take the unlikely path here.
*/
if (unlikely(delta > vd->max_cycles)) {
/*
diff --git a/arch/x86/include/asm/vdso/vsyscall.h b/arch/x86/include/asm/vdso/vsyscall.h
index be199a9b2676..93226281b450 100644
--- a/arch/x86/include/asm/vdso/vsyscall.h
+++ b/arch/x86/include/asm/vdso/vsyscall.h
@@ -4,7 +4,6 @@
#ifndef __ASSEMBLY__
-#include <linux/hrtimer.h>
#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h>
#include <asm/vgtod.h>
diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h
index 7aa38b2ad8a9..a0ce291abcae 100644
--- a/arch/x86/include/asm/vgtod.h
+++ b/arch/x86/include/asm/vgtod.h
@@ -14,11 +14,6 @@
#include <uapi/linux/time.h>
-#ifdef BUILD_VDSO32_64
-typedef u64 gtod_long_t;
-#else
-typedef unsigned long gtod_long_t;
-#endif
#endif /* CONFIG_GENERIC_GETTIMEOFDAY */
#endif /* _ASM_X86_VGTOD_H */
diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h
index ac9fc51e2b18..c9cf43d5ef23 100644
--- a/arch/x86/include/asm/vmware.h
+++ b/arch/x86/include/asm/vmware.h
@@ -7,51 +7,321 @@
#include <linux/stringify.h>
/*
- * The hypercall definitions differ in the low word of the %edx argument
- * in the following way: the old port base interface uses the port
- * number to distinguish between high- and low bandwidth versions.
+ * VMware hypercall ABI.
+ *
+ * - Low bandwidth (LB) hypercalls (I/O port based, vmcall and vmmcall)
+ * have up to 6 input and 6 output arguments passed and returned using
+ * registers: %eax (arg0), %ebx (arg1), %ecx (arg2), %edx (arg3),
+ * %esi (arg4), %edi (arg5).
+ * The following input arguments must be initialized by the caller:
+ * arg0 - VMWARE_HYPERVISOR_MAGIC
+ * arg2 - Hypercall command
+ * arg3 bits [15:0] - Port number, LB and direction flags
+ *
+ * - Low bandwidth TDX hypercalls (x86_64 only) are similar to LB
+ * hypercalls. They also have up to 6 input and 6 output on registers
+ * arguments, with different argument to register mapping:
+ * %r12 (arg0), %rbx (arg1), %r13 (arg2), %rdx (arg3),
+ * %rsi (arg4), %rdi (arg5).
+ *
+ * - High bandwidth (HB) hypercalls are I/O port based only. They have
+ * up to 7 input and 7 output arguments passed and returned using
+ * registers: %eax (arg0), %ebx (arg1), %ecx (arg2), %edx (arg3),
+ * %esi (arg4), %edi (arg5), %ebp (arg6).
+ * The following input arguments must be initialized by the caller:
+ * arg0 - VMWARE_HYPERVISOR_MAGIC
+ * arg1 - Hypercall command
+ * arg3 bits [15:0] - Port number, HB and direction flags
+ *
+ * For compatibility purposes, x86_64 systems use only lower 32 bits
+ * for input and output arguments.
+ *
+ * The hypercall definitions differ in the low word of the %edx (arg3)
+ * in the following way: the old I/O port based interface uses the port
+ * number to distinguish between high- and low bandwidth versions, and
+ * uses IN/OUT instructions to define transfer direction.
*
* The new vmcall interface instead uses a set of flags to select
* bandwidth mode and transfer direction. The flags should be loaded
- * into %dx by any user and are automatically replaced by the port
- * number if the VMWARE_HYPERVISOR_PORT method is used.
- *
- * In short, new driver code should strictly use the new definition of
- * %dx content.
+ * into arg3 by any user and are automatically replaced by the port
+ * number if the I/O port method is used.
*/
-/* Old port-based version */
-#define VMWARE_HYPERVISOR_PORT 0x5658
-#define VMWARE_HYPERVISOR_PORT_HB 0x5659
+#define VMWARE_HYPERVISOR_HB BIT(0)
+#define VMWARE_HYPERVISOR_OUT BIT(1)
-/* Current vmcall / vmmcall version */
-#define VMWARE_HYPERVISOR_HB BIT(0)
-#define VMWARE_HYPERVISOR_OUT BIT(1)
+#define VMWARE_HYPERVISOR_PORT 0x5658
+#define VMWARE_HYPERVISOR_PORT_HB (VMWARE_HYPERVISOR_PORT | \
+ VMWARE_HYPERVISOR_HB)
-/* The low bandwidth call. The low word of edx is presumed clear. */
-#define VMWARE_HYPERCALL \
- ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT) ", %%dx; " \
- "inl (%%dx), %%eax", \
- "vmcall", X86_FEATURE_VMCALL, \
- "vmmcall", X86_FEATURE_VMW_VMMCALL)
+#define VMWARE_HYPERVISOR_MAGIC 0x564d5868U
+#define VMWARE_CMD_GETVERSION 10
+#define VMWARE_CMD_GETHZ 45
+#define VMWARE_CMD_GETVCPU_INFO 68
+#define VMWARE_CMD_STEALCLOCK 91
/*
- * The high bandwidth out call. The low word of edx is presumed to have the
- * HB and OUT bits set.
+ * Hypercall command mask:
+ * bits [6:0] command, range [0, 127]
+ * bits [19:16] sub-command, range [0, 15]
*/
-#define VMWARE_HYPERCALL_HB_OUT \
- ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \
- "rep outsb", \
- "vmcall", X86_FEATURE_VMCALL, \
- "vmmcall", X86_FEATURE_VMW_VMMCALL)
+#define VMWARE_CMD_MASK 0xf007fU
+
+#define CPUID_VMWARE_FEATURES_ECX_VMMCALL BIT(0)
+#define CPUID_VMWARE_FEATURES_ECX_VMCALL BIT(1)
+
+extern unsigned long vmware_hypercall_slow(unsigned long cmd,
+ unsigned long in1, unsigned long in3,
+ unsigned long in4, unsigned long in5,
+ u32 *out1, u32 *out2, u32 *out3,
+ u32 *out4, u32 *out5);
+
+#define VMWARE_TDX_VENDOR_LEAF 0x1af7e4909ULL
+#define VMWARE_TDX_HCALL_FUNC 1
+
+extern unsigned long vmware_tdx_hypercall(unsigned long cmd,
+ unsigned long in1, unsigned long in3,
+ unsigned long in4, unsigned long in5,
+ u32 *out1, u32 *out2, u32 *out3,
+ u32 *out4, u32 *out5);
/*
- * The high bandwidth in call. The low word of edx is presumed to have the
- * HB bit set.
+ * The low bandwidth call. The low word of %edx is presumed to have OUT bit
+ * set. The high word of %edx may contain input data from the caller.
*/
-#define VMWARE_HYPERCALL_HB_IN \
- ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \
- "rep insb", \
- "vmcall", X86_FEATURE_VMCALL, \
+#define VMWARE_HYPERCALL \
+ ALTERNATIVE_2("movw %[port], %%dx\n\t" \
+ "inl (%%dx), %%eax", \
+ "vmcall", X86_FEATURE_VMCALL, \
"vmmcall", X86_FEATURE_VMW_VMMCALL)
+
+static inline
+unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
+{
+ unsigned long out0;
+
+ if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+ return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
+
+ if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+ return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
+
+ asm_inline volatile (VMWARE_HYPERCALL
+ : "=a" (out0)
+ : [port] "i" (VMWARE_HYPERVISOR_PORT),
+ "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd),
+ "d" (0)
+ : "cc", "memory");
+ return out0;
+}
+
+static inline
+unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
+ u32 *out1, u32 *out2)
+{
+ unsigned long out0;
+
+ if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+ return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
+ out1, out2, NULL, NULL, NULL);
+
+ if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+ return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
+ out1, out2, NULL, NULL, NULL);
+
+ asm_inline volatile (VMWARE_HYPERCALL
+ : "=a" (out0), "=b" (*out1), "=c" (*out2)
+ : [port] "i" (VMWARE_HYPERVISOR_PORT),
+ "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd),
+ "d" (0)
+ : "cc", "memory");
+ return out0;
+}
+
+static inline
+unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1,
+ u32 *out1, u32 *out2, u32 *out3)
+{
+ unsigned long out0;
+
+ if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+ return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
+ out1, out2, out3, NULL, NULL);
+
+ if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+ return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
+ out1, out2, out3, NULL, NULL);
+
+ asm_inline volatile (VMWARE_HYPERCALL
+ : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3)
+ : [port] "i" (VMWARE_HYPERVISOR_PORT),
+ "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd),
+ "d" (0)
+ : "cc", "memory");
+ return out0;
+}
+
+static inline
+unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, u32 *out2)
+{
+ unsigned long out0;
+
+ if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+ return vmware_tdx_hypercall(cmd, in1, in3, in4, in5,
+ NULL, out2, NULL, NULL, NULL);
+
+ if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+ return vmware_hypercall_slow(cmd, in1, in3, in4, in5,
+ NULL, out2, NULL, NULL, NULL);
+
+ asm_inline volatile (VMWARE_HYPERCALL
+ : "=a" (out0), "=c" (*out2)
+ : [port] "i" (VMWARE_HYPERVISOR_PORT),
+ "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd),
+ "d" (in3),
+ "S" (in4),
+ "D" (in5)
+ : "cc", "memory");
+ return out0;
+}
+
+static inline
+unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1,
+ unsigned long in3, u32 *out2,
+ u32 *out3, u32 *out4, u32 *out5)
+{
+ unsigned long out0;
+
+ if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+ return vmware_tdx_hypercall(cmd, in1, in3, 0, 0,
+ NULL, out2, out3, out4, out5);
+
+ if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+ return vmware_hypercall_slow(cmd, in1, in3, 0, 0,
+ NULL, out2, out3, out4, out5);
+
+ asm_inline volatile (VMWARE_HYPERCALL
+ : "=a" (out0), "=c" (*out2), "=d" (*out3), "=S" (*out4),
+ "=D" (*out5)
+ : [port] "i" (VMWARE_HYPERVISOR_PORT),
+ "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd),
+ "d" (in3)
+ : "cc", "memory");
+ return out0;
+}
+
+static inline
+unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, u32 *out1,
+ u32 *out2, u32 *out3)
+{
+ unsigned long out0;
+
+ if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+ return vmware_tdx_hypercall(cmd, in1, in3, in4, in5,
+ out1, out2, out3, NULL, NULL);
+
+ if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+ return vmware_hypercall_slow(cmd, in1, in3, in4, in5,
+ out1, out2, out3, NULL, NULL);
+
+ asm_inline volatile (VMWARE_HYPERCALL
+ : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3)
+ : [port] "i" (VMWARE_HYPERVISOR_PORT),
+ "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd),
+ "d" (in3),
+ "S" (in4),
+ "D" (in5)
+ : "cc", "memory");
+ return out0;
+}
+
+#ifdef CONFIG_X86_64
+#define VMW_BP_CONSTRAINT "r"
+#else
+#define VMW_BP_CONSTRAINT "m"
+#endif
+
+/*
+ * High bandwidth calls are not supported on encrypted memory guests.
+ * The caller should check cc_platform_has(CC_ATTR_MEM_ENCRYPT) and use
+ * low bandwidth hypercall if memory encryption is set.
+ * This assumption simplifies HB hypercall implementation to just I/O port
+ * based approach without alternative patching.
+ */
+static inline
+unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, unsigned long in6,
+ u32 *out1)
+{
+ unsigned long out0;
+
+ asm_inline volatile (
+ UNWIND_HINT_SAVE
+ "push %%" _ASM_BP "\n\t"
+ UNWIND_HINT_UNDEFINED
+ "mov %[in6], %%" _ASM_BP "\n\t"
+ "rep outsb\n\t"
+ "pop %%" _ASM_BP "\n\t"
+ UNWIND_HINT_RESTORE
+ : "=a" (out0), "=b" (*out1)
+ : "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (cmd),
+ "c" (in2),
+ "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
+ "S" (in4),
+ "D" (in5),
+ [in6] VMW_BP_CONSTRAINT (in6)
+ : "cc", "memory");
+ return out0;
+}
+
+static inline
+unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, unsigned long in6,
+ u32 *out1)
+{
+ unsigned long out0;
+
+ asm_inline volatile (
+ UNWIND_HINT_SAVE
+ "push %%" _ASM_BP "\n\t"
+ UNWIND_HINT_UNDEFINED
+ "mov %[in6], %%" _ASM_BP "\n\t"
+ "rep insb\n\t"
+ "pop %%" _ASM_BP "\n\t"
+ UNWIND_HINT_RESTORE
+ : "=a" (out0), "=b" (*out1)
+ : "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (cmd),
+ "c" (in2),
+ "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
+ "S" (in4),
+ "D" (in5),
+ [in6] VMW_BP_CONSTRAINT (in6)
+ : "cc", "memory");
+ return out0;
+}
+#undef VMW_BP_CONSTRAINT
+#undef VMWARE_HYPERCALL
+
#endif
diff --git a/arch/x86/include/asm/vmxfeatures.h b/arch/x86/include/asm/vmxfeatures.h
index 695f36664889..09b1d7e607c1 100644
--- a/arch/x86/include/asm/vmxfeatures.h
+++ b/arch/x86/include/asm/vmxfeatures.h
@@ -9,85 +9,85 @@
/*
* Note: If the comment begins with a quoted string, that string is used
- * in /proc/cpuinfo instead of the macro name. If the string is "",
- * this feature bit is not displayed in /proc/cpuinfo at all.
+ * in /proc/cpuinfo instead of the macro name. Otherwise, this feature bit
+ * is not displayed in /proc/cpuinfo at all.
*/
/* Pin-Based VM-Execution Controls, EPT/VPID, APIC and VM-Functions, word 0 */
-#define VMX_FEATURE_INTR_EXITING ( 0*32+ 0) /* "" VM-Exit on vectored interrupts */
-#define VMX_FEATURE_NMI_EXITING ( 0*32+ 3) /* "" VM-Exit on NMIs */
+#define VMX_FEATURE_INTR_EXITING ( 0*32+ 0) /* VM-Exit on vectored interrupts */
+#define VMX_FEATURE_NMI_EXITING ( 0*32+ 3) /* VM-Exit on NMIs */
#define VMX_FEATURE_VIRTUAL_NMIS ( 0*32+ 5) /* "vnmi" NMI virtualization */
-#define VMX_FEATURE_PREEMPTION_TIMER ( 0*32+ 6) /* VMX Preemption Timer */
-#define VMX_FEATURE_POSTED_INTR ( 0*32+ 7) /* Posted Interrupts */
+#define VMX_FEATURE_PREEMPTION_TIMER ( 0*32+ 6) /* "preemption_timer" VMX Preemption Timer */
+#define VMX_FEATURE_POSTED_INTR ( 0*32+ 7) /* "posted_intr" Posted Interrupts */
/* EPT/VPID features, scattered to bits 16-23 */
-#define VMX_FEATURE_INVVPID ( 0*32+ 16) /* INVVPID is supported */
+#define VMX_FEATURE_INVVPID ( 0*32+ 16) /* "invvpid" INVVPID is supported */
#define VMX_FEATURE_EPT_EXECUTE_ONLY ( 0*32+ 17) /* "ept_x_only" EPT entries can be execute only */
-#define VMX_FEATURE_EPT_AD ( 0*32+ 18) /* EPT Accessed/Dirty bits */
-#define VMX_FEATURE_EPT_1GB ( 0*32+ 19) /* 1GB EPT pages */
-#define VMX_FEATURE_EPT_5LEVEL ( 0*32+ 20) /* 5-level EPT paging */
+#define VMX_FEATURE_EPT_AD ( 0*32+ 18) /* "ept_ad" EPT Accessed/Dirty bits */
+#define VMX_FEATURE_EPT_1GB ( 0*32+ 19) /* "ept_1gb" 1GB EPT pages */
+#define VMX_FEATURE_EPT_5LEVEL ( 0*32+ 20) /* "ept_5level" 5-level EPT paging */
/* Aggregated APIC features 24-27 */
-#define VMX_FEATURE_FLEXPRIORITY ( 0*32+ 24) /* TPR shadow + virt APIC */
-#define VMX_FEATURE_APICV ( 0*32+ 25) /* TPR shadow + APIC reg virt + virt intr delivery + posted interrupts */
+#define VMX_FEATURE_FLEXPRIORITY ( 0*32+ 24) /* "flexpriority" TPR shadow + virt APIC */
+#define VMX_FEATURE_APICV ( 0*32+ 25) /* "apicv" TPR shadow + APIC reg virt + virt intr delivery + posted interrupts */
/* VM-Functions, shifted to bits 28-31 */
-#define VMX_FEATURE_EPTP_SWITCHING ( 0*32+ 28) /* EPTP switching (in guest) */
+#define VMX_FEATURE_EPTP_SWITCHING ( 0*32+ 28) /* "eptp_switching" EPTP switching (in guest) */
/* Primary Processor-Based VM-Execution Controls, word 1 */
-#define VMX_FEATURE_INTR_WINDOW_EXITING ( 1*32+ 2) /* "" VM-Exit if INTRs are unblocked in guest */
+#define VMX_FEATURE_INTR_WINDOW_EXITING ( 1*32+ 2) /* VM-Exit if INTRs are unblocked in guest */
#define VMX_FEATURE_USE_TSC_OFFSETTING ( 1*32+ 3) /* "tsc_offset" Offset hardware TSC when read in guest */
-#define VMX_FEATURE_HLT_EXITING ( 1*32+ 7) /* "" VM-Exit on HLT */
-#define VMX_FEATURE_INVLPG_EXITING ( 1*32+ 9) /* "" VM-Exit on INVLPG */
-#define VMX_FEATURE_MWAIT_EXITING ( 1*32+ 10) /* "" VM-Exit on MWAIT */
-#define VMX_FEATURE_RDPMC_EXITING ( 1*32+ 11) /* "" VM-Exit on RDPMC */
-#define VMX_FEATURE_RDTSC_EXITING ( 1*32+ 12) /* "" VM-Exit on RDTSC */
-#define VMX_FEATURE_CR3_LOAD_EXITING ( 1*32+ 15) /* "" VM-Exit on writes to CR3 */
-#define VMX_FEATURE_CR3_STORE_EXITING ( 1*32+ 16) /* "" VM-Exit on reads from CR3 */
-#define VMX_FEATURE_TERTIARY_CONTROLS ( 1*32+ 17) /* "" Enable Tertiary VM-Execution Controls */
-#define VMX_FEATURE_CR8_LOAD_EXITING ( 1*32+ 19) /* "" VM-Exit on writes to CR8 */
-#define VMX_FEATURE_CR8_STORE_EXITING ( 1*32+ 20) /* "" VM-Exit on reads from CR8 */
+#define VMX_FEATURE_HLT_EXITING ( 1*32+ 7) /* VM-Exit on HLT */
+#define VMX_FEATURE_INVLPG_EXITING ( 1*32+ 9) /* VM-Exit on INVLPG */
+#define VMX_FEATURE_MWAIT_EXITING ( 1*32+ 10) /* VM-Exit on MWAIT */
+#define VMX_FEATURE_RDPMC_EXITING ( 1*32+ 11) /* VM-Exit on RDPMC */
+#define VMX_FEATURE_RDTSC_EXITING ( 1*32+ 12) /* VM-Exit on RDTSC */
+#define VMX_FEATURE_CR3_LOAD_EXITING ( 1*32+ 15) /* VM-Exit on writes to CR3 */
+#define VMX_FEATURE_CR3_STORE_EXITING ( 1*32+ 16) /* VM-Exit on reads from CR3 */
+#define VMX_FEATURE_TERTIARY_CONTROLS ( 1*32+ 17) /* Enable Tertiary VM-Execution Controls */
+#define VMX_FEATURE_CR8_LOAD_EXITING ( 1*32+ 19) /* VM-Exit on writes to CR8 */
+#define VMX_FEATURE_CR8_STORE_EXITING ( 1*32+ 20) /* VM-Exit on reads from CR8 */
#define VMX_FEATURE_VIRTUAL_TPR ( 1*32+ 21) /* "vtpr" TPR virtualization, a.k.a. TPR shadow */
-#define VMX_FEATURE_NMI_WINDOW_EXITING ( 1*32+ 22) /* "" VM-Exit if NMIs are unblocked in guest */
-#define VMX_FEATURE_MOV_DR_EXITING ( 1*32+ 23) /* "" VM-Exit on accesses to debug registers */
-#define VMX_FEATURE_UNCOND_IO_EXITING ( 1*32+ 24) /* "" VM-Exit on *all* IN{S} and OUT{S}*/
-#define VMX_FEATURE_USE_IO_BITMAPS ( 1*32+ 25) /* "" VM-Exit based on I/O port */
+#define VMX_FEATURE_NMI_WINDOW_EXITING ( 1*32+ 22) /* VM-Exit if NMIs are unblocked in guest */
+#define VMX_FEATURE_MOV_DR_EXITING ( 1*32+ 23) /* VM-Exit on accesses to debug registers */
+#define VMX_FEATURE_UNCOND_IO_EXITING ( 1*32+ 24) /* VM-Exit on *all* IN{S} and OUT{S}*/
+#define VMX_FEATURE_USE_IO_BITMAPS ( 1*32+ 25) /* VM-Exit based on I/O port */
#define VMX_FEATURE_MONITOR_TRAP_FLAG ( 1*32+ 27) /* "mtf" VMX single-step VM-Exits */
-#define VMX_FEATURE_USE_MSR_BITMAPS ( 1*32+ 28) /* "" VM-Exit based on MSR index */
-#define VMX_FEATURE_MONITOR_EXITING ( 1*32+ 29) /* "" VM-Exit on MONITOR (MWAIT's accomplice) */
-#define VMX_FEATURE_PAUSE_EXITING ( 1*32+ 30) /* "" VM-Exit on PAUSE (unconditionally) */
-#define VMX_FEATURE_SEC_CONTROLS ( 1*32+ 31) /* "" Enable Secondary VM-Execution Controls */
+#define VMX_FEATURE_USE_MSR_BITMAPS ( 1*32+ 28) /* VM-Exit based on MSR index */
+#define VMX_FEATURE_MONITOR_EXITING ( 1*32+ 29) /* VM-Exit on MONITOR (MWAIT's accomplice) */
+#define VMX_FEATURE_PAUSE_EXITING ( 1*32+ 30) /* VM-Exit on PAUSE (unconditionally) */
+#define VMX_FEATURE_SEC_CONTROLS ( 1*32+ 31) /* Enable Secondary VM-Execution Controls */
/* Secondary Processor-Based VM-Execution Controls, word 2 */
#define VMX_FEATURE_VIRT_APIC_ACCESSES ( 2*32+ 0) /* "vapic" Virtualize memory mapped APIC accesses */
-#define VMX_FEATURE_EPT ( 2*32+ 1) /* Extended Page Tables, a.k.a. Two-Dimensional Paging */
-#define VMX_FEATURE_DESC_EXITING ( 2*32+ 2) /* "" VM-Exit on {S,L}*DT instructions */
-#define VMX_FEATURE_RDTSCP ( 2*32+ 3) /* "" Enable RDTSCP in guest */
-#define VMX_FEATURE_VIRTUAL_X2APIC ( 2*32+ 4) /* "" Virtualize X2APIC for the guest */
-#define VMX_FEATURE_VPID ( 2*32+ 5) /* Virtual Processor ID (TLB ASID modifier) */
-#define VMX_FEATURE_WBINVD_EXITING ( 2*32+ 6) /* "" VM-Exit on WBINVD */
-#define VMX_FEATURE_UNRESTRICTED_GUEST ( 2*32+ 7) /* Allow Big Real Mode and other "invalid" states */
+#define VMX_FEATURE_EPT ( 2*32+ 1) /* "ept" Extended Page Tables, a.k.a. Two-Dimensional Paging */
+#define VMX_FEATURE_DESC_EXITING ( 2*32+ 2) /* VM-Exit on {S,L}*DT instructions */
+#define VMX_FEATURE_RDTSCP ( 2*32+ 3) /* Enable RDTSCP in guest */
+#define VMX_FEATURE_VIRTUAL_X2APIC ( 2*32+ 4) /* Virtualize X2APIC for the guest */
+#define VMX_FEATURE_VPID ( 2*32+ 5) /* "vpid" Virtual Processor ID (TLB ASID modifier) */
+#define VMX_FEATURE_WBINVD_EXITING ( 2*32+ 6) /* VM-Exit on WBINVD */
+#define VMX_FEATURE_UNRESTRICTED_GUEST ( 2*32+ 7) /* "unrestricted_guest" Allow Big Real Mode and other "invalid" states */
#define VMX_FEATURE_APIC_REGISTER_VIRT ( 2*32+ 8) /* "vapic_reg" Hardware emulation of reads to the virtual-APIC */
#define VMX_FEATURE_VIRT_INTR_DELIVERY ( 2*32+ 9) /* "vid" Evaluation and delivery of pending virtual interrupts */
#define VMX_FEATURE_PAUSE_LOOP_EXITING ( 2*32+ 10) /* "ple" Conditionally VM-Exit on PAUSE at CPL0 */
-#define VMX_FEATURE_RDRAND_EXITING ( 2*32+ 11) /* "" VM-Exit on RDRAND*/
-#define VMX_FEATURE_INVPCID ( 2*32+ 12) /* "" Enable INVPCID in guest */
-#define VMX_FEATURE_VMFUNC ( 2*32+ 13) /* "" Enable VM-Functions (leaf dependent) */
-#define VMX_FEATURE_SHADOW_VMCS ( 2*32+ 14) /* VMREAD/VMWRITE in guest can access shadow VMCS */
-#define VMX_FEATURE_ENCLS_EXITING ( 2*32+ 15) /* "" VM-Exit on ENCLS (leaf dependent) */
-#define VMX_FEATURE_RDSEED_EXITING ( 2*32+ 16) /* "" VM-Exit on RDSEED */
+#define VMX_FEATURE_RDRAND_EXITING ( 2*32+ 11) /* VM-Exit on RDRAND*/
+#define VMX_FEATURE_INVPCID ( 2*32+ 12) /* Enable INVPCID in guest */
+#define VMX_FEATURE_VMFUNC ( 2*32+ 13) /* Enable VM-Functions (leaf dependent) */
+#define VMX_FEATURE_SHADOW_VMCS ( 2*32+ 14) /* "shadow_vmcs" VMREAD/VMWRITE in guest can access shadow VMCS */
+#define VMX_FEATURE_ENCLS_EXITING ( 2*32+ 15) /* VM-Exit on ENCLS (leaf dependent) */
+#define VMX_FEATURE_RDSEED_EXITING ( 2*32+ 16) /* VM-Exit on RDSEED */
#define VMX_FEATURE_PAGE_MOD_LOGGING ( 2*32+ 17) /* "pml" Log dirty pages into buffer */
-#define VMX_FEATURE_EPT_VIOLATION_VE ( 2*32+ 18) /* Conditionally reflect EPT violations as #VE exceptions */
-#define VMX_FEATURE_PT_CONCEAL_VMX ( 2*32+ 19) /* "" Suppress VMX indicators in Processor Trace */
-#define VMX_FEATURE_XSAVES ( 2*32+ 20) /* "" Enable XSAVES and XRSTORS in guest */
+#define VMX_FEATURE_EPT_VIOLATION_VE ( 2*32+ 18) /* "ept_violation_ve" Conditionally reflect EPT violations as #VE exceptions */
+#define VMX_FEATURE_PT_CONCEAL_VMX ( 2*32+ 19) /* Suppress VMX indicators in Processor Trace */
+#define VMX_FEATURE_XSAVES ( 2*32+ 20) /* Enable XSAVES and XRSTORS in guest */
#define VMX_FEATURE_MODE_BASED_EPT_EXEC ( 2*32+ 22) /* "ept_mode_based_exec" Enable separate EPT EXEC bits for supervisor vs. user */
-#define VMX_FEATURE_PT_USE_GPA ( 2*32+ 24) /* "" Processor Trace logs GPAs */
-#define VMX_FEATURE_TSC_SCALING ( 2*32+ 25) /* Scale hardware TSC when read in guest */
-#define VMX_FEATURE_USR_WAIT_PAUSE ( 2*32+ 26) /* Enable TPAUSE, UMONITOR, UMWAIT in guest */
-#define VMX_FEATURE_ENCLV_EXITING ( 2*32+ 28) /* "" VM-Exit on ENCLV (leaf dependent) */
-#define VMX_FEATURE_BUS_LOCK_DETECTION ( 2*32+ 30) /* "" VM-Exit when bus lock caused */
-#define VMX_FEATURE_NOTIFY_VM_EXITING ( 2*32+ 31) /* VM-Exit when no event windows after notify window */
+#define VMX_FEATURE_PT_USE_GPA ( 2*32+ 24) /* Processor Trace logs GPAs */
+#define VMX_FEATURE_TSC_SCALING ( 2*32+ 25) /* "tsc_scaling" Scale hardware TSC when read in guest */
+#define VMX_FEATURE_USR_WAIT_PAUSE ( 2*32+ 26) /* "usr_wait_pause" Enable TPAUSE, UMONITOR, UMWAIT in guest */
+#define VMX_FEATURE_ENCLV_EXITING ( 2*32+ 28) /* VM-Exit on ENCLV (leaf dependent) */
+#define VMX_FEATURE_BUS_LOCK_DETECTION ( 2*32+ 30) /* VM-Exit when bus lock caused */
+#define VMX_FEATURE_NOTIFY_VM_EXITING ( 2*32+ 31) /* "notify_vm_exiting" VM-Exit when no event windows after notify window */
/* Tertiary Processor-Based VM-Execution Controls, word 3 */
-#define VMX_FEATURE_IPI_VIRT ( 3*32+ 4) /* Enable IPI virtualization */
+#define VMX_FEATURE_IPI_VIRT ( 3*32+ 4) /* "ipi_virt" Enable IPI virtualization */
#endif /* _ASM_X86_VMXFEATURES_H */
diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h
index e8d7d4941c4c..422a47746657 100644
--- a/arch/x86/include/asm/word-at-a-time.h
+++ b/arch/x86/include/asm/word-at-a-time.h
@@ -5,45 +5,12 @@
#include <linux/bitops.h>
#include <linux/wordpart.h>
-/*
- * This is largely generic for little-endian machines, but the
- * optimal byte mask counting is probably going to be something
- * that is architecture-specific. If you have a reliably fast
- * bit count instruction, that might be better than the multiply
- * and shift, for example.
- */
struct word_at_a_time {
const unsigned long one_bits, high_bits;
};
#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
-#ifdef CONFIG_64BIT
-
-/*
- * Jan Achrenius on G+: microoptimized version of
- * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56"
- * that works for the bytemasks without having to
- * mask them first.
- */
-static inline long count_masked_bytes(unsigned long mask)
-{
- return mask*0x0001020304050608ul >> 56;
-}
-
-#else /* 32-bit case */
-
-/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
-static inline long count_masked_bytes(long mask)
-{
- /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
- long a = (0x0ff0001+mask) >> 23;
- /* Fix the 1 for 00 case */
- return a & mask;
-}
-
-#endif
-
/* Return nonzero if it has a zero */
static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c)
{
@@ -57,6 +24,22 @@ static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits,
return bits;
}
+#ifdef CONFIG_64BIT
+
+/* Keep the initial has_zero() value for both bitmask and size calc */
+#define create_zero_mask(bits) (bits)
+
+static inline unsigned long zero_bytemask(unsigned long bits)
+{
+ bits = (bits - 1) & ~bits;
+ return bits >> 7;
+}
+
+#define find_zero(bits) (__ffs(bits) >> 3)
+
+#else
+
+/* Create the final mask for both bytemask and size */
static inline unsigned long create_zero_mask(unsigned long bits)
{
bits = (bits - 1) & ~bits;
@@ -66,11 +49,17 @@ static inline unsigned long create_zero_mask(unsigned long bits)
/* The mask we created is directly usable as a bytemask */
#define zero_bytemask(mask) (mask)
+/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
static inline unsigned long find_zero(unsigned long mask)
{
- return count_masked_bytes(mask);
+ /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
+ long a = (0x0ff0001+mask) >> 23;
+ /* Fix the 1 for 00 case */
+ return a & mask;
}
+#endif
+
/*
* Load an unaligned word from kernel space.
*
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 6149eabe200f..213cf5379a5a 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -149,12 +149,22 @@ struct x86_init_acpi {
* @enc_status_change_finish Notify HV after the encryption status of a range is changed
* @enc_tlb_flush_required Returns true if a TLB flush is needed before changing page encryption status
* @enc_cache_flush_required Returns true if a cache flush is needed before changing page encryption status
+ * @enc_kexec_begin Begin the two-step process of converting shared memory back
+ * to private. It stops the new conversions from being started
+ * and waits in-flight conversions to finish, if possible.
+ * @enc_kexec_finish Finish the two-step process of converting shared memory to
+ * private. All memory is private after the call when
+ * the function returns.
+ * It is called on only one CPU while the others are shut down
+ * and with interrupts disabled.
*/
struct x86_guest {
- bool (*enc_status_change_prepare)(unsigned long vaddr, int npages, bool enc);
- bool (*enc_status_change_finish)(unsigned long vaddr, int npages, bool enc);
+ int (*enc_status_change_prepare)(unsigned long vaddr, int npages, bool enc);
+ int (*enc_status_change_finish)(unsigned long vaddr, int npages, bool enc);
bool (*enc_tlb_flush_required)(bool enc);
bool (*enc_cache_flush_required)(void);
+ void (*enc_kexec_begin)(void);
+ void (*enc_kexec_finish)(void);
};
/**
diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h
index 80e1df482337..1814b413fd57 100644
--- a/arch/x86/include/uapi/asm/svm.h
+++ b/arch/x86/include/uapi/asm/svm.h
@@ -115,6 +115,7 @@
#define SVM_VMGEXIT_AP_CREATE_ON_INIT 0
#define SVM_VMGEXIT_AP_CREATE 1
#define SVM_VMGEXIT_AP_DESTROY 2
+#define SVM_VMGEXIT_SNP_RUN_VMPL 0x80000018
#define SVM_VMGEXIT_HV_FEATURES 0x8000fffd
#define SVM_VMGEXIT_TERM_REQUEST 0x8000fffe
#define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code) \
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 20a0dd51700a..a847180836e4 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -17,7 +17,6 @@ CFLAGS_REMOVE_ftrace.o = -pg
CFLAGS_REMOVE_early_printk.o = -pg
CFLAGS_REMOVE_head64.o = -pg
CFLAGS_REMOVE_head32.o = -pg
-CFLAGS_REMOVE_sev.o = -pg
CFLAGS_REMOVE_rethook.o = -pg
endif
@@ -26,19 +25,16 @@ KASAN_SANITIZE_dumpstack.o := n
KASAN_SANITIZE_dumpstack_$(BITS).o := n
KASAN_SANITIZE_stacktrace.o := n
KASAN_SANITIZE_paravirt.o := n
-KASAN_SANITIZE_sev.o := n
# With some compiler versions the generated code results in boot hangs, caused
# by several compilation units. To be safe, disable all instrumentation.
KCSAN_SANITIZE := n
KMSAN_SANITIZE_head$(BITS).o := n
KMSAN_SANITIZE_nmi.o := n
-KMSAN_SANITIZE_sev.o := n
# If instrumentation of the following files is enabled, boot hangs during
# first second.
KCOV_INSTRUMENT_head$(BITS).o := n
-KCOV_INSTRUMENT_sev.o := n
CFLAGS_irq.o := -I $(src)/../include/asm/trace
@@ -142,8 +138,6 @@ obj-$(CONFIG_UNWINDER_ORC) += unwind_orc.o
obj-$(CONFIG_UNWINDER_FRAME_POINTER) += unwind_frame.o
obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o
-obj-$(CONFIG_AMD_MEM_ENCRYPT) += sev.o
-
obj-$(CONFIG_CFI_CLANG) += cfi.o
obj-$(CONFIG_CALL_THUNKS) += callthunks.o
diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile
index fc17b3f136fe..842a5f449404 100644
--- a/arch/x86/kernel/acpi/Makefile
+++ b/arch/x86/kernel/acpi/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_ACPI) += boot.o
obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o
obj-$(CONFIG_ACPI_APEI) += apei.o
obj-$(CONFIG_ACPI_CPPC_LIB) += cppc.o
+obj-$(CONFIG_ACPI_MADT_WAKEUP) += madt_wakeup.o madt_playdead.o
ifneq ($(CONFIG_ACPI_PROCESSOR),)
obj-y += cstate.o
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 4bf82dbd2a6b..9f4618dcd704 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -67,13 +67,6 @@ static bool has_lapic_cpus __initdata;
static bool acpi_support_online_capable;
#endif
-#ifdef CONFIG_X86_64
-/* Physical address of the Multiprocessor Wakeup Structure mailbox */
-static u64 acpi_mp_wake_mailbox_paddr;
-/* Virtual address of the Multiprocessor Wakeup Structure mailbox */
-static struct acpi_madt_multiproc_wakeup_mailbox *acpi_mp_wake_mailbox;
-#endif
-
#ifdef CONFIG_X86_IO_APIC
/*
* Locks related to IOAPIC hotplug
@@ -341,60 +334,6 @@ acpi_parse_lapic_nmi(union acpi_subtable_headers * header, const unsigned long e
return 0;
}
-
-#ifdef CONFIG_X86_64
-static int acpi_wakeup_cpu(u32 apicid, unsigned long start_ip)
-{
- /*
- * Remap mailbox memory only for the first call to acpi_wakeup_cpu().
- *
- * Wakeup of secondary CPUs is fully serialized in the core code.
- * No need to protect acpi_mp_wake_mailbox from concurrent accesses.
- */
- if (!acpi_mp_wake_mailbox) {
- acpi_mp_wake_mailbox = memremap(acpi_mp_wake_mailbox_paddr,
- sizeof(*acpi_mp_wake_mailbox),
- MEMREMAP_WB);
- }
-
- /*
- * Mailbox memory is shared between the firmware and OS. Firmware will
- * listen on mailbox command address, and once it receives the wakeup
- * command, the CPU associated with the given apicid will be booted.
- *
- * The value of 'apic_id' and 'wakeup_vector' must be visible to the
- * firmware before the wakeup command is visible. smp_store_release()
- * ensures ordering and visibility.
- */
- acpi_mp_wake_mailbox->apic_id = apicid;
- acpi_mp_wake_mailbox->wakeup_vector = start_ip;
- smp_store_release(&acpi_mp_wake_mailbox->command,
- ACPI_MP_WAKE_COMMAND_WAKEUP);
-
- /*
- * Wait for the CPU to wake up.
- *
- * The CPU being woken up is essentially in a spin loop waiting to be
- * woken up. It should not take long for it wake up and acknowledge by
- * zeroing out ->command.
- *
- * ACPI specification doesn't provide any guidance on how long kernel
- * has to wait for a wake up acknowledgement. It also doesn't provide
- * a way to cancel a wake up request if it takes too long.
- *
- * In TDX environment, the VMM has control over how long it takes to
- * wake up secondary. It can postpone scheduling secondary vCPU
- * indefinitely. Giving up on wake up request and reporting error opens
- * possible attack vector for VMM: it can wake up a secondary CPU when
- * kernel doesn't expect it. Wait until positive result of the wake up
- * request.
- */
- while (READ_ONCE(acpi_mp_wake_mailbox->command))
- cpu_relax();
-
- return 0;
-}
-#endif /* CONFIG_X86_64 */
#endif /* CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_IO_APIC
@@ -1124,29 +1063,6 @@ static int __init acpi_parse_madt_lapic_entries(void)
}
return 0;
}
-
-#ifdef CONFIG_X86_64
-static int __init acpi_parse_mp_wake(union acpi_subtable_headers *header,
- const unsigned long end)
-{
- struct acpi_madt_multiproc_wakeup *mp_wake;
-
- if (!IS_ENABLED(CONFIG_SMP))
- return -ENODEV;
-
- mp_wake = (struct acpi_madt_multiproc_wakeup *)header;
- if (BAD_MADT_ENTRY(mp_wake, end))
- return -EINVAL;
-
- acpi_table_print_madt_entry(&header->common);
-
- acpi_mp_wake_mailbox_paddr = mp_wake->base_address;
-
- apic_update_callback(wakeup_secondary_cpu_64, acpi_wakeup_cpu);
-
- return 0;
-}
-#endif /* CONFIG_X86_64 */
#endif /* CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_IO_APIC
@@ -1343,7 +1259,7 @@ static void __init acpi_process_madt(void)
smp_found_config = 1;
}
-#ifdef CONFIG_X86_64
+#ifdef CONFIG_ACPI_MADT_WAKEUP
/*
* Parse MADT MP Wake entry.
*/
diff --git a/arch/x86/kernel/acpi/madt_playdead.S b/arch/x86/kernel/acpi/madt_playdead.S
new file mode 100644
index 000000000000..4e498d28cdc8
--- /dev/null
+++ b/arch/x86/kernel/acpi/madt_playdead.S
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/linkage.h>
+#include <asm/nospec-branch.h>
+#include <asm/page_types.h>
+#include <asm/processor-flags.h>
+
+ .text
+ .align PAGE_SIZE
+
+/*
+ * asm_acpi_mp_play_dead() - Hand over control of the CPU to the BIOS
+ *
+ * rdi: Address of the ACPI MADT MPWK ResetVector
+ * rsi: PGD of the identity mapping
+ */
+SYM_FUNC_START(asm_acpi_mp_play_dead)
+ /* Turn off global entries. Following CR3 write will flush them. */
+ movq %cr4, %rdx
+ andq $~(X86_CR4_PGE), %rdx
+ movq %rdx, %cr4
+
+ /* Switch to identity mapping */
+ movq %rsi, %cr3
+
+ /* Jump to reset vector */
+ ANNOTATE_RETPOLINE_SAFE
+ jmp *%rdi
+SYM_FUNC_END(asm_acpi_mp_play_dead)
diff --git a/arch/x86/kernel/acpi/madt_wakeup.c b/arch/x86/kernel/acpi/madt_wakeup.c
new file mode 100644
index 000000000000..6cfe762be28b
--- /dev/null
+++ b/arch/x86/kernel/acpi/madt_wakeup.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <linux/acpi.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kexec.h>
+#include <linux/memblock.h>
+#include <linux/pgtable.h>
+#include <linux/sched/hotplug.h>
+#include <asm/apic.h>
+#include <asm/barrier.h>
+#include <asm/init.h>
+#include <asm/intel_pt.h>
+#include <asm/nmi.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+
+/* Physical address of the Multiprocessor Wakeup Structure mailbox */
+static u64 acpi_mp_wake_mailbox_paddr __ro_after_init;
+
+/* Virtual address of the Multiprocessor Wakeup Structure mailbox */
+static struct acpi_madt_multiproc_wakeup_mailbox *acpi_mp_wake_mailbox __ro_after_init;
+
+static u64 acpi_mp_pgd __ro_after_init;
+static u64 acpi_mp_reset_vector_paddr __ro_after_init;
+
+static void acpi_mp_stop_this_cpu(void)
+{
+ asm_acpi_mp_play_dead(acpi_mp_reset_vector_paddr, acpi_mp_pgd);
+}
+
+static void acpi_mp_play_dead(void)
+{
+ play_dead_common();
+ asm_acpi_mp_play_dead(acpi_mp_reset_vector_paddr, acpi_mp_pgd);
+}
+
+static void acpi_mp_cpu_die(unsigned int cpu)
+{
+ u32 apicid = per_cpu(x86_cpu_to_apicid, cpu);
+ unsigned long timeout;
+
+ /*
+ * Use TEST mailbox command to prove that BIOS got control over
+ * the CPU before declaring it dead.
+ *
+ * BIOS has to clear 'command' field of the mailbox.
+ */
+ acpi_mp_wake_mailbox->apic_id = apicid;
+ smp_store_release(&acpi_mp_wake_mailbox->command,
+ ACPI_MP_WAKE_COMMAND_TEST);
+
+ /* Don't wait longer than a second. */
+ timeout = USEC_PER_SEC;
+ while (READ_ONCE(acpi_mp_wake_mailbox->command) && --timeout)
+ udelay(1);
+
+ if (!timeout)
+ pr_err("Failed to hand over CPU %d to BIOS\n", cpu);
+}
+
+/* The argument is required to match type of x86_mapping_info::alloc_pgt_page */
+static void __init *alloc_pgt_page(void *dummy)
+{
+ return memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+}
+
+static void __init free_pgt_page(void *pgt, void *dummy)
+{
+ return memblock_free(pgt, PAGE_SIZE);
+}
+
+/*
+ * Make sure asm_acpi_mp_play_dead() is present in the identity mapping at
+ * the same place as in the kernel page tables. asm_acpi_mp_play_dead() switches
+ * to the identity mapping and the function has be present at the same spot in
+ * the virtual address space before and after switching page tables.
+ */
+static int __init init_transition_pgtable(pgd_t *pgd)
+{
+ pgprot_t prot = PAGE_KERNEL_EXEC_NOENC;
+ unsigned long vaddr, paddr;
+ p4d_t *p4d;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ vaddr = (unsigned long)asm_acpi_mp_play_dead;
+ pgd += pgd_index(vaddr);
+ if (!pgd_present(*pgd)) {
+ p4d = (p4d_t *)alloc_pgt_page(NULL);
+ if (!p4d)
+ return -ENOMEM;
+ set_pgd(pgd, __pgd(__pa(p4d) | _KERNPG_TABLE));
+ }
+ p4d = p4d_offset(pgd, vaddr);
+ if (!p4d_present(*p4d)) {
+ pud = (pud_t *)alloc_pgt_page(NULL);
+ if (!pud)
+ return -ENOMEM;
+ set_p4d(p4d, __p4d(__pa(pud) | _KERNPG_TABLE));
+ }
+ pud = pud_offset(p4d, vaddr);
+ if (!pud_present(*pud)) {
+ pmd = (pmd_t *)alloc_pgt_page(NULL);
+ if (!pmd)
+ return -ENOMEM;
+ set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
+ }
+ pmd = pmd_offset(pud, vaddr);
+ if (!pmd_present(*pmd)) {
+ pte = (pte_t *)alloc_pgt_page(NULL);
+ if (!pte)
+ return -ENOMEM;
+ set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE));
+ }
+ pte = pte_offset_kernel(pmd, vaddr);
+
+ paddr = __pa(vaddr);
+ set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, prot));
+
+ return 0;
+}
+
+static int __init acpi_mp_setup_reset(u64 reset_vector)
+{
+ struct x86_mapping_info info = {
+ .alloc_pgt_page = alloc_pgt_page,
+ .free_pgt_page = free_pgt_page,
+ .page_flag = __PAGE_KERNEL_LARGE_EXEC,
+ .kernpg_flag = _KERNPG_TABLE_NOENC,
+ };
+ pgd_t *pgd;
+
+ pgd = alloc_pgt_page(NULL);
+ if (!pgd)
+ return -ENOMEM;
+
+ for (int i = 0; i < nr_pfn_mapped; i++) {
+ unsigned long mstart, mend;
+
+ mstart = pfn_mapped[i].start << PAGE_SHIFT;
+ mend = pfn_mapped[i].end << PAGE_SHIFT;
+ if (kernel_ident_mapping_init(&info, pgd, mstart, mend)) {
+ kernel_ident_mapping_free(&info, pgd);
+ return -ENOMEM;
+ }
+ }
+
+ if (kernel_ident_mapping_init(&info, pgd,
+ PAGE_ALIGN_DOWN(reset_vector),
+ PAGE_ALIGN(reset_vector + 1))) {
+ kernel_ident_mapping_free(&info, pgd);
+ return -ENOMEM;
+ }
+
+ if (init_transition_pgtable(pgd)) {
+ kernel_ident_mapping_free(&info, pgd);
+ return -ENOMEM;
+ }
+
+ smp_ops.play_dead = acpi_mp_play_dead;
+ smp_ops.stop_this_cpu = acpi_mp_stop_this_cpu;
+ smp_ops.cpu_die = acpi_mp_cpu_die;
+
+ acpi_mp_reset_vector_paddr = reset_vector;
+ acpi_mp_pgd = __pa(pgd);
+
+ return 0;
+}
+
+static int acpi_wakeup_cpu(u32 apicid, unsigned long start_ip)
+{
+ if (!acpi_mp_wake_mailbox_paddr) {
+ pr_warn_once("No MADT mailbox: cannot bringup secondary CPUs. Booting with kexec?\n");
+ return -EOPNOTSUPP;
+ }
+
+ /*
+ * Remap mailbox memory only for the first call to acpi_wakeup_cpu().
+ *
+ * Wakeup of secondary CPUs is fully serialized in the core code.
+ * No need to protect acpi_mp_wake_mailbox from concurrent accesses.
+ */
+ if (!acpi_mp_wake_mailbox) {
+ acpi_mp_wake_mailbox = memremap(acpi_mp_wake_mailbox_paddr,
+ sizeof(*acpi_mp_wake_mailbox),
+ MEMREMAP_WB);
+ }
+
+ /*
+ * Mailbox memory is shared between the firmware and OS. Firmware will
+ * listen on mailbox command address, and once it receives the wakeup
+ * command, the CPU associated with the given apicid will be booted.
+ *
+ * The value of 'apic_id' and 'wakeup_vector' must be visible to the
+ * firmware before the wakeup command is visible. smp_store_release()
+ * ensures ordering and visibility.
+ */
+ acpi_mp_wake_mailbox->apic_id = apicid;
+ acpi_mp_wake_mailbox->wakeup_vector = start_ip;
+ smp_store_release(&acpi_mp_wake_mailbox->command,
+ ACPI_MP_WAKE_COMMAND_WAKEUP);
+
+ /*
+ * Wait for the CPU to wake up.
+ *
+ * The CPU being woken up is essentially in a spin loop waiting to be
+ * woken up. It should not take long for it wake up and acknowledge by
+ * zeroing out ->command.
+ *
+ * ACPI specification doesn't provide any guidance on how long kernel
+ * has to wait for a wake up acknowledgment. It also doesn't provide
+ * a way to cancel a wake up request if it takes too long.
+ *
+ * In TDX environment, the VMM has control over how long it takes to
+ * wake up secondary. It can postpone scheduling secondary vCPU
+ * indefinitely. Giving up on wake up request and reporting error opens
+ * possible attack vector for VMM: it can wake up a secondary CPU when
+ * kernel doesn't expect it. Wait until positive result of the wake up
+ * request.
+ */
+ while (READ_ONCE(acpi_mp_wake_mailbox->command))
+ cpu_relax();
+
+ return 0;
+}
+
+static void acpi_mp_disable_offlining(struct acpi_madt_multiproc_wakeup *mp_wake)
+{
+ cpu_hotplug_disable_offlining();
+
+ /*
+ * ACPI MADT doesn't allow to offline a CPU after it was onlined. This
+ * limits kexec: the second kernel won't be able to use more than one CPU.
+ *
+ * To prevent a kexec kernel from onlining secondary CPUs invalidate the
+ * mailbox address in the ACPI MADT wakeup structure which prevents a
+ * kexec kernel to use it.
+ *
+ * This is safe as the booting kernel has the mailbox address cached
+ * already and acpi_wakeup_cpu() uses the cached value to bring up the
+ * secondary CPUs.
+ *
+ * Note: This is a Linux specific convention and not covered by the
+ * ACPI specification.
+ */
+ mp_wake->mailbox_address = 0;
+}
+
+int __init acpi_parse_mp_wake(union acpi_subtable_headers *header,
+ const unsigned long end)
+{
+ struct acpi_madt_multiproc_wakeup *mp_wake;
+
+ mp_wake = (struct acpi_madt_multiproc_wakeup *)header;
+
+ /*
+ * Cannot use the standard BAD_MADT_ENTRY() to sanity check the @mp_wake
+ * entry. 'sizeof (struct acpi_madt_multiproc_wakeup)' can be larger
+ * than the actual size of the MP wakeup entry in ACPI table because the
+ * 'reset_vector' is only available in the V1 MP wakeup structure.
+ */
+ if (!mp_wake)
+ return -EINVAL;
+ if (end - (unsigned long)mp_wake < ACPI_MADT_MP_WAKEUP_SIZE_V0)
+ return -EINVAL;
+ if (mp_wake->header.length < ACPI_MADT_MP_WAKEUP_SIZE_V0)
+ return -EINVAL;
+
+ acpi_table_print_madt_entry(&header->common);
+
+ acpi_mp_wake_mailbox_paddr = mp_wake->mailbox_address;
+
+ if (mp_wake->version >= ACPI_MADT_MP_WAKEUP_VERSION_V1 &&
+ mp_wake->header.length >= ACPI_MADT_MP_WAKEUP_SIZE_V1) {
+ if (acpi_mp_setup_reset(mp_wake->reset_vector)) {
+ pr_warn("Failed to setup MADT reset vector\n");
+ acpi_mp_disable_offlining(mp_wake);
+ }
+ } else {
+ /*
+ * CPU offlining requires version 1 of the ACPI MADT wakeup
+ * structure.
+ */
+ acpi_mp_disable_offlining(mp_wake);
+ }
+
+ apic_update_callback(wakeup_secondary_cpu_64, acpi_wakeup_cpu);
+
+ return 0;
+}
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 89de61243272..333b16181357 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -432,6 +432,11 @@ static int alt_replace_call(u8 *instr, u8 *insn_buff, struct alt_instr *a)
return 5;
}
+static inline u8 * instr_va(struct alt_instr *i)
+{
+ return (u8 *)&i->instr_offset + i->instr_offset;
+}
+
/*
* Replace instructions with better alternatives for this CPU type. This runs
* before SMP is initialized to avoid SMP problems with self modifying code.
@@ -447,7 +452,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
{
u8 insn_buff[MAX_PATCH_LEN];
u8 *instr, *replacement;
- struct alt_instr *a;
+ struct alt_instr *a, *b;
DPRINTK(ALT, "alt table %px, -> %px", start, end);
@@ -473,7 +478,18 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
for (a = start; a < end; a++) {
int insn_buff_sz = 0;
- instr = (u8 *)&a->instr_offset + a->instr_offset;
+ /*
+ * In case of nested ALTERNATIVE()s the outer alternative might
+ * add more padding. To ensure consistent patching find the max
+ * padding for all alt_instr entries for this site (nested
+ * alternatives result in consecutive entries).
+ */
+ for (b = a+1; b < end && instr_va(b) == instr_va(a); b++) {
+ u8 len = max(a->instrlen, b->instrlen);
+ a->instrlen = b->instrlen = len;
+ }
+
+ instr = instr_va(a);
replacement = (u8 *)&a->repl_offset + a->repl_offset;
BUG_ON(a->instrlen > sizeof(insn_buff));
BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32);
@@ -1641,7 +1657,7 @@ static noinline void __init alt_reloc_selftest(void)
*/
asm_inline volatile (
ALTERNATIVE("", "lea %[mem], %%" _ASM_ARG1 "; call __alt_reloc_selftest;", X86_FEATURE_ALWAYS)
- : /* output */
+ : ASM_CALL_CONSTRAINT
: [mem] "m" (__alt_reloc_selftest_addr)
: _ASM_ARG1
);
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 027a8c7a2c9e..059e5c16af05 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -180,6 +180,43 @@ static struct pci_dev *next_northbridge(struct pci_dev *dev,
return dev;
}
+/*
+ * SMN accesses may fail in ways that are difficult to detect here in the called
+ * functions amd_smn_read() and amd_smn_write(). Therefore, callers must do
+ * their own checking based on what behavior they expect.
+ *
+ * For SMN reads, the returned value may be zero if the register is Read-as-Zero.
+ * Or it may be a "PCI Error Response", e.g. all 0xFFs. The "PCI Error Response"
+ * can be checked here, and a proper error code can be returned.
+ *
+ * But the Read-as-Zero response cannot be verified here. A value of 0 may be
+ * correct in some cases, so callers must check that this correct is for the
+ * register/fields they need.
+ *
+ * For SMN writes, success can be determined through a "write and read back"
+ * However, this is not robust when done here.
+ *
+ * Possible issues:
+ *
+ * 1) Bits that are "Write-1-to-Clear". In this case, the read value should
+ * *not* match the write value.
+ *
+ * 2) Bits that are "Read-as-Zero"/"Writes-Ignored". This information cannot be
+ * known here.
+ *
+ * 3) Bits that are "Reserved / Set to 1". Ditto above.
+ *
+ * Callers of amd_smn_write() should do the "write and read back" check
+ * themselves, if needed.
+ *
+ * For #1, they can see if their target bits got cleared.
+ *
+ * For #2 and #3, they can check if their target bits got set as intended.
+ *
+ * This matches what is done for RDMSR/WRMSR. As long as there's no #GP, then
+ * the operation is considered a success, and the caller does their own
+ * checking.
+ */
static int __amd_smn_rw(u16 node, u32 address, u32 *value, bool write)
{
struct pci_dev *root;
@@ -202,9 +239,6 @@ static int __amd_smn_rw(u16 node, u32 address, u32 *value, bool write)
err = (write ? pci_write_config_dword(root, 0x64, *value)
: pci_read_config_dword(root, 0x64, value));
- if (err)
- pr_warn("Error %s SMN address 0x%x.\n",
- (write ? "writing to" : "reading from"), address);
out_unlock:
mutex_unlock(&smn_mutex);
@@ -213,7 +247,7 @@ out:
return err;
}
-int amd_smn_read(u16 node, u32 address, u32 *value)
+int __must_check amd_smn_read(u16 node, u32 address, u32 *value)
{
int err = __amd_smn_rw(node, address, value, false);
@@ -226,7 +260,7 @@ int amd_smn_read(u16 node, u32 address, u32 *value)
}
EXPORT_SYMBOL_GPL(amd_smn_read);
-int amd_smn_write(u16 node, u32 address, u32 value)
+int __must_check amd_smn_write(u16 node, u32 address, u32 value)
{
return __amd_smn_rw(node, address, &value, true);
}
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index a02bba0ed6b9..5857a0f5d514 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -34,7 +34,7 @@ obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_IA32_FEAT_CTL) += feat_ctl.o
ifdef CONFIG_CPU_SUP_INTEL
-obj-y += intel.o intel_pconfig.o tsx.o
+obj-y += intel.o tsx.o
obj-$(CONFIG_PM) += intel_epb.o
endif
obj-$(CONFIG_CPU_SUP_AMD) += amd.o
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 44df3f11e731..be5889bded49 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1220,14 +1220,3 @@ void amd_check_microcode(void)
on_each_cpu(zenbleed_check_cpu, NULL, 1);
}
-
-/*
- * Issue a DIV 0/1 insn to clear any division data from previous DIV
- * operations.
- */
-void noinstr amd_clear_divider(void)
-{
- asm volatile(ALTERNATIVE("", "div %2\n\t", X86_BUG_DIV0)
- :: "a" (0), "d" (0), "r" (1));
-}
-EXPORT_SYMBOL_GPL(amd_clear_divider);
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index b6f927f6c567..45675da354f3 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -1625,6 +1625,7 @@ static bool __init spec_ctrl_bhi_dis(void)
enum bhi_mitigations {
BHI_MITIGATION_OFF,
BHI_MITIGATION_ON,
+ BHI_MITIGATION_VMEXIT_ONLY,
};
static enum bhi_mitigations bhi_mitigation __ro_after_init =
@@ -1639,6 +1640,8 @@ static int __init spectre_bhi_parse_cmdline(char *str)
bhi_mitigation = BHI_MITIGATION_OFF;
else if (!strcmp(str, "on"))
bhi_mitigation = BHI_MITIGATION_ON;
+ else if (!strcmp(str, "vmexit"))
+ bhi_mitigation = BHI_MITIGATION_VMEXIT_ONLY;
else
pr_err("Ignoring unknown spectre_bhi option (%s)", str);
@@ -1659,19 +1662,22 @@ static void __init bhi_select_mitigation(void)
return;
}
+ /* Mitigate in hardware if supported */
if (spec_ctrl_bhi_dis())
return;
if (!IS_ENABLED(CONFIG_X86_64))
return;
- /* Mitigate KVM by default */
- setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
- pr_info("Spectre BHI mitigation: SW BHB clearing on vm exit\n");
+ if (bhi_mitigation == BHI_MITIGATION_VMEXIT_ONLY) {
+ pr_info("Spectre BHI mitigation: SW BHB clearing on VM exit only\n");
+ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
+ return;
+ }
- /* Mitigate syscalls when the mitigation is forced =on */
+ pr_info("Spectre BHI mitigation: SW BHB clearing on syscall and VM exit\n");
setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP);
- pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n");
+ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
}
static void __init spectre_v2_select_mitigation(void)
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index fdf3489d92a4..08b95a35b5cb 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -72,19 +72,19 @@ static bool cpu_model_supports_sld __ro_after_init;
*/
static void check_memory_type_self_snoop_errata(struct cpuinfo_x86 *c)
{
- switch (c->x86_model) {
- case INTEL_FAM6_CORE_YONAH:
- case INTEL_FAM6_CORE2_MEROM:
- case INTEL_FAM6_CORE2_MEROM_L:
- case INTEL_FAM6_CORE2_PENRYN:
- case INTEL_FAM6_CORE2_DUNNINGTON:
- case INTEL_FAM6_NEHALEM:
- case INTEL_FAM6_NEHALEM_G:
- case INTEL_FAM6_NEHALEM_EP:
- case INTEL_FAM6_NEHALEM_EX:
- case INTEL_FAM6_WESTMERE:
- case INTEL_FAM6_WESTMERE_EP:
- case INTEL_FAM6_SANDYBRIDGE:
+ switch (c->x86_vfm) {
+ case INTEL_CORE_YONAH:
+ case INTEL_CORE2_MEROM:
+ case INTEL_CORE2_MEROM_L:
+ case INTEL_CORE2_PENRYN:
+ case INTEL_CORE2_DUNNINGTON:
+ case INTEL_NEHALEM:
+ case INTEL_NEHALEM_G:
+ case INTEL_NEHALEM_EP:
+ case INTEL_NEHALEM_EX:
+ case INTEL_WESTMERE:
+ case INTEL_WESTMERE_EP:
+ case INTEL_SANDYBRIDGE:
setup_clear_cpu_cap(X86_FEATURE_SELFSNOOP);
}
}
@@ -106,9 +106,9 @@ static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *c)
*/
if (c->x86 != 6)
return;
- switch (c->x86_model) {
- case INTEL_FAM6_XEON_PHI_KNL:
- case INTEL_FAM6_XEON_PHI_KNM:
+ switch (c->x86_vfm) {
+ case INTEL_XEON_PHI_KNL:
+ case INTEL_XEON_PHI_KNM:
break;
default:
return;
@@ -134,32 +134,32 @@ static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *c)
* - Release note from 20180108 microcode release
*/
struct sku_microcode {
- u8 model;
+ u32 vfm;
u8 stepping;
u32 microcode;
};
static const struct sku_microcode spectre_bad_microcodes[] = {
- { INTEL_FAM6_KABYLAKE, 0x0B, 0x80 },
- { INTEL_FAM6_KABYLAKE, 0x0A, 0x80 },
- { INTEL_FAM6_KABYLAKE, 0x09, 0x80 },
- { INTEL_FAM6_KABYLAKE_L, 0x0A, 0x80 },
- { INTEL_FAM6_KABYLAKE_L, 0x09, 0x80 },
- { INTEL_FAM6_SKYLAKE_X, 0x03, 0x0100013e },
- { INTEL_FAM6_SKYLAKE_X, 0x04, 0x0200003c },
- { INTEL_FAM6_BROADWELL, 0x04, 0x28 },
- { INTEL_FAM6_BROADWELL_G, 0x01, 0x1b },
- { INTEL_FAM6_BROADWELL_D, 0x02, 0x14 },
- { INTEL_FAM6_BROADWELL_D, 0x03, 0x07000011 },
- { INTEL_FAM6_BROADWELL_X, 0x01, 0x0b000025 },
- { INTEL_FAM6_HASWELL_L, 0x01, 0x21 },
- { INTEL_FAM6_HASWELL_G, 0x01, 0x18 },
- { INTEL_FAM6_HASWELL, 0x03, 0x23 },
- { INTEL_FAM6_HASWELL_X, 0x02, 0x3b },
- { INTEL_FAM6_HASWELL_X, 0x04, 0x10 },
- { INTEL_FAM6_IVYBRIDGE_X, 0x04, 0x42a },
+ { INTEL_KABYLAKE, 0x0B, 0x80 },
+ { INTEL_KABYLAKE, 0x0A, 0x80 },
+ { INTEL_KABYLAKE, 0x09, 0x80 },
+ { INTEL_KABYLAKE_L, 0x0A, 0x80 },
+ { INTEL_KABYLAKE_L, 0x09, 0x80 },
+ { INTEL_SKYLAKE_X, 0x03, 0x0100013e },
+ { INTEL_SKYLAKE_X, 0x04, 0x0200003c },
+ { INTEL_BROADWELL, 0x04, 0x28 },
+ { INTEL_BROADWELL_G, 0x01, 0x1b },
+ { INTEL_BROADWELL_D, 0x02, 0x14 },
+ { INTEL_BROADWELL_D, 0x03, 0x07000011 },
+ { INTEL_BROADWELL_X, 0x01, 0x0b000025 },
+ { INTEL_HASWELL_L, 0x01, 0x21 },
+ { INTEL_HASWELL_G, 0x01, 0x18 },
+ { INTEL_HASWELL, 0x03, 0x23 },
+ { INTEL_HASWELL_X, 0x02, 0x3b },
+ { INTEL_HASWELL_X, 0x04, 0x10 },
+ { INTEL_IVYBRIDGE_X, 0x04, 0x42a },
/* Observed in the wild */
- { INTEL_FAM6_SANDYBRIDGE_X, 0x06, 0x61b },
- { INTEL_FAM6_SANDYBRIDGE_X, 0x07, 0x712 },
+ { INTEL_SANDYBRIDGE_X, 0x06, 0x61b },
+ { INTEL_SANDYBRIDGE_X, 0x07, 0x712 },
};
static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
@@ -173,11 +173,8 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
if (cpu_has(c, X86_FEATURE_HYPERVISOR))
return false;
- if (c->x86 != 6)
- return false;
-
for (i = 0; i < ARRAY_SIZE(spectre_bad_microcodes); i++) {
- if (c->x86_model == spectre_bad_microcodes[i].model &&
+ if (c->x86_vfm == spectre_bad_microcodes[i].vfm &&
c->x86_stepping == spectre_bad_microcodes[i].stepping)
return (c->microcode <= spectre_bad_microcodes[i].microcode);
}
@@ -190,83 +187,35 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
#define TME_ACTIVATE_LOCKED(x) (x & 0x1)
#define TME_ACTIVATE_ENABLED(x) (x & 0x2)
-#define TME_ACTIVATE_POLICY(x) ((x >> 4) & 0xf) /* Bits 7:4 */
-#define TME_ACTIVATE_POLICY_AES_XTS_128 0
-
#define TME_ACTIVATE_KEYID_BITS(x) ((x >> 32) & 0xf) /* Bits 35:32 */
-#define TME_ACTIVATE_CRYPTO_ALGS(x) ((x >> 48) & 0xffff) /* Bits 63:48 */
-#define TME_ACTIVATE_CRYPTO_AES_XTS_128 1
-
-/* Values for mktme_status (SW only construct) */
-#define MKTME_ENABLED 0
-#define MKTME_DISABLED 1
-#define MKTME_UNINITIALIZED 2
-static int mktme_status = MKTME_UNINITIALIZED;
-
static void detect_tme_early(struct cpuinfo_x86 *c)
{
- u64 tme_activate, tme_policy, tme_crypto_algs;
- int keyid_bits = 0, nr_keyids = 0;
- static u64 tme_activate_cpu0 = 0;
+ u64 tme_activate;
+ int keyid_bits;
rdmsrl(MSR_IA32_TME_ACTIVATE, tme_activate);
- if (mktme_status != MKTME_UNINITIALIZED) {
- if (tme_activate != tme_activate_cpu0) {
- /* Broken BIOS? */
- pr_err_once("x86/tme: configuration is inconsistent between CPUs\n");
- pr_err_once("x86/tme: MKTME is not usable\n");
- mktme_status = MKTME_DISABLED;
-
- /* Proceed. We may need to exclude bits from x86_phys_bits. */
- }
- } else {
- tme_activate_cpu0 = tme_activate;
- }
-
if (!TME_ACTIVATE_LOCKED(tme_activate) || !TME_ACTIVATE_ENABLED(tme_activate)) {
pr_info_once("x86/tme: not enabled by BIOS\n");
- mktme_status = MKTME_DISABLED;
clear_cpu_cap(c, X86_FEATURE_TME);
return;
}
-
- if (mktme_status != MKTME_UNINITIALIZED)
- goto detect_keyid_bits;
-
- pr_info("x86/tme: enabled by BIOS\n");
-
- tme_policy = TME_ACTIVATE_POLICY(tme_activate);
- if (tme_policy != TME_ACTIVATE_POLICY_AES_XTS_128)
- pr_warn("x86/tme: Unknown policy is active: %#llx\n", tme_policy);
-
- tme_crypto_algs = TME_ACTIVATE_CRYPTO_ALGS(tme_activate);
- if (!(tme_crypto_algs & TME_ACTIVATE_CRYPTO_AES_XTS_128)) {
- pr_err("x86/mktme: No known encryption algorithm is supported: %#llx\n",
- tme_crypto_algs);
- mktme_status = MKTME_DISABLED;
- }
-detect_keyid_bits:
+ pr_info_once("x86/tme: enabled by BIOS\n");
keyid_bits = TME_ACTIVATE_KEYID_BITS(tme_activate);
- nr_keyids = (1UL << keyid_bits) - 1;
- if (nr_keyids) {
- pr_info_once("x86/mktme: enabled by BIOS\n");
- pr_info_once("x86/mktme: %d KeyIDs available\n", nr_keyids);
- } else {
- pr_info_once("x86/mktme: disabled by BIOS\n");
- }
-
- if (mktme_status == MKTME_UNINITIALIZED) {
- /* MKTME is usable */
- mktme_status = MKTME_ENABLED;
- }
+ if (!keyid_bits)
+ return;
/*
- * KeyID bits effectively lower the number of physical address
- * bits. Update cpuinfo_x86::x86_phys_bits accordingly.
+ * KeyID bits are set by BIOS and can be present regardless
+ * of whether the kernel is using them. They effectively lower
+ * the number of physical address bits.
+ *
+ * Update cpuinfo_x86::x86_phys_bits accordingly.
*/
c->x86_phys_bits -= keyid_bits;
+ pr_info_once("x86/mktme: BIOS enabled: x86_phys_bits reduced by %d\n",
+ keyid_bits);
}
void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c)
@@ -320,7 +269,7 @@ static void early_init_intel(struct cpuinfo_x86 *c)
* need the microcode to have already been loaded... so if it is
* not, recommend a BIOS update and disable large pages.
*/
- if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_stepping <= 2 &&
+ if (c->x86_vfm == INTEL_ATOM_BONNELL && c->x86_stepping <= 2 &&
c->microcode < 0x20e) {
pr_warn("Atom PSE erratum detected, BIOS microcode update recommended\n");
clear_cpu_cap(c, X86_FEATURE_PSE);
@@ -352,17 +301,13 @@ static void early_init_intel(struct cpuinfo_x86 *c)
}
/* Penwell and Cloverview have the TSC which doesn't sleep on S3 */
- if (c->x86 == 6) {
- switch (c->x86_model) {
- case INTEL_FAM6_ATOM_SALTWELL_MID:
- case INTEL_FAM6_ATOM_SALTWELL_TABLET:
- case INTEL_FAM6_ATOM_SILVERMONT_MID:
- case INTEL_FAM6_ATOM_AIRMONT_NP:
- set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC_S3);
- break;
- default:
- break;
- }
+ switch (c->x86_vfm) {
+ case INTEL_ATOM_SALTWELL_MID:
+ case INTEL_ATOM_SALTWELL_TABLET:
+ case INTEL_ATOM_SILVERMONT_MID:
+ case INTEL_ATOM_AIRMONT_NP:
+ set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC_S3);
+ break;
}
/*
@@ -401,7 +346,7 @@ static void early_init_intel(struct cpuinfo_x86 *c)
* should be false so that __flush_tlb_all() causes CR3 instead of CR4.PGE
* to be modified.
*/
- if (c->x86 == 5 && c->x86_model == 9) {
+ if (c->x86_vfm == INTEL_QUARK_X1000) {
pr_info("Disabling PGE capability bit\n");
setup_clear_cpu_cap(X86_FEATURE_PGE);
}
@@ -633,12 +578,13 @@ static void init_intel(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_PEBS);
}
- if (c->x86 == 6 && boot_cpu_has(X86_FEATURE_CLFLUSH) &&
- (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
+ if (boot_cpu_has(X86_FEATURE_CLFLUSH) &&
+ (c->x86_vfm == INTEL_CORE2_DUNNINGTON ||
+ c->x86_vfm == INTEL_NEHALEM_EX ||
+ c->x86_vfm == INTEL_WESTMERE_EX))
set_cpu_bug(c, X86_BUG_CLFLUSH_MONITOR);
- if (c->x86 == 6 && boot_cpu_has(X86_FEATURE_MWAIT) &&
- ((c->x86_model == INTEL_FAM6_ATOM_GOLDMONT)))
+ if (boot_cpu_has(X86_FEATURE_MWAIT) && c->x86_vfm == INTEL_ATOM_GOLDMONT)
set_cpu_bug(c, X86_BUG_MONITOR);
#ifdef CONFIG_X86_64
@@ -1254,9 +1200,9 @@ void handle_bus_lock(struct pt_regs *regs)
* feature even though they do not enumerate IA32_CORE_CAPABILITIES.
*/
static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = {
- X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, 0),
- X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, 0),
- X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, 0),
+ X86_MATCH_VFM(INTEL_ICELAKE_X, 0),
+ X86_MATCH_VFM(INTEL_ICELAKE_L, 0),
+ X86_MATCH_VFM(INTEL_ICELAKE_D, 0),
{}
};
diff --git a/arch/x86/kernel/cpu/intel_pconfig.c b/arch/x86/kernel/cpu/intel_pconfig.c
deleted file mode 100644
index 5be2b1790282..000000000000
--- a/arch/x86/kernel/cpu/intel_pconfig.c
+++ /dev/null
@@ -1,84 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Intel PCONFIG instruction support.
- *
- * Copyright (C) 2017 Intel Corporation
- *
- * Author:
- * Kirill A. Shutemov <[email protected]>
- */
-#include <linux/bug.h>
-#include <linux/limits.h>
-
-#include <asm/cpufeature.h>
-#include <asm/intel_pconfig.h>
-
-#define PCONFIG_CPUID 0x1b
-
-#define PCONFIG_CPUID_SUBLEAF_MASK ((1 << 12) - 1)
-
-/* Subleaf type (EAX) for PCONFIG CPUID leaf (0x1B) */
-enum {
- PCONFIG_CPUID_SUBLEAF_INVALID = 0,
- PCONFIG_CPUID_SUBLEAF_TARGETID = 1,
-};
-
-/* Bitmask of supported targets */
-static u64 targets_supported __read_mostly;
-
-int pconfig_target_supported(enum pconfig_target target)
-{
- /*
- * We would need to re-think the implementation once we get > 64
- * PCONFIG targets. Spec allows up to 2^32 targets.
- */
- BUILD_BUG_ON(PCONFIG_TARGET_NR >= 64);
-
- if (WARN_ON_ONCE(target >= 64))
- return 0;
- return targets_supported & (1ULL << target);
-}
-
-static int __init intel_pconfig_init(void)
-{
- int subleaf;
-
- if (!boot_cpu_has(X86_FEATURE_PCONFIG))
- return 0;
-
- /*
- * Scan subleafs of PCONFIG CPUID leaf.
- *
- * Subleafs of the same type need not to be consecutive.
- *
- * Stop on the first invalid subleaf type. All subleafs after the first
- * invalid are invalid too.
- */
- for (subleaf = 0; subleaf < INT_MAX; subleaf++) {
- struct cpuid_regs regs;
-
- cpuid_count(PCONFIG_CPUID, subleaf,
- &regs.eax, &regs.ebx, &regs.ecx, &regs.edx);
-
- switch (regs.eax & PCONFIG_CPUID_SUBLEAF_MASK) {
- case PCONFIG_CPUID_SUBLEAF_INVALID:
- /* Stop on the first invalid subleaf */
- goto out;
- case PCONFIG_CPUID_SUBLEAF_TARGETID:
- /* Mark supported PCONFIG targets */
- if (regs.ebx < 64)
- targets_supported |= (1ULL << regs.ebx);
- if (regs.ecx < 64)
- targets_supported |= (1ULL << regs.ecx);
- if (regs.edx < 64)
- targets_supported |= (1ULL << regs.edx);
- break;
- default:
- /* Unknown CPUID.PCONFIG subleaf: ignore */
- break;
- }
- }
-out:
- return 0;
-}
-arch_initcall(intel_pconfig_init);
diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
index ad0623b659ed..b85ec7a4ec9e 100644
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -677,10 +677,9 @@ DEFINE_PER_CPU(unsigned, mce_poll_count);
* is already totally * confused. In this case it's likely it will
* not fully execute the machine check handler either.
*/
-bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
+void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
{
struct mce_bank *mce_banks = this_cpu_ptr(mce_banks_array);
- bool error_seen = false;
struct mce m;
int i;
@@ -754,8 +753,6 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
continue;
log_it:
- error_seen = true;
-
if (flags & MCP_DONTLOG)
goto clear_it;
@@ -787,8 +784,6 @@ clear_it:
*/
sync_core();
-
- return error_seen;
}
EXPORT_SYMBOL_GPL(machine_check_poll);
diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inject.c
index 94953d749475..49ed3428785d 100644
--- a/arch/x86/kernel/cpu/mce/inject.c
+++ b/arch/x86/kernel/cpu/mce/inject.c
@@ -487,12 +487,16 @@ static void prepare_msrs(void *info)
wrmsrl(MSR_AMD64_SMCA_MCx_ADDR(b), m.addr);
}
- wrmsrl(MSR_AMD64_SMCA_MCx_MISC(b), m.misc);
wrmsrl(MSR_AMD64_SMCA_MCx_SYND(b), m.synd);
+
+ if (m.misc)
+ wrmsrl(MSR_AMD64_SMCA_MCx_MISC(b), m.misc);
} else {
wrmsrl(MSR_IA32_MCx_STATUS(b), m.status);
wrmsrl(MSR_IA32_MCx_ADDR(b), m.addr);
- wrmsrl(MSR_IA32_MCx_MISC(b), m.misc);
+
+ if (m.misc)
+ wrmsrl(MSR_IA32_MCx_MISC(b), m.misc);
}
}
@@ -795,4 +799,5 @@ static void __exit inject_exit(void)
module_init(inject_init);
module_exit(inject_exit);
+MODULE_DESCRIPTION("Machine check injection support");
MODULE_LICENSE("GPL");
diff --git a/arch/x86/kernel/cpu/mkcapflags.sh b/arch/x86/kernel/cpu/mkcapflags.sh
index 1db560ed2ca3..68f537347466 100644
--- a/arch/x86/kernel/cpu/mkcapflags.sh
+++ b/arch/x86/kernel/cpu/mkcapflags.sh
@@ -30,8 +30,7 @@ dump_array()
# If the /* comment */ starts with a quote string, grab that.
VALUE="$(echo "$i" | sed -n 's@.*/\* *\("[^"]*"\).*\*/@\1@p')"
- [ -z "$VALUE" ] && VALUE="\"$NAME\""
- [ "$VALUE" = '""' ] && continue
+ [ ! "$VALUE" ] && continue
# Name is uppercase, VALUE is all lowercase
VALUE="$(echo "$VALUE" | tr A-Z a-z)"
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index a113d9aba553..1930fce9dfe9 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -19,7 +19,6 @@
#include <linux/cpu.h>
#include <linux/slab.h>
#include <linux/err.h>
-#include <linux/cacheinfo.h>
#include <linux/cpuhotplug.h>
#include <asm/cpu_device_id.h>
@@ -60,7 +59,8 @@ static void mba_wrmsr_intel(struct msr_param *m);
static void cat_wrmsr(struct msr_param *m);
static void mba_wrmsr_amd(struct msr_param *m);
-#define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].r_resctrl.domains)
+#define ctrl_domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].r_resctrl.ctrl_domains)
+#define mon_domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].r_resctrl.mon_domains)
struct rdt_hw_resource rdt_resources_all[] = {
[RDT_RESOURCE_L3] =
@@ -68,8 +68,10 @@ struct rdt_hw_resource rdt_resources_all[] = {
.r_resctrl = {
.rid = RDT_RESOURCE_L3,
.name = "L3",
- .cache_level = 3,
- .domains = domain_init(RDT_RESOURCE_L3),
+ .ctrl_scope = RESCTRL_L3_CACHE,
+ .mon_scope = RESCTRL_L3_CACHE,
+ .ctrl_domains = ctrl_domain_init(RDT_RESOURCE_L3),
+ .mon_domains = mon_domain_init(RDT_RESOURCE_L3),
.parse_ctrlval = parse_cbm,
.format_str = "%d=%0*x",
.fflags = RFTYPE_RES_CACHE,
@@ -82,8 +84,8 @@ struct rdt_hw_resource rdt_resources_all[] = {
.r_resctrl = {
.rid = RDT_RESOURCE_L2,
.name = "L2",
- .cache_level = 2,
- .domains = domain_init(RDT_RESOURCE_L2),
+ .ctrl_scope = RESCTRL_L2_CACHE,
+ .ctrl_domains = ctrl_domain_init(RDT_RESOURCE_L2),
.parse_ctrlval = parse_cbm,
.format_str = "%d=%0*x",
.fflags = RFTYPE_RES_CACHE,
@@ -96,8 +98,8 @@ struct rdt_hw_resource rdt_resources_all[] = {
.r_resctrl = {
.rid = RDT_RESOURCE_MBA,
.name = "MB",
- .cache_level = 3,
- .domains = domain_init(RDT_RESOURCE_MBA),
+ .ctrl_scope = RESCTRL_L3_CACHE,
+ .ctrl_domains = ctrl_domain_init(RDT_RESOURCE_MBA),
.parse_ctrlval = parse_bw,
.format_str = "%d=%*u",
.fflags = RFTYPE_RES_MB,
@@ -108,8 +110,8 @@ struct rdt_hw_resource rdt_resources_all[] = {
.r_resctrl = {
.rid = RDT_RESOURCE_SMBA,
.name = "SMBA",
- .cache_level = 3,
- .domains = domain_init(RDT_RESOURCE_SMBA),
+ .ctrl_scope = RESCTRL_L3_CACHE,
+ .ctrl_domains = ctrl_domain_init(RDT_RESOURCE_SMBA),
.parse_ctrlval = parse_bw,
.format_str = "%d=%*u",
.fflags = RFTYPE_RES_MB,
@@ -306,8 +308,8 @@ static void rdt_get_cdp_l2_config(void)
static void mba_wrmsr_amd(struct msr_param *m)
{
+ struct rdt_hw_ctrl_domain *hw_dom = resctrl_to_arch_ctrl_dom(m->dom);
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
- struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(m->dom);
unsigned int i;
for (i = m->low; i < m->high; i++)
@@ -330,8 +332,8 @@ static u32 delay_bw_map(unsigned long bw, struct rdt_resource *r)
static void mba_wrmsr_intel(struct msr_param *m)
{
+ struct rdt_hw_ctrl_domain *hw_dom = resctrl_to_arch_ctrl_dom(m->dom);
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
- struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(m->dom);
unsigned int i;
/* Write the delay values for mba. */
@@ -341,23 +343,38 @@ static void mba_wrmsr_intel(struct msr_param *m)
static void cat_wrmsr(struct msr_param *m)
{
+ struct rdt_hw_ctrl_domain *hw_dom = resctrl_to_arch_ctrl_dom(m->dom);
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(m->res);
- struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(m->dom);
unsigned int i;
for (i = m->low; i < m->high; i++)
wrmsrl(hw_res->msr_base + i, hw_dom->ctrl_val[i]);
}
-struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r)
+struct rdt_ctrl_domain *get_ctrl_domain_from_cpu(int cpu, struct rdt_resource *r)
{
- struct rdt_domain *d;
+ struct rdt_ctrl_domain *d;
lockdep_assert_cpus_held();
- list_for_each_entry(d, &r->domains, list) {
+ list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
/* Find the domain that contains this CPU */
- if (cpumask_test_cpu(cpu, &d->cpu_mask))
+ if (cpumask_test_cpu(cpu, &d->hdr.cpu_mask))
+ return d;
+ }
+
+ return NULL;
+}
+
+struct rdt_mon_domain *get_mon_domain_from_cpu(int cpu, struct rdt_resource *r)
+{
+ struct rdt_mon_domain *d;
+
+ lockdep_assert_cpus_held();
+
+ list_for_each_entry(d, &r->mon_domains, hdr.list) {
+ /* Find the domain that contains this CPU */
+ if (cpumask_test_cpu(cpu, &d->hdr.cpu_mask))
return d;
}
@@ -379,24 +396,21 @@ void rdt_ctrl_update(void *arg)
}
/*
- * rdt_find_domain - Find a domain in a resource that matches input resource id
+ * rdt_find_domain - Search for a domain id in a resource domain list.
*
- * Search resource r's domain list to find the resource id. If the resource
- * id is found in a domain, return the domain. Otherwise, if requested by
- * caller, return the first domain whose id is bigger than the input id.
- * The domain list is sorted by id in ascending order.
+ * Search the domain list to find the domain id. If the domain id is
+ * found, return the domain. NULL otherwise. If the domain id is not
+ * found (and NULL returned) then the first domain with id bigger than
+ * the input id can be returned to the caller via @pos.
*/
-struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
- struct list_head **pos)
+struct rdt_domain_hdr *rdt_find_domain(struct list_head *h, int id,
+ struct list_head **pos)
{
- struct rdt_domain *d;
+ struct rdt_domain_hdr *d;
struct list_head *l;
- if (id < 0)
- return ERR_PTR(-ENODEV);
-
- list_for_each(l, &r->domains) {
- d = list_entry(l, struct rdt_domain, list);
+ list_for_each(l, h) {
+ d = list_entry(l, struct rdt_domain_hdr, list);
/* When id is found, return its domain. */
if (id == d->id)
return d;
@@ -425,18 +439,23 @@ static void setup_default_ctrlval(struct rdt_resource *r, u32 *dc)
*dc = r->default_ctrl;
}
-static void domain_free(struct rdt_hw_domain *hw_dom)
+static void ctrl_domain_free(struct rdt_hw_ctrl_domain *hw_dom)
+{
+ kfree(hw_dom->ctrl_val);
+ kfree(hw_dom);
+}
+
+static void mon_domain_free(struct rdt_hw_mon_domain *hw_dom)
{
kfree(hw_dom->arch_mbm_total);
kfree(hw_dom->arch_mbm_local);
- kfree(hw_dom->ctrl_val);
kfree(hw_dom);
}
-static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
+static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_ctrl_domain *d)
{
+ struct rdt_hw_ctrl_domain *hw_dom = resctrl_to_arch_ctrl_dom(d);
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
- struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
struct msr_param m;
u32 *dc;
@@ -461,7 +480,7 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
* @num_rmid: The size of the MBM counter array
* @hw_dom: The domain that owns the allocated arrays
*/
-static int arch_domain_mbm_alloc(u32 num_rmid, struct rdt_hw_domain *hw_dom)
+static int arch_domain_mbm_alloc(u32 num_rmid, struct rdt_hw_mon_domain *hw_dom)
{
size_t tsize;
@@ -484,37 +503,45 @@ static int arch_domain_mbm_alloc(u32 num_rmid, struct rdt_hw_domain *hw_dom)
return 0;
}
-/*
- * domain_add_cpu - Add a cpu to a resource's domain list.
- *
- * If an existing domain in the resource r's domain list matches the cpu's
- * resource id, add the cpu in the domain.
- *
- * Otherwise, a new domain is allocated and inserted into the right position
- * in the domain list sorted by id in ascending order.
- *
- * The order in the domain list is visible to users when we print entries
- * in the schemata file and schemata input is validated to have the same order
- * as this list.
- */
-static void domain_add_cpu(int cpu, struct rdt_resource *r)
+static int get_domain_id_from_scope(int cpu, enum resctrl_scope scope)
{
- int id = get_cpu_cacheinfo_id(cpu, r->cache_level);
+ switch (scope) {
+ case RESCTRL_L2_CACHE:
+ case RESCTRL_L3_CACHE:
+ return get_cpu_cacheinfo_id(cpu, scope);
+ case RESCTRL_L3_NODE:
+ return cpu_to_node(cpu);
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static void domain_add_cpu_ctrl(int cpu, struct rdt_resource *r)
+{
+ int id = get_domain_id_from_scope(cpu, r->ctrl_scope);
+ struct rdt_hw_ctrl_domain *hw_dom;
struct list_head *add_pos = NULL;
- struct rdt_hw_domain *hw_dom;
- struct rdt_domain *d;
+ struct rdt_domain_hdr *hdr;
+ struct rdt_ctrl_domain *d;
int err;
lockdep_assert_held(&domain_list_lock);
- d = rdt_find_domain(r, id, &add_pos);
- if (IS_ERR(d)) {
- pr_warn("Couldn't find cache id for CPU %d\n", cpu);
+ if (id < 0) {
+ pr_warn_once("Can't find control domain id for CPU:%d scope:%d for resource %s\n",
+ cpu, r->ctrl_scope, r->name);
return;
}
- if (d) {
- cpumask_set_cpu(cpu, &d->cpu_mask);
+ hdr = rdt_find_domain(&r->ctrl_domains, id, &add_pos);
+ if (hdr) {
+ if (WARN_ON_ONCE(hdr->type != RESCTRL_CTRL_DOMAIN))
+ return;
+ d = container_of(hdr, struct rdt_ctrl_domain, hdr);
+
+ cpumask_set_cpu(cpu, &d->hdr.cpu_mask);
if (r->cache.arch_has_per_cpu_cfg)
rdt_domain_reconfigure_cdp(r);
return;
@@ -525,64 +552,187 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
return;
d = &hw_dom->d_resctrl;
- d->id = id;
- cpumask_set_cpu(cpu, &d->cpu_mask);
+ d->hdr.id = id;
+ d->hdr.type = RESCTRL_CTRL_DOMAIN;
+ cpumask_set_cpu(cpu, &d->hdr.cpu_mask);
rdt_domain_reconfigure_cdp(r);
- if (r->alloc_capable && domain_setup_ctrlval(r, d)) {
- domain_free(hw_dom);
+ if (domain_setup_ctrlval(r, d)) {
+ ctrl_domain_free(hw_dom);
return;
}
- if (r->mon_capable && arch_domain_mbm_alloc(r->num_rmid, hw_dom)) {
- domain_free(hw_dom);
+ list_add_tail_rcu(&d->hdr.list, add_pos);
+
+ err = resctrl_online_ctrl_domain(r, d);
+ if (err) {
+ list_del_rcu(&d->hdr.list);
+ synchronize_rcu();
+ ctrl_domain_free(hw_dom);
+ }
+}
+
+static void domain_add_cpu_mon(int cpu, struct rdt_resource *r)
+{
+ int id = get_domain_id_from_scope(cpu, r->mon_scope);
+ struct list_head *add_pos = NULL;
+ struct rdt_hw_mon_domain *hw_dom;
+ struct rdt_domain_hdr *hdr;
+ struct rdt_mon_domain *d;
+ int err;
+
+ lockdep_assert_held(&domain_list_lock);
+
+ if (id < 0) {
+ pr_warn_once("Can't find monitor domain id for CPU:%d scope:%d for resource %s\n",
+ cpu, r->mon_scope, r->name);
return;
}
- list_add_tail_rcu(&d->list, add_pos);
+ hdr = rdt_find_domain(&r->mon_domains, id, &add_pos);
+ if (hdr) {
+ if (WARN_ON_ONCE(hdr->type != RESCTRL_MON_DOMAIN))
+ return;
+ d = container_of(hdr, struct rdt_mon_domain, hdr);
+
+ cpumask_set_cpu(cpu, &d->hdr.cpu_mask);
+ return;
+ }
- err = resctrl_online_domain(r, d);
+ hw_dom = kzalloc_node(sizeof(*hw_dom), GFP_KERNEL, cpu_to_node(cpu));
+ if (!hw_dom)
+ return;
+
+ d = &hw_dom->d_resctrl;
+ d->hdr.id = id;
+ d->hdr.type = RESCTRL_MON_DOMAIN;
+ d->ci = get_cpu_cacheinfo_level(cpu, RESCTRL_L3_CACHE);
+ if (!d->ci) {
+ pr_warn_once("Can't find L3 cache for CPU:%d resource %s\n", cpu, r->name);
+ mon_domain_free(hw_dom);
+ return;
+ }
+ cpumask_set_cpu(cpu, &d->hdr.cpu_mask);
+
+ arch_mon_domain_online(r, d);
+
+ if (arch_domain_mbm_alloc(r->num_rmid, hw_dom)) {
+ mon_domain_free(hw_dom);
+ return;
+ }
+
+ list_add_tail_rcu(&d->hdr.list, add_pos);
+
+ err = resctrl_online_mon_domain(r, d);
if (err) {
- list_del_rcu(&d->list);
+ list_del_rcu(&d->hdr.list);
synchronize_rcu();
- domain_free(hw_dom);
+ mon_domain_free(hw_dom);
}
}
-static void domain_remove_cpu(int cpu, struct rdt_resource *r)
+static void domain_add_cpu(int cpu, struct rdt_resource *r)
+{
+ if (r->alloc_capable)
+ domain_add_cpu_ctrl(cpu, r);
+ if (r->mon_capable)
+ domain_add_cpu_mon(cpu, r);
+}
+
+static void domain_remove_cpu_ctrl(int cpu, struct rdt_resource *r)
{
- int id = get_cpu_cacheinfo_id(cpu, r->cache_level);
- struct rdt_hw_domain *hw_dom;
- struct rdt_domain *d;
+ int id = get_domain_id_from_scope(cpu, r->ctrl_scope);
+ struct rdt_hw_ctrl_domain *hw_dom;
+ struct rdt_domain_hdr *hdr;
+ struct rdt_ctrl_domain *d;
lockdep_assert_held(&domain_list_lock);
- d = rdt_find_domain(r, id, NULL);
- if (IS_ERR_OR_NULL(d)) {
- pr_warn("Couldn't find cache id for CPU %d\n", cpu);
+ if (id < 0) {
+ pr_warn_once("Can't find control domain id for CPU:%d scope:%d for resource %s\n",
+ cpu, r->ctrl_scope, r->name);
+ return;
+ }
+
+ hdr = rdt_find_domain(&r->ctrl_domains, id, NULL);
+ if (!hdr) {
+ pr_warn("Can't find control domain for id=%d for CPU %d for resource %s\n",
+ id, cpu, r->name);
return;
}
- hw_dom = resctrl_to_arch_dom(d);
- cpumask_clear_cpu(cpu, &d->cpu_mask);
- if (cpumask_empty(&d->cpu_mask)) {
- resctrl_offline_domain(r, d);
- list_del_rcu(&d->list);
+ if (WARN_ON_ONCE(hdr->type != RESCTRL_CTRL_DOMAIN))
+ return;
+
+ d = container_of(hdr, struct rdt_ctrl_domain, hdr);
+ hw_dom = resctrl_to_arch_ctrl_dom(d);
+
+ cpumask_clear_cpu(cpu, &d->hdr.cpu_mask);
+ if (cpumask_empty(&d->hdr.cpu_mask)) {
+ resctrl_offline_ctrl_domain(r, d);
+ list_del_rcu(&d->hdr.list);
synchronize_rcu();
/*
- * rdt_domain "d" is going to be freed below, so clear
+ * rdt_ctrl_domain "d" is going to be freed below, so clear
* its pointer from pseudo_lock_region struct.
*/
if (d->plr)
d->plr->d = NULL;
- domain_free(hw_dom);
+ ctrl_domain_free(hw_dom);
return;
}
}
+static void domain_remove_cpu_mon(int cpu, struct rdt_resource *r)
+{
+ int id = get_domain_id_from_scope(cpu, r->mon_scope);
+ struct rdt_hw_mon_domain *hw_dom;
+ struct rdt_domain_hdr *hdr;
+ struct rdt_mon_domain *d;
+
+ lockdep_assert_held(&domain_list_lock);
+
+ if (id < 0) {
+ pr_warn_once("Can't find monitor domain id for CPU:%d scope:%d for resource %s\n",
+ cpu, r->mon_scope, r->name);
+ return;
+ }
+
+ hdr = rdt_find_domain(&r->mon_domains, id, NULL);
+ if (!hdr) {
+ pr_warn("Can't find monitor domain for id=%d for CPU %d for resource %s\n",
+ id, cpu, r->name);
+ return;
+ }
+
+ if (WARN_ON_ONCE(hdr->type != RESCTRL_MON_DOMAIN))
+ return;
+
+ d = container_of(hdr, struct rdt_mon_domain, hdr);
+ hw_dom = resctrl_to_arch_mon_dom(d);
+
+ cpumask_clear_cpu(cpu, &d->hdr.cpu_mask);
+ if (cpumask_empty(&d->hdr.cpu_mask)) {
+ resctrl_offline_mon_domain(r, d);
+ list_del_rcu(&d->hdr.list);
+ synchronize_rcu();
+ mon_domain_free(hw_dom);
+
+ return;
+ }
+}
+
+static void domain_remove_cpu(int cpu, struct rdt_resource *r)
+{
+ if (r->alloc_capable)
+ domain_remove_cpu_ctrl(cpu, r);
+ if (r->mon_capable)
+ domain_remove_cpu_mon(cpu, r);
+}
+
static void clear_closid_rmid(int cpu)
{
struct resctrl_pqr_state *state = this_cpu_ptr(&pqr_state);
diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
index b7291f60399c..50fa1fe9a073 100644
--- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
+++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
@@ -60,7 +60,7 @@ static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r)
}
int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s,
- struct rdt_domain *d)
+ struct rdt_ctrl_domain *d)
{
struct resctrl_staged_config *cfg;
u32 closid = data->rdtgrp->closid;
@@ -69,7 +69,7 @@ int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s,
cfg = &d->staged_config[s->conf_type];
if (cfg->have_new_ctrl) {
- rdt_last_cmd_printf("Duplicate domain %d\n", d->id);
+ rdt_last_cmd_printf("Duplicate domain %d\n", d->hdr.id);
return -EINVAL;
}
@@ -139,7 +139,7 @@ static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
* resource type.
*/
int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
- struct rdt_domain *d)
+ struct rdt_ctrl_domain *d)
{
struct rdtgroup *rdtgrp = data->rdtgrp;
struct resctrl_staged_config *cfg;
@@ -148,7 +148,7 @@ int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
cfg = &d->staged_config[s->conf_type];
if (cfg->have_new_ctrl) {
- rdt_last_cmd_printf("Duplicate domain %d\n", d->id);
+ rdt_last_cmd_printf("Duplicate domain %d\n", d->hdr.id);
return -EINVAL;
}
@@ -208,8 +208,8 @@ static int parse_line(char *line, struct resctrl_schema *s,
struct resctrl_staged_config *cfg;
struct rdt_resource *r = s->res;
struct rdt_parse_data data;
+ struct rdt_ctrl_domain *d;
char *dom = NULL, *id;
- struct rdt_domain *d;
unsigned long dom_id;
/* Walking r->domains, ensure it can't race with cpuhp */
@@ -231,8 +231,8 @@ next:
return -EINVAL;
}
dom = strim(dom);
- list_for_each_entry(d, &r->domains, list) {
- if (d->id == dom_id) {
+ list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
+ if (d->hdr.id == dom_id) {
data.buf = dom;
data.rdtgrp = rdtgrp;
if (r->parse_ctrlval(&data, s, d))
@@ -272,15 +272,15 @@ static u32 get_config_index(u32 closid, enum resctrl_conf_type type)
}
}
-int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
+int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
u32 closid, enum resctrl_conf_type t, u32 cfg_val)
{
+ struct rdt_hw_ctrl_domain *hw_dom = resctrl_to_arch_ctrl_dom(d);
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
- struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
u32 idx = get_config_index(closid, t);
struct msr_param msr_param;
- if (!cpumask_test_cpu(smp_processor_id(), &d->cpu_mask))
+ if (!cpumask_test_cpu(smp_processor_id(), &d->hdr.cpu_mask))
return -EINVAL;
hw_dom->ctrl_val[idx] = cfg_val;
@@ -297,17 +297,17 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid)
{
struct resctrl_staged_config *cfg;
- struct rdt_hw_domain *hw_dom;
+ struct rdt_hw_ctrl_domain *hw_dom;
struct msr_param msr_param;
+ struct rdt_ctrl_domain *d;
enum resctrl_conf_type t;
- struct rdt_domain *d;
u32 idx;
/* Walking r->domains, ensure it can't race with cpuhp */
lockdep_assert_cpus_held();
- list_for_each_entry(d, &r->domains, list) {
- hw_dom = resctrl_to_arch_dom(d);
+ list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
+ hw_dom = resctrl_to_arch_ctrl_dom(d);
msr_param.res = NULL;
for (t = 0; t < CDP_NUM_TYPES; t++) {
cfg = &hw_dom->d_resctrl.staged_config[t];
@@ -330,7 +330,7 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid)
}
}
if (msr_param.res)
- smp_call_function_any(&d->cpu_mask, rdt_ctrl_update, &msr_param, 1);
+ smp_call_function_any(&d->hdr.cpu_mask, rdt_ctrl_update, &msr_param, 1);
}
return 0;
@@ -430,10 +430,10 @@ out:
return ret ?: nbytes;
}
-u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,
+u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
u32 closid, enum resctrl_conf_type type)
{
- struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
+ struct rdt_hw_ctrl_domain *hw_dom = resctrl_to_arch_ctrl_dom(d);
u32 idx = get_config_index(closid, type);
return hw_dom->ctrl_val[idx];
@@ -442,7 +442,7 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,
static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int closid)
{
struct rdt_resource *r = schema->res;
- struct rdt_domain *dom;
+ struct rdt_ctrl_domain *dom;
bool sep = false;
u32 ctrl_val;
@@ -450,7 +450,7 @@ static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int clo
lockdep_assert_cpus_held();
seq_printf(s, "%*s:", max_name_width, schema->name);
- list_for_each_entry(dom, &r->domains, list) {
+ list_for_each_entry(dom, &r->ctrl_domains, hdr.list) {
if (sep)
seq_puts(s, ";");
@@ -460,7 +460,7 @@ static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int clo
ctrl_val = resctrl_arch_get_config(r, dom, closid,
schema->conf_type);
- seq_printf(s, r->format_str, dom->id, max_data_width,
+ seq_printf(s, r->format_str, dom->hdr.id, max_data_width,
ctrl_val);
sep = true;
}
@@ -489,7 +489,7 @@ int rdtgroup_schemata_show(struct kernfs_open_file *of,
} else {
seq_printf(s, "%s:%d=%x\n",
rdtgrp->plr->s->res->name,
- rdtgrp->plr->d->id,
+ rdtgrp->plr->d->hdr.id,
rdtgrp->plr->cbm);
}
} else {
@@ -514,8 +514,8 @@ static int smp_mon_event_count(void *arg)
}
void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
- struct rdt_domain *d, struct rdtgroup *rdtgrp,
- int evtid, int first)
+ struct rdt_mon_domain *d, struct rdtgroup *rdtgrp,
+ cpumask_t *cpumask, int evtid, int first)
{
int cpu;
@@ -529,7 +529,6 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
rr->evtid = evtid;
rr->r = r;
rr->d = d;
- rr->val = 0;
rr->first = first;
rr->arch_mon_ctx = resctrl_arch_mon_ctx_alloc(r, evtid);
if (IS_ERR(rr->arch_mon_ctx)) {
@@ -537,7 +536,7 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
return;
}
- cpu = cpumask_any_housekeeping(&d->cpu_mask, RESCTRL_PICK_ANY_CPU);
+ cpu = cpumask_any_housekeeping(cpumask, RESCTRL_PICK_ANY_CPU);
/*
* cpumask_any_housekeeping() prefers housekeeping CPUs, but
@@ -546,7 +545,7 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
* counters on some platforms if its called in IRQ context.
*/
if (tick_nohz_full_cpu(cpu))
- smp_call_function_any(&d->cpu_mask, mon_event_count, rr, 1);
+ smp_call_function_any(cpumask, mon_event_count, rr, 1);
else
smp_call_on_cpu(cpu, smp_mon_event_count, rr, false);
@@ -556,12 +555,13 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
int rdtgroup_mondata_show(struct seq_file *m, void *arg)
{
struct kernfs_open_file *of = m->private;
+ struct rdt_domain_hdr *hdr;
+ struct rmid_read rr = {0};
+ struct rdt_mon_domain *d;
u32 resid, evtid, domid;
struct rdtgroup *rdtgrp;
struct rdt_resource *r;
union mon_data_bits md;
- struct rdt_domain *d;
- struct rmid_read rr;
int ret = 0;
rdtgrp = rdtgroup_kn_lock_live(of->kn);
@@ -574,15 +574,40 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg)
resid = md.u.rid;
domid = md.u.domid;
evtid = md.u.evtid;
-
r = &rdt_resources_all[resid].r_resctrl;
- d = rdt_find_domain(r, domid, NULL);
- if (IS_ERR_OR_NULL(d)) {
+
+ if (md.u.sum) {
+ /*
+ * This file requires summing across all domains that share
+ * the L3 cache id that was provided in the "domid" field of the
+ * mon_data_bits union. Search all domains in the resource for
+ * one that matches this cache id.
+ */
+ list_for_each_entry(d, &r->mon_domains, hdr.list) {
+ if (d->ci->id == domid) {
+ rr.ci = d->ci;
+ mon_event_read(&rr, r, NULL, rdtgrp,
+ &d->ci->shared_cpu_map, evtid, false);
+ goto checkresult;
+ }
+ }
ret = -ENOENT;
goto out;
+ } else {
+ /*
+ * This file provides data from a single domain. Search
+ * the resource to find the domain with "domid".
+ */
+ hdr = rdt_find_domain(&r->mon_domains, domid, NULL);
+ if (!hdr || WARN_ON_ONCE(hdr->type != RESCTRL_MON_DOMAIN)) {
+ ret = -ENOENT;
+ goto out;
+ }
+ d = container_of(hdr, struct rdt_mon_domain, hdr);
+ mon_event_read(&rr, r, d, rdtgrp, &d->hdr.cpu_mask, evtid, false);
}
- mon_event_read(&rr, r, d, rdtgrp, evtid, false);
+checkresult:
if (rr.err == -EIO)
seq_puts(m, "Error\n");
diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index f1d926832ec8..955999aecfca 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -127,29 +127,54 @@ struct mon_evt {
};
/**
- * union mon_data_bits - Monitoring details for each event file
+ * union mon_data_bits - Monitoring details for each event file.
* @priv: Used to store monitoring event data in @u
- * as kernfs private data
- * @rid: Resource id associated with the event file
- * @evtid: Event id associated with the event file
- * @domid: The domain to which the event file belongs
- * @u: Name of the bit fields struct
+ * as kernfs private data.
+ * @u.rid: Resource id associated with the event file.
+ * @u.evtid: Event id associated with the event file.
+ * @u.sum: Set when event must be summed across multiple
+ * domains.
+ * @u.domid: When @u.sum is zero this is the domain to which
+ * the event file belongs. When @sum is one this
+ * is the id of the L3 cache that all domains to be
+ * summed share.
+ * @u: Name of the bit fields struct.
*/
union mon_data_bits {
void *priv;
struct {
unsigned int rid : 10;
- enum resctrl_event_id evtid : 8;
+ enum resctrl_event_id evtid : 7;
+ unsigned int sum : 1;
unsigned int domid : 14;
} u;
};
+/**
+ * struct rmid_read - Data passed across smp_call*() to read event count.
+ * @rgrp: Resource group for which the counter is being read. If it is a parent
+ * resource group then its event count is summed with the count from all
+ * its child resource groups.
+ * @r: Resource describing the properties of the event being read.
+ * @d: Domain that the counter should be read from. If NULL then sum all
+ * domains in @r sharing L3 @ci.id
+ * @evtid: Which monitor event to read.
+ * @first: Initialize MBM counter when true.
+ * @ci: Cacheinfo for L3. Only set when @d is NULL. Used when summing domains.
+ * @err: Error encountered when reading counter.
+ * @val: Returned value of event counter. If @rgrp is a parent resource group,
+ * @val includes the sum of event counts from its child resource groups.
+ * If @d is NULL, @val includes the sum of all domains in @r sharing @ci.id,
+ * (summed across child resource groups if @rgrp is a parent resource group).
+ * @arch_mon_ctx: Hardware monitor allocated for this read request (MPAM only).
+ */
struct rmid_read {
struct rdtgroup *rgrp;
struct rdt_resource *r;
- struct rdt_domain *d;
+ struct rdt_mon_domain *d;
enum resctrl_event_id evtid;
bool first;
+ struct cacheinfo *ci;
int err;
u64 val;
void *arch_mon_ctx;
@@ -232,7 +257,7 @@ struct mongroup {
*/
struct pseudo_lock_region {
struct resctrl_schema *s;
- struct rdt_domain *d;
+ struct rdt_ctrl_domain *d;
u32 cbm;
wait_queue_head_t lock_thread_wq;
int thread_done;
@@ -355,25 +380,41 @@ struct arch_mbm_state {
};
/**
- * struct rdt_hw_domain - Arch private attributes of a set of CPUs that share
- * a resource
+ * struct rdt_hw_ctrl_domain - Arch private attributes of a set of CPUs that share
+ * a resource for a control function
* @d_resctrl: Properties exposed to the resctrl file system
* @ctrl_val: array of cache or mem ctrl values (indexed by CLOSID)
+ *
+ * Members of this structure are accessed via helpers that provide abstraction.
+ */
+struct rdt_hw_ctrl_domain {
+ struct rdt_ctrl_domain d_resctrl;
+ u32 *ctrl_val;
+};
+
+/**
+ * struct rdt_hw_mon_domain - Arch private attributes of a set of CPUs that share
+ * a resource for a monitor function
+ * @d_resctrl: Properties exposed to the resctrl file system
* @arch_mbm_total: arch private state for MBM total bandwidth
* @arch_mbm_local: arch private state for MBM local bandwidth
*
* Members of this structure are accessed via helpers that provide abstraction.
*/
-struct rdt_hw_domain {
- struct rdt_domain d_resctrl;
- u32 *ctrl_val;
+struct rdt_hw_mon_domain {
+ struct rdt_mon_domain d_resctrl;
struct arch_mbm_state *arch_mbm_total;
struct arch_mbm_state *arch_mbm_local;
};
-static inline struct rdt_hw_domain *resctrl_to_arch_dom(struct rdt_domain *r)
+static inline struct rdt_hw_ctrl_domain *resctrl_to_arch_ctrl_dom(struct rdt_ctrl_domain *r)
{
- return container_of(r, struct rdt_hw_domain, d_resctrl);
+ return container_of(r, struct rdt_hw_ctrl_domain, d_resctrl);
+}
+
+static inline struct rdt_hw_mon_domain *resctrl_to_arch_mon_dom(struct rdt_mon_domain *r)
+{
+ return container_of(r, struct rdt_hw_mon_domain, d_resctrl);
}
/**
@@ -385,7 +426,7 @@ static inline struct rdt_hw_domain *resctrl_to_arch_dom(struct rdt_domain *r)
*/
struct msr_param {
struct rdt_resource *res;
- struct rdt_domain *dom;
+ struct rdt_ctrl_domain *dom;
u32 low;
u32 high;
};
@@ -458,9 +499,9 @@ static inline struct rdt_hw_resource *resctrl_to_arch_res(struct rdt_resource *r
}
int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s,
- struct rdt_domain *d);
+ struct rdt_ctrl_domain *d);
int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s,
- struct rdt_domain *d);
+ struct rdt_ctrl_domain *d);
extern struct mutex rdtgroup_mutex;
@@ -493,6 +534,8 @@ static inline bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l)
int resctrl_arch_set_cdp_enabled(enum resctrl_res_level l, bool enable);
+void arch_mon_domain_online(struct rdt_resource *r, struct rdt_mon_domain *d);
+
/*
* To return the common struct rdt_resource, which is contained in struct
* rdt_hw_resource, walk the resctrl member of struct rdt_hw_resource.
@@ -558,27 +601,28 @@ void rdtgroup_kn_unlock(struct kernfs_node *kn);
int rdtgroup_kn_mode_restrict(struct rdtgroup *r, const char *name);
int rdtgroup_kn_mode_restore(struct rdtgroup *r, const char *name,
umode_t mask);
-struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
- struct list_head **pos);
+struct rdt_domain_hdr *rdt_find_domain(struct list_head *h, int id,
+ struct list_head **pos);
ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
char *buf, size_t nbytes, loff_t off);
int rdtgroup_schemata_show(struct kernfs_open_file *of,
struct seq_file *s, void *v);
-bool rdtgroup_cbm_overlaps(struct resctrl_schema *s, struct rdt_domain *d,
+bool rdtgroup_cbm_overlaps(struct resctrl_schema *s, struct rdt_ctrl_domain *d,
unsigned long cbm, int closid, bool exclusive);
-unsigned int rdtgroup_cbm_to_size(struct rdt_resource *r, struct rdt_domain *d,
+unsigned int rdtgroup_cbm_to_size(struct rdt_resource *r, struct rdt_ctrl_domain *d,
unsigned long cbm);
enum rdtgrp_mode rdtgroup_mode_by_closid(int closid);
int rdtgroup_tasks_assigned(struct rdtgroup *r);
int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp);
int rdtgroup_locksetup_exit(struct rdtgroup *rdtgrp);
-bool rdtgroup_cbm_overlaps_pseudo_locked(struct rdt_domain *d, unsigned long cbm);
-bool rdtgroup_pseudo_locked_in_hierarchy(struct rdt_domain *d);
+bool rdtgroup_cbm_overlaps_pseudo_locked(struct rdt_ctrl_domain *d, unsigned long cbm);
+bool rdtgroup_pseudo_locked_in_hierarchy(struct rdt_ctrl_domain *d);
int rdt_pseudo_lock_init(void);
void rdt_pseudo_lock_release(void);
int rdtgroup_pseudo_lock_create(struct rdtgroup *rdtgrp);
void rdtgroup_pseudo_lock_remove(struct rdtgroup *rdtgrp);
-struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r);
+struct rdt_ctrl_domain *get_ctrl_domain_from_cpu(int cpu, struct rdt_resource *r);
+struct rdt_mon_domain *get_mon_domain_from_cpu(int cpu, struct rdt_resource *r);
int closids_supported(void);
void closid_free(int closid);
int alloc_rmid(u32 closid);
@@ -589,19 +633,19 @@ bool __init rdt_cpu_has(int flag);
void mon_event_count(void *info);
int rdtgroup_mondata_show(struct seq_file *m, void *arg);
void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
- struct rdt_domain *d, struct rdtgroup *rdtgrp,
- int evtid, int first);
-void mbm_setup_overflow_handler(struct rdt_domain *dom,
+ struct rdt_mon_domain *d, struct rdtgroup *rdtgrp,
+ cpumask_t *cpumask, int evtid, int first);
+void mbm_setup_overflow_handler(struct rdt_mon_domain *dom,
unsigned long delay_ms,
int exclude_cpu);
void mbm_handle_overflow(struct work_struct *work);
void __init intel_rdt_mbm_apply_quirk(void);
bool is_mba_sc(struct rdt_resource *r);
-void cqm_setup_limbo_handler(struct rdt_domain *dom, unsigned long delay_ms,
+void cqm_setup_limbo_handler(struct rdt_mon_domain *dom, unsigned long delay_ms,
int exclude_cpu);
void cqm_handle_limbo(struct work_struct *work);
-bool has_busy_rmid(struct rdt_domain *d);
-void __check_limbo(struct rdt_domain *d, bool force_free);
+bool has_busy_rmid(struct rdt_mon_domain *d);
+void __check_limbo(struct rdt_mon_domain *d, bool force_free);
void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
void __init thread_throttle_mode_init(void);
void __init mbm_config_rftype_init(const char *config);
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index 366f496ca3ce..851b561850e0 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -15,6 +15,8 @@
* Software Developer Manual June 2016, volume 3, section 17.17.
*/
+#define pr_fmt(fmt) "resctrl: " fmt
+
#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/sizes.h>
@@ -97,6 +99,8 @@ unsigned int resctrl_rmid_realloc_limit;
#define CF(cf) ((unsigned long)(1048576 * (cf) + 0.5))
+static int snc_nodes_per_l3_cache = 1;
+
/*
* The correction factor table is documented in Documentation/arch/x86/resctrl.rst.
* If rmid > rmid threshold, MBM total and local values should be multiplied
@@ -185,7 +189,43 @@ static inline struct rmid_entry *__rmid_entry(u32 idx)
return entry;
}
-static int __rmid_read(u32 rmid, enum resctrl_event_id eventid, u64 *val)
+/*
+ * When Sub-NUMA Cluster (SNC) mode is not enabled (as indicated by
+ * "snc_nodes_per_l3_cache == 1") no translation of the RMID value is
+ * needed. The physical RMID is the same as the logical RMID.
+ *
+ * On a platform with SNC mode enabled, Linux enables RMID sharing mode
+ * via MSR 0xCA0 (see the "RMID Sharing Mode" section in the "Intel
+ * Resource Director Technology Architecture Specification" for a full
+ * description of RMID sharing mode).
+ *
+ * In RMID sharing mode there are fewer "logical RMID" values available
+ * to accumulate data ("physical RMIDs" are divided evenly between SNC
+ * nodes that share an L3 cache). Linux creates an rdt_mon_domain for
+ * each SNC node.
+ *
+ * The value loaded into IA32_PQR_ASSOC is the "logical RMID".
+ *
+ * Data is collected independently on each SNC node and can be retrieved
+ * using the "physical RMID" value computed by this function and loaded
+ * into IA32_QM_EVTSEL. @cpu can be any CPU in the SNC node.
+ *
+ * The scope of the IA32_QM_EVTSEL and IA32_QM_CTR MSRs is at the L3
+ * cache. So a "physical RMID" may be read from any CPU that shares
+ * the L3 cache with the desired SNC node, not just from a CPU in
+ * the specific SNC node.
+ */
+static int logical_rmid_to_physical_rmid(int cpu, int lrmid)
+{
+ struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl;
+
+ if (snc_nodes_per_l3_cache == 1)
+ return lrmid;
+
+ return lrmid + (cpu_to_node(cpu) % snc_nodes_per_l3_cache) * r->num_rmid;
+}
+
+static int __rmid_read_phys(u32 prmid, enum resctrl_event_id eventid, u64 *val)
{
u64 msr_val;
@@ -197,7 +237,7 @@ static int __rmid_read(u32 rmid, enum resctrl_event_id eventid, u64 *val)
* IA32_QM_CTR.Error (bit 63) and IA32_QM_CTR.Unavailable (bit 62)
* are error bits.
*/
- wrmsr(MSR_IA32_QM_EVTSEL, eventid, rmid);
+ wrmsr(MSR_IA32_QM_EVTSEL, eventid, prmid);
rdmsrl(MSR_IA32_QM_CTR, msr_val);
if (msr_val & RMID_VAL_ERROR)
@@ -209,7 +249,7 @@ static int __rmid_read(u32 rmid, enum resctrl_event_id eventid, u64 *val)
return 0;
}
-static struct arch_mbm_state *get_arch_mbm_state(struct rdt_hw_domain *hw_dom,
+static struct arch_mbm_state *get_arch_mbm_state(struct rdt_hw_mon_domain *hw_dom,
u32 rmid,
enum resctrl_event_id eventid)
{
@@ -228,19 +268,22 @@ static struct arch_mbm_state *get_arch_mbm_state(struct rdt_hw_domain *hw_dom,
return NULL;
}
-void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_domain *d,
+void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_mon_domain *d,
u32 unused, u32 rmid,
enum resctrl_event_id eventid)
{
- struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
+ struct rdt_hw_mon_domain *hw_dom = resctrl_to_arch_mon_dom(d);
+ int cpu = cpumask_any(&d->hdr.cpu_mask);
struct arch_mbm_state *am;
+ u32 prmid;
am = get_arch_mbm_state(hw_dom, rmid, eventid);
if (am) {
memset(am, 0, sizeof(*am));
+ prmid = logical_rmid_to_physical_rmid(cpu, rmid);
/* Record any initial, non-zero count value. */
- __rmid_read(rmid, eventid, &am->prev_msr);
+ __rmid_read_phys(prmid, eventid, &am->prev_msr);
}
}
@@ -248,9 +291,9 @@ void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_domain *d,
* Assumes that hardware counters are also reset and thus that there is
* no need to record initial non-zero counts.
*/
-void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_domain *d)
+void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain *d)
{
- struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
+ struct rdt_hw_mon_domain *hw_dom = resctrl_to_arch_mon_dom(d);
if (is_mbm_total_enabled())
memset(hw_dom->arch_mbm_total, 0,
@@ -269,22 +312,22 @@ static u64 mbm_overflow_count(u64 prev_msr, u64 cur_msr, unsigned int width)
return chunks >> shift;
}
-int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain *d,
+int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_mon_domain *d,
u32 unused, u32 rmid, enum resctrl_event_id eventid,
u64 *val, void *ignored)
{
+ struct rdt_hw_mon_domain *hw_dom = resctrl_to_arch_mon_dom(d);
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
- struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d);
+ int cpu = cpumask_any(&d->hdr.cpu_mask);
struct arch_mbm_state *am;
u64 msr_val, chunks;
+ u32 prmid;
int ret;
resctrl_arch_rmid_read_context_check();
- if (!cpumask_test_cpu(smp_processor_id(), &d->cpu_mask))
- return -EINVAL;
-
- ret = __rmid_read(rmid, eventid, &msr_val);
+ prmid = logical_rmid_to_physical_rmid(cpu, rmid);
+ ret = __rmid_read_phys(prmid, eventid, &msr_val);
if (ret)
return ret;
@@ -320,7 +363,7 @@ static void limbo_release_entry(struct rmid_entry *entry)
* decrement the count. If the busy count gets to zero on an RMID, we
* free the RMID
*/
-void __check_limbo(struct rdt_domain *d, bool force_free)
+void __check_limbo(struct rdt_mon_domain *d, bool force_free)
{
struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl;
u32 idx_limit = resctrl_arch_system_num_rmid_idx();
@@ -364,7 +407,7 @@ void __check_limbo(struct rdt_domain *d, bool force_free)
* CLOSID and RMID because there may be dependencies between them
* on some architectures.
*/
- trace_mon_llc_occupancy_limbo(entry->closid, entry->rmid, d->id, val);
+ trace_mon_llc_occupancy_limbo(entry->closid, entry->rmid, d->hdr.id, val);
}
if (force_free || !rmid_dirty) {
@@ -378,7 +421,7 @@ void __check_limbo(struct rdt_domain *d, bool force_free)
resctrl_arch_mon_ctx_free(r, QOS_L3_OCCUP_EVENT_ID, arch_mon_ctx);
}
-bool has_busy_rmid(struct rdt_domain *d)
+bool has_busy_rmid(struct rdt_mon_domain *d)
{
u32 idx_limit = resctrl_arch_system_num_rmid_idx();
@@ -479,7 +522,7 @@ int alloc_rmid(u32 closid)
static void add_rmid_to_limbo(struct rmid_entry *entry)
{
struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl;
- struct rdt_domain *d;
+ struct rdt_mon_domain *d;
u32 idx;
lockdep_assert_held(&rdtgroup_mutex);
@@ -490,7 +533,7 @@ static void add_rmid_to_limbo(struct rmid_entry *entry)
idx = resctrl_arch_rmid_idx_encode(entry->closid, entry->rmid);
entry->busy = 0;
- list_for_each_entry(d, &r->domains, list) {
+ list_for_each_entry(d, &r->mon_domains, hdr.list) {
/*
* For the first limbo RMID in the domain,
* setup up the limbo worker.
@@ -532,7 +575,7 @@ void free_rmid(u32 closid, u32 rmid)
list_add_tail(&entry->list, &rmid_free_lru);
}
-static struct mbm_state *get_mbm_state(struct rdt_domain *d, u32 closid,
+static struct mbm_state *get_mbm_state(struct rdt_mon_domain *d, u32 closid,
u32 rmid, enum resctrl_event_id evtid)
{
u32 idx = resctrl_arch_rmid_idx_encode(closid, rmid);
@@ -549,7 +592,10 @@ static struct mbm_state *get_mbm_state(struct rdt_domain *d, u32 closid,
static int __mon_event_count(u32 closid, u32 rmid, struct rmid_read *rr)
{
+ int cpu = smp_processor_id();
+ struct rdt_mon_domain *d;
struct mbm_state *m;
+ int err, ret;
u64 tval = 0;
if (rr->first) {
@@ -560,14 +606,47 @@ static int __mon_event_count(u32 closid, u32 rmid, struct rmid_read *rr)
return 0;
}
- rr->err = resctrl_arch_rmid_read(rr->r, rr->d, closid, rmid, rr->evtid,
- &tval, rr->arch_mon_ctx);
- if (rr->err)
- return rr->err;
+ if (rr->d) {
+ /* Reading a single domain, must be on a CPU in that domain. */
+ if (!cpumask_test_cpu(cpu, &rr->d->hdr.cpu_mask))
+ return -EINVAL;
+ rr->err = resctrl_arch_rmid_read(rr->r, rr->d, closid, rmid,
+ rr->evtid, &tval, rr->arch_mon_ctx);
+ if (rr->err)
+ return rr->err;
- rr->val += tval;
+ rr->val += tval;
- return 0;
+ return 0;
+ }
+
+ /* Summing domains that share a cache, must be on a CPU for that cache. */
+ if (!cpumask_test_cpu(cpu, &rr->ci->shared_cpu_map))
+ return -EINVAL;
+
+ /*
+ * Legacy files must report the sum of an event across all
+ * domains that share the same L3 cache instance.
+ * Report success if a read from any domain succeeds, -EINVAL
+ * (translated to "Unavailable" for user space) if reading from
+ * all domains fail for any reason.
+ */
+ ret = -EINVAL;
+ list_for_each_entry(d, &rr->r->mon_domains, hdr.list) {
+ if (d->ci->id != rr->ci->id)
+ continue;
+ err = resctrl_arch_rmid_read(rr->r, d, closid, rmid,
+ rr->evtid, &tval, rr->arch_mon_ctx);
+ if (!err) {
+ rr->val += tval;
+ ret = 0;
+ }
+ }
+
+ if (ret)
+ rr->err = ret;
+
+ return ret;
}
/*
@@ -668,12 +747,12 @@ void mon_event_count(void *info)
* throttle MSRs already have low percentage values. To avoid
* unnecessarily restricting such rdtgroups, we also increase the bandwidth.
*/
-static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
+static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_mon_domain *dom_mbm)
{
u32 closid, rmid, cur_msr_val, new_msr_val;
struct mbm_state *pmbm_data, *cmbm_data;
+ struct rdt_ctrl_domain *dom_mba;
struct rdt_resource *r_mba;
- struct rdt_domain *dom_mba;
u32 cur_bw, user_bw, idx;
struct list_head *head;
struct rdtgroup *entry;
@@ -688,7 +767,7 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
idx = resctrl_arch_rmid_idx_encode(closid, rmid);
pmbm_data = &dom_mbm->mbm_local[idx];
- dom_mba = get_domain_from_cpu(smp_processor_id(), r_mba);
+ dom_mba = get_ctrl_domain_from_cpu(smp_processor_id(), r_mba);
if (!dom_mba) {
pr_warn_once("Failure to get domain for MBA update\n");
return;
@@ -734,12 +813,11 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
resctrl_arch_update_one(r_mba, dom_mba, closid, CDP_NONE, new_msr_val);
}
-static void mbm_update(struct rdt_resource *r, struct rdt_domain *d,
+static void mbm_update(struct rdt_resource *r, struct rdt_mon_domain *d,
u32 closid, u32 rmid)
{
- struct rmid_read rr;
+ struct rmid_read rr = {0};
- rr.first = false;
rr.r = r;
rr.d = d;
@@ -792,17 +870,17 @@ static void mbm_update(struct rdt_resource *r, struct rdt_domain *d,
void cqm_handle_limbo(struct work_struct *work)
{
unsigned long delay = msecs_to_jiffies(CQM_LIMBOCHECK_INTERVAL);
- struct rdt_domain *d;
+ struct rdt_mon_domain *d;
cpus_read_lock();
mutex_lock(&rdtgroup_mutex);
- d = container_of(work, struct rdt_domain, cqm_limbo.work);
+ d = container_of(work, struct rdt_mon_domain, cqm_limbo.work);
__check_limbo(d, false);
if (has_busy_rmid(d)) {
- d->cqm_work_cpu = cpumask_any_housekeeping(&d->cpu_mask,
+ d->cqm_work_cpu = cpumask_any_housekeeping(&d->hdr.cpu_mask,
RESCTRL_PICK_ANY_CPU);
schedule_delayed_work_on(d->cqm_work_cpu, &d->cqm_limbo,
delay);
@@ -820,13 +898,13 @@ void cqm_handle_limbo(struct work_struct *work)
* @exclude_cpu: Which CPU the handler should not run on,
* RESCTRL_PICK_ANY_CPU to pick any CPU.
*/
-void cqm_setup_limbo_handler(struct rdt_domain *dom, unsigned long delay_ms,
+void cqm_setup_limbo_handler(struct rdt_mon_domain *dom, unsigned long delay_ms,
int exclude_cpu)
{
unsigned long delay = msecs_to_jiffies(delay_ms);
int cpu;
- cpu = cpumask_any_housekeeping(&dom->cpu_mask, exclude_cpu);
+ cpu = cpumask_any_housekeeping(&dom->hdr.cpu_mask, exclude_cpu);
dom->cqm_work_cpu = cpu;
if (cpu < nr_cpu_ids)
@@ -837,9 +915,9 @@ void mbm_handle_overflow(struct work_struct *work)
{
unsigned long delay = msecs_to_jiffies(MBM_OVERFLOW_INTERVAL);
struct rdtgroup *prgrp, *crgrp;
+ struct rdt_mon_domain *d;
struct list_head *head;
struct rdt_resource *r;
- struct rdt_domain *d;
cpus_read_lock();
mutex_lock(&rdtgroup_mutex);
@@ -852,7 +930,7 @@ void mbm_handle_overflow(struct work_struct *work)
goto out_unlock;
r = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl;
- d = container_of(work, struct rdt_domain, mbm_over.work);
+ d = container_of(work, struct rdt_mon_domain, mbm_over.work);
list_for_each_entry(prgrp, &rdt_all_groups, rdtgroup_list) {
mbm_update(r, d, prgrp->closid, prgrp->mon.rmid);
@@ -869,7 +947,7 @@ void mbm_handle_overflow(struct work_struct *work)
* Re-check for housekeeping CPUs. This allows the overflow handler to
* move off a nohz_full CPU quickly.
*/
- d->mbm_work_cpu = cpumask_any_housekeeping(&d->cpu_mask,
+ d->mbm_work_cpu = cpumask_any_housekeeping(&d->hdr.cpu_mask,
RESCTRL_PICK_ANY_CPU);
schedule_delayed_work_on(d->mbm_work_cpu, &d->mbm_over, delay);
@@ -886,7 +964,7 @@ out_unlock:
* @exclude_cpu: Which CPU the handler should not run on,
* RESCTRL_PICK_ANY_CPU to pick any CPU.
*/
-void mbm_setup_overflow_handler(struct rdt_domain *dom, unsigned long delay_ms,
+void mbm_setup_overflow_handler(struct rdt_mon_domain *dom, unsigned long delay_ms,
int exclude_cpu)
{
unsigned long delay = msecs_to_jiffies(delay_ms);
@@ -898,7 +976,7 @@ void mbm_setup_overflow_handler(struct rdt_domain *dom, unsigned long delay_ms,
*/
if (!resctrl_mounted || !resctrl_arch_mon_capable())
return;
- cpu = cpumask_any_housekeeping(&dom->cpu_mask, exclude_cpu);
+ cpu = cpumask_any_housekeeping(&dom->hdr.cpu_mask, exclude_cpu);
dom->mbm_work_cpu = cpu;
if (cpu < nr_cpu_ids)
@@ -1015,6 +1093,88 @@ static void l3_mon_evt_init(struct rdt_resource *r)
list_add_tail(&mbm_local_event.list, &r->evt_list);
}
+/*
+ * The power-on reset value of MSR_RMID_SNC_CONFIG is 0x1
+ * which indicates that RMIDs are configured in legacy mode.
+ * This mode is incompatible with Linux resctrl semantics
+ * as RMIDs are partitioned between SNC nodes, which requires
+ * a user to know which RMID is allocated to a task.
+ * Clearing bit 0 reconfigures the RMID counters for use
+ * in RMID sharing mode. This mode is better for Linux.
+ * The RMID space is divided between all SNC nodes with the
+ * RMIDs renumbered to start from zero in each node when
+ * counting operations from tasks. Code to read the counters
+ * must adjust RMID counter numbers based on SNC node. See
+ * logical_rmid_to_physical_rmid() for code that does this.
+ */
+void arch_mon_domain_online(struct rdt_resource *r, struct rdt_mon_domain *d)
+{
+ if (snc_nodes_per_l3_cache > 1)
+ msr_clear_bit(MSR_RMID_SNC_CONFIG, 0);
+}
+
+/* CPU models that support MSR_RMID_SNC_CONFIG */
+static const struct x86_cpu_id snc_cpu_ids[] __initconst = {
+ X86_MATCH_VFM(INTEL_ICELAKE_X, 0),
+ X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, 0),
+ X86_MATCH_VFM(INTEL_EMERALDRAPIDS_X, 0),
+ X86_MATCH_VFM(INTEL_GRANITERAPIDS_X, 0),
+ X86_MATCH_VFM(INTEL_ATOM_CRESTMONT_X, 0),
+ {}
+};
+
+/*
+ * There isn't a simple hardware bit that indicates whether a CPU is running
+ * in Sub-NUMA Cluster (SNC) mode. Infer the state by comparing the
+ * number of CPUs sharing the L3 cache with CPU0 to the number of CPUs in
+ * the same NUMA node as CPU0.
+ * It is not possible to accurately determine SNC state if the system is
+ * booted with a maxcpus=N parameter. That distorts the ratio of SNC nodes
+ * to L3 caches. It will be OK if system is booted with hyperthreading
+ * disabled (since this doesn't affect the ratio).
+ */
+static __init int snc_get_config(void)
+{
+ struct cacheinfo *ci = get_cpu_cacheinfo_level(0, RESCTRL_L3_CACHE);
+ const cpumask_t *node0_cpumask;
+ int cpus_per_node, cpus_per_l3;
+ int ret;
+
+ if (!x86_match_cpu(snc_cpu_ids) || !ci)
+ return 1;
+
+ cpus_read_lock();
+ if (num_online_cpus() != num_present_cpus())
+ pr_warn("Some CPUs offline, SNC detection may be incorrect\n");
+ cpus_read_unlock();
+
+ node0_cpumask = cpumask_of_node(cpu_to_node(0));
+
+ cpus_per_node = cpumask_weight(node0_cpumask);
+ cpus_per_l3 = cpumask_weight(&ci->shared_cpu_map);
+
+ if (!cpus_per_node || !cpus_per_l3)
+ return 1;
+
+ ret = cpus_per_l3 / cpus_per_node;
+
+ /* sanity check: Only valid results are 1, 2, 3, 4 */
+ switch (ret) {
+ case 1:
+ break;
+ case 2 ... 4:
+ 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;
+ default:
+ pr_warn("Ignore improbable SNC node count %d\n", ret);
+ ret = 1;
+ break;
+ }
+
+ return ret;
+}
+
int __init rdt_get_mon_l3_config(struct rdt_resource *r)
{
unsigned int mbm_offset = boot_cpu_data.x86_cache_mbm_width_offset;
@@ -1022,9 +1182,11 @@ int __init rdt_get_mon_l3_config(struct rdt_resource *r)
unsigned int threshold;
int ret;
+ snc_nodes_per_l3_cache = snc_get_config();
+
resctrl_rmid_realloc_limit = boot_cpu_data.x86_cache_size * 1024;
- hw_res->mon_scale = boot_cpu_data.x86_cache_occ_scale;
- r->num_rmid = boot_cpu_data.x86_cache_max_rmid + 1;
+ hw_res->mon_scale = boot_cpu_data.x86_cache_occ_scale / snc_nodes_per_l3_cache;
+ r->num_rmid = (boot_cpu_data.x86_cache_max_rmid + 1) / snc_nodes_per_l3_cache;
hw_res->mbm_width = MBM_CNTR_WIDTH_BASE;
if (mbm_offset > 0 && mbm_offset <= MBM_CNTR_WIDTH_OFFSET_MAX)
diff --git a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c
index aacf236dfe3b..e69489d48625 100644
--- a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c
+++ b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c
@@ -11,7 +11,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/cacheinfo.h>
#include <linux/cpu.h>
#include <linux/cpumask.h>
#include <linux/debugfs.h>
@@ -221,7 +220,7 @@ static int pseudo_lock_cstates_constrain(struct pseudo_lock_region *plr)
int cpu;
int ret;
- for_each_cpu(cpu, &plr->d->cpu_mask) {
+ for_each_cpu(cpu, &plr->d->hdr.cpu_mask) {
pm_req = kzalloc(sizeof(*pm_req), GFP_KERNEL);
if (!pm_req) {
rdt_last_cmd_puts("Failure to allocate memory for PM QoS\n");
@@ -292,12 +291,15 @@ static void pseudo_lock_region_clear(struct pseudo_lock_region *plr)
*/
static int pseudo_lock_region_init(struct pseudo_lock_region *plr)
{
- struct cpu_cacheinfo *ci;
+ enum resctrl_scope scope = plr->s->res->ctrl_scope;
+ struct cacheinfo *ci;
int ret;
- int i;
+
+ if (WARN_ON_ONCE(scope != RESCTRL_L2_CACHE && scope != RESCTRL_L3_CACHE))
+ return -ENODEV;
/* Pick the first cpu we find that is associated with the cache. */
- plr->cpu = cpumask_first(&plr->d->cpu_mask);
+ plr->cpu = cpumask_first(&plr->d->hdr.cpu_mask);
if (!cpu_online(plr->cpu)) {
rdt_last_cmd_printf("CPU %u associated with cache not online\n",
@@ -306,15 +308,11 @@ static int pseudo_lock_region_init(struct pseudo_lock_region *plr)
goto out_region;
}
- ci = get_cpu_cacheinfo(plr->cpu);
-
- plr->size = rdtgroup_cbm_to_size(plr->s->res, plr->d, plr->cbm);
-
- for (i = 0; i < ci->num_leaves; i++) {
- if (ci->info_list[i].level == plr->s->res->cache_level) {
- plr->line_size = ci->info_list[i].coherency_line_size;
- return 0;
- }
+ ci = get_cpu_cacheinfo_level(plr->cpu, scope);
+ if (ci) {
+ plr->line_size = ci->coherency_line_size;
+ plr->size = rdtgroup_cbm_to_size(plr->s->res, plr->d, plr->cbm);
+ return 0;
}
ret = -1;
@@ -810,7 +808,7 @@ int rdtgroup_locksetup_exit(struct rdtgroup *rdtgrp)
* Return: true if @cbm overlaps with pseudo-locked region on @d, false
* otherwise.
*/
-bool rdtgroup_cbm_overlaps_pseudo_locked(struct rdt_domain *d, unsigned long cbm)
+bool rdtgroup_cbm_overlaps_pseudo_locked(struct rdt_ctrl_domain *d, unsigned long cbm)
{
unsigned int cbm_len;
unsigned long cbm_b;
@@ -837,11 +835,11 @@ bool rdtgroup_cbm_overlaps_pseudo_locked(struct rdt_domain *d, unsigned long cbm
* if it is not possible to test due to memory allocation issue,
* false otherwise.
*/
-bool rdtgroup_pseudo_locked_in_hierarchy(struct rdt_domain *d)
+bool rdtgroup_pseudo_locked_in_hierarchy(struct rdt_ctrl_domain *d)
{
+ struct rdt_ctrl_domain *d_i;
cpumask_var_t cpu_with_psl;
struct rdt_resource *r;
- struct rdt_domain *d_i;
bool ret = false;
/* Walking r->domains, ensure it can't race with cpuhp */
@@ -855,10 +853,10 @@ bool rdtgroup_pseudo_locked_in_hierarchy(struct rdt_domain *d)
* associated with them.
*/
for_each_alloc_capable_rdt_resource(r) {
- list_for_each_entry(d_i, &r->domains, list) {
+ list_for_each_entry(d_i, &r->ctrl_domains, hdr.list) {
if (d_i->plr)
cpumask_or(cpu_with_psl, cpu_with_psl,
- &d_i->cpu_mask);
+ &d_i->hdr.cpu_mask);
}
}
@@ -866,7 +864,7 @@ bool rdtgroup_pseudo_locked_in_hierarchy(struct rdt_domain *d)
* Next test if new pseudo-locked region would intersect with
* existing region.
*/
- if (cpumask_intersects(&d->cpu_mask, cpu_with_psl))
+ if (cpumask_intersects(&d->hdr.cpu_mask, cpu_with_psl))
ret = true;
free_cpumask_var(cpu_with_psl);
@@ -1198,7 +1196,7 @@ static int pseudo_lock_measure_cycles(struct rdtgroup *rdtgrp, int sel)
}
plr->thread_done = 0;
- cpu = cpumask_first(&plr->d->cpu_mask);
+ cpu = cpumask_first(&plr->d->hdr.cpu_mask);
if (!cpu_online(cpu)) {
ret = -ENODEV;
goto out;
@@ -1528,7 +1526,7 @@ static int pseudo_lock_dev_mmap(struct file *filp, struct vm_area_struct *vma)
* may be scheduled elsewhere and invalidate entries in the
* pseudo-locked region.
*/
- if (!cpumask_subset(current->cpus_ptr, &plr->d->cpu_mask)) {
+ if (!cpumask_subset(current->cpus_ptr, &plr->d->hdr.cpu_mask)) {
mutex_unlock(&rdtgroup_mutex);
return -EINVAL;
}
diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
index 02f213f1c51c..d7163b764c62 100644
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -12,7 +12,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/cacheinfo.h>
#include <linux/cpu.h>
#include <linux/debugfs.h>
#include <linux/fs.h>
@@ -92,13 +91,13 @@ void rdt_last_cmd_printf(const char *fmt, ...)
void rdt_staged_configs_clear(void)
{
+ struct rdt_ctrl_domain *dom;
struct rdt_resource *r;
- struct rdt_domain *dom;
lockdep_assert_held(&rdtgroup_mutex);
for_each_alloc_capable_rdt_resource(r) {
- list_for_each_entry(dom, &r->domains, list)
+ list_for_each_entry(dom, &r->ctrl_domains, hdr.list)
memset(dom->staged_config, 0, sizeof(dom->staged_config));
}
}
@@ -317,7 +316,7 @@ static int rdtgroup_cpus_show(struct kernfs_open_file *of,
rdt_last_cmd_puts("Cache domain offline\n");
ret = -ENODEV;
} else {
- mask = &rdtgrp->plr->d->cpu_mask;
+ mask = &rdtgrp->plr->d->hdr.cpu_mask;
seq_printf(s, is_cpu_list(of) ?
"%*pbl\n" : "%*pb\n",
cpumask_pr_args(mask));
@@ -1012,7 +1011,7 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of,
unsigned long sw_shareable = 0, hw_shareable = 0;
unsigned long exclusive = 0, pseudo_locked = 0;
struct rdt_resource *r = s->res;
- struct rdt_domain *dom;
+ struct rdt_ctrl_domain *dom;
int i, hwb, swb, excl, psl;
enum rdtgrp_mode mode;
bool sep = false;
@@ -1021,12 +1020,12 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of,
cpus_read_lock();
mutex_lock(&rdtgroup_mutex);
hw_shareable = r->cache.shareable_bits;
- list_for_each_entry(dom, &r->domains, list) {
+ list_for_each_entry(dom, &r->ctrl_domains, hdr.list) {
if (sep)
seq_putc(seq, ';');
sw_shareable = 0;
exclusive = 0;
- seq_printf(seq, "%d=", dom->id);
+ seq_printf(seq, "%d=", dom->hdr.id);
for (i = 0; i < closids_supported(); i++) {
if (!closid_allocated(i))
continue;
@@ -1243,7 +1242,7 @@ static int rdt_has_sparse_bitmasks_show(struct kernfs_open_file *of,
*
* Return: false if CBM does not overlap, true if it does.
*/
-static bool __rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d,
+static bool __rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_ctrl_domain *d,
unsigned long cbm, int closid,
enum resctrl_conf_type type, bool exclusive)
{
@@ -1298,7 +1297,7 @@ static bool __rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d
*
* Return: true if CBM overlap detected, false if there is no overlap
*/
-bool rdtgroup_cbm_overlaps(struct resctrl_schema *s, struct rdt_domain *d,
+bool rdtgroup_cbm_overlaps(struct resctrl_schema *s, struct rdt_ctrl_domain *d,
unsigned long cbm, int closid, bool exclusive)
{
enum resctrl_conf_type peer_type = resctrl_peer_type(s->conf_type);
@@ -1329,10 +1328,10 @@ bool rdtgroup_cbm_overlaps(struct resctrl_schema *s, struct rdt_domain *d,
static bool rdtgroup_mode_test_exclusive(struct rdtgroup *rdtgrp)
{
int closid = rdtgrp->closid;
+ struct rdt_ctrl_domain *d;
struct resctrl_schema *s;
struct rdt_resource *r;
bool has_cache = false;
- struct rdt_domain *d;
u32 ctrl;
/* Walking r->domains, ensure it can't race with cpuhp */
@@ -1343,7 +1342,7 @@ static bool rdtgroup_mode_test_exclusive(struct rdtgroup *rdtgrp)
if (r->rid == RDT_RESOURCE_MBA || r->rid == RDT_RESOURCE_SMBA)
continue;
has_cache = true;
- list_for_each_entry(d, &r->domains, list) {
+ list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
ctrl = resctrl_arch_get_config(r, d, closid,
s->conf_type);
if (rdtgroup_cbm_overlaps(s, d, ctrl, closid, false)) {
@@ -1448,20 +1447,19 @@ out:
* bitmap functions work correctly.
*/
unsigned int rdtgroup_cbm_to_size(struct rdt_resource *r,
- struct rdt_domain *d, unsigned long cbm)
+ struct rdt_ctrl_domain *d, unsigned long cbm)
{
- struct cpu_cacheinfo *ci;
unsigned int size = 0;
- int num_b, i;
+ struct cacheinfo *ci;
+ int num_b;
+
+ if (WARN_ON_ONCE(r->ctrl_scope != RESCTRL_L2_CACHE && r->ctrl_scope != RESCTRL_L3_CACHE))
+ return size;
num_b = bitmap_weight(&cbm, r->cache.cbm_len);
- ci = get_cpu_cacheinfo(cpumask_any(&d->cpu_mask));
- for (i = 0; i < ci->num_leaves; i++) {
- if (ci->info_list[i].level == r->cache_level) {
- size = ci->info_list[i].size / r->cache.cbm_len * num_b;
- break;
- }
- }
+ ci = get_cpu_cacheinfo_level(cpumask_any(&d->hdr.cpu_mask), r->ctrl_scope);
+ if (ci)
+ size = ci->size / r->cache.cbm_len * num_b;
return size;
}
@@ -1477,9 +1475,9 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
{
struct resctrl_schema *schema;
enum resctrl_conf_type type;
+ struct rdt_ctrl_domain *d;
struct rdtgroup *rdtgrp;
struct rdt_resource *r;
- struct rdt_domain *d;
unsigned int size;
int ret = 0;
u32 closid;
@@ -1503,7 +1501,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
size = rdtgroup_cbm_to_size(rdtgrp->plr->s->res,
rdtgrp->plr->d,
rdtgrp->plr->cbm);
- seq_printf(s, "%d=%u\n", rdtgrp->plr->d->id, size);
+ seq_printf(s, "%d=%u\n", rdtgrp->plr->d->hdr.id, size);
}
goto out;
}
@@ -1515,7 +1513,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
type = schema->conf_type;
sep = false;
seq_printf(s, "%*s:", max_name_width, schema->name);
- list_for_each_entry(d, &r->domains, list) {
+ list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
if (sep)
seq_putc(s, ';');
if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
@@ -1533,7 +1531,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
else
size = rdtgroup_cbm_to_size(r, d, ctrl);
}
- seq_printf(s, "%d=%u", d->id, size);
+ seq_printf(s, "%d=%u", d->hdr.id, size);
sep = true;
}
seq_putc(s, '\n');
@@ -1591,21 +1589,21 @@ static void mon_event_config_read(void *info)
mon_info->mon_config = msrval & MAX_EVT_CONFIG_BITS;
}
-static void mondata_config_read(struct rdt_domain *d, struct mon_config_info *mon_info)
+static void mondata_config_read(struct rdt_mon_domain *d, struct mon_config_info *mon_info)
{
- smp_call_function_any(&d->cpu_mask, mon_event_config_read, mon_info, 1);
+ smp_call_function_any(&d->hdr.cpu_mask, mon_event_config_read, mon_info, 1);
}
static int mbm_config_show(struct seq_file *s, struct rdt_resource *r, u32 evtid)
{
struct mon_config_info mon_info = {0};
- struct rdt_domain *dom;
+ struct rdt_mon_domain *dom;
bool sep = false;
cpus_read_lock();
mutex_lock(&rdtgroup_mutex);
- list_for_each_entry(dom, &r->domains, list) {
+ list_for_each_entry(dom, &r->mon_domains, hdr.list) {
if (sep)
seq_puts(s, ";");
@@ -1613,7 +1611,7 @@ static int mbm_config_show(struct seq_file *s, struct rdt_resource *r, u32 evtid
mon_info.evtid = evtid;
mondata_config_read(dom, &mon_info);
- seq_printf(s, "%d=0x%02x", dom->id, mon_info.mon_config);
+ seq_printf(s, "%d=0x%02x", dom->hdr.id, mon_info.mon_config);
sep = true;
}
seq_puts(s, "\n");
@@ -1658,7 +1656,7 @@ static void mon_event_config_write(void *info)
}
static void mbm_config_write_domain(struct rdt_resource *r,
- struct rdt_domain *d, u32 evtid, u32 val)
+ struct rdt_mon_domain *d, u32 evtid, u32 val)
{
struct mon_config_info mon_info = {0};
@@ -1679,7 +1677,7 @@ static void mbm_config_write_domain(struct rdt_resource *r,
* are scoped at the domain level. Writing any of these MSRs
* on one CPU is observed by all the CPUs in the domain.
*/
- smp_call_function_any(&d->cpu_mask, mon_event_config_write,
+ smp_call_function_any(&d->hdr.cpu_mask, mon_event_config_write,
&mon_info, 1);
/*
@@ -1699,7 +1697,7 @@ static int mon_config_write(struct rdt_resource *r, char *tok, u32 evtid)
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
char *dom_str = NULL, *id_str;
unsigned long dom_id, val;
- struct rdt_domain *d;
+ struct rdt_mon_domain *d;
/* Walking r->domains, ensure it can't race with cpuhp */
lockdep_assert_cpus_held();
@@ -1729,8 +1727,8 @@ next:
return -EINVAL;
}
- list_for_each_entry(d, &r->domains, list) {
- if (d->id == dom_id) {
+ list_for_each_entry(d, &r->mon_domains, hdr.list) {
+ if (d->hdr.id == dom_id) {
mbm_config_write_domain(r, d, evtid, val);
goto next;
}
@@ -2258,9 +2256,9 @@ static inline bool is_mba_linear(void)
static int set_cache_qos_cfg(int level, bool enable)
{
void (*update)(void *arg);
+ struct rdt_ctrl_domain *d;
struct rdt_resource *r_l;
cpumask_var_t cpu_mask;
- struct rdt_domain *d;
int cpu;
/* Walking r->domains, ensure it can't race with cpuhp */
@@ -2277,14 +2275,14 @@ static int set_cache_qos_cfg(int level, bool enable)
return -ENOMEM;
r_l = &rdt_resources_all[level].r_resctrl;
- list_for_each_entry(d, &r_l->domains, list) {
+ list_for_each_entry(d, &r_l->ctrl_domains, hdr.list) {
if (r_l->cache.arch_has_per_cpu_cfg)
/* Pick all the CPUs in the domain instance */
- for_each_cpu(cpu, &d->cpu_mask)
+ for_each_cpu(cpu, &d->hdr.cpu_mask)
cpumask_set_cpu(cpu, cpu_mask);
else
/* Pick one CPU from each domain instance to update MSR */
- cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
+ cpumask_set_cpu(cpumask_any(&d->hdr.cpu_mask), cpu_mask);
}
/* Update QOS_CFG MSR on all the CPUs in cpu_mask */
@@ -2310,10 +2308,10 @@ void rdt_domain_reconfigure_cdp(struct rdt_resource *r)
l3_qos_cfg_update(&hw_res->cdp_enabled);
}
-static int mba_sc_domain_allocate(struct rdt_resource *r, struct rdt_domain *d)
+static int mba_sc_domain_allocate(struct rdt_resource *r, struct rdt_ctrl_domain *d)
{
u32 num_closid = resctrl_arch_get_num_closid(r);
- int cpu = cpumask_any(&d->cpu_mask);
+ int cpu = cpumask_any(&d->hdr.cpu_mask);
int i;
d->mbps_val = kcalloc_node(num_closid, sizeof(*d->mbps_val),
@@ -2328,7 +2326,7 @@ static int mba_sc_domain_allocate(struct rdt_resource *r, struct rdt_domain *d)
}
static void mba_sc_domain_destroy(struct rdt_resource *r,
- struct rdt_domain *d)
+ struct rdt_ctrl_domain *d)
{
kfree(d->mbps_val);
d->mbps_val = NULL;
@@ -2336,14 +2334,18 @@ static void mba_sc_domain_destroy(struct rdt_resource *r,
/*
* MBA software controller is supported only if
- * MBM is supported and MBA is in linear scale.
+ * MBM is supported and MBA is in linear scale,
+ * and the MBM monitor scope is the same as MBA
+ * control scope.
*/
static bool supports_mba_mbps(void)
{
+ struct rdt_resource *rmbm = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl;
struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_MBA].r_resctrl;
return (is_mbm_local_enabled() &&
- r->alloc_capable && is_mba_linear());
+ r->alloc_capable && is_mba_linear() &&
+ r->ctrl_scope == rmbm->mon_scope);
}
/*
@@ -2354,7 +2356,7 @@ static int set_mba_sc(bool mba_sc)
{
struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_MBA].r_resctrl;
u32 num_closid = resctrl_arch_get_num_closid(r);
- struct rdt_domain *d;
+ struct rdt_ctrl_domain *d;
int i;
if (!supports_mba_mbps() || mba_sc == is_mba_sc(r))
@@ -2362,7 +2364,7 @@ static int set_mba_sc(bool mba_sc)
r->membw.mba_sc = mba_sc;
- list_for_each_entry(d, &r->domains, list) {
+ list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
for (i = 0; i < num_closid; i++)
d->mbps_val[i] = MBA_MAX_MBPS;
}
@@ -2626,7 +2628,7 @@ static int rdt_get_tree(struct fs_context *fc)
{
struct rdt_fs_context *ctx = rdt_fc2context(fc);
unsigned long flags = RFTYPE_CTRL_BASE;
- struct rdt_domain *dom;
+ struct rdt_mon_domain *dom;
struct rdt_resource *r;
int ret;
@@ -2701,7 +2703,7 @@ static int rdt_get_tree(struct fs_context *fc)
if (is_mbm_enabled()) {
r = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl;
- list_for_each_entry(dom, &r->domains, list)
+ list_for_each_entry(dom, &r->mon_domains, hdr.list)
mbm_setup_overflow_handler(dom, MBM_OVERFLOW_INTERVAL,
RESCTRL_PICK_ANY_CPU);
}
@@ -2751,6 +2753,7 @@ static int rdt_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
struct rdt_fs_context *ctx = rdt_fc2context(fc);
struct fs_parse_result result;
+ const char *msg;
int opt;
opt = fs_parse(fc, rdt_fs_parameters, param, &result);
@@ -2765,8 +2768,9 @@ static int rdt_parse_param(struct fs_context *fc, struct fs_parameter *param)
ctx->enable_cdpl2 = true;
return 0;
case Opt_mba_mbps:
+ msg = "mba_MBps requires local MBM and linear scale MBA at L3 scope";
if (!supports_mba_mbps())
- return -EINVAL;
+ return invalfc(fc, msg);
ctx->enable_mba_mbps = true;
return 0;
case Opt_debug:
@@ -2811,9 +2815,9 @@ static int rdt_init_fs_context(struct fs_context *fc)
static int reset_all_ctrls(struct rdt_resource *r)
{
struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
- struct rdt_hw_domain *hw_dom;
+ struct rdt_hw_ctrl_domain *hw_dom;
struct msr_param msr_param;
- struct rdt_domain *d;
+ struct rdt_ctrl_domain *d;
int i;
/* Walking r->domains, ensure it can't race with cpuhp */
@@ -2825,16 +2829,16 @@ static int reset_all_ctrls(struct rdt_resource *r)
/*
* Disable resource control for this resource by setting all
- * CBMs in all domains to the maximum mask value. Pick one CPU
+ * CBMs in all ctrl_domains to the maximum mask value. Pick one CPU
* from each domain to update the MSRs below.
*/
- list_for_each_entry(d, &r->domains, list) {
- hw_dom = resctrl_to_arch_dom(d);
+ list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
+ hw_dom = resctrl_to_arch_ctrl_dom(d);
for (i = 0; i < hw_res->num_closid; i++)
hw_dom->ctrl_val[i] = r->default_ctrl;
msr_param.dom = d;
- smp_call_function_any(&d->cpu_mask, rdt_ctrl_update, &msr_param, 1);
+ smp_call_function_any(&d->hdr.cpu_mask, rdt_ctrl_update, &msr_param, 1);
}
return 0;
@@ -3002,62 +3006,126 @@ static int mon_addfile(struct kernfs_node *parent_kn, const char *name,
return ret;
}
+static void mon_rmdir_one_subdir(struct kernfs_node *pkn, char *name, char *subname)
+{
+ struct kernfs_node *kn;
+
+ kn = kernfs_find_and_get(pkn, name);
+ if (!kn)
+ return;
+ kernfs_put(kn);
+
+ if (kn->dir.subdirs <= 1)
+ kernfs_remove(kn);
+ else
+ kernfs_remove_by_name(kn, subname);
+}
+
/*
* Remove all subdirectories of mon_data of ctrl_mon groups
- * and monitor groups with given domain id.
+ * and monitor groups for the given domain.
+ * Remove files and directories containing "sum" of domain data
+ * when last domain being summed is removed.
*/
static void rmdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
- unsigned int dom_id)
+ struct rdt_mon_domain *d)
{
struct rdtgroup *prgrp, *crgrp;
+ char subname[32];
+ bool snc_mode;
char name[32];
+ snc_mode = r->mon_scope == RESCTRL_L3_NODE;
+ sprintf(name, "mon_%s_%02d", r->name, snc_mode ? d->ci->id : d->hdr.id);
+ if (snc_mode)
+ sprintf(subname, "mon_sub_%s_%02d", r->name, d->hdr.id);
+
list_for_each_entry(prgrp, &rdt_all_groups, rdtgroup_list) {
- sprintf(name, "mon_%s_%02d", r->name, dom_id);
- kernfs_remove_by_name(prgrp->mon.mon_data_kn, name);
+ mon_rmdir_one_subdir(prgrp->mon.mon_data_kn, name, subname);
list_for_each_entry(crgrp, &prgrp->mon.crdtgrp_list, mon.crdtgrp_list)
- kernfs_remove_by_name(crgrp->mon.mon_data_kn, name);
+ mon_rmdir_one_subdir(crgrp->mon.mon_data_kn, name, subname);
}
}
-static int mkdir_mondata_subdir(struct kernfs_node *parent_kn,
- struct rdt_domain *d,
- struct rdt_resource *r, struct rdtgroup *prgrp)
+static int mon_add_all_files(struct kernfs_node *kn, struct rdt_mon_domain *d,
+ struct rdt_resource *r, struct rdtgroup *prgrp,
+ bool do_sum)
{
+ struct rmid_read rr = {0};
union mon_data_bits priv;
- struct kernfs_node *kn;
struct mon_evt *mevt;
- struct rmid_read rr;
- char name[32];
int ret;
- sprintf(name, "mon_%s_%02d", r->name, d->id);
- /* create the directory */
- kn = kernfs_create_dir(parent_kn, name, parent_kn->mode, prgrp);
- if (IS_ERR(kn))
- return PTR_ERR(kn);
-
- ret = rdtgroup_kn_set_ugid(kn);
- if (ret)
- goto out_destroy;
-
- if (WARN_ON(list_empty(&r->evt_list))) {
- ret = -EPERM;
- goto out_destroy;
- }
+ if (WARN_ON(list_empty(&r->evt_list)))
+ return -EPERM;
priv.u.rid = r->rid;
- priv.u.domid = d->id;
+ priv.u.domid = do_sum ? d->ci->id : d->hdr.id;
+ priv.u.sum = do_sum;
list_for_each_entry(mevt, &r->evt_list, list) {
priv.u.evtid = mevt->evtid;
ret = mon_addfile(kn, mevt->name, priv.priv);
if (ret)
+ return ret;
+
+ if (!do_sum && is_mbm_event(mevt->evtid))
+ mon_event_read(&rr, r, d, prgrp, &d->hdr.cpu_mask, mevt->evtid, true);
+ }
+
+ return 0;
+}
+
+static int mkdir_mondata_subdir(struct kernfs_node *parent_kn,
+ struct rdt_mon_domain *d,
+ struct rdt_resource *r, struct rdtgroup *prgrp)
+{
+ struct kernfs_node *kn, *ckn;
+ char name[32];
+ bool snc_mode;
+ int ret = 0;
+
+ lockdep_assert_held(&rdtgroup_mutex);
+
+ snc_mode = r->mon_scope == RESCTRL_L3_NODE;
+ sprintf(name, "mon_%s_%02d", r->name, snc_mode ? d->ci->id : d->hdr.id);
+ kn = kernfs_find_and_get(parent_kn, name);
+ if (kn) {
+ /*
+ * rdtgroup_mutex will prevent this directory from being
+ * removed. No need to keep this hold.
+ */
+ kernfs_put(kn);
+ } else {
+ kn = kernfs_create_dir(parent_kn, name, parent_kn->mode, prgrp);
+ if (IS_ERR(kn))
+ return PTR_ERR(kn);
+
+ ret = rdtgroup_kn_set_ugid(kn);
+ if (ret)
+ goto out_destroy;
+ ret = mon_add_all_files(kn, d, r, prgrp, snc_mode);
+ if (ret)
+ goto out_destroy;
+ }
+
+ if (snc_mode) {
+ sprintf(name, "mon_sub_%s_%02d", r->name, d->hdr.id);
+ ckn = kernfs_create_dir(kn, name, parent_kn->mode, prgrp);
+ if (IS_ERR(ckn)) {
+ ret = -EINVAL;
+ goto out_destroy;
+ }
+
+ ret = rdtgroup_kn_set_ugid(ckn);
+ if (ret)
goto out_destroy;
- if (is_mbm_event(mevt->evtid))
- mon_event_read(&rr, r, d, prgrp, mevt->evtid, true);
+ ret = mon_add_all_files(ckn, d, r, prgrp, false);
+ if (ret)
+ goto out_destroy;
}
+
kernfs_activate(kn);
return 0;
@@ -3071,7 +3139,7 @@ out_destroy:
* and "monitor" groups with given domain id.
*/
static void mkdir_mondata_subdir_allrdtgrp(struct rdt_resource *r,
- struct rdt_domain *d)
+ struct rdt_mon_domain *d)
{
struct kernfs_node *parent_kn;
struct rdtgroup *prgrp, *crgrp;
@@ -3093,13 +3161,13 @@ static int mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn,
struct rdt_resource *r,
struct rdtgroup *prgrp)
{
- struct rdt_domain *dom;
+ struct rdt_mon_domain *dom;
int ret;
/* Walking r->domains, ensure it can't race with cpuhp */
lockdep_assert_cpus_held();
- list_for_each_entry(dom, &r->domains, list) {
+ list_for_each_entry(dom, &r->mon_domains, hdr.list) {
ret = mkdir_mondata_subdir(parent_kn, dom, r, prgrp);
if (ret)
return ret;
@@ -3198,7 +3266,7 @@ static u32 cbm_ensure_valid(u32 _val, struct rdt_resource *r)
* Set the RDT domain up to start off with all usable allocations. That is,
* all shareable and unused bits. All-zero CBM is invalid.
*/
-static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s,
+static int __init_one_rdt_domain(struct rdt_ctrl_domain *d, struct resctrl_schema *s,
u32 closid)
{
enum resctrl_conf_type peer_type = resctrl_peer_type(s->conf_type);
@@ -3258,7 +3326,7 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s,
*/
tmp_cbm = cfg->new_ctrl;
if (bitmap_weight(&tmp_cbm, r->cache.cbm_len) < r->cache.min_cbm_bits) {
- rdt_last_cmd_printf("No space on %s:%d\n", s->name, d->id);
+ rdt_last_cmd_printf("No space on %s:%d\n", s->name, d->hdr.id);
return -ENOSPC;
}
cfg->have_new_ctrl = true;
@@ -3278,10 +3346,10 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s,
*/
static int rdtgroup_init_cat(struct resctrl_schema *s, u32 closid)
{
- struct rdt_domain *d;
+ struct rdt_ctrl_domain *d;
int ret;
- list_for_each_entry(d, &s->res->domains, list) {
+ list_for_each_entry(d, &s->res->ctrl_domains, hdr.list) {
ret = __init_one_rdt_domain(d, s, closid);
if (ret < 0)
return ret;
@@ -3294,9 +3362,9 @@ static int rdtgroup_init_cat(struct resctrl_schema *s, u32 closid)
static void rdtgroup_init_mba(struct rdt_resource *r, u32 closid)
{
struct resctrl_staged_config *cfg;
- struct rdt_domain *d;
+ struct rdt_ctrl_domain *d;
- list_for_each_entry(d, &r->domains, list) {
+ list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
if (is_mba_sc(r)) {
d->mbps_val[closid] = MBA_MAX_MBPS;
continue;
@@ -3920,29 +3988,33 @@ static void __init rdtgroup_setup_default(void)
mutex_unlock(&rdtgroup_mutex);
}
-static void domain_destroy_mon_state(struct rdt_domain *d)
+static void domain_destroy_mon_state(struct rdt_mon_domain *d)
{
bitmap_free(d->rmid_busy_llc);
kfree(d->mbm_total);
kfree(d->mbm_local);
}
-void resctrl_offline_domain(struct rdt_resource *r, struct rdt_domain *d)
+void resctrl_offline_ctrl_domain(struct rdt_resource *r, struct rdt_ctrl_domain *d)
{
mutex_lock(&rdtgroup_mutex);
if (supports_mba_mbps() && r->rid == RDT_RESOURCE_MBA)
mba_sc_domain_destroy(r, d);
- if (!r->mon_capable)
- goto out_unlock;
+ mutex_unlock(&rdtgroup_mutex);
+}
+
+void resctrl_offline_mon_domain(struct rdt_resource *r, struct rdt_mon_domain *d)
+{
+ mutex_lock(&rdtgroup_mutex);
/*
* If resctrl is mounted, remove all the
* per domain monitor data directories.
*/
if (resctrl_mounted && resctrl_arch_mon_capable())
- rmdir_mondata_subdir_allrdtgrp(r, d->id);
+ rmdir_mondata_subdir_allrdtgrp(r, d);
if (is_mbm_enabled())
cancel_delayed_work(&d->mbm_over);
@@ -3961,11 +4033,10 @@ void resctrl_offline_domain(struct rdt_resource *r, struct rdt_domain *d)
domain_destroy_mon_state(d);
-out_unlock:
mutex_unlock(&rdtgroup_mutex);
}
-static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
+static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_mon_domain *d)
{
u32 idx_limit = resctrl_arch_system_num_rmid_idx();
size_t tsize;
@@ -3996,7 +4067,7 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
return 0;
}
-int resctrl_online_domain(struct rdt_resource *r, struct rdt_domain *d)
+int resctrl_online_ctrl_domain(struct rdt_resource *r, struct rdt_ctrl_domain *d)
{
int err = 0;
@@ -4005,11 +4076,18 @@ int resctrl_online_domain(struct rdt_resource *r, struct rdt_domain *d)
if (supports_mba_mbps() && r->rid == RDT_RESOURCE_MBA) {
/* RDT_RESOURCE_MBA is never mon_capable */
err = mba_sc_domain_allocate(r, d);
- goto out_unlock;
}
- if (!r->mon_capable)
- goto out_unlock;
+ mutex_unlock(&rdtgroup_mutex);
+
+ return err;
+}
+
+int resctrl_online_mon_domain(struct rdt_resource *r, struct rdt_mon_domain *d)
+{
+ int err;
+
+ mutex_lock(&rdtgroup_mutex);
err = domain_setup_mon_state(r, d);
if (err)
@@ -4060,8 +4138,8 @@ static void clear_childcpus(struct rdtgroup *r, unsigned int cpu)
void resctrl_offline_cpu(unsigned int cpu)
{
struct rdt_resource *l3 = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl;
+ struct rdt_mon_domain *d;
struct rdtgroup *rdtgrp;
- struct rdt_domain *d;
mutex_lock(&rdtgroup_mutex);
list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
@@ -4074,7 +4152,7 @@ void resctrl_offline_cpu(unsigned int cpu)
if (!l3->mon_capable)
goto out_unlock;
- d = get_domain_from_cpu(cpu, l3);
+ d = get_mon_domain_from_cpu(cpu, l3);
if (d) {
if (is_mbm_enabled() && cpu == d->mbm_work_cpu) {
cancel_delayed_work(&d->mbm_over);
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 11f83d07925e..00189cdeb775 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -41,80 +41,97 @@
#define CPUID_VMWARE_INFO_LEAF 0x40000000
#define CPUID_VMWARE_FEATURES_LEAF 0x40000010
-#define CPUID_VMWARE_FEATURES_ECX_VMMCALL BIT(0)
-#define CPUID_VMWARE_FEATURES_ECX_VMCALL BIT(1)
-#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
-
-#define VMWARE_CMD_GETVERSION 10
-#define VMWARE_CMD_GETHZ 45
-#define VMWARE_CMD_GETVCPU_INFO 68
-#define VMWARE_CMD_LEGACY_X2APIC 3
-#define VMWARE_CMD_VCPU_RESERVED 31
-#define VMWARE_CMD_STEALCLOCK 91
+#define GETVCPU_INFO_LEGACY_X2APIC BIT(3)
+#define GETVCPU_INFO_VCPU_RESERVED BIT(31)
#define STEALCLOCK_NOT_AVAILABLE (-1)
#define STEALCLOCK_DISABLED 0
#define STEALCLOCK_ENABLED 1
-#define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \
- __asm__("inl (%%dx), %%eax" : \
- "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
- "a"(VMWARE_HYPERVISOR_MAGIC), \
- "c"(VMWARE_CMD_##cmd), \
- "d"(VMWARE_HYPERVISOR_PORT), "b"(UINT_MAX) : \
- "memory")
-
-#define VMWARE_VMCALL(cmd, eax, ebx, ecx, edx) \
- __asm__("vmcall" : \
- "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
- "a"(VMWARE_HYPERVISOR_MAGIC), \
- "c"(VMWARE_CMD_##cmd), \
- "d"(0), "b"(UINT_MAX) : \
- "memory")
-
-#define VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx) \
- __asm__("vmmcall" : \
- "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
- "a"(VMWARE_HYPERVISOR_MAGIC), \
- "c"(VMWARE_CMD_##cmd), \
- "d"(0), "b"(UINT_MAX) : \
- "memory")
-
-#define VMWARE_CMD(cmd, eax, ebx, ecx, edx) do { \
- switch (vmware_hypercall_mode) { \
- case CPUID_VMWARE_FEATURES_ECX_VMCALL: \
- VMWARE_VMCALL(cmd, eax, ebx, ecx, edx); \
- break; \
- case CPUID_VMWARE_FEATURES_ECX_VMMCALL: \
- VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx); \
- break; \
- default: \
- VMWARE_PORT(cmd, eax, ebx, ecx, edx); \
- break; \
- } \
- } while (0)
-
struct vmware_steal_time {
union {
- uint64_t clock; /* stolen time counter in units of vtsc */
+ u64 clock; /* stolen time counter in units of vtsc */
struct {
/* only for little-endian */
- uint32_t clock_low;
- uint32_t clock_high;
+ u32 clock_low;
+ u32 clock_high;
};
};
- uint64_t reserved[7];
+ u64 reserved[7];
};
static unsigned long vmware_tsc_khz __ro_after_init;
static u8 vmware_hypercall_mode __ro_after_init;
+unsigned long vmware_hypercall_slow(unsigned long cmd,
+ unsigned long in1, unsigned long in3,
+ unsigned long in4, unsigned long in5,
+ u32 *out1, u32 *out2, u32 *out3,
+ u32 *out4, u32 *out5)
+{
+ unsigned long out0, rbx, rcx, rdx, rsi, rdi;
+
+ switch (vmware_hypercall_mode) {
+ case CPUID_VMWARE_FEATURES_ECX_VMCALL:
+ asm_inline volatile ("vmcall"
+ : "=a" (out0), "=b" (rbx), "=c" (rcx),
+ "=d" (rdx), "=S" (rsi), "=D" (rdi)
+ : "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd),
+ "d" (in3),
+ "S" (in4),
+ "D" (in5)
+ : "cc", "memory");
+ break;
+ case CPUID_VMWARE_FEATURES_ECX_VMMCALL:
+ asm_inline volatile ("vmmcall"
+ : "=a" (out0), "=b" (rbx), "=c" (rcx),
+ "=d" (rdx), "=S" (rsi), "=D" (rdi)
+ : "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd),
+ "d" (in3),
+ "S" (in4),
+ "D" (in5)
+ : "cc", "memory");
+ break;
+ default:
+ asm_inline volatile ("movw %[port], %%dx; inl (%%dx), %%eax"
+ : "=a" (out0), "=b" (rbx), "=c" (rcx),
+ "=d" (rdx), "=S" (rsi), "=D" (rdi)
+ : [port] "i" (VMWARE_HYPERVISOR_PORT),
+ "a" (VMWARE_HYPERVISOR_MAGIC),
+ "b" (in1),
+ "c" (cmd),
+ "d" (in3),
+ "S" (in4),
+ "D" (in5)
+ : "cc", "memory");
+ break;
+ }
+
+ if (out1)
+ *out1 = rbx;
+ if (out2)
+ *out2 = rcx;
+ if (out3)
+ *out3 = rdx;
+ if (out4)
+ *out4 = rsi;
+ if (out5)
+ *out5 = rdi;
+
+ return out0;
+}
+
static inline int __vmware_platform(void)
{
- uint32_t eax, ebx, ecx, edx;
- VMWARE_CMD(GETVERSION, eax, ebx, ecx, edx);
- return eax != (uint32_t)-1 && ebx == VMWARE_HYPERVISOR_MAGIC;
+ u32 eax, ebx, ecx;
+
+ eax = vmware_hypercall3(VMWARE_CMD_GETVERSION, 0, &ebx, &ecx);
+ return eax != UINT_MAX && ebx == VMWARE_HYPERVISOR_MAGIC;
}
static unsigned long vmware_get_tsc_khz(void)
@@ -166,21 +183,12 @@ static void __init vmware_cyc2ns_setup(void)
pr_info("using clock offset of %llu ns\n", d->cyc2ns_offset);
}
-static int vmware_cmd_stealclock(uint32_t arg1, uint32_t arg2)
+static int vmware_cmd_stealclock(u32 addr_hi, u32 addr_lo)
{
- uint32_t result, info;
-
- asm volatile (VMWARE_HYPERCALL :
- "=a"(result),
- "=c"(info) :
- "a"(VMWARE_HYPERVISOR_MAGIC),
- "b"(0),
- "c"(VMWARE_CMD_STEALCLOCK),
- "d"(0),
- "S"(arg1),
- "D"(arg2) :
- "memory");
- return result;
+ u32 info;
+
+ return vmware_hypercall5(VMWARE_CMD_STEALCLOCK, 0, 0, addr_hi, addr_lo,
+ &info);
}
static bool stealclock_enable(phys_addr_t pa)
@@ -215,15 +223,15 @@ static bool vmware_is_stealclock_available(void)
* Return:
* The steal clock reading in ns.
*/
-static uint64_t vmware_steal_clock(int cpu)
+static u64 vmware_steal_clock(int cpu)
{
struct vmware_steal_time *steal = &per_cpu(vmw_steal_time, cpu);
- uint64_t clock;
+ u64 clock;
if (IS_ENABLED(CONFIG_64BIT))
clock = READ_ONCE(steal->clock);
else {
- uint32_t initial_high, low, high;
+ u32 initial_high, low, high;
do {
initial_high = READ_ONCE(steal->clock_high);
@@ -235,7 +243,7 @@ static uint64_t vmware_steal_clock(int cpu)
high = READ_ONCE(steal->clock_high);
} while (initial_high != high);
- clock = ((uint64_t)high << 32) | low;
+ clock = ((u64)high << 32) | low;
}
return mul_u64_u32_shr(clock, vmware_cyc2ns.cyc2ns_mul,
@@ -389,13 +397,13 @@ static void __init vmware_set_capabilities(void)
static void __init vmware_platform_setup(void)
{
- uint32_t eax, ebx, ecx, edx;
- uint64_t lpj, tsc_khz;
+ u32 eax, ebx, ecx;
+ u64 lpj, tsc_khz;
- VMWARE_CMD(GETHZ, eax, ebx, ecx, edx);
+ eax = vmware_hypercall3(VMWARE_CMD_GETHZ, UINT_MAX, &ebx, &ecx);
if (ebx != UINT_MAX) {
- lpj = tsc_khz = eax | (((uint64_t)ebx) << 32);
+ lpj = tsc_khz = eax | (((u64)ebx) << 32);
do_div(tsc_khz, 1000);
WARN_ON(tsc_khz >> 32);
pr_info("TSC freq read from hypervisor : %lu.%03lu MHz\n",
@@ -446,7 +454,7 @@ static u8 __init vmware_select_hypercall(void)
* If !boot_cpu_has(X86_FEATURE_HYPERVISOR), vmware_hypercall_mode
* intentionally defaults to 0.
*/
-static uint32_t __init vmware_platform(void)
+static u32 __init vmware_platform(void)
{
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
unsigned int eax;
@@ -474,12 +482,65 @@ static uint32_t __init vmware_platform(void)
/* Checks if hypervisor supports x2apic without VT-D interrupt remapping. */
static bool __init vmware_legacy_x2apic_available(void)
{
- uint32_t eax, ebx, ecx, edx;
- VMWARE_CMD(GETVCPU_INFO, eax, ebx, ecx, edx);
- return !(eax & BIT(VMWARE_CMD_VCPU_RESERVED)) &&
- (eax & BIT(VMWARE_CMD_LEGACY_X2APIC));
+ u32 eax;
+
+ eax = vmware_hypercall1(VMWARE_CMD_GETVCPU_INFO, 0);
+ return !(eax & GETVCPU_INFO_VCPU_RESERVED) &&
+ (eax & GETVCPU_INFO_LEGACY_X2APIC);
}
+#ifdef CONFIG_INTEL_TDX_GUEST
+/*
+ * TDCALL[TDG.VP.VMCALL] uses %rax (arg0) and %rcx (arg2). Therefore,
+ * we remap those registers to %r12 and %r13, respectively.
+ */
+unsigned long vmware_tdx_hypercall(unsigned long cmd,
+ unsigned long in1, unsigned long in3,
+ unsigned long in4, unsigned long in5,
+ u32 *out1, u32 *out2, u32 *out3,
+ u32 *out4, u32 *out5)
+{
+ struct tdx_module_args args = {};
+
+ if (!hypervisor_is_type(X86_HYPER_VMWARE)) {
+ pr_warn_once("Incorrect usage\n");
+ return ULONG_MAX;
+ }
+
+ if (cmd & ~VMWARE_CMD_MASK) {
+ pr_warn_once("Out of range command %lx\n", cmd);
+ return ULONG_MAX;
+ }
+
+ args.rbx = in1;
+ args.rdx = in3;
+ args.rsi = in4;
+ args.rdi = in5;
+ args.r10 = VMWARE_TDX_VENDOR_LEAF;
+ args.r11 = VMWARE_TDX_HCALL_FUNC;
+ args.r12 = VMWARE_HYPERVISOR_MAGIC;
+ args.r13 = cmd;
+ /* CPL */
+ args.r15 = 0;
+
+ __tdx_hypercall(&args);
+
+ if (out1)
+ *out1 = args.rbx;
+ if (out2)
+ *out2 = args.r13;
+ if (out3)
+ *out3 = args.rdx;
+ if (out4)
+ *out4 = args.rsi;
+ if (out5)
+ *out5 = args.rdi;
+
+ return args.r12;
+}
+EXPORT_SYMBOL_GPL(vmware_tdx_hypercall);
+#endif
+
#ifdef CONFIG_AMD_MEM_ENCRYPT
static void vmware_sev_es_hcall_prepare(struct ghcb *ghcb,
struct pt_regs *regs)
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index f06501445cd9..340af8155658 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -128,6 +128,18 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
#ifdef CONFIG_HPET_TIMER
hpet_disable();
#endif
+
+ /*
+ * Non-crash kexec calls enc_kexec_begin() while scheduling is still
+ * active. This allows the callback to wait until all in-flight
+ * shared<->private conversions are complete. In a crash scenario,
+ * enc_kexec_begin() gets called after all but one CPU have been shut
+ * down and interrupts have been disabled. This allows the callback to
+ * detect a race with the conversion and report it.
+ */
+ x86_platform.guest.enc_kexec_begin();
+ x86_platform.guest.enc_kexec_finish();
+
crash_save_cpu(regs, safe_smp_processor_id());
}
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 8e3c53b4d070..64280879c68c 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -83,7 +83,7 @@ static int x86_of_pci_irq_enable(struct pci_dev *dev)
ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (ret)
- return ret;
+ return pcibios_err_to_errno(ret);
if (!pin)
return 0;
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 68b09f718f10..4893d30ce438 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -828,7 +828,7 @@ u64 __init e820__memblock_alloc_reserved(u64 size, u64 align)
/*
* Find the highest page frame number we have available
*/
-static unsigned long __init e820_end_pfn(unsigned long limit_pfn, enum e820_type type)
+static unsigned long __init e820__end_ram_pfn(unsigned long limit_pfn)
{
int i;
unsigned long last_pfn = 0;
@@ -839,7 +839,8 @@ static unsigned long __init e820_end_pfn(unsigned long limit_pfn, enum e820_type
unsigned long start_pfn;
unsigned long end_pfn;
- if (entry->type != type)
+ if (entry->type != E820_TYPE_RAM &&
+ entry->type != E820_TYPE_ACPI)
continue;
start_pfn = entry->addr >> PAGE_SHIFT;
@@ -865,12 +866,12 @@ static unsigned long __init e820_end_pfn(unsigned long limit_pfn, enum e820_type
unsigned long __init e820__end_of_ram_pfn(void)
{
- return e820_end_pfn(MAX_ARCH_PFN, E820_TYPE_RAM);
+ return e820__end_ram_pfn(MAX_ARCH_PFN);
}
unsigned long __init e820__end_of_low_ram_pfn(void)
{
- return e820_end_pfn(1UL << (32 - PAGE_SHIFT), E820_TYPE_RAM);
+ return e820__end_ram_pfn(1UL << (32 - PAGE_SHIFT));
}
static void __init early_panic(char *msg)
diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h
index 05df04f39628..2ee0b9c53dcc 100644
--- a/arch/x86/kernel/fpu/xstate.h
+++ b/arch/x86/kernel/fpu/xstate.h
@@ -106,21 +106,17 @@ static inline u64 xfeatures_mask_independent(void)
* Otherwise, if XSAVEOPT is enabled, XSAVEOPT replaces XSAVE because XSAVEOPT
* supports modified optimization which is not supported by XSAVE.
*
- * We use XSAVE as a fallback.
- *
- * The 661 label is defined in the ALTERNATIVE* macros as the address of the
- * original instruction which gets replaced. We need to use it here as the
- * address of the instruction where we might get an exception at.
+ * Use XSAVE as a fallback.
*/
#define XSTATE_XSAVE(st, lmask, hmask, err) \
- asm volatile(ALTERNATIVE_3(XSAVE, \
+ asm volatile("1: " ALTERNATIVE_3(XSAVE, \
XSAVEOPT, X86_FEATURE_XSAVEOPT, \
XSAVEC, X86_FEATURE_XSAVEC, \
XSAVES, X86_FEATURE_XSAVES) \
"\n" \
"xor %[err], %[err]\n" \
"3:\n" \
- _ASM_EXTABLE_TYPE_REG(661b, 3b, EX_TYPE_EFAULT_REG, %[err]) \
+ _ASM_EXTABLE_TYPE_REG(1b, 3b, EX_TYPE_EFAULT_REG, %[err]) \
: [err] "=r" (err) \
: "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \
: "memory")
@@ -130,11 +126,11 @@ static inline u64 xfeatures_mask_independent(void)
* XSAVE area format.
*/
#define XSTATE_XRESTORE(st, lmask, hmask) \
- asm volatile(ALTERNATIVE(XRSTOR, \
+ asm volatile("1: " ALTERNATIVE(XRSTOR, \
XRSTORS, X86_FEATURE_XSAVES) \
"\n" \
"3:\n" \
- _ASM_EXTABLE_TYPE(661b, 3b, EX_TYPE_FPU_RESTORE) \
+ _ASM_EXTABLE_TYPE(1b, 3b, EX_TYPE_FPU_RESTORE) \
: \
: "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \
: "memory")
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index b8441147eb5e..f63f8fd00a91 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -835,6 +835,13 @@ void __noreturn stop_this_cpu(void *dummy)
*/
cpumask_clear_cpu(cpu, &cpus_stop_mask);
+#ifdef CONFIG_SMP
+ if (smp_ops.stop_this_cpu) {
+ smp_ops.stop_this_cpu();
+ unreachable();
+ }
+#endif
+
for (;;) {
/*
* Use native_halt() so that memory contents don't change
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index f3130f762784..0e0a4cf6b5eb 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/objtool.h>
#include <linux/pgtable.h>
+#include <linux/kexec.h>
#include <acpi/reboot.h>
#include <asm/io.h>
#include <asm/apic.h>
@@ -716,6 +717,14 @@ static void native_machine_emergency_restart(void)
void native_machine_shutdown(void)
{
+ /*
+ * Call enc_kexec_begin() while all CPUs are still active and
+ * interrupts are enabled. This will allow all in-flight memory
+ * conversions to finish cleanly.
+ */
+ if (kexec_in_progress)
+ x86_platform.guest.enc_kexec_begin();
+
/* Stop the cpus and apics */
#ifdef CONFIG_X86_IO_APIC
/*
@@ -752,6 +761,9 @@ void native_machine_shutdown(void)
#ifdef CONFIG_X86_64
x86_platform.iommu_shutdown();
#endif
+
+ if (kexec_in_progress)
+ x86_platform.guest.enc_kexec_finish();
}
static void __machine_emergency_restart(int emergency)
@@ -868,6 +880,12 @@ static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)
cpu_emergency_disable_virtualization();
atomic_dec(&waiting_for_crash_ipi);
+
+ if (smp_ops.stop_this_cpu) {
+ smp_ops.stop_this_cpu();
+ unreachable();
+ }
+
/* Assume hlt works */
halt();
for (;;)
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 56cab1bb25f5..042c9a0334e9 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -5,6 +5,8 @@
*/
#include <linux/linkage.h>
+#include <linux/stringify.h>
+#include <asm/alternative.h>
#include <asm/page_types.h>
#include <asm/kexec.h>
#include <asm/processor-flags.h>
@@ -145,16 +147,15 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
* Set cr4 to a known state:
* - physical address extension enabled
* - 5-level paging, if it was enabled before
+ * - Machine check exception on TDX guest, if it was enabled before.
+ * Clearing MCE might not be allowed in TDX guests, depending on setup.
+ *
+ * Use R13 that contains the original CR4 value, read in relocate_kernel().
+ * PAE is always set in the original CR4.
*/
- movl $X86_CR4_PAE, %eax
- testq $X86_CR4_LA57, %r13
- jz 1f
- orl $X86_CR4_LA57, %eax
-1:
- movq %rax, %cr4
-
- jmp 1f
-1:
+ andl $(X86_CR4_PAE | X86_CR4_LA57), %r13d
+ ALTERNATIVE "", __stringify(orl $X86_CR4_MCE, %r13d), X86_FEATURE_TDX_GUEST
+ movq %r13, %cr4
/* Flush the TLB (needed?) */
movq %r9, %cr3
@@ -165,9 +166,9 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
* used by kexec. Flush the caches before copying the kernel.
*/
testq %r12, %r12
- jz 1f
+ jz .Lsme_off
wbinvd
-1:
+.Lsme_off:
movq %rcx, %r11
call swap_pages
@@ -187,7 +188,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
*/
testq %r11, %r11
- jnz 1f
+ jnz .Lrelocate
xorl %eax, %eax
xorl %ebx, %ebx
xorl %ecx, %ecx
@@ -208,7 +209,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
ret
int3
-1:
+.Lrelocate:
popq %rdx
leaq PAGE_SIZE(%r10), %rsp
ANNOTATE_RETPOLINE_SAFE
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 05c5aa951da7..5d34cad9b7b1 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -165,6 +165,7 @@ unsigned long saved_video_mode;
static char __initdata command_line[COMMAND_LINE_SIZE];
#ifdef CONFIG_CMDLINE_BOOL
static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
+bool builtin_cmdline_added __ro_after_init;
#endif
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
@@ -765,6 +766,7 @@ void __init setup_arch(char **cmdline_p)
strscpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
}
#endif
+ builtin_cmdline_added = true;
#endif
strscpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
@@ -995,7 +997,6 @@ void __init setup_arch(char **cmdline_p)
mem_encrypt_setup_arch();
cc_random_init();
- efi_fake_memmap();
efi_find_mirror();
efi_esrt_init();
efi_mokvar_table_init();
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 06b170759e5b..d4462fb26299 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -50,9 +50,9 @@ int tsc_clocksource_reliable;
static int __read_mostly tsc_force_recalibrate;
-static u32 art_to_tsc_numerator;
-static u32 art_to_tsc_denominator;
-static u64 art_to_tsc_offset;
+static struct clocksource_base art_base_clk = {
+ .id = CSID_X86_ART,
+};
static bool have_art;
struct cyc2ns {
@@ -1074,7 +1074,7 @@ core_initcall(cpufreq_register_tsc_scaling);
*/
static void __init detect_art(void)
{
- unsigned int unused[2];
+ unsigned int unused;
if (boot_cpu_data.cpuid_level < ART_CPUID_LEAF)
return;
@@ -1089,13 +1089,14 @@ static void __init detect_art(void)
tsc_async_resets)
return;
- cpuid(ART_CPUID_LEAF, &art_to_tsc_denominator,
- &art_to_tsc_numerator, unused, unused+1);
+ cpuid(ART_CPUID_LEAF, &art_base_clk.denominator,
+ &art_base_clk.numerator, &art_base_clk.freq_khz, &unused);
- if (art_to_tsc_denominator < ART_MIN_DENOMINATOR)
+ art_base_clk.freq_khz /= KHZ;
+ if (art_base_clk.denominator < ART_MIN_DENOMINATOR)
return;
- rdmsrl(MSR_IA32_TSC_ADJUST, art_to_tsc_offset);
+ rdmsrl(MSR_IA32_TSC_ADJUST, art_base_clk.offset);
/* Make this sticky over multiple CPU init calls */
setup_force_cpu_cap(X86_FEATURE_ART);
@@ -1296,67 +1297,6 @@ int unsynchronized_tsc(void)
return 0;
}
-/*
- * Convert ART to TSC given numerator/denominator found in detect_art()
- */
-struct system_counterval_t convert_art_to_tsc(u64 art)
-{
- u64 tmp, res, rem;
-
- rem = do_div(art, art_to_tsc_denominator);
-
- res = art * art_to_tsc_numerator;
- tmp = rem * art_to_tsc_numerator;
-
- do_div(tmp, art_to_tsc_denominator);
- res += tmp + art_to_tsc_offset;
-
- return (struct system_counterval_t) {
- .cs_id = have_art ? CSID_X86_TSC : CSID_GENERIC,
- .cycles = res,
- };
-}
-EXPORT_SYMBOL(convert_art_to_tsc);
-
-/**
- * convert_art_ns_to_tsc() - Convert ART in nanoseconds to TSC.
- * @art_ns: ART (Always Running Timer) in unit of nanoseconds
- *
- * PTM requires all timestamps to be in units of nanoseconds. When user
- * software requests a cross-timestamp, this function converts system timestamp
- * to TSC.
- *
- * This is valid when CPU feature flag X86_FEATURE_TSC_KNOWN_FREQ is set
- * indicating the tsc_khz is derived from CPUID[15H]. Drivers should check
- * that this flag is set before conversion to TSC is attempted.
- *
- * Return:
- * struct system_counterval_t - system counter value with the ID of the
- * corresponding clocksource:
- * cycles: System counter value
- * cs_id: The clocksource ID for validating comparability
- */
-
-struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns)
-{
- u64 tmp, res, rem;
-
- rem = do_div(art_ns, USEC_PER_SEC);
-
- res = art_ns * tsc_khz;
- tmp = rem * tsc_khz;
-
- do_div(tmp, USEC_PER_SEC);
- res += tmp;
-
- return (struct system_counterval_t) {
- .cs_id = have_art ? CSID_X86_TSC : CSID_GENERIC,
- .cycles = res,
- };
-}
-EXPORT_SYMBOL(convert_art_ns_to_tsc);
-
-
static void tsc_refine_calibration_work(struct work_struct *work);
static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work);
/**
@@ -1458,8 +1398,10 @@ out:
if (tsc_unstable)
goto unreg;
- if (boot_cpu_has(X86_FEATURE_ART))
+ if (boot_cpu_has(X86_FEATURE_ART)) {
have_art = true;
+ clocksource_tsc.base = &art_base_clk;
+ }
clocksource_register_khz(&clocksource_tsc, tsc_khz);
unreg:
clocksource_unregister(&clocksource_tsc_early);
@@ -1484,8 +1426,10 @@ static int __init init_tsc_clocksource(void)
* the refined calibration and directly register it as a clocksource.
*/
if (boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ)) {
- if (boot_cpu_has(X86_FEATURE_ART))
+ if (boot_cpu_has(X86_FEATURE_ART)) {
have_art = true;
+ clocksource_tsc.base = &art_base_clk;
+ }
clocksource_register_khz(&clocksource_tsc, tsc_khz);
clocksource_unregister(&clocksource_tsc_early);
@@ -1509,10 +1453,12 @@ static bool __init determine_cpu_tsc_frequencies(bool early)
if (early) {
cpu_khz = x86_platform.calibrate_cpu();
- if (tsc_early_khz)
+ if (tsc_early_khz) {
tsc_khz = tsc_early_khz;
- else
+ } else {
tsc_khz = x86_platform.calibrate_tsc();
+ clocksource_tsc.freq_khz = tsc_khz;
+ }
} else {
/* We should not be here with non-native cpu calibration */
WARN_ON(x86_platform.calibrate_cpu != native_calibrate_cpu);
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 3509afc6a672..6e73403e874f 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -357,6 +357,9 @@ SECTIONS
PERCPU_SECTION(INTERNODE_CACHE_BYTES)
#endif
+ RUNTIME_CONST(shift, d_hash_shift)
+ RUNTIME_CONST(ptr, dentry_hashtable)
+
. = ALIGN(PAGE_SIZE);
/* freed after init ends here */
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index d5dc5a92635a..82b128d3f309 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -134,10 +134,12 @@ struct x86_cpuinit_ops x86_cpuinit = {
static void default_nmi_init(void) { };
-static bool enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool enc) { return true; }
-static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return true; }
+static int enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool enc) { return 0; }
+static int enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return 0; }
static bool enc_tlb_flush_required_noop(bool enc) { return false; }
static bool enc_cache_flush_required_noop(void) { return false; }
+static void enc_kexec_begin_noop(void) {}
+static void enc_kexec_finish_noop(void) {}
static bool is_private_mmio_noop(u64 addr) {return false; }
struct x86_platform_ops x86_platform __ro_after_init = {
@@ -161,6 +163,8 @@ struct x86_platform_ops x86_platform __ro_after_init = {
.enc_status_change_finish = enc_status_change_finish_noop,
.enc_tlb_flush_required = enc_tlb_flush_required_noop,
.enc_cache_flush_required = enc_cache_flush_required_noop,
+ .enc_kexec_begin = enc_kexec_begin_noop,
+ .enc_kexec_finish = enc_kexec_finish_noop,
},
};
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 5d4c86133453..c8cc578646d0 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1069,7 +1069,7 @@ static __always_inline u8 test_cc(unsigned int condition, unsigned long flags)
flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF;
asm("push %[flags]; popf; " CALL_NOSPEC
- : "=a"(rc) : [thunk_target]"r"(fop), [flags]"r"(flags));
+ : "=a"(rc), ASM_CALL_CONSTRAINT : [thunk_target]"r"(fop), [flags]"r"(flags));
return rc;
}
diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c
index 80570eb3c89b..384da1fdd5c6 100644
--- a/arch/x86/lib/cmdline.c
+++ b/arch/x86/lib/cmdline.c
@@ -6,8 +6,10 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ctype.h>
+
#include <asm/setup.h>
#include <asm/cmdline.h>
+#include <asm/bug.h>
static inline int myisspace(u8 c)
{
@@ -205,12 +207,18 @@ __cmdline_find_option(const char *cmdline, int max_cmdline_size,
int cmdline_find_option_bool(const char *cmdline, const char *option)
{
+ if (IS_ENABLED(CONFIG_CMDLINE_BOOL))
+ WARN_ON_ONCE(!builtin_cmdline_added);
+
return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option);
}
int cmdline_find_option(const char *cmdline, const char *option, char *buffer,
int bufsize)
{
+ if (IS_ENABLED(CONFIG_CMDLINE_BOOL))
+ WARN_ON_ONCE(!builtin_cmdline_added);
+
return __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option,
buffer, bufsize);
}
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index a1cb3a4e6742..a314622aa093 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -44,21 +44,23 @@
or %rdx, %rax
.else
cmp $TASK_SIZE_MAX-\size+1, %eax
-.if \size != 8
jae .Lbad_get_user
-.else
- jae .Lbad_get_user_8
-.endif
sbb %edx, %edx /* array_index_mask_nospec() */
and %edx, %eax
.endif
.endm
+.macro UACCESS op src dst
+1: \op \src,\dst
+ _ASM_EXTABLE_UA(1b, __get_user_handle_exception)
+.endm
+
+
.text
SYM_FUNC_START(__get_user_1)
check_range size=1
ASM_STAC
-1: movzbl (%_ASM_AX),%edx
+ UACCESS movzbl (%_ASM_AX),%edx
xor %eax,%eax
ASM_CLAC
RET
@@ -68,7 +70,7 @@ EXPORT_SYMBOL(__get_user_1)
SYM_FUNC_START(__get_user_2)
check_range size=2
ASM_STAC
-2: movzwl (%_ASM_AX),%edx
+ UACCESS movzwl (%_ASM_AX),%edx
xor %eax,%eax
ASM_CLAC
RET
@@ -78,7 +80,7 @@ EXPORT_SYMBOL(__get_user_2)
SYM_FUNC_START(__get_user_4)
check_range size=4
ASM_STAC
-3: movl (%_ASM_AX),%edx
+ UACCESS movl (%_ASM_AX),%edx
xor %eax,%eax
ASM_CLAC
RET
@@ -89,10 +91,11 @@ SYM_FUNC_START(__get_user_8)
check_range size=8
ASM_STAC
#ifdef CONFIG_X86_64
-4: movq (%_ASM_AX),%rdx
+ UACCESS movq (%_ASM_AX),%rdx
#else
-4: movl (%_ASM_AX),%edx
-5: movl 4(%_ASM_AX),%ecx
+ xor %ecx,%ecx
+ UACCESS movl (%_ASM_AX),%edx
+ UACCESS movl 4(%_ASM_AX),%ecx
#endif
xor %eax,%eax
ASM_CLAC
@@ -104,7 +107,7 @@ EXPORT_SYMBOL(__get_user_8)
SYM_FUNC_START(__get_user_nocheck_1)
ASM_STAC
ASM_BARRIER_NOSPEC
-6: movzbl (%_ASM_AX),%edx
+ UACCESS movzbl (%_ASM_AX),%edx
xor %eax,%eax
ASM_CLAC
RET
@@ -114,7 +117,7 @@ EXPORT_SYMBOL(__get_user_nocheck_1)
SYM_FUNC_START(__get_user_nocheck_2)
ASM_STAC
ASM_BARRIER_NOSPEC
-7: movzwl (%_ASM_AX),%edx
+ UACCESS movzwl (%_ASM_AX),%edx
xor %eax,%eax
ASM_CLAC
RET
@@ -124,7 +127,7 @@ EXPORT_SYMBOL(__get_user_nocheck_2)
SYM_FUNC_START(__get_user_nocheck_4)
ASM_STAC
ASM_BARRIER_NOSPEC
-8: movl (%_ASM_AX),%edx
+ UACCESS movl (%_ASM_AX),%edx
xor %eax,%eax
ASM_CLAC
RET
@@ -135,10 +138,11 @@ SYM_FUNC_START(__get_user_nocheck_8)
ASM_STAC
ASM_BARRIER_NOSPEC
#ifdef CONFIG_X86_64
-9: movq (%_ASM_AX),%rdx
+ UACCESS movq (%_ASM_AX),%rdx
#else
-9: movl (%_ASM_AX),%edx
-10: movl 4(%_ASM_AX),%ecx
+ xor %ecx,%ecx
+ UACCESS movl (%_ASM_AX),%edx
+ UACCESS movl 4(%_ASM_AX),%ecx
#endif
xor %eax,%eax
ASM_CLAC
@@ -154,36 +158,3 @@ SYM_CODE_START_LOCAL(__get_user_handle_exception)
mov $(-EFAULT),%_ASM_AX
RET
SYM_CODE_END(__get_user_handle_exception)
-
-#ifdef CONFIG_X86_32
-SYM_CODE_START_LOCAL(__get_user_8_handle_exception)
- ASM_CLAC
-.Lbad_get_user_8:
- xor %edx,%edx
- xor %ecx,%ecx
- mov $(-EFAULT),%_ASM_AX
- RET
-SYM_CODE_END(__get_user_8_handle_exception)
-#endif
-
-/* get_user */
- _ASM_EXTABLE_UA(1b, __get_user_handle_exception)
- _ASM_EXTABLE_UA(2b, __get_user_handle_exception)
- _ASM_EXTABLE_UA(3b, __get_user_handle_exception)
-#ifdef CONFIG_X86_64
- _ASM_EXTABLE_UA(4b, __get_user_handle_exception)
-#else
- _ASM_EXTABLE_UA(4b, __get_user_8_handle_exception)
- _ASM_EXTABLE_UA(5b, __get_user_8_handle_exception)
-#endif
-
-/* __get_user */
- _ASM_EXTABLE_UA(6b, __get_user_handle_exception)
- _ASM_EXTABLE_UA(7b, __get_user_handle_exception)
- _ASM_EXTABLE_UA(8b, __get_user_handle_exception)
-#ifdef CONFIG_X86_64
- _ASM_EXTABLE_UA(9b, __get_user_handle_exception)
-#else
- _ASM_EXTABLE_UA(9b, __get_user_8_handle_exception)
- _ASM_EXTABLE_UA(10b, __get_user_8_handle_exception)
-#endif
diff --git a/arch/x86/lib/iomem.c b/arch/x86/lib/iomem.c
index e0411a3774d4..5eecb45d05d5 100644
--- a/arch/x86/lib/iomem.c
+++ b/arch/x86/lib/iomem.c
@@ -25,6 +25,9 @@ static __always_inline void rep_movs(void *to, const void *from, size_t n)
static void string_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
{
+ const void *orig_to = to;
+ const size_t orig_n = n;
+
if (unlikely(!n))
return;
@@ -39,7 +42,7 @@ static void string_memcpy_fromio(void *to, const volatile void __iomem *from, si
}
rep_movs(to, (const void *)from, n);
/* KMSAN must treat values read from devices as initialized. */
- kmsan_unpoison_memory(to, n);
+ kmsan_unpoison_memory(orig_to, orig_n);
}
static void string_memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c
index 968d7005f4a7..c45127265f2f 100644
--- a/arch/x86/mm/ident_map.c
+++ b/arch/x86/mm/ident_map.c
@@ -4,6 +4,79 @@
* included by both the compressed kernel and the regular kernel.
*/
+static void free_pte(struct x86_mapping_info *info, pmd_t *pmd)
+{
+ pte_t *pte = pte_offset_kernel(pmd, 0);
+
+ info->free_pgt_page(pte, info->context);
+}
+
+static void free_pmd(struct x86_mapping_info *info, pud_t *pud)
+{
+ pmd_t *pmd = pmd_offset(pud, 0);
+ int i;
+
+ for (i = 0; i < PTRS_PER_PMD; i++) {
+ if (!pmd_present(pmd[i]))
+ continue;
+
+ if (pmd_leaf(pmd[i]))
+ continue;
+
+ free_pte(info, &pmd[i]);
+ }
+
+ info->free_pgt_page(pmd, info->context);
+}
+
+static void free_pud(struct x86_mapping_info *info, p4d_t *p4d)
+{
+ pud_t *pud = pud_offset(p4d, 0);
+ int i;
+
+ for (i = 0; i < PTRS_PER_PUD; i++) {
+ if (!pud_present(pud[i]))
+ continue;
+
+ if (pud_leaf(pud[i]))
+ continue;
+
+ free_pmd(info, &pud[i]);
+ }
+
+ info->free_pgt_page(pud, info->context);
+}
+
+static void free_p4d(struct x86_mapping_info *info, pgd_t *pgd)
+{
+ p4d_t *p4d = p4d_offset(pgd, 0);
+ int i;
+
+ for (i = 0; i < PTRS_PER_P4D; i++) {
+ if (!p4d_present(p4d[i]))
+ continue;
+
+ free_pud(info, &p4d[i]);
+ }
+
+ if (pgtable_l5_enabled())
+ info->free_pgt_page(p4d, info->context);
+}
+
+void kernel_ident_mapping_free(struct x86_mapping_info *info, pgd_t *pgd)
+{
+ int i;
+
+ for (i = 0; i < PTRS_PER_PGD; i++) {
+ if (!pgd_present(pgd[i]))
+ continue;
+
+ free_p4d(info, &pgd[i]);
+ }
+
+ info->free_pgt_page(pgd, info->context);
+}
+
static void ident_pmd_init(struct x86_mapping_info *info, pmd_t *pmd_page,
unsigned long addr, unsigned long end)
{
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 7e177856ee4f..28002cc7a37d 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -469,7 +469,9 @@ phys_pte_init(pte_t *pte_page, unsigned long paddr, unsigned long paddr_end,
!e820__mapped_any(paddr & PAGE_MASK, paddr_next,
E820_TYPE_RAM) &&
!e820__mapped_any(paddr & PAGE_MASK, paddr_next,
- E820_TYPE_RESERVED_KERN))
+ E820_TYPE_RESERVED_KERN) &&
+ !e820__mapped_any(paddr & PAGE_MASK, paddr_next,
+ E820_TYPE_ACPI))
set_pte_init(pte, __pte(0), init);
continue;
}
@@ -524,7 +526,9 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long paddr, unsigned long paddr_end,
!e820__mapped_any(paddr & PMD_MASK, paddr_next,
E820_TYPE_RAM) &&
!e820__mapped_any(paddr & PMD_MASK, paddr_next,
- E820_TYPE_RESERVED_KERN))
+ E820_TYPE_RESERVED_KERN) &&
+ !e820__mapped_any(paddr & PMD_MASK, paddr_next,
+ E820_TYPE_ACPI))
set_pmd_init(pmd, __pmd(0), init);
continue;
}
@@ -611,7 +615,9 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end,
!e820__mapped_any(paddr & PUD_MASK, paddr_next,
E820_TYPE_RAM) &&
!e820__mapped_any(paddr & PUD_MASK, paddr_next,
- E820_TYPE_RESERVED_KERN))
+ E820_TYPE_RESERVED_KERN) &&
+ !e820__mapped_any(paddr & PUD_MASK, paddr_next,
+ E820_TYPE_ACPI))
set_pud_init(pud, __pud(0), init);
continue;
}
@@ -698,7 +704,9 @@ phys_p4d_init(p4d_t *p4d_page, unsigned long paddr, unsigned long paddr_end,
!e820__mapped_any(paddr & P4D_MASK, paddr_next,
E820_TYPE_RAM) &&
!e820__mapped_any(paddr & P4D_MASK, paddr_next,
- E820_TYPE_RESERVED_KERN))
+ E820_TYPE_RESERVED_KERN) &&
+ !e820__mapped_any(paddr & P4D_MASK, paddr_next,
+ E820_TYPE_ACPI))
set_p4d_init(p4d, __p4d(0), init);
continue;
}
diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c
index 422602f6039b..86a476a426c2 100644
--- a/arch/x86/mm/mem_encrypt_amd.c
+++ b/arch/x86/mm/mem_encrypt_amd.c
@@ -2,7 +2,7 @@
/*
* AMD Memory Encryption Support
*
- * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ * Copyright (C) 2016-2024 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <[email protected]>
*/
@@ -283,7 +283,7 @@ static void enc_dec_hypercall(unsigned long vaddr, unsigned long size, bool enc)
#endif
}
-static bool amd_enc_status_change_prepare(unsigned long vaddr, int npages, bool enc)
+static int amd_enc_status_change_prepare(unsigned long vaddr, int npages, bool enc)
{
/*
* To maintain the security guarantees of SEV-SNP guests, make sure
@@ -292,11 +292,11 @@ static bool amd_enc_status_change_prepare(unsigned long vaddr, int npages, bool
if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP) && !enc)
snp_set_memory_shared(vaddr, npages);
- return true;
+ return 0;
}
/* Return true unconditionally: return value doesn't matter for the SEV side */
-static bool amd_enc_status_change_finish(unsigned long vaddr, int npages, bool enc)
+static int amd_enc_status_change_finish(unsigned long vaddr, int npages, bool enc)
{
/*
* After memory is mapped encrypted in the page table, validate it
@@ -308,7 +308,7 @@ static bool amd_enc_status_change_finish(unsigned long vaddr, int npages, bool e
if (!cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT))
enc_dec_hypercall(vaddr, npages << PAGE_SHIFT, enc);
- return true;
+ return 0;
}
static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
@@ -510,6 +510,12 @@ void __init sme_early_init(void)
*/
x86_init.resources.dmi_setup = snp_dmi_setup;
}
+
+ /*
+ * Switch the SVSM CA mapping (if active) from identity mapped to
+ * kernel mapped.
+ */
+ snp_update_svsm_ca();
}
void __init mem_encrypt_free_decrypted_mem(void)
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index 19fdfbb171ed..443a97e515c0 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -662,8 +662,9 @@ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long star
/*
* Lookup the page table entry for a virtual address in a specific pgd.
- * Return a pointer to the entry, the level of the mapping, and the effective
- * NX and RW bits of all page table levels.
+ * Return a pointer to the entry (or NULL if the entry does not exist),
+ * the level of the entry, and the effective NX and RW bits of all
+ * page table levels.
*/
pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address,
unsigned int *level, bool *nx, bool *rw)
@@ -672,13 +673,14 @@ pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address,
pud_t *pud;
pmd_t *pmd;
- *level = PG_LEVEL_NONE;
+ *level = PG_LEVEL_256T;
*nx = false;
*rw = true;
if (pgd_none(*pgd))
return NULL;
+ *level = PG_LEVEL_512G;
*nx |= pgd_flags(*pgd) & _PAGE_NX;
*rw &= pgd_flags(*pgd) & _PAGE_RW;
@@ -686,10 +688,10 @@ pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address,
if (p4d_none(*p4d))
return NULL;
- *level = PG_LEVEL_512G;
if (p4d_leaf(*p4d) || !p4d_present(*p4d))
return (pte_t *)p4d;
+ *level = PG_LEVEL_1G;
*nx |= p4d_flags(*p4d) & _PAGE_NX;
*rw &= p4d_flags(*p4d) & _PAGE_RW;
@@ -697,10 +699,10 @@ pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address,
if (pud_none(*pud))
return NULL;
- *level = PG_LEVEL_1G;
if (pud_leaf(*pud) || !pud_present(*pud))
return (pte_t *)pud;
+ *level = PG_LEVEL_2M;
*nx |= pud_flags(*pud) & _PAGE_NX;
*rw &= pud_flags(*pud) & _PAGE_RW;
@@ -708,15 +710,13 @@ pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address,
if (pmd_none(*pmd))
return NULL;
- *level = PG_LEVEL_2M;
if (pmd_leaf(*pmd) || !pmd_present(*pmd))
return (pte_t *)pmd;
+ *level = PG_LEVEL_4K;
*nx |= pmd_flags(*pmd) & _PAGE_NX;
*rw &= pmd_flags(*pmd) & _PAGE_RW;
- *level = PG_LEVEL_4K;
-
return pte_offset_kernel(pmd, address);
}
@@ -736,9 +736,8 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
* Lookup the page table entry for a virtual address. Return a pointer
* to the entry and the level of the mapping.
*
- * Note: We return pud and pmd either when the entry is marked large
- * or when the present bit is not set. Otherwise we would return a
- * pointer to a nonexisting mapping.
+ * Note: the function returns p4d, pud or pmd either when the entry is marked
+ * large or when the present bit is not set. Otherwise it returns NULL.
*/
pte_t *lookup_address(unsigned long address, unsigned int *level)
{
@@ -2196,7 +2195,8 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc)
cpa_flush(&cpa, x86_platform.guest.enc_cache_flush_required());
/* Notify hypervisor that we are about to set/clr encryption attribute. */
- if (!x86_platform.guest.enc_status_change_prepare(addr, numpages, enc))
+ ret = x86_platform.guest.enc_status_change_prepare(addr, numpages, enc);
+ if (ret)
goto vmm_fail;
ret = __change_page_attr_set_clr(&cpa, 1);
@@ -2214,24 +2214,61 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc)
return ret;
/* Notify hypervisor that we have successfully set/clr encryption attribute. */
- if (!x86_platform.guest.enc_status_change_finish(addr, numpages, enc))
+ ret = x86_platform.guest.enc_status_change_finish(addr, numpages, enc);
+ if (ret)
goto vmm_fail;
return 0;
vmm_fail:
- WARN_ONCE(1, "CPA VMM failure to convert memory (addr=%p, numpages=%d) to %s.\n",
- (void *)addr, numpages, enc ? "private" : "shared");
+ WARN_ONCE(1, "CPA VMM failure to convert memory (addr=%p, numpages=%d) to %s: %d\n",
+ (void *)addr, numpages, enc ? "private" : "shared", ret);
+
+ return ret;
+}
+
+/*
+ * The lock serializes conversions between private and shared memory.
+ *
+ * It is taken for read on conversion. A write lock guarantees that no
+ * concurrent conversions are in progress.
+ */
+static DECLARE_RWSEM(mem_enc_lock);
+
+/*
+ * Stop new private<->shared conversions.
+ *
+ * Taking the exclusive mem_enc_lock waits for in-flight conversions to complete.
+ * The lock is not released to prevent new conversions from being started.
+ */
+bool set_memory_enc_stop_conversion(void)
+{
+ /*
+ * In a crash scenario, sleep is not allowed. Try to take the lock.
+ * Failure indicates that there is a race with the conversion.
+ */
+ if (oops_in_progress)
+ return down_write_trylock(&mem_enc_lock);
+
+ down_write(&mem_enc_lock);
- return -EIO;
+ return true;
}
static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)
{
- if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
- return __set_memory_enc_pgtable(addr, numpages, enc);
+ int ret = 0;
- return 0;
+ if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) {
+ if (!down_read_trylock(&mem_enc_lock))
+ return -EBUSY;
+
+ ret = __set_memory_enc_pgtable(addr, numpages, enc);
+
+ up_read(&mem_enc_lock);
+ }
+
+ return ret;
}
int set_memory_encrypted(unsigned long addr, int numpages)
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 8edd62206604..b433b1753016 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -216,7 +216,7 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
}
static const struct x86_cpu_id intel_mid_cpu_ids[] = {
- X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, NULL),
+ X86_MATCH_VFM(INTEL_ATOM_SILVERMONT_MID, NULL),
{}
};
@@ -233,9 +233,9 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
return 0;
ret = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
- if (ret < 0) {
+ if (ret) {
dev_warn(&dev->dev, "Failed to read interrupt line: %d\n", ret);
- return ret;
+ return pcibios_err_to_errno(ret);
}
id = x86_match_cpu(intel_mid_cpu_ids);
@@ -243,7 +243,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
model = id->model;
switch (model) {
- case INTEL_FAM6_ATOM_SILVERMONT_MID:
+ case VFM_MODEL(INTEL_ATOM_SILVERMONT_MID):
polarity_low = false;
/* Special treatment for IRQ0 */
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 652cd53e77f6..0f2fe524f60d 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -38,10 +38,10 @@ static int xen_pcifront_enable_irq(struct pci_dev *dev)
u8 gsi;
rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
- if (rc < 0) {
+ if (rc) {
dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
rc);
- return rc;
+ return pcibios_err_to_errno(rc);
}
/* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
pirq = gsi;
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index 543df9a1379d..500cab4a7f7c 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -5,5 +5,4 @@ GCOV_PROFILE := n
obj-$(CONFIG_EFI) += memmap.o quirks.o efi.o efi_$(BITS).o \
efi_stub_$(BITS).o
obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o
-obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o
obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index f090ec972d7b..88a96816de9a 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -226,8 +226,6 @@ int __init efi_memblock_x86_reserve_range(void)
if (add_efi_memmap || do_efi_soft_reserve())
do_add_efi_memmap();
- efi_fake_memmap_early();
-
WARN(efi.memmap.desc_version != 1,
"Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
efi.memmap.desc_version);
diff --git a/arch/x86/platform/efi/fake_mem.c b/arch/x86/platform/efi/fake_mem.c
deleted file mode 100644
index 41d57cad3d84..000000000000
--- a/arch/x86/platform/efi/fake_mem.c
+++ /dev/null
@@ -1,197 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * fake_mem.c
- *
- * Copyright (C) 2015 FUJITSU LIMITED
- * Author: Taku Izumi <[email protected]>
- *
- * This code introduces new boot option named "efi_fake_mem"
- * By specifying this parameter, you can add arbitrary attribute to
- * specific memory range by updating original (firmware provided) EFI
- * memmap.
- */
-
-#include <linux/kernel.h>
-#include <linux/efi.h>
-#include <linux/init.h>
-#include <linux/memblock.h>
-#include <linux/types.h>
-#include <linux/sort.h>
-#include <asm/e820/api.h>
-#include <asm/efi.h>
-
-#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKE_MEM
-
-static struct efi_mem_range efi_fake_mems[EFI_MAX_FAKEMEM];
-static int nr_fake_mem;
-
-static int __init cmp_fake_mem(const void *x1, const void *x2)
-{
- const struct efi_mem_range *m1 = x1;
- const struct efi_mem_range *m2 = x2;
-
- if (m1->range.start < m2->range.start)
- return -1;
- if (m1->range.start > m2->range.start)
- return 1;
- return 0;
-}
-
-static void __init efi_fake_range(struct efi_mem_range *efi_range)
-{
- struct efi_memory_map_data data = { 0 };
- int new_nr_map = efi.memmap.nr_map;
- efi_memory_desc_t *md;
- void *new_memmap;
-
- /* count up the number of EFI memory descriptor */
- for_each_efi_memory_desc(md)
- new_nr_map += efi_memmap_split_count(md, &efi_range->range);
-
- /* allocate memory for new EFI memmap */
- if (efi_memmap_alloc(new_nr_map, &data) != 0)
- return;
-
- /* create new EFI memmap */
- new_memmap = early_memremap(data.phys_map, data.size);
- if (!new_memmap) {
- __efi_memmap_free(data.phys_map, data.size, data.flags);
- return;
- }
-
- efi_memmap_insert(&efi.memmap, new_memmap, efi_range);
-
- /* swap into new EFI memmap */
- early_memunmap(new_memmap, data.size);
-
- efi_memmap_install(&data);
-}
-
-void __init efi_fake_memmap(void)
-{
- int i;
-
- if (!efi_enabled(EFI_MEMMAP) || !nr_fake_mem)
- return;
-
- for (i = 0; i < nr_fake_mem; i++)
- efi_fake_range(&efi_fake_mems[i]);
-
- /* print new EFI memmap */
- efi_print_memmap();
-}
-
-static int __init setup_fake_mem(char *p)
-{
- u64 start = 0, mem_size = 0, attribute = 0;
- int i;
-
- if (!p)
- return -EINVAL;
-
- while (*p != '\0') {
- mem_size = memparse(p, &p);
- if (*p == '@')
- start = memparse(p+1, &p);
- else
- break;
-
- if (*p == ':')
- attribute = simple_strtoull(p+1, &p, 0);
- else
- break;
-
- if (nr_fake_mem >= EFI_MAX_FAKEMEM)
- break;
-
- efi_fake_mems[nr_fake_mem].range.start = start;
- efi_fake_mems[nr_fake_mem].range.end = start + mem_size - 1;
- efi_fake_mems[nr_fake_mem].attribute = attribute;
- nr_fake_mem++;
-
- if (*p == ',')
- p++;
- }
-
- sort(efi_fake_mems, nr_fake_mem, sizeof(struct efi_mem_range),
- cmp_fake_mem, NULL);
-
- for (i = 0; i < nr_fake_mem; i++)
- pr_info("efi_fake_mem: add attr=0x%016llx to [mem 0x%016llx-0x%016llx]",
- efi_fake_mems[i].attribute, efi_fake_mems[i].range.start,
- efi_fake_mems[i].range.end);
-
- return *p == '\0' ? 0 : -EINVAL;
-}
-
-early_param("efi_fake_mem", setup_fake_mem);
-
-void __init efi_fake_memmap_early(void)
-{
- int i;
-
- /*
- * The late efi_fake_mem() call can handle all requests if
- * EFI_MEMORY_SP support is disabled.
- */
- if (!efi_soft_reserve_enabled())
- return;
-
- if (!efi_enabled(EFI_MEMMAP) || !nr_fake_mem)
- return;
-
- /*
- * Given that efi_fake_memmap() needs to perform memblock
- * allocations it needs to run after e820__memblock_setup().
- * However, if efi_fake_mem specifies EFI_MEMORY_SP for a given
- * address range that potentially needs to mark the memory as
- * reserved prior to e820__memblock_setup(). Update e820
- * directly if EFI_MEMORY_SP is specified for an
- * EFI_CONVENTIONAL_MEMORY descriptor.
- */
- for (i = 0; i < nr_fake_mem; i++) {
- struct efi_mem_range *mem = &efi_fake_mems[i];
- efi_memory_desc_t *md;
- u64 m_start, m_end;
-
- if ((mem->attribute & EFI_MEMORY_SP) == 0)
- continue;
-
- m_start = mem->range.start;
- m_end = mem->range.end;
- for_each_efi_memory_desc(md) {
- u64 start, end, size;
-
- if (md->type != EFI_CONVENTIONAL_MEMORY)
- continue;
-
- start = md->phys_addr;
- end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
-
- if (m_start <= end && m_end >= start)
- /* fake range overlaps descriptor */;
- else
- continue;
-
- /*
- * Trim the boundary of the e820 update to the
- * descriptor in case the fake range overlaps
- * !EFI_CONVENTIONAL_MEMORY
- */
- start = max(start, m_start);
- end = min(end, m_end);
- size = end - start + 1;
-
- if (end <= start)
- continue;
-
- /*
- * Ensure each efi_fake_mem instance results in
- * a unique e820 resource
- */
- e820__range_remove(start, size, E820_TYPE_RAM, 1);
- e820__range_add(start, size, E820_TYPE_SOFT_RESERVED);
- e820__update_table(e820_table);
- }
- }
-}
diff --git a/arch/x86/platform/efi/memmap.c b/arch/x86/platform/efi/memmap.c
index 6ed1935504b9..061b8ecc71a1 100644
--- a/arch/x86/platform/efi/memmap.c
+++ b/arch/x86/platform/efi/memmap.c
@@ -30,6 +30,7 @@ static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size)
return PFN_PHYS(page_to_pfn(p));
}
+static
void __init __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags)
{
if (flags & EFI_MEMMAP_MEMBLOCK) {
diff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c
index 7be71c2cdc83..f83bbe0acd4a 100644
--- a/arch/x86/platform/intel-mid/intel-mid.c
+++ b/arch/x86/platform/intel-mid/intel-mid.c
@@ -22,6 +22,7 @@
#include <asm/mpspec_def.h>
#include <asm/hw_irq.h>
#include <asm/apic.h>
+#include <asm/cpu_device_id.h>
#include <asm/io_apic.h>
#include <asm/intel-mid.h>
#include <asm/io.h>
@@ -55,9 +56,8 @@ static void __init intel_mid_time_init(void)
static void intel_mid_arch_setup(void)
{
- switch (boot_cpu_data.x86_model) {
- case 0x3C:
- case 0x4A:
+ switch (boot_cpu_data.x86_vfm) {
+ case INTEL_ATOM_SILVERMONT_MID:
x86_platform.legacy.rtc = 1;
break;
default:
diff --git a/arch/x86/platform/intel/iosf_mbi.c b/arch/x86/platform/intel/iosf_mbi.c
index fdd49d70b437..c81cea208c2c 100644
--- a/arch/x86/platform/intel/iosf_mbi.c
+++ b/arch/x86/platform/intel/iosf_mbi.c
@@ -62,7 +62,7 @@ static int iosf_mbi_pci_read_mdr(u32 mcrx, u32 mcr, u32 *mdr)
fail_read:
dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
- return result;
+ return pcibios_err_to_errno(result);
}
static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr)
@@ -91,7 +91,7 @@ static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr)
fail_write:
dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
- return result;
+ return pcibios_err_to_errno(result);
}
int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr)
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c
index 89df5d89d664..51655133eee3 100644
--- a/arch/x86/um/sys_call_table_32.c
+++ b/arch/x86/um/sys_call_table_32.c
@@ -9,6 +9,10 @@
#include <linux/cache.h>
#include <asm/syscall.h>
+extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long, unsigned long);
+
/*
* Below you can see, in terms of #define's, the differences between the x86-64
* and the UML syscall table.
@@ -22,15 +26,13 @@
#define sys_vm86 sys_ni_syscall
#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
+#define __SYSCALL_NORETURN __SYSCALL
#define __SYSCALL(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
#include <asm/syscalls_32.h>
+#undef __SYSCALL
-#undef __SYSCALL
#define __SYSCALL(nr, sym) sym,
-
-extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
-
const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = {
#include <asm/syscalls_32.h>
};
diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c
index b0b4cfd2308c..943d414f2109 100644
--- a/arch/x86/um/sys_call_table_64.c
+++ b/arch/x86/um/sys_call_table_64.c
@@ -9,6 +9,10 @@
#include <linux/cache.h>
#include <asm/syscall.h>
+extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long, unsigned long);
+
/*
* Below you can see, in terms of #define's, the differences between the x86-64
* and the UML syscall table.
@@ -18,14 +22,13 @@
#define sys_iopl sys_ni_syscall
#define sys_ioperm sys_ni_syscall
+#define __SYSCALL_NORETURN __SYSCALL
+
#define __SYSCALL(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
#include <asm/syscalls_64.h>
+#undef __SYSCALL
-#undef __SYSCALL
#define __SYSCALL(nr, sym) sym,
-
-extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
-
const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = {
#include <asm/syscalls_64.h>
};
diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c
index 0ae10535c699..0ce17766c0e5 100644
--- a/arch/x86/virt/svm/sev.c
+++ b/arch/x86/virt/svm/sev.c
@@ -120,7 +120,7 @@ static __init void snp_enable(void *arg)
bool snp_probe_rmptable_info(void)
{
- u64 max_rmp_pfn, calc_rmp_sz, rmp_sz, rmp_base, rmp_end;
+ u64 rmp_sz, rmp_base, rmp_end;
rdmsrl(MSR_AMD64_RMP_BASE, rmp_base);
rdmsrl(MSR_AMD64_RMP_END, rmp_end);
@@ -137,28 +137,11 @@ bool snp_probe_rmptable_info(void)
rmp_sz = rmp_end - rmp_base + 1;
- /*
- * Calculate the amount the memory that must be reserved by the BIOS to
- * address the whole RAM, including the bookkeeping area. The RMP itself
- * must also be covered.
- */
- max_rmp_pfn = max_pfn;
- if (PHYS_PFN(rmp_end) > max_pfn)
- max_rmp_pfn = PHYS_PFN(rmp_end);
-
- calc_rmp_sz = (max_rmp_pfn << 4) + RMPTABLE_CPU_BOOKKEEPING_SZ;
-
- if (calc_rmp_sz > rmp_sz) {
- pr_err("Memory reserved for the RMP table does not cover full system RAM (expected 0x%llx got 0x%llx)\n",
- calc_rmp_sz, rmp_sz);
- return false;
- }
-
probed_rmp_base = rmp_base;
probed_rmp_size = rmp_sz;
pr_info("RMP table physical range [0x%016llx - 0x%016llx]\n",
- probed_rmp_base, probed_rmp_base + probed_rmp_size - 1);
+ rmp_base, rmp_end);
return true;
}
@@ -206,9 +189,8 @@ void __init snp_fixup_e820_tables(void)
*/
static int __init snp_rmptable_init(void)
{
+ u64 max_rmp_pfn, calc_rmp_sz, rmptable_size, rmp_end, val;
void *rmptable_start;
- u64 rmptable_size;
- u64 val;
if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
return 0;
@@ -219,10 +201,28 @@ static int __init snp_rmptable_init(void)
if (!probed_rmp_size)
goto nosnp;
+ rmp_end = probed_rmp_base + probed_rmp_size - 1;
+
+ /*
+ * Calculate the amount the memory that must be reserved by the BIOS to
+ * address the whole RAM, including the bookkeeping area. The RMP itself
+ * must also be covered.
+ */
+ max_rmp_pfn = max_pfn;
+ if (PFN_UP(rmp_end) > max_pfn)
+ max_rmp_pfn = PFN_UP(rmp_end);
+
+ calc_rmp_sz = (max_rmp_pfn << 4) + RMPTABLE_CPU_BOOKKEEPING_SZ;
+ if (calc_rmp_sz > probed_rmp_size) {
+ pr_err("Memory reserved for the RMP table does not cover full system RAM (expected 0x%llx got 0x%llx)\n",
+ calc_rmp_sz, probed_rmp_size);
+ goto nosnp;
+ }
+
rmptable_start = memremap(probed_rmp_base, probed_rmp_size, MEMREMAP_WB);
if (!rmptable_start) {
pr_err("Failed to map RMP table\n");
- return 1;
+ goto nosnp;
}
/*
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 49a1c6890b55..4e2b2e2ac9f9 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -33,7 +33,7 @@
#include <asm/msr.h>
#include <asm/cpufeature.h>
#include <asm/tdx.h>
-#include <asm/intel-family.h>
+#include <asm/cpu_device_id.h>
#include <asm/processor.h>
#include <asm/mce.h>
#include "tdx.h"
@@ -1426,9 +1426,9 @@ static void __init check_tdx_erratum(void)
* private memory poisons that memory, and a subsequent read of
* that memory triggers #MC.
*/
- switch (boot_cpu_data.x86_model) {
- case INTEL_FAM6_SAPPHIRERAPIDS_X:
- case INTEL_FAM6_EMERALDRAPIDS_X:
+ switch (boot_cpu_data.x86_vfm) {
+ case INTEL_SAPPHIRERAPIDS_X:
+ case INTEL_EMERALDRAPIDS_X:
setup_force_cpu_bug(X86_BUG_TDX_PW_MCE);
}
}
diff --git a/arch/xtensa/include/asm/current.h b/arch/xtensa/include/asm/current.h
index 08010dbf5e09..df275d554788 100644
--- a/arch/xtensa/include/asm/current.h
+++ b/arch/xtensa/include/asm/current.h
@@ -19,7 +19,7 @@
struct task_struct;
-static inline struct task_struct *get_current(void)
+static __always_inline struct task_struct *get_current(void)
{
return current_thread_info()->task;
}
diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h
index 326db1c1d5d8..e0dffcc43b9e 100644
--- a/arch/xtensa/include/asm/thread_info.h
+++ b/arch/xtensa/include/asm/thread_info.h
@@ -91,7 +91,7 @@ struct thread_info {
}
/* how to get the thread information struct from C */
-static inline struct thread_info *current_thread_info(void)
+static __always_inline struct thread_info *current_thread_info(void)
{
struct thread_info *ti;
__asm__("extui %0, a1, 0, "__stringify(CURRENT_SHIFT)"\n\t"
diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h
index b52236245e51..30af4dc3ce7b 100644
--- a/arch/xtensa/include/asm/unistd.h
+++ b/arch/xtensa/include/asm/unistd.h
@@ -3,7 +3,6 @@
#define _XTENSA_UNISTD_H
#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
#include <uapi/asm/unistd.h>
#define __ARCH_WANT_NEW_STAT
diff --git a/arch/xtensa/platforms/iss/simdisk.c b/arch/xtensa/platforms/iss/simdisk.c
index defc67909a9c..d6d2b533a574 100644
--- a/arch/xtensa/platforms/iss/simdisk.c
+++ b/arch/xtensa/platforms/iss/simdisk.c
@@ -263,6 +263,9 @@ static const struct proc_ops simdisk_proc_ops = {
static int __init simdisk_setup(struct simdisk *dev, int which,
struct proc_dir_entry *procdir)
{
+ struct queue_limits lim = {
+ .features = BLK_FEAT_ROTATIONAL,
+ };
char tmp[2] = { '0' + which, 0 };
int err;
@@ -271,7 +274,7 @@ static int __init simdisk_setup(struct simdisk *dev, int which,
spin_lock_init(&dev->lock);
dev->users = 0;
- dev->gd = blk_alloc_disk(NULL, NUMA_NO_NODE);
+ dev->gd = blk_alloc_disk(&lim, NUMA_NO_NODE);
if (IS_ERR(dev->gd)) {
err = PTR_ERR(dev->gd);
goto out;
diff --git a/block/Kconfig b/block/Kconfig
index dc12af58dbae..5b623b876d3b 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -62,6 +62,8 @@ config BLK_DEV_BSGLIB
config BLK_DEV_INTEGRITY
bool "Block layer data integrity support"
+ select CRC_T10DIF
+ select CRC64_ROCKSOFT
help
Some storage devices allow extra information to be
stored/retrieved to help protect the data. The block layer
@@ -72,12 +74,6 @@ config BLK_DEV_INTEGRITY
T10/SCSI Data Integrity Field or the T13/ATA External Path
Protection. If in doubt, say N.
-config BLK_DEV_INTEGRITY_T10
- tristate
- depends on BLK_DEV_INTEGRITY
- select CRC_T10DIF
- select CRC64_ROCKSOFT
-
config BLK_DEV_WRITE_MOUNTED
bool "Allow writing to mounted block devices"
default y
diff --git a/block/Makefile b/block/Makefile
index 168150b9c510..ddfd21c1a9ff 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -26,8 +26,7 @@ obj-$(CONFIG_MQ_IOSCHED_KYBER) += kyber-iosched.o
bfq-y := bfq-iosched.o bfq-wf2q.o bfq-cgroup.o
obj-$(CONFIG_IOSCHED_BFQ) += bfq.o
-obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o
-obj-$(CONFIG_BLK_DEV_INTEGRITY_T10) += t10-pi.o
+obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o
obj-$(CONFIG_BLK_MQ_PCI) += blk-mq-pci.o
obj-$(CONFIG_BLK_MQ_VIRTIO) += blk-mq-virtio.o
obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned.o
diff --git a/block/bdev.c b/block/bdev.c
index 353677ac49b3..c5507b6f63b8 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -385,7 +385,7 @@ static struct file_system_type bd_type = {
};
struct super_block *blockdev_superblock __ro_after_init;
-struct vfsmount *blockdev_mnt __ro_after_init;
+static struct vfsmount *blockdev_mnt __ro_after_init;
EXPORT_SYMBOL_GPL(blockdev_superblock);
void __init bdev_cache_init(void)
@@ -1260,23 +1260,42 @@ void sync_bdevs(bool wait)
}
/*
- * Handle STATX_DIOALIGN for block devices.
- *
- * Note that the inode passed to this is the inode of a block device node file,
- * not the block device's internal inode. Therefore it is *not* valid to use
- * I_BDEV() here; the block device has to be looked up by i_rdev instead.
+ * Handle STATX_{DIOALIGN, WRITE_ATOMIC} for block devices.
*/
-void bdev_statx_dioalign(struct inode *inode, struct kstat *stat)
+void bdev_statx(struct path *path, struct kstat *stat,
+ u32 request_mask)
{
+ struct inode *backing_inode;
struct block_device *bdev;
- bdev = blkdev_get_no_open(inode->i_rdev);
+ if (!(request_mask & (STATX_DIOALIGN | STATX_WRITE_ATOMIC)))
+ return;
+
+ backing_inode = d_backing_inode(path->dentry);
+
+ /*
+ * Note that backing_inode is the inode of a block device node file,
+ * not the block device's internal inode. Therefore it is *not* valid
+ * to use I_BDEV() here; the block device has to be looked up by i_rdev
+ * instead.
+ */
+ bdev = blkdev_get_no_open(backing_inode->i_rdev);
if (!bdev)
return;
- stat->dio_mem_align = bdev_dma_alignment(bdev) + 1;
- stat->dio_offset_align = bdev_logical_block_size(bdev);
- stat->result_mask |= STATX_DIOALIGN;
+ if (request_mask & STATX_DIOALIGN) {
+ stat->dio_mem_align = bdev_dma_alignment(bdev) + 1;
+ stat->dio_offset_align = bdev_logical_block_size(bdev);
+ stat->result_mask |= STATX_DIOALIGN;
+ }
+
+ if (request_mask & STATX_WRITE_ATOMIC && bdev_can_atomic_write(bdev)) {
+ struct request_queue *bd_queue = bdev->bd_queue;
+
+ generic_fill_statx_atomic_writes(stat,
+ queue_atomic_write_unit_min_bytes(bd_queue),
+ queue_atomic_write_unit_max_bytes(bd_queue));
+ }
blkdev_put_no_open(bdev);
}
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index d442ee358fc2..b758693697c0 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -797,57 +797,6 @@ void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio)
*/
bfq_link_bfqg(bfqd, bfqg);
__bfq_bic_change_cgroup(bfqd, bic, bfqg);
- /*
- * Update blkg_path for bfq_log_* functions. We cache this
- * path, and update it here, for the following
- * reasons. Operations on blkg objects in blk-cgroup are
- * protected with the request_queue lock, and not with the
- * lock that protects the instances of this scheduler
- * (bfqd->lock). This exposes BFQ to the following sort of
- * race.
- *
- * The blkg_lookup performed in bfq_get_queue, protected
- * through rcu, may happen to return the address of a copy of
- * the original blkg. If this is the case, then the
- * bfqg_and_blkg_get performed in bfq_get_queue, to pin down
- * the blkg, is useless: it does not prevent blk-cgroup code
- * from destroying both the original blkg and all objects
- * directly or indirectly referred by the copy of the
- * blkg.
- *
- * On the bright side, destroy operations on a blkg invoke, as
- * a first step, hooks of the scheduler associated with the
- * blkg. And these hooks are executed with bfqd->lock held for
- * BFQ. As a consequence, for any blkg associated with the
- * request queue this instance of the scheduler is attached
- * to, we are guaranteed that such a blkg is not destroyed, and
- * that all the pointers it contains are consistent, while we
- * are holding bfqd->lock. A blkg_lookup performed with
- * bfqd->lock held then returns a fully consistent blkg, which
- * remains consistent until this lock is held.
- *
- * Thanks to the last fact, and to the fact that: (1) bfqg has
- * been obtained through a blkg_lookup in the above
- * assignment, and (2) bfqd->lock is being held, here we can
- * safely use the policy data for the involved blkg (i.e., the
- * field bfqg->pd) to get to the blkg associated with bfqg,
- * and then we can safely use any field of blkg. After we
- * release bfqd->lock, even just getting blkg through this
- * bfqg may cause dangling references to be traversed, as
- * bfqg->pd may not exist any more.
- *
- * In view of the above facts, here we cache, in the bfqg, any
- * blkg data we may need for this bic, and for its associated
- * bfq_queue. As of now, we need to cache only the path of the
- * blkg, which is used in the bfq_log_* functions.
- *
- * Finally, note that bfqg itself needs to be protected from
- * destruction on the blkg_free of the original blkg (which
- * invokes bfq_pd_free). We use an additional private
- * refcounter for bfqg, to let it disappear only after no
- * bfq_queue refers to it any longer.
- */
- blkg_path(bfqg_to_blkg(bfqg), bfqg->blkg_path, sizeof(bfqg->blkg_path));
bic->blkcg_serial_nr = serial_nr;
}
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 4b88a54a9b76..36a4998c4b37 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -5463,40 +5463,42 @@ static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync,
}
}
+static void _bfq_exit_icq(struct bfq_io_cq *bic, unsigned int num_actuators)
+{
+ struct bfq_iocq_bfqq_data *bfqq_data = bic->bfqq_data;
+ unsigned int act_idx;
+
+ for (act_idx = 0; act_idx < num_actuators; act_idx++) {
+ if (bfqq_data[act_idx].stable_merge_bfqq)
+ bfq_put_stable_ref(bfqq_data[act_idx].stable_merge_bfqq);
+
+ bfq_exit_icq_bfqq(bic, true, act_idx);
+ bfq_exit_icq_bfqq(bic, false, act_idx);
+ }
+}
+
static void bfq_exit_icq(struct io_cq *icq)
{
struct bfq_io_cq *bic = icq_to_bic(icq);
struct bfq_data *bfqd = bic_to_bfqd(bic);
unsigned long flags;
- unsigned int act_idx;
+
/*
* If bfqd and thus bfqd->num_actuators is not available any
* longer, then cycle over all possible per-actuator bfqqs in
* next loop. We rely on bic being zeroed on creation, and
* therefore on its unused per-actuator fields being NULL.
- */
- unsigned int num_actuators = BFQ_MAX_ACTUATORS;
- struct bfq_iocq_bfqq_data *bfqq_data = bic->bfqq_data;
-
- /*
+ *
* bfqd is NULL if scheduler already exited, and in that case
* this is the last time these queues are accessed.
*/
if (bfqd) {
spin_lock_irqsave(&bfqd->lock, flags);
- num_actuators = bfqd->num_actuators;
- }
-
- for (act_idx = 0; act_idx < num_actuators; act_idx++) {
- if (bfqq_data[act_idx].stable_merge_bfqq)
- bfq_put_stable_ref(bfqq_data[act_idx].stable_merge_bfqq);
-
- bfq_exit_icq_bfqq(bic, true, act_idx);
- bfq_exit_icq_bfqq(bic, false, act_idx);
- }
-
- if (bfqd)
+ _bfq_exit_icq(bic, bfqd->num_actuators);
spin_unlock_irqrestore(&bfqd->lock, flags);
+ } else {
+ _bfq_exit_icq(bic, BFQ_MAX_ACTUATORS);
+ }
}
/*
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
index 467e8cfc41a2..08ddf2cfae5b 100644
--- a/block/bfq-iosched.h
+++ b/block/bfq-iosched.h
@@ -1003,9 +1003,6 @@ struct bfq_group {
/* must be the first member */
struct blkg_policy_data pd;
- /* cached path for this blkg (see comments in bfq_bic_update_cgroup) */
- char blkg_path[128];
-
/* reference counter (see comments in bfq_bic_update_cgroup) */
refcount_t ref;
diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index 8b528e12136f..b78c145eb026 100644
--- a/block/bio-integrity.c
+++ b/block/bio-integrity.c
@@ -76,7 +76,7 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
&bip->bip_max_vcnt, gfp_mask);
if (!bip->bip_vec)
goto err;
- } else {
+ } else if (nr_vecs) {
bip->bip_vec = bip->bip_inline_vecs;
}
@@ -276,6 +276,7 @@ static int bio_integrity_copy_user(struct bio *bio, struct bio_vec *bvec,
bip->bip_flags |= BIP_INTEGRITY_USER | BIP_COPY_USER;
bip->bip_iter.bi_sector = seed;
+ bip->bip_vcnt = nr_vecs;
return 0;
free_bip:
bio_integrity_free(bio);
@@ -297,6 +298,7 @@ static int bio_integrity_init_user(struct bio *bio, struct bio_vec *bvec,
bip->bip_flags |= BIP_INTEGRITY_USER;
bip->bip_iter.bi_sector = seed;
bip->bip_iter.bi_size = len;
+ bip->bip_vcnt = nr_vecs;
return 0;
}
@@ -334,7 +336,7 @@ int bio_integrity_map_user(struct bio *bio, void __user *ubuf, ssize_t bytes,
u32 seed)
{
struct request_queue *q = bdev_get_queue(bio->bi_bdev);
- unsigned int align = q->dma_pad_mask | queue_dma_alignment(q);
+ unsigned int align = blk_lim_dma_alignment_and_pad(&q->limits);
struct page *stack_pages[UIO_FASTIOV], **pages = stack_pages;
struct bio_vec stack_vec[UIO_FASTIOV], *bvec = stack_vec;
unsigned int direction, nr_bvecs;
@@ -397,44 +399,6 @@ free_bvec:
EXPORT_SYMBOL_GPL(bio_integrity_map_user);
/**
- * bio_integrity_process - Process integrity metadata for a bio
- * @bio: bio to generate/verify integrity metadata for
- * @proc_iter: iterator to process
- * @proc_fn: Pointer to the relevant processing function
- */
-static blk_status_t bio_integrity_process(struct bio *bio,
- struct bvec_iter *proc_iter, integrity_processing_fn *proc_fn)
-{
- struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
- struct blk_integrity_iter iter;
- struct bvec_iter bviter;
- struct bio_vec bv;
- struct bio_integrity_payload *bip = bio_integrity(bio);
- blk_status_t ret = BLK_STS_OK;
-
- iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
- iter.interval = 1 << bi->interval_exp;
- iter.tuple_size = bi->tuple_size;
- iter.seed = proc_iter->bi_sector;
- iter.prot_buf = bvec_virt(bip->bip_vec);
- iter.pi_offset = bi->pi_offset;
-
- __bio_for_each_segment(bv, bio, bviter, *proc_iter) {
- void *kaddr = bvec_kmap_local(&bv);
-
- iter.data_buf = kaddr;
- iter.data_size = bv.bv_len;
- ret = proc_fn(&iter);
- kunmap_local(kaddr);
-
- if (ret)
- break;
-
- }
- return ret;
-}
-
-/**
* bio_integrity_prep - Prepare bio for integrity I/O
* @bio: bio to prepare
*
@@ -450,17 +414,13 @@ bool bio_integrity_prep(struct bio *bio)
{
struct bio_integrity_payload *bip;
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
+ unsigned int len;
void *buf;
- unsigned long start, end;
- unsigned int len, nr_pages;
- unsigned int bytes, offset, i;
+ gfp_t gfp = GFP_NOIO;
if (!bi)
return true;
- if (bio_op(bio) != REQ_OP_READ && bio_op(bio) != REQ_OP_WRITE)
- return true;
-
if (!bio_sectors(bio))
return true;
@@ -468,32 +428,36 @@ bool bio_integrity_prep(struct bio *bio)
if (bio_integrity(bio))
return true;
- if (bio_data_dir(bio) == READ) {
- if (!bi->profile->verify_fn ||
- !(bi->flags & BLK_INTEGRITY_VERIFY))
+ switch (bio_op(bio)) {
+ case REQ_OP_READ:
+ if (bi->flags & BLK_INTEGRITY_NOVERIFY)
return true;
- } else {
- if (!bi->profile->generate_fn ||
- !(bi->flags & BLK_INTEGRITY_GENERATE))
+ break;
+ case REQ_OP_WRITE:
+ if (bi->flags & BLK_INTEGRITY_NOGENERATE)
return true;
+
+ /*
+ * Zero the memory allocated to not leak uninitialized kernel
+ * memory to disk for non-integrity metadata where nothing else
+ * initializes the memory.
+ */
+ if (bi->csum_type == BLK_INTEGRITY_CSUM_NONE)
+ gfp |= __GFP_ZERO;
+ break;
+ default:
+ return true;
}
/* Allocate kernel buffer for protection data */
len = bio_integrity_bytes(bi, bio_sectors(bio));
- buf = kmalloc(len, GFP_NOIO);
+ buf = kmalloc(len, gfp);
if (unlikely(buf == NULL)) {
- printk(KERN_ERR "could not allocate integrity buffer\n");
goto err_end_io;
}
- end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
- start = ((unsigned long) buf) >> PAGE_SHIFT;
- nr_pages = end - start;
-
- /* Allocate bio integrity payload and integrity vectors */
- bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages);
+ bip = bio_integrity_alloc(bio, GFP_NOIO, 1);
if (IS_ERR(bip)) {
- printk(KERN_ERR "could not allocate data integrity bioset\n");
kfree(buf);
goto err_end_io;
}
@@ -501,35 +465,20 @@ bool bio_integrity_prep(struct bio *bio)
bip->bip_flags |= BIP_BLOCK_INTEGRITY;
bip_set_seed(bip, bio->bi_iter.bi_sector);
- if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM)
+ if (bi->csum_type == BLK_INTEGRITY_CSUM_IP)
bip->bip_flags |= BIP_IP_CHECKSUM;
- /* Map it */
- offset = offset_in_page(buf);
- for (i = 0; i < nr_pages && len > 0; i++) {
- bytes = PAGE_SIZE - offset;
-
- if (bytes > len)
- bytes = len;
-
- if (bio_integrity_add_page(bio, virt_to_page(buf),
- bytes, offset) < bytes) {
- printk(KERN_ERR "could not attach integrity payload\n");
- goto err_end_io;
- }
-
- buf += bytes;
- len -= bytes;
- offset = 0;
+ if (bio_integrity_add_page(bio, virt_to_page(buf), len,
+ offset_in_page(buf)) < len) {
+ printk(KERN_ERR "could not attach integrity payload\n");
+ goto err_end_io;
}
/* Auto-generate integrity metadata if this is a write */
- if (bio_data_dir(bio) == WRITE) {
- bio_integrity_process(bio, &bio->bi_iter,
- bi->profile->generate_fn);
- } else {
+ if (bio_data_dir(bio) == WRITE)
+ blk_integrity_generate(bio);
+ else
bip->bio_iter = bio->bi_iter;
- }
return true;
err_end_io:
@@ -552,15 +501,8 @@ static void bio_integrity_verify_fn(struct work_struct *work)
struct bio_integrity_payload *bip =
container_of(work, struct bio_integrity_payload, bip_work);
struct bio *bio = bip->bip_bio;
- struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
- /*
- * At the moment verify is called bio's iterator was advanced
- * during split and completion, we need to rewind iterator to
- * it's original position.
- */
- bio->bi_status = bio_integrity_process(bio, &bip->bio_iter,
- bi->profile->verify_fn);
+ blk_integrity_verify(bio);
bio_integrity_free(bio);
bio_endio(bio);
}
@@ -582,7 +524,7 @@ bool __bio_integrity_endio(struct bio *bio)
struct bio_integrity_payload *bip = bio_integrity(bio);
if (bio_op(bio) == REQ_OP_READ && !bio->bi_status &&
- (bip->bip_flags & BIP_BLOCK_INTEGRITY) && bi->profile->verify_fn) {
+ (bip->bip_flags & BIP_BLOCK_INTEGRITY) && bi->csum_type) {
INIT_WORK(&bip->bip_work, bio_integrity_verify_fn);
queue_work(kintegrityd_wq, &bip->bip_work);
return false;
@@ -642,14 +584,11 @@ int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
BUG_ON(bip_src == NULL);
- bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
+ bip = bio_integrity_alloc(bio, gfp_mask, 0);
if (IS_ERR(bip))
return PTR_ERR(bip);
- memcpy(bip->bip_vec, bip_src->bip_vec,
- bip_src->bip_vcnt * sizeof(struct bio_vec));
-
- bip->bip_vcnt = bip_src->bip_vcnt;
+ bip->bip_vec = bip_src->bip_vec;
bip->bip_iter = bip_src->bip_iter;
bip->bip_flags = bip_src->bip_flags & ~BIP_BLOCK_INTEGRITY;
diff --git a/block/bio.c b/block/bio.c
index e9e809a63c59..a3b1b2266c50 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -953,7 +953,7 @@ bool bvec_try_merge_hw_page(struct request_queue *q, struct bio_vec *bv,
bool *same_page)
{
unsigned long mask = queue_segment_boundary(q);
- phys_addr_t addr1 = page_to_phys(bv->bv_page) + bv->bv_offset;
+ phys_addr_t addr1 = bvec_phys(bv);
phys_addr_t addr2 = page_to_phys(page) + offset + len - 1;
if ((addr1 | mask) != (addr2 | mask))
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 90b3959d88cf..bd472a30bc61 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -301,19 +301,6 @@ static inline struct blkcg *cpd_to_blkcg(struct blkcg_policy_data *cpd)
}
/**
- * blkg_path - format cgroup path of blkg
- * @blkg: blkg of interest
- * @buf: target buffer
- * @buflen: target buffer length
- *
- * Format the path of the cgroup of @blkg into @buf.
- */
-static inline int blkg_path(struct blkcg_gq *blkg, char *buf, int buflen)
-{
- return cgroup_path(blkg->blkcg->css.cgroup, buf, buflen);
-}
-
-/**
* blkg_get - get a blkg reference
* @blkg: blkg to get
*
diff --git a/block/blk-core.c b/block/blk-core.c
index 82c3ae22d76d..02bceeb36f2c 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -94,20 +94,6 @@ void blk_queue_flag_clear(unsigned int flag, struct request_queue *q)
}
EXPORT_SYMBOL(blk_queue_flag_clear);
-/**
- * blk_queue_flag_test_and_set - atomically test and set a queue flag
- * @flag: flag to be set
- * @q: request queue
- *
- * Returns the previous value of @flag - 0 if the flag was not set and 1 if
- * the flag was already set.
- */
-bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q)
-{
- return test_and_set_bit(flag, &q->queue_flags);
-}
-EXPORT_SYMBOL_GPL(blk_queue_flag_test_and_set);
-
#define REQ_OP_NAME(name) [REQ_OP_##name] = #name
static const char *const blk_op_name[] = {
REQ_OP_NAME(READ),
@@ -174,6 +160,8 @@ static const struct {
/* Command duration limit device-side timeout */
[BLK_STS_DURATION_LIMIT] = { -ETIME, "duration limit exceeded" },
+ [BLK_STS_INVAL] = { -EINVAL, "invalid" },
+
/* everything else not covered above: */
[BLK_STS_IOERR] = { -EIO, "I/O" },
};
@@ -739,6 +727,18 @@ void submit_bio_noacct_nocheck(struct bio *bio)
__submit_bio_noacct(bio);
}
+static blk_status_t blk_validate_atomic_write_op_size(struct request_queue *q,
+ struct bio *bio)
+{
+ if (bio->bi_iter.bi_size > queue_atomic_write_unit_max_bytes(q))
+ return BLK_STS_INVAL;
+
+ if (bio->bi_iter.bi_size % queue_atomic_write_unit_min_bytes(q))
+ return BLK_STS_INVAL;
+
+ return BLK_STS_OK;
+}
+
/**
* submit_bio_noacct - re-submit a bio to the block device layer for I/O
* @bio: The bio describing the location in memory and on the device.
@@ -782,7 +782,7 @@ void submit_bio_noacct(struct bio *bio)
if (WARN_ON_ONCE(bio_op(bio) != REQ_OP_WRITE &&
bio_op(bio) != REQ_OP_ZONE_APPEND))
goto end_io;
- if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) {
+ if (!bdev_write_cache(bdev)) {
bio->bi_opf &= ~(REQ_PREFLUSH | REQ_FUA);
if (!bio_sectors(bio)) {
status = BLK_STS_OK;
@@ -791,12 +791,17 @@ void submit_bio_noacct(struct bio *bio)
}
}
- if (!test_bit(QUEUE_FLAG_POLL, &q->queue_flags))
+ if (!(q->limits.features & BLK_FEAT_POLL))
bio_clear_polled(bio);
switch (bio_op(bio)) {
case REQ_OP_READ:
case REQ_OP_WRITE:
+ if (bio->bi_opf & REQ_ATOMIC) {
+ status = blk_validate_atomic_write_op_size(q, bio);
+ if (status != BLK_STS_OK)
+ goto end_io;
+ }
break;
case REQ_OP_FLUSH:
/*
@@ -825,11 +830,8 @@ void submit_bio_noacct(struct bio *bio)
case REQ_OP_ZONE_OPEN:
case REQ_OP_ZONE_CLOSE:
case REQ_OP_ZONE_FINISH:
- if (!bdev_is_zoned(bio->bi_bdev))
- goto not_supported;
- break;
case REQ_OP_ZONE_RESET_ALL:
- if (!bdev_is_zoned(bio->bi_bdev) || !blk_queue_zone_resetall(q))
+ if (!bdev_is_zoned(bio->bi_bdev))
goto not_supported;
break;
case REQ_OP_DRV_IN:
@@ -915,8 +917,7 @@ int bio_poll(struct bio *bio, struct io_comp_batch *iob, unsigned int flags)
return 0;
q = bdev_get_queue(bdev);
- if (cookie == BLK_QC_T_NONE ||
- !test_bit(QUEUE_FLAG_POLL, &q->queue_flags))
+ if (cookie == BLK_QC_T_NONE || !(q->limits.features & BLK_FEAT_POLL))
return 0;
blk_flush_plug(current->plug, false);
diff --git a/block/blk-flush.c b/block/blk-flush.c
index cca4f9131f79..a72e2a83d075 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -100,23 +100,6 @@ blk_get_flush_queue(struct request_queue *q, struct blk_mq_ctx *ctx)
return blk_mq_map_queue(q, REQ_OP_FLUSH, ctx)->fq;
}
-static unsigned int blk_flush_policy(unsigned long fflags, struct request *rq)
-{
- unsigned int policy = 0;
-
- if (blk_rq_sectors(rq))
- policy |= REQ_FSEQ_DATA;
-
- if (fflags & (1UL << QUEUE_FLAG_WC)) {
- if (rq->cmd_flags & REQ_PREFLUSH)
- policy |= REQ_FSEQ_PREFLUSH;
- if (!(fflags & (1UL << QUEUE_FLAG_FUA)) &&
- (rq->cmd_flags & REQ_FUA))
- policy |= REQ_FSEQ_POSTFLUSH;
- }
- return policy;
-}
-
static unsigned int blk_flush_cur_seq(struct request *rq)
{
return 1 << ffz(rq->flush.seq);
@@ -399,19 +382,32 @@ static void blk_rq_init_flush(struct request *rq)
bool blk_insert_flush(struct request *rq)
{
struct request_queue *q = rq->q;
- unsigned long fflags = q->queue_flags; /* may change, cache */
- unsigned int policy = blk_flush_policy(fflags, rq);
struct blk_flush_queue *fq = blk_get_flush_queue(q, rq->mq_ctx);
+ bool supports_fua = q->limits.features & BLK_FEAT_FUA;
+ unsigned int policy = 0;
/* FLUSH/FUA request must never be merged */
WARN_ON_ONCE(rq->bio != rq->biotail);
+ if (blk_rq_sectors(rq))
+ policy |= REQ_FSEQ_DATA;
+
+ /*
+ * Check which flushes we need to sequence for this operation.
+ */
+ if (blk_queue_write_cache(q)) {
+ if (rq->cmd_flags & REQ_PREFLUSH)
+ policy |= REQ_FSEQ_PREFLUSH;
+ if ((rq->cmd_flags & REQ_FUA) && !supports_fua)
+ policy |= REQ_FSEQ_POSTFLUSH;
+ }
+
/*
* @policy now records what operations need to be done. Adjust
* REQ_PREFLUSH and FUA for the driver.
*/
rq->cmd_flags &= ~REQ_PREFLUSH;
- if (!(fflags & (1UL << QUEUE_FLAG_FUA)))
+ if (!supports_fua)
rq->cmd_flags &= ~REQ_FUA;
/*
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index ccbeb6dfa87a..010decc892ea 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -107,60 +107,6 @@ new_segment:
}
EXPORT_SYMBOL(blk_rq_map_integrity_sg);
-/**
- * blk_integrity_compare - Compare integrity profile of two disks
- * @gd1: Disk to compare
- * @gd2: Disk to compare
- *
- * Description: Meta-devices like DM and MD need to verify that all
- * sub-devices use the same integrity format before advertising to
- * upper layers that they can send/receive integrity metadata. This
- * function can be used to check whether two gendisk devices have
- * compatible integrity formats.
- */
-int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2)
-{
- struct blk_integrity *b1 = &gd1->queue->integrity;
- struct blk_integrity *b2 = &gd2->queue->integrity;
-
- if (!b1->profile && !b2->profile)
- return 0;
-
- if (!b1->profile || !b2->profile)
- return -1;
-
- if (b1->interval_exp != b2->interval_exp) {
- pr_err("%s: %s/%s protection interval %u != %u\n",
- __func__, gd1->disk_name, gd2->disk_name,
- 1 << b1->interval_exp, 1 << b2->interval_exp);
- return -1;
- }
-
- if (b1->tuple_size != b2->tuple_size) {
- pr_err("%s: %s/%s tuple sz %u != %u\n", __func__,
- gd1->disk_name, gd2->disk_name,
- b1->tuple_size, b2->tuple_size);
- return -1;
- }
-
- if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) {
- pr_err("%s: %s/%s tag sz %u != %u\n", __func__,
- gd1->disk_name, gd2->disk_name,
- b1->tag_size, b2->tag_size);
- return -1;
- }
-
- if (b1->profile != b2->profile) {
- pr_err("%s: %s/%s type %s != %s\n", __func__,
- gd1->disk_name, gd2->disk_name,
- b1->profile->name, b2->profile->name);
- return -1;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(blk_integrity_compare);
-
bool blk_integrity_merge_rq(struct request_queue *q, struct request *req,
struct request *next)
{
@@ -214,7 +160,64 @@ bool blk_integrity_merge_bio(struct request_queue *q, struct request *req,
static inline struct blk_integrity *dev_to_bi(struct device *dev)
{
- return &dev_to_disk(dev)->queue->integrity;
+ return &dev_to_disk(dev)->queue->limits.integrity;
+}
+
+const char *blk_integrity_profile_name(struct blk_integrity *bi)
+{
+ switch (bi->csum_type) {
+ case BLK_INTEGRITY_CSUM_IP:
+ if (bi->flags & BLK_INTEGRITY_REF_TAG)
+ return "T10-DIF-TYPE1-IP";
+ return "T10-DIF-TYPE3-IP";
+ case BLK_INTEGRITY_CSUM_CRC:
+ if (bi->flags & BLK_INTEGRITY_REF_TAG)
+ return "T10-DIF-TYPE1-CRC";
+ return "T10-DIF-TYPE3-CRC";
+ case BLK_INTEGRITY_CSUM_CRC64:
+ if (bi->flags & BLK_INTEGRITY_REF_TAG)
+ return "EXT-DIF-TYPE1-CRC64";
+ return "EXT-DIF-TYPE3-CRC64";
+ case BLK_INTEGRITY_CSUM_NONE:
+ break;
+ }
+
+ return "nop";
+}
+EXPORT_SYMBOL_GPL(blk_integrity_profile_name);
+
+static ssize_t flag_store(struct device *dev, const char *page, size_t count,
+ unsigned char flag)
+{
+ struct request_queue *q = dev_to_disk(dev)->queue;
+ struct queue_limits lim;
+ unsigned long val;
+ int err;
+
+ err = kstrtoul(page, 10, &val);
+ if (err)
+ return err;
+
+ /* note that the flags are inverted vs the values in the sysfs files */
+ lim = queue_limits_start_update(q);
+ if (val)
+ lim.integrity.flags &= ~flag;
+ else
+ lim.integrity.flags |= flag;
+
+ blk_mq_freeze_queue(q);
+ err = queue_limits_commit_update(q, &lim);
+ blk_mq_unfreeze_queue(q);
+ if (err)
+ return err;
+ return count;
+}
+
+static ssize_t flag_show(struct device *dev, char *page, unsigned char flag)
+{
+ struct blk_integrity *bi = dev_to_bi(dev);
+
+ return sysfs_emit(page, "%d\n", !(bi->flags & flag));
}
static ssize_t format_show(struct device *dev, struct device_attribute *attr,
@@ -222,9 +225,9 @@ static ssize_t format_show(struct device *dev, struct device_attribute *attr,
{
struct blk_integrity *bi = dev_to_bi(dev);
- if (bi->profile && bi->profile->name)
- return sysfs_emit(page, "%s\n", bi->profile->name);
- return sysfs_emit(page, "none\n");
+ if (!bi->tuple_size)
+ return sysfs_emit(page, "none\n");
+ return sysfs_emit(page, "%s\n", blk_integrity_profile_name(bi));
}
static ssize_t tag_size_show(struct device *dev, struct device_attribute *attr,
@@ -249,49 +252,26 @@ static ssize_t read_verify_store(struct device *dev,
struct device_attribute *attr,
const char *page, size_t count)
{
- struct blk_integrity *bi = dev_to_bi(dev);
- char *p = (char *) page;
- unsigned long val = simple_strtoul(p, &p, 10);
-
- if (val)
- bi->flags |= BLK_INTEGRITY_VERIFY;
- else
- bi->flags &= ~BLK_INTEGRITY_VERIFY;
-
- return count;
+ return flag_store(dev, page, count, BLK_INTEGRITY_NOVERIFY);
}
static ssize_t read_verify_show(struct device *dev,
struct device_attribute *attr, char *page)
{
- struct blk_integrity *bi = dev_to_bi(dev);
-
- return sysfs_emit(page, "%d\n", !!(bi->flags & BLK_INTEGRITY_VERIFY));
+ return flag_show(dev, page, BLK_INTEGRITY_NOVERIFY);
}
static ssize_t write_generate_store(struct device *dev,
struct device_attribute *attr,
const char *page, size_t count)
{
- struct blk_integrity *bi = dev_to_bi(dev);
-
- char *p = (char *) page;
- unsigned long val = simple_strtoul(p, &p, 10);
-
- if (val)
- bi->flags |= BLK_INTEGRITY_GENERATE;
- else
- bi->flags &= ~BLK_INTEGRITY_GENERATE;
-
- return count;
+ return flag_store(dev, page, count, BLK_INTEGRITY_NOGENERATE);
}
static ssize_t write_generate_show(struct device *dev,
struct device_attribute *attr, char *page)
{
- struct blk_integrity *bi = dev_to_bi(dev);
-
- return sysfs_emit(page, "%d\n", !!(bi->flags & BLK_INTEGRITY_GENERATE));
+ return flag_show(dev, page, BLK_INTEGRITY_NOGENERATE);
}
static ssize_t device_is_integrity_capable_show(struct device *dev,
@@ -325,81 +305,3 @@ const struct attribute_group blk_integrity_attr_group = {
.name = "integrity",
.attrs = integrity_attrs,
};
-
-static blk_status_t blk_integrity_nop_fn(struct blk_integrity_iter *iter)
-{
- return BLK_STS_OK;
-}
-
-static void blk_integrity_nop_prepare(struct request *rq)
-{
-}
-
-static void blk_integrity_nop_complete(struct request *rq,
- unsigned int nr_bytes)
-{
-}
-
-static const struct blk_integrity_profile nop_profile = {
- .name = "nop",
- .generate_fn = blk_integrity_nop_fn,
- .verify_fn = blk_integrity_nop_fn,
- .prepare_fn = blk_integrity_nop_prepare,
- .complete_fn = blk_integrity_nop_complete,
-};
-
-/**
- * blk_integrity_register - Register a gendisk as being integrity-capable
- * @disk: struct gendisk pointer to make integrity-aware
- * @template: block integrity profile to register
- *
- * Description: When a device needs to advertise itself as being able to
- * send/receive integrity metadata it must use this function to register
- * the capability with the block layer. The template is a blk_integrity
- * struct with values appropriate for the underlying hardware. See
- * Documentation/block/data-integrity.rst.
- */
-void blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
-{
- struct blk_integrity *bi = &disk->queue->integrity;
-
- bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE |
- template->flags;
- bi->interval_exp = template->interval_exp ? :
- ilog2(queue_logical_block_size(disk->queue));
- bi->profile = template->profile ? template->profile : &nop_profile;
- bi->tuple_size = template->tuple_size;
- bi->tag_size = template->tag_size;
- bi->pi_offset = template->pi_offset;
-
- blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, disk->queue);
-
-#ifdef CONFIG_BLK_INLINE_ENCRYPTION
- if (disk->queue->crypto_profile) {
- pr_warn("blk-integrity: Integrity and hardware inline encryption are not supported together. Disabling hardware inline encryption.\n");
- disk->queue->crypto_profile = NULL;
- }
-#endif
-}
-EXPORT_SYMBOL(blk_integrity_register);
-
-/**
- * blk_integrity_unregister - Unregister block integrity profile
- * @disk: disk whose integrity profile to unregister
- *
- * Description: This function unregisters the integrity capability from
- * a block device.
- */
-void blk_integrity_unregister(struct gendisk *disk)
-{
- struct blk_integrity *bi = &disk->queue->integrity;
-
- if (!bi->profile)
- return;
-
- /* ensure all bios are off the integrity workqueue */
- blk_flush_integrity();
- blk_queue_flag_clear(QUEUE_FLAG_STABLE_WRITES, disk->queue);
- memset(bi, 0, sizeof(*bi));
-}
-EXPORT_SYMBOL(blk_integrity_unregister);
diff --git a/block/blk-lib.c b/block/blk-lib.c
index 442da9dad042..9f735efa6c94 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -103,38 +103,71 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
}
EXPORT_SYMBOL(blkdev_issue_discard);
-static int __blkdev_issue_write_zeroes(struct block_device *bdev,
- sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
- struct bio **biop, unsigned flags)
+static sector_t bio_write_zeroes_limit(struct block_device *bdev)
{
- struct bio *bio = *biop;
- unsigned int max_sectors;
-
- if (bdev_read_only(bdev))
- return -EPERM;
-
- /* Ensure that max_sectors doesn't overflow bi_size */
- max_sectors = bdev_write_zeroes_sectors(bdev);
+ sector_t bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
- if (max_sectors == 0)
- return -EOPNOTSUPP;
+ return min(bdev_write_zeroes_sectors(bdev),
+ (UINT_MAX >> SECTOR_SHIFT) & ~bs_mask);
+}
+static void __blkdev_issue_write_zeroes(struct block_device *bdev,
+ sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
+ struct bio **biop, unsigned flags)
+{
while (nr_sects) {
- unsigned int len = min_t(sector_t, nr_sects, max_sectors);
+ unsigned int len = min_t(sector_t, nr_sects,
+ bio_write_zeroes_limit(bdev));
+ struct bio *bio;
+
+ if ((flags & BLKDEV_ZERO_KILLABLE) &&
+ fatal_signal_pending(current))
+ break;
- bio = blk_next_bio(bio, bdev, 0, REQ_OP_WRITE_ZEROES, gfp_mask);
+ bio = bio_alloc(bdev, 0, REQ_OP_WRITE_ZEROES, gfp_mask);
bio->bi_iter.bi_sector = sector;
if (flags & BLKDEV_ZERO_NOUNMAP)
bio->bi_opf |= REQ_NOUNMAP;
bio->bi_iter.bi_size = len << SECTOR_SHIFT;
+ *biop = bio_chain_and_submit(*biop, bio);
+
nr_sects -= len;
sector += len;
cond_resched();
}
+}
- *biop = bio;
- return 0;
+static int blkdev_issue_write_zeroes(struct block_device *bdev, sector_t sector,
+ sector_t nr_sects, gfp_t gfp, unsigned flags)
+{
+ struct bio *bio = NULL;
+ struct blk_plug plug;
+ int ret = 0;
+
+ blk_start_plug(&plug);
+ __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp, &bio, flags);
+ if (bio) {
+ if ((flags & BLKDEV_ZERO_KILLABLE) &&
+ fatal_signal_pending(current)) {
+ bio_await_chain(bio);
+ blk_finish_plug(&plug);
+ return -EINTR;
+ }
+ ret = submit_bio_wait(bio);
+ bio_put(bio);
+ }
+ blk_finish_plug(&plug);
+
+ /*
+ * For some devices there is no non-destructive way to verify whether
+ * WRITE ZEROES is actually supported. These will clear the capability
+ * on an I/O error, in which case we'll turn any error into
+ * "not supported" here.
+ */
+ if (ret && !bdev_write_zeroes_sectors(bdev))
+ return -EOPNOTSUPP;
+ return ret;
}
/*
@@ -150,35 +183,63 @@ static unsigned int __blkdev_sectors_to_bio_pages(sector_t nr_sects)
return min(pages, (sector_t)BIO_MAX_VECS);
}
-static int __blkdev_issue_zero_pages(struct block_device *bdev,
+static void __blkdev_issue_zero_pages(struct block_device *bdev,
sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
- struct bio **biop)
+ struct bio **biop, unsigned int flags)
{
- struct bio *bio = *biop;
- int bi_size = 0;
- unsigned int sz;
-
- if (bdev_read_only(bdev))
- return -EPERM;
+ while (nr_sects) {
+ unsigned int nr_vecs = __blkdev_sectors_to_bio_pages(nr_sects);
+ struct bio *bio;
- while (nr_sects != 0) {
- bio = blk_next_bio(bio, bdev, __blkdev_sectors_to_bio_pages(nr_sects),
- REQ_OP_WRITE, gfp_mask);
+ bio = bio_alloc(bdev, nr_vecs, REQ_OP_WRITE, gfp_mask);
bio->bi_iter.bi_sector = sector;
- while (nr_sects != 0) {
- sz = min((sector_t) PAGE_SIZE, nr_sects << 9);
- bi_size = bio_add_page(bio, ZERO_PAGE(0), sz, 0);
- nr_sects -= bi_size >> 9;
- sector += bi_size >> 9;
- if (bi_size < sz)
+ if ((flags & BLKDEV_ZERO_KILLABLE) &&
+ fatal_signal_pending(current))
+ break;
+
+ do {
+ unsigned int len, added;
+
+ len = min_t(sector_t,
+ PAGE_SIZE, nr_sects << SECTOR_SHIFT);
+ added = bio_add_page(bio, ZERO_PAGE(0), len, 0);
+ if (added < len)
break;
- }
+ nr_sects -= added >> SECTOR_SHIFT;
+ sector += added >> SECTOR_SHIFT;
+ } while (nr_sects);
+
+ *biop = bio_chain_and_submit(*biop, bio);
cond_resched();
}
+}
- *biop = bio;
- return 0;
+static int blkdev_issue_zero_pages(struct block_device *bdev, sector_t sector,
+ sector_t nr_sects, gfp_t gfp, unsigned flags)
+{
+ struct bio *bio = NULL;
+ struct blk_plug plug;
+ int ret = 0;
+
+ if (flags & BLKDEV_ZERO_NOFALLBACK)
+ return -EOPNOTSUPP;
+
+ blk_start_plug(&plug);
+ __blkdev_issue_zero_pages(bdev, sector, nr_sects, gfp, &bio, flags);
+ if (bio) {
+ if ((flags & BLKDEV_ZERO_KILLABLE) &&
+ fatal_signal_pending(current)) {
+ bio_await_chain(bio);
+ blk_finish_plug(&plug);
+ return -EINTR;
+ }
+ ret = submit_bio_wait(bio);
+ bio_put(bio);
+ }
+ blk_finish_plug(&plug);
+
+ return ret;
}
/**
@@ -204,20 +265,19 @@ int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp_mask, struct bio **biop,
unsigned flags)
{
- int ret;
- sector_t bs_mask;
-
- bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
- if ((sector | nr_sects) & bs_mask)
- return -EINVAL;
-
- ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp_mask,
- biop, flags);
- if (ret != -EOPNOTSUPP || (flags & BLKDEV_ZERO_NOFALLBACK))
- return ret;
+ if (bdev_read_only(bdev))
+ return -EPERM;
- return __blkdev_issue_zero_pages(bdev, sector, nr_sects, gfp_mask,
- biop);
+ if (bdev_write_zeroes_sectors(bdev)) {
+ __blkdev_issue_write_zeroes(bdev, sector, nr_sects,
+ gfp_mask, biop, flags);
+ } else {
+ if (flags & BLKDEV_ZERO_NOFALLBACK)
+ return -EOPNOTSUPP;
+ __blkdev_issue_zero_pages(bdev, sector, nr_sects, gfp_mask,
+ biop, flags);
+ }
+ return 0;
}
EXPORT_SYMBOL(__blkdev_issue_zeroout);
@@ -237,51 +297,21 @@ EXPORT_SYMBOL(__blkdev_issue_zeroout);
int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp_mask, unsigned flags)
{
- int ret = 0;
- sector_t bs_mask;
- struct bio *bio;
- struct blk_plug plug;
- bool try_write_zeroes = !!bdev_write_zeroes_sectors(bdev);
+ int ret;
- bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
- if ((sector | nr_sects) & bs_mask)
+ if ((sector | nr_sects) & ((bdev_logical_block_size(bdev) >> 9) - 1))
return -EINVAL;
+ if (bdev_read_only(bdev))
+ return -EPERM;
-retry:
- bio = NULL;
- blk_start_plug(&plug);
- if (try_write_zeroes) {
- ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects,
- gfp_mask, &bio, flags);
- } else if (!(flags & BLKDEV_ZERO_NOFALLBACK)) {
- ret = __blkdev_issue_zero_pages(bdev, sector, nr_sects,
- gfp_mask, &bio);
- } else {
- /* No zeroing offload support */
- ret = -EOPNOTSUPP;
- }
- if (ret == 0 && bio) {
- ret = submit_bio_wait(bio);
- bio_put(bio);
- }
- blk_finish_plug(&plug);
- if (ret && try_write_zeroes) {
- if (!(flags & BLKDEV_ZERO_NOFALLBACK)) {
- try_write_zeroes = false;
- goto retry;
- }
- if (!bdev_write_zeroes_sectors(bdev)) {
- /*
- * Zeroing offload support was indicated, but the
- * device reported ILLEGAL REQUEST (for some devices
- * there is no non-destructive way to verify whether
- * WRITE ZEROES is actually supported).
- */
- ret = -EOPNOTSUPP;
- }
+ if (bdev_write_zeroes_sectors(bdev)) {
+ ret = blkdev_issue_write_zeroes(bdev, sector, nr_sects,
+ gfp_mask, flags);
+ if (ret != -EOPNOTSUPP)
+ return ret;
}
- return ret;
+ return blkdev_issue_zero_pages(bdev, sector, nr_sects, gfp_mask, flags);
}
EXPORT_SYMBOL(blkdev_issue_zeroout);
diff --git a/block/blk-map.c b/block/blk-map.c
index 71210cdb3442..bce144091128 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -634,7 +634,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
const struct iov_iter *iter, gfp_t gfp_mask)
{
bool copy = false, map_bvec = false;
- unsigned long align = q->dma_pad_mask | queue_dma_alignment(q);
+ unsigned long align = blk_lim_dma_alignment_and_pad(&q->limits);
struct bio *bio = NULL;
struct iov_iter i;
int ret = -EINVAL;
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 8534c35e0497..de5281bcadc5 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -154,6 +154,19 @@ static struct bio *bio_split_write_zeroes(struct bio *bio,
return bio_split(bio, lim->max_write_zeroes_sectors, GFP_NOIO, bs);
}
+static inline unsigned int blk_boundary_sectors(const struct queue_limits *lim,
+ bool is_atomic)
+{
+ /*
+ * chunk_sectors must be a multiple of atomic_write_boundary_sectors if
+ * both non-zero.
+ */
+ if (is_atomic && lim->atomic_write_boundary_sectors)
+ return lim->atomic_write_boundary_sectors;
+
+ return lim->chunk_sectors;
+}
+
/*
* Return the maximum number of sectors from the start of a bio that may be
* submitted as a single request to a block device. If enough sectors remain,
@@ -167,12 +180,23 @@ static inline unsigned get_max_io_size(struct bio *bio,
{
unsigned pbs = lim->physical_block_size >> SECTOR_SHIFT;
unsigned lbs = lim->logical_block_size >> SECTOR_SHIFT;
- unsigned max_sectors = lim->max_sectors, start, end;
+ bool is_atomic = bio->bi_opf & REQ_ATOMIC;
+ unsigned boundary_sectors = blk_boundary_sectors(lim, is_atomic);
+ unsigned max_sectors, start, end;
- if (lim->chunk_sectors) {
+ /*
+ * We ignore lim->max_sectors for atomic writes because it may less
+ * than the actual bio size, which we cannot tolerate.
+ */
+ if (is_atomic)
+ max_sectors = lim->atomic_write_max_sectors;
+ else
+ max_sectors = lim->max_sectors;
+
+ if (boundary_sectors) {
max_sectors = min(max_sectors,
- blk_chunk_sectors_left(bio->bi_iter.bi_sector,
- lim->chunk_sectors));
+ blk_boundary_sectors_left(bio->bi_iter.bi_sector,
+ boundary_sectors));
}
start = bio->bi_iter.bi_sector & (pbs - 1);
@@ -185,23 +209,22 @@ static inline unsigned get_max_io_size(struct bio *bio,
/**
* get_max_segment_size() - maximum number of bytes to add as a single segment
* @lim: Request queue limits.
- * @start_page: See below.
- * @offset: Offset from @start_page where to add a segment.
+ * @paddr: address of the range to add
+ * @len: maximum length available to add at @paddr
*
- * Returns the maximum number of bytes that can be added as a single segment.
+ * Returns the maximum number of bytes of the range starting at @paddr that can
+ * be added to a single segment.
*/
static inline unsigned get_max_segment_size(const struct queue_limits *lim,
- struct page *start_page, unsigned long offset)
+ phys_addr_t paddr, unsigned int len)
{
- unsigned long mask = lim->seg_boundary_mask;
-
- offset = mask & (page_to_phys(start_page) + offset);
-
/*
* Prevent an overflow if mask = ULONG_MAX and offset = 0 by adding 1
* after having calculated the minimum.
*/
- return min(mask - offset, (unsigned long)lim->max_segment_size - 1) + 1;
+ return min_t(unsigned long, len,
+ min(lim->seg_boundary_mask - (lim->seg_boundary_mask & paddr),
+ (unsigned long)lim->max_segment_size - 1) + 1);
}
/**
@@ -234,9 +257,7 @@ static bool bvec_split_segs(const struct queue_limits *lim,
unsigned seg_size = 0;
while (len && *nsegs < max_segs) {
- seg_size = get_max_segment_size(lim, bv->bv_page,
- bv->bv_offset + total_len);
- seg_size = min(seg_size, len);
+ seg_size = get_max_segment_size(lim, bvec_phys(bv) + total_len, len);
(*nsegs)++;
total_len += seg_size;
@@ -305,6 +326,11 @@ struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
*segs = nsegs;
return NULL;
split:
+ if (bio->bi_opf & REQ_ATOMIC) {
+ bio->bi_status = BLK_STS_INVAL;
+ bio_endio(bio);
+ return ERR_PTR(-EINVAL);
+ }
/*
* We can't sanely support splitting for a REQ_NOWAIT bio. End it
* with EAGAIN if splitting is required and return an error pointer.
@@ -465,8 +491,8 @@ static unsigned blk_bvec_map_sg(struct request_queue *q,
while (nbytes > 0) {
unsigned offset = bvec->bv_offset + total;
- unsigned len = min(get_max_segment_size(&q->limits,
- bvec->bv_page, offset), nbytes);
+ unsigned len = get_max_segment_size(&q->limits,
+ bvec_phys(bvec) + total, nbytes);
struct page *page = bvec->bv_page;
/*
@@ -588,18 +614,22 @@ static inline unsigned int blk_rq_get_max_sectors(struct request *rq,
sector_t offset)
{
struct request_queue *q = rq->q;
- unsigned int max_sectors;
+ struct queue_limits *lim = &q->limits;
+ unsigned int max_sectors, boundary_sectors;
+ bool is_atomic = rq->cmd_flags & REQ_ATOMIC;
if (blk_rq_is_passthrough(rq))
return q->limits.max_hw_sectors;
- max_sectors = blk_queue_get_max_sectors(q, req_op(rq));
- if (!q->limits.chunk_sectors ||
+ boundary_sectors = blk_boundary_sectors(lim, is_atomic);
+ max_sectors = blk_queue_get_max_sectors(rq);
+
+ if (!boundary_sectors ||
req_op(rq) == REQ_OP_DISCARD ||
req_op(rq) == REQ_OP_SECURE_ERASE)
return max_sectors;
return min(max_sectors,
- blk_chunk_sectors_left(offset, q->limits.chunk_sectors));
+ blk_boundary_sectors_left(offset, boundary_sectors));
}
static inline int ll_new_hw_segment(struct request *req, struct bio *bio,
@@ -797,6 +827,18 @@ static enum elv_merge blk_try_req_merge(struct request *req,
return ELEVATOR_NO_MERGE;
}
+static bool blk_atomic_write_mergeable_rq_bio(struct request *rq,
+ struct bio *bio)
+{
+ return (rq->cmd_flags & REQ_ATOMIC) == (bio->bi_opf & REQ_ATOMIC);
+}
+
+static bool blk_atomic_write_mergeable_rqs(struct request *rq,
+ struct request *next)
+{
+ return (rq->cmd_flags & REQ_ATOMIC) == (next->cmd_flags & REQ_ATOMIC);
+}
+
/*
* For non-mq, this has to be called with the request spinlock acquired.
* For mq with scheduling, the appropriate queue wide lock should be held.
@@ -820,6 +862,9 @@ static struct request *attempt_merge(struct request_queue *q,
if (req->ioprio != next->ioprio)
return NULL;
+ if (!blk_atomic_write_mergeable_rqs(req, next))
+ return NULL;
+
/*
* If we are allowed to merge, then append bio list
* from next to rq and release next. merge_requests_fn
@@ -951,6 +996,9 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
if (rq->ioprio != bio_prio(bio))
return false;
+ if (blk_atomic_write_mergeable_rq_bio(rq, bio) == false)
+ return false;
+
return true;
}
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 770c0c2b72fa..344f9e503bdb 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -84,28 +84,15 @@ static const char *const blk_queue_flag_name[] = {
QUEUE_FLAG_NAME(NOMERGES),
QUEUE_FLAG_NAME(SAME_COMP),
QUEUE_FLAG_NAME(FAIL_IO),
- QUEUE_FLAG_NAME(NONROT),
- QUEUE_FLAG_NAME(IO_STAT),
QUEUE_FLAG_NAME(NOXMERGES),
- QUEUE_FLAG_NAME(ADD_RANDOM),
- QUEUE_FLAG_NAME(SYNCHRONOUS),
QUEUE_FLAG_NAME(SAME_FORCE),
QUEUE_FLAG_NAME(INIT_DONE),
- QUEUE_FLAG_NAME(STABLE_WRITES),
- QUEUE_FLAG_NAME(POLL),
- QUEUE_FLAG_NAME(WC),
- QUEUE_FLAG_NAME(FUA),
- QUEUE_FLAG_NAME(DAX),
QUEUE_FLAG_NAME(STATS),
QUEUE_FLAG_NAME(REGISTERED),
QUEUE_FLAG_NAME(QUIESCED),
- QUEUE_FLAG_NAME(PCI_P2PDMA),
- QUEUE_FLAG_NAME(ZONE_RESETALL),
QUEUE_FLAG_NAME(RQ_ALLOC_TIME),
QUEUE_FLAG_NAME(HCTX_ACTIVE),
- QUEUE_FLAG_NAME(NOWAIT),
QUEUE_FLAG_NAME(SQ_SCHED),
- QUEUE_FLAG_NAME(SKIP_TAGSET_QUIESCE),
};
#undef QUEUE_FLAG_NAME
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 3b4df8e5ac9e..e3c3c0c21b55 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -448,6 +448,10 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)
if (data->cmd_flags & REQ_NOWAIT)
data->flags |= BLK_MQ_REQ_NOWAIT;
+retry:
+ data->ctx = blk_mq_get_ctx(q);
+ data->hctx = blk_mq_map_queue(q, data->cmd_flags, data->ctx);
+
if (q->elevator) {
/*
* All requests use scheduler tags when an I/O scheduler is
@@ -469,13 +473,9 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)
if (ops->limit_depth)
ops->limit_depth(data->cmd_flags, data);
}
- }
-
-retry:
- data->ctx = blk_mq_get_ctx(q);
- data->hctx = blk_mq_map_queue(q, data->cmd_flags, data->ctx);
- if (!(data->rq_flags & RQF_SCHED_TAGS))
+ } else {
blk_mq_tag_busy(data->hctx);
+ }
if (data->flags & BLK_MQ_REQ_RESERVED)
data->rq_flags |= RQF_RESV;
@@ -804,10 +804,8 @@ static void blk_complete_request(struct request *req)
if (!bio)
return;
-#ifdef CONFIG_BLK_DEV_INTEGRITY
if (blk_integrity_rq(req) && req_op(req) == REQ_OP_READ)
- req->q->integrity.profile->complete_fn(req, total_bytes);
-#endif
+ blk_integrity_complete(req, total_bytes);
/*
* Upper layers may call blk_crypto_evict_key() anytime after the last
@@ -875,11 +873,9 @@ bool blk_update_request(struct request *req, blk_status_t error,
if (!req->bio)
return false;
-#ifdef CONFIG_BLK_DEV_INTEGRITY
if (blk_integrity_rq(req) && req_op(req) == REQ_OP_READ &&
error == BLK_STS_OK)
- req->q->integrity.profile->complete_fn(req, nr_bytes);
-#endif
+ blk_integrity_complete(req, nr_bytes);
/*
* Upper layers may call blk_crypto_evict_key() anytime after the last
@@ -1264,10 +1260,9 @@ void blk_mq_start_request(struct request *rq)
WRITE_ONCE(rq->state, MQ_RQ_IN_FLIGHT);
rq->mq_hctx->tags->rqs[rq->tag] = rq;
-#ifdef CONFIG_BLK_DEV_INTEGRITY
if (blk_integrity_rq(rq) && req_op(rq) == REQ_OP_WRITE)
- q->integrity.profile->prepare_fn(rq);
-#endif
+ blk_integrity_prepare(rq);
+
if (rq->bio && rq->bio->bi_opf & REQ_POLLED)
WRITE_ONCE(rq->bio->bi_cookie, rq->mq_hctx->queue_num);
}
@@ -2914,6 +2909,17 @@ static void blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug,
INIT_LIST_HEAD(&rq->queuelist);
}
+static bool bio_unaligned(const struct bio *bio, struct request_queue *q)
+{
+ unsigned int bs_mask = queue_logical_block_size(q) - 1;
+
+ /* .bi_sector of any zero sized bio need to be initialized */
+ if ((bio->bi_iter.bi_size & bs_mask) ||
+ ((bio->bi_iter.bi_sector << SECTOR_SHIFT) & bs_mask))
+ return true;
+ return false;
+}
+
/**
* blk_mq_submit_bio - Create and send a request to block device.
* @bio: Bio pointer.
@@ -2966,6 +2972,15 @@ void blk_mq_submit_bio(struct bio *bio)
return;
}
+ /*
+ * Device reconfiguration may change logical block size, so alignment
+ * check has to be done with queue usage counter held
+ */
+ if (unlikely(bio_unaligned(bio, q))) {
+ bio_io_error(bio);
+ goto queue_exit;
+ }
+
if (unlikely(bio_may_exceed_limits(bio, &q->limits))) {
bio = __bio_split_to_limits(bio, &q->limits, &nr_segs);
if (!bio)
@@ -3041,7 +3056,7 @@ queue_exit:
blk_status_t blk_insert_cloned_request(struct request *rq)
{
struct request_queue *q = rq->q;
- unsigned int max_sectors = blk_queue_get_max_sectors(q, req_op(rq));
+ unsigned int max_sectors = blk_queue_get_max_sectors(rq);
unsigned int max_segments = blk_rq_get_max_segments(rq);
blk_status_t ret;
@@ -4114,6 +4129,12 @@ void blk_mq_release(struct request_queue *q)
blk_mq_sysfs_deinit(q);
}
+static bool blk_mq_can_poll(struct blk_mq_tag_set *set)
+{
+ return set->nr_maps > HCTX_TYPE_POLL &&
+ set->map[HCTX_TYPE_POLL].nr_queues;
+}
+
struct request_queue *blk_mq_alloc_queue(struct blk_mq_tag_set *set,
struct queue_limits *lim, void *queuedata)
{
@@ -4121,7 +4142,13 @@ struct request_queue *blk_mq_alloc_queue(struct blk_mq_tag_set *set,
struct request_queue *q;
int ret;
- q = blk_alloc_queue(lim ? lim : &default_lim, set->numa_node);
+ if (!lim)
+ lim = &default_lim;
+ lim->features |= BLK_FEAT_IO_STAT | BLK_FEAT_NOWAIT;
+ if (blk_mq_can_poll(set))
+ lim->features |= BLK_FEAT_POLL;
+
+ q = blk_alloc_queue(lim, set->numa_node);
if (IS_ERR(q))
return q;
q->queuedata = queuedata;
@@ -4274,17 +4301,6 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
mutex_unlock(&q->sysfs_lock);
}
-static void blk_mq_update_poll_flag(struct request_queue *q)
-{
- struct blk_mq_tag_set *set = q->tag_set;
-
- if (set->nr_maps > HCTX_TYPE_POLL &&
- set->map[HCTX_TYPE_POLL].nr_queues)
- blk_queue_flag_set(QUEUE_FLAG_POLL, q);
- else
- blk_queue_flag_clear(QUEUE_FLAG_POLL, q);
-}
-
int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
struct request_queue *q)
{
@@ -4312,7 +4328,6 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
q->tag_set = set;
q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT;
- blk_mq_update_poll_flag(q);
INIT_DELAYED_WORK(&q->requeue_work, blk_mq_requeue_work);
INIT_LIST_HEAD(&q->flush_list);
@@ -4636,13 +4651,15 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr)
int ret;
unsigned long i;
+ if (WARN_ON_ONCE(!q->mq_freeze_depth))
+ return -EINVAL;
+
if (!set)
return -EINVAL;
if (q->nr_requests == nr)
return 0;
- blk_mq_freeze_queue(q);
blk_mq_quiesce_queue(q);
ret = 0;
@@ -4676,7 +4693,6 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr)
}
blk_mq_unquiesce_queue(q);
- blk_mq_unfreeze_queue(q);
return ret;
}
@@ -4798,8 +4814,10 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
fallback:
blk_mq_update_queue_map(set);
list_for_each_entry(q, &set->tag_list, tag_set_list) {
+ struct queue_limits lim;
+
blk_mq_realloc_hw_ctxs(set, q);
- blk_mq_update_poll_flag(q);
+
if (q->nr_hw_queues != set->nr_hw_queues) {
int i = prev_nr_hw_queues;
@@ -4811,6 +4829,13 @@ fallback:
set->nr_hw_queues = prev_nr_hw_queues;
goto fallback;
}
+ lim = queue_limits_start_update(q);
+ if (blk_mq_can_poll(set))
+ lim.features |= BLK_FEAT_POLL;
+ else
+ lim.features &= ~BLK_FEAT_POLL;
+ if (queue_limits_commit_update(q, &lim) < 0)
+ pr_warn("updating the poll flag failed\n");
blk_mq_map_swqueue(q);
}
diff --git a/block/blk-settings.c b/block/blk-settings.c
index effeb9a639bb..cd8a8eabc9a5 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -6,7 +6,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/bio.h>
-#include <linux/blkdev.h>
+#include <linux/blk-integrity.h>
#include <linux/pagemap.h>
#include <linux/backing-dev-defs.h>
#include <linux/gcd.h>
@@ -55,7 +55,7 @@ void blk_set_stacking_limits(struct queue_limits *lim)
}
EXPORT_SYMBOL(blk_set_stacking_limits);
-static void blk_apply_bdi_limits(struct backing_dev_info *bdi,
+void blk_apply_bdi_limits(struct backing_dev_info *bdi,
struct queue_limits *lim)
{
/*
@@ -68,7 +68,7 @@ static void blk_apply_bdi_limits(struct backing_dev_info *bdi,
static int blk_validate_zoned_limits(struct queue_limits *lim)
{
- if (!lim->zoned) {
+ if (!(lim->features & BLK_FEAT_ZONED)) {
if (WARN_ON_ONCE(lim->max_open_zones) ||
WARN_ON_ONCE(lim->max_active_zones) ||
WARN_ON_ONCE(lim->zone_write_granularity) ||
@@ -80,6 +80,14 @@ static int blk_validate_zoned_limits(struct queue_limits *lim)
if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_BLK_DEV_ZONED)))
return -EINVAL;
+ /*
+ * Given that active zones include open zones, the maximum number of
+ * open zones cannot be larger than the maximum number of active zones.
+ */
+ if (lim->max_active_zones &&
+ lim->max_open_zones > lim->max_active_zones)
+ return -EINVAL;
+
if (lim->zone_write_granularity < lim->logical_block_size)
lim->zone_write_granularity = lim->logical_block_size;
@@ -97,6 +105,120 @@ static int blk_validate_zoned_limits(struct queue_limits *lim)
return 0;
}
+static int blk_validate_integrity_limits(struct queue_limits *lim)
+{
+ struct blk_integrity *bi = &lim->integrity;
+
+ if (!bi->tuple_size) {
+ if (bi->csum_type != BLK_INTEGRITY_CSUM_NONE ||
+ bi->tag_size || ((bi->flags & BLK_INTEGRITY_REF_TAG))) {
+ pr_warn("invalid PI settings.\n");
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ if (!IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) {
+ pr_warn("integrity support disabled.\n");
+ return -EINVAL;
+ }
+
+ if (bi->csum_type == BLK_INTEGRITY_CSUM_NONE &&
+ (bi->flags & BLK_INTEGRITY_REF_TAG)) {
+ pr_warn("ref tag not support without checksum.\n");
+ return -EINVAL;
+ }
+
+ if (!bi->interval_exp)
+ bi->interval_exp = ilog2(lim->logical_block_size);
+
+ return 0;
+}
+
+/*
+ * Returns max guaranteed bytes which we can fit in a bio.
+ *
+ * We request that an atomic_write is ITER_UBUF iov_iter (so a single vector),
+ * so we assume that we can fit in at least PAGE_SIZE in a segment, apart from
+ * the first and last segments.
+ */
+static unsigned int blk_queue_max_guaranteed_bio(struct queue_limits *lim)
+{
+ unsigned int max_segments = min(BIO_MAX_VECS, lim->max_segments);
+ unsigned int length;
+
+ length = min(max_segments, 2) * lim->logical_block_size;
+ if (max_segments > 2)
+ length += (max_segments - 2) * PAGE_SIZE;
+
+ return length;
+}
+
+static void blk_atomic_writes_update_limits(struct queue_limits *lim)
+{
+ unsigned int unit_limit = min(lim->max_hw_sectors << SECTOR_SHIFT,
+ blk_queue_max_guaranteed_bio(lim));
+
+ unit_limit = rounddown_pow_of_two(unit_limit);
+
+ lim->atomic_write_max_sectors =
+ min(lim->atomic_write_hw_max >> SECTOR_SHIFT,
+ lim->max_hw_sectors);
+ lim->atomic_write_unit_min =
+ min(lim->atomic_write_hw_unit_min, unit_limit);
+ lim->atomic_write_unit_max =
+ min(lim->atomic_write_hw_unit_max, unit_limit);
+ lim->atomic_write_boundary_sectors =
+ lim->atomic_write_hw_boundary >> SECTOR_SHIFT;
+}
+
+static void blk_validate_atomic_write_limits(struct queue_limits *lim)
+{
+ unsigned int boundary_sectors;
+
+ if (!lim->atomic_write_hw_max)
+ goto unsupported;
+
+ boundary_sectors = lim->atomic_write_hw_boundary >> SECTOR_SHIFT;
+
+ if (boundary_sectors) {
+ /*
+ * A feature of boundary support is that it disallows bios to
+ * be merged which would result in a merged request which
+ * crosses either a chunk sector or atomic write HW boundary,
+ * even though chunk sectors may be just set for performance.
+ * For simplicity, disallow atomic writes for a chunk sector
+ * which is non-zero and smaller than atomic write HW boundary.
+ * Furthermore, chunk sectors must be a multiple of atomic
+ * write HW boundary. Otherwise boundary support becomes
+ * complicated.
+ * Devices which do not conform to these rules can be dealt
+ * with if and when they show up.
+ */
+ if (WARN_ON_ONCE(lim->chunk_sectors % boundary_sectors))
+ goto unsupported;
+
+ /*
+ * The boundary size just needs to be a multiple of unit_max
+ * (and not necessarily a power-of-2), so this following check
+ * could be relaxed in future.
+ * Furthermore, if needed, unit_max could even be reduced so
+ * that it is compliant with a !power-of-2 boundary.
+ */
+ if (!is_power_of_2(boundary_sectors))
+ goto unsupported;
+ }
+
+ blk_atomic_writes_update_limits(lim);
+ return;
+
+unsupported:
+ lim->atomic_write_max_sectors = 0;
+ lim->atomic_write_boundary_sectors = 0;
+ lim->atomic_write_unit_min = 0;
+ lim->atomic_write_unit_max = 0;
+}
+
/*
* Check that the limits in lim are valid, initialize defaults for unset
* values, and cap values based on others where needed.
@@ -105,6 +227,7 @@ static int blk_validate_limits(struct queue_limits *lim)
{
unsigned int max_hw_sectors;
unsigned int logical_block_sectors;
+ int err;
/*
* Unless otherwise specified, default to 512 byte logical blocks and a
@@ -112,6 +235,10 @@ static int blk_validate_limits(struct queue_limits *lim)
*/
if (!lim->logical_block_size)
lim->logical_block_size = SECTOR_SIZE;
+ else if (blk_validate_block_size(lim->logical_block_size)) {
+ pr_warn("Invalid logical block size (%d)\n", lim->logical_block_size);
+ return -EINVAL;
+ }
if (lim->physical_block_size < lim->logical_block_size)
lim->physical_block_size = lim->logical_block_size;
@@ -153,6 +280,12 @@ static int blk_validate_limits(struct queue_limits *lim)
if (lim->max_user_sectors < PAGE_SIZE / SECTOR_SIZE)
return -EINVAL;
lim->max_sectors = min(max_hw_sectors, lim->max_user_sectors);
+ } else if (lim->io_opt > (BLK_DEF_MAX_SECTORS_CAP << SECTOR_SHIFT)) {
+ lim->max_sectors =
+ min(max_hw_sectors, lim->io_opt >> SECTOR_SHIFT);
+ } else if (lim->io_min > (BLK_DEF_MAX_SECTORS_CAP << SECTOR_SHIFT)) {
+ lim->max_sectors =
+ min(max_hw_sectors, lim->io_min >> SECTOR_SHIFT);
} else {
lim->max_sectors = min(max_hw_sectors, BLK_DEF_MAX_SECTORS_CAP);
}
@@ -220,9 +353,17 @@ static int blk_validate_limits(struct queue_limits *lim)
if (lim->alignment_offset) {
lim->alignment_offset &= (lim->physical_block_size - 1);
- lim->misaligned = 0;
+ lim->flags &= ~BLK_FLAG_MISALIGNED;
}
+ if (!(lim->features & BLK_FEAT_WRITE_CACHE))
+ lim->features &= ~BLK_FEAT_FUA;
+
+ blk_validate_atomic_write_limits(lim);
+
+ err = blk_validate_integrity_limits(lim);
+ if (err)
+ return err;
return blk_validate_zoned_limits(lim);
}
@@ -254,15 +395,25 @@ int blk_set_default_limits(struct queue_limits *lim)
*/
int queue_limits_commit_update(struct request_queue *q,
struct queue_limits *lim)
- __releases(q->limits_lock)
{
- int error = blk_validate_limits(lim);
+ int error;
- if (!error) {
- q->limits = *lim;
- if (q->disk)
- blk_apply_bdi_limits(q->disk->bdi, lim);
+ error = blk_validate_limits(lim);
+ if (error)
+ goto out_unlock;
+
+#ifdef CONFIG_BLK_INLINE_ENCRYPTION
+ if (q->crypto_profile && lim->integrity.tag_size) {
+ pr_warn("blk-integrity: Integrity and hardware inline encryption are not supported together.\n");
+ error = -EINVAL;
+ goto out_unlock;
}
+#endif
+
+ q->limits = *lim;
+ if (q->disk)
+ blk_apply_bdi_limits(q->disk->bdi, lim);
+out_unlock:
mutex_unlock(&q->limits_lock);
return error;
}
@@ -287,204 +438,6 @@ int queue_limits_set(struct request_queue *q, struct queue_limits *lim)
EXPORT_SYMBOL_GPL(queue_limits_set);
/**
- * blk_queue_chunk_sectors - set size of the chunk for this queue
- * @q: the request queue for the device
- * @chunk_sectors: chunk sectors in the usual 512b unit
- *
- * Description:
- * If a driver doesn't want IOs to cross a given chunk size, it can set
- * this limit and prevent merging across chunks. Note that the block layer
- * must accept a page worth of data at any offset. So if the crossing of
- * chunks is a hard limitation in the driver, it must still be prepared
- * to split single page bios.
- **/
-void blk_queue_chunk_sectors(struct request_queue *q, unsigned int chunk_sectors)
-{
- q->limits.chunk_sectors = chunk_sectors;
-}
-EXPORT_SYMBOL(blk_queue_chunk_sectors);
-
-/**
- * blk_queue_max_discard_sectors - set max sectors for a single discard
- * @q: the request queue for the device
- * @max_discard_sectors: maximum number of sectors to discard
- **/
-void blk_queue_max_discard_sectors(struct request_queue *q,
- unsigned int max_discard_sectors)
-{
- struct queue_limits *lim = &q->limits;
-
- lim->max_hw_discard_sectors = max_discard_sectors;
- lim->max_discard_sectors =
- min(max_discard_sectors, lim->max_user_discard_sectors);
-}
-EXPORT_SYMBOL(blk_queue_max_discard_sectors);
-
-/**
- * blk_queue_max_secure_erase_sectors - set max sectors for a secure erase
- * @q: the request queue for the device
- * @max_sectors: maximum number of sectors to secure_erase
- **/
-void blk_queue_max_secure_erase_sectors(struct request_queue *q,
- unsigned int max_sectors)
-{
- q->limits.max_secure_erase_sectors = max_sectors;
-}
-EXPORT_SYMBOL(blk_queue_max_secure_erase_sectors);
-
-/**
- * blk_queue_max_write_zeroes_sectors - set max sectors for a single
- * write zeroes
- * @q: the request queue for the device
- * @max_write_zeroes_sectors: maximum number of sectors to write per command
- **/
-void blk_queue_max_write_zeroes_sectors(struct request_queue *q,
- unsigned int max_write_zeroes_sectors)
-{
- q->limits.max_write_zeroes_sectors = max_write_zeroes_sectors;
-}
-EXPORT_SYMBOL(blk_queue_max_write_zeroes_sectors);
-
-/**
- * blk_queue_max_zone_append_sectors - set max sectors for a single zone append
- * @q: the request queue for the device
- * @max_zone_append_sectors: maximum number of sectors to write per command
- *
- * Sets the maximum number of sectors allowed for zone append commands. If
- * Specifying 0 for @max_zone_append_sectors indicates that the queue does
- * not natively support zone append operations and that the block layer must
- * emulate these operations using regular writes.
- **/
-void blk_queue_max_zone_append_sectors(struct request_queue *q,
- unsigned int max_zone_append_sectors)
-{
- unsigned int max_sectors = 0;
-
- if (WARN_ON(!blk_queue_is_zoned(q)))
- return;
-
- if (max_zone_append_sectors) {
- max_sectors = min(q->limits.max_hw_sectors,
- max_zone_append_sectors);
- max_sectors = min(q->limits.chunk_sectors, max_sectors);
-
- /*
- * Signal eventual driver bugs resulting in the max_zone_append
- * sectors limit being 0 due to the chunk_sectors limit (zone
- * size) not set or the max_hw_sectors limit not set.
- */
- WARN_ON_ONCE(!max_sectors);
- }
-
- q->limits.max_zone_append_sectors = max_sectors;
-}
-EXPORT_SYMBOL_GPL(blk_queue_max_zone_append_sectors);
-
-/**
- * blk_queue_logical_block_size - set logical block size for the queue
- * @q: the request queue for the device
- * @size: the logical block size, in bytes
- *
- * Description:
- * This should be set to the lowest possible block size that the
- * storage device can address. The default of 512 covers most
- * hardware.
- **/
-void blk_queue_logical_block_size(struct request_queue *q, unsigned int size)
-{
- struct queue_limits *limits = &q->limits;
-
- limits->logical_block_size = size;
-
- if (limits->discard_granularity < limits->logical_block_size)
- limits->discard_granularity = limits->logical_block_size;
-
- if (limits->physical_block_size < size)
- limits->physical_block_size = size;
-
- if (limits->io_min < limits->physical_block_size)
- limits->io_min = limits->physical_block_size;
-
- limits->max_hw_sectors =
- round_down(limits->max_hw_sectors, size >> SECTOR_SHIFT);
- limits->max_sectors =
- round_down(limits->max_sectors, size >> SECTOR_SHIFT);
-}
-EXPORT_SYMBOL(blk_queue_logical_block_size);
-
-/**
- * blk_queue_physical_block_size - set physical block size for the queue
- * @q: the request queue for the device
- * @size: the physical block size, in bytes
- *
- * Description:
- * This should be set to the lowest possible sector size that the
- * hardware can operate on without reverting to read-modify-write
- * operations.
- */
-void blk_queue_physical_block_size(struct request_queue *q, unsigned int size)
-{
- q->limits.physical_block_size = size;
-
- if (q->limits.physical_block_size < q->limits.logical_block_size)
- q->limits.physical_block_size = q->limits.logical_block_size;
-
- if (q->limits.discard_granularity < q->limits.physical_block_size)
- q->limits.discard_granularity = q->limits.physical_block_size;
-
- if (q->limits.io_min < q->limits.physical_block_size)
- q->limits.io_min = q->limits.physical_block_size;
-}
-EXPORT_SYMBOL(blk_queue_physical_block_size);
-
-/**
- * blk_queue_zone_write_granularity - set zone write granularity for the queue
- * @q: the request queue for the zoned device
- * @size: the zone write granularity size, in bytes
- *
- * Description:
- * This should be set to the lowest possible size allowing to write in
- * sequential zones of a zoned block device.
- */
-void blk_queue_zone_write_granularity(struct request_queue *q,
- unsigned int size)
-{
- if (WARN_ON_ONCE(!blk_queue_is_zoned(q)))
- return;
-
- q->limits.zone_write_granularity = size;
-
- if (q->limits.zone_write_granularity < q->limits.logical_block_size)
- q->limits.zone_write_granularity = q->limits.logical_block_size;
-}
-EXPORT_SYMBOL_GPL(blk_queue_zone_write_granularity);
-
-/**
- * blk_queue_alignment_offset - set physical block alignment offset
- * @q: the request queue for the device
- * @offset: alignment offset in bytes
- *
- * Description:
- * Some devices are naturally misaligned to compensate for things like
- * the legacy DOS partition table 63-sector offset. Low-level drivers
- * should call this function for devices whose first sector is not
- * naturally aligned.
- */
-void blk_queue_alignment_offset(struct request_queue *q, unsigned int offset)
-{
- q->limits.alignment_offset =
- offset & (q->limits.physical_block_size - 1);
- q->limits.misaligned = 0;
-}
-EXPORT_SYMBOL(blk_queue_alignment_offset);
-
-void disk_update_readahead(struct gendisk *disk)
-{
- blk_apply_bdi_limits(disk->bdi, &disk->queue->limits);
-}
-EXPORT_SYMBOL_GPL(disk_update_readahead);
-
-/**
* blk_limits_io_min - set minimum request size for a device
* @limits: the queue limits
* @min: smallest I/O size in bytes
@@ -508,26 +461,6 @@ void blk_limits_io_min(struct queue_limits *limits, unsigned int min)
EXPORT_SYMBOL(blk_limits_io_min);
/**
- * blk_queue_io_min - set minimum request size for the queue
- * @q: the request queue for the device
- * @min: smallest I/O size in bytes
- *
- * Description:
- * Storage devices may report a granularity or preferred minimum I/O
- * size which is the smallest request the device can perform without
- * incurring a performance penalty. For disk drives this is often the
- * physical block size. For RAID arrays it is often the stripe chunk
- * size. A properly aligned multiple of minimum_io_size is the
- * preferred request size for workloads where a high number of I/O
- * operations is desired.
- */
-void blk_queue_io_min(struct request_queue *q, unsigned int min)
-{
- blk_limits_io_min(&q->limits, min);
-}
-EXPORT_SYMBOL(blk_queue_io_min);
-
-/**
* blk_limits_io_opt - set optimal request size for a device
* @limits: the queue limits
* @opt: smallest I/O size in bytes
@@ -614,6 +547,21 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
{
unsigned int top, bottom, alignment, ret = 0;
+ 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.
+ */
+ if (!(b->features & BLK_FEAT_NOWAIT))
+ t->features &= ~BLK_FEAT_NOWAIT;
+ if (!(b->features & BLK_FEAT_POLL))
+ t->features &= ~BLK_FEAT_POLL;
+
+ t->flags |= (b->flags & BLK_FLAG_MISALIGNED);
+
t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
t->max_user_sectors = min_not_zero(t->max_user_sectors,
b->max_user_sectors);
@@ -623,7 +571,6 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
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->bounce = max(t->bounce, b->bounce);
t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask,
b->seg_boundary_mask);
@@ -639,8 +586,6 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
t->max_segment_size = min_not_zero(t->max_segment_size,
b->max_segment_size);
- t->misaligned |= b->misaligned;
-
alignment = queue_limit_alignment_offset(b, start);
/* Bottom device has different alignment. Check that it is
@@ -654,7 +599,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
/* Verify that top and bottom intervals line up */
if (max(top, bottom) % min(top, bottom)) {
- t->misaligned = 1;
+ t->flags |= BLK_FLAG_MISALIGNED;
ret = -1;
}
}
@@ -676,42 +621,38 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
/* Physical block size a multiple of the logical block size? */
if (t->physical_block_size & (t->logical_block_size - 1)) {
t->physical_block_size = t->logical_block_size;
- t->misaligned = 1;
+ t->flags |= BLK_FLAG_MISALIGNED;
ret = -1;
}
/* Minimum I/O a multiple of the physical block size? */
if (t->io_min & (t->physical_block_size - 1)) {
t->io_min = t->physical_block_size;
- t->misaligned = 1;
+ t->flags |= BLK_FLAG_MISALIGNED;
ret = -1;
}
/* Optimal I/O a multiple of the physical block size? */
if (t->io_opt & (t->physical_block_size - 1)) {
t->io_opt = 0;
- t->misaligned = 1;
+ t->flags |= BLK_FLAG_MISALIGNED;
ret = -1;
}
/* chunk_sectors a multiple of the physical block size? */
if ((t->chunk_sectors << 9) & (t->physical_block_size - 1)) {
t->chunk_sectors = 0;
- t->misaligned = 1;
+ t->flags |= BLK_FLAG_MISALIGNED;
ret = -1;
}
- t->raid_partial_stripes_expensive =
- max(t->raid_partial_stripes_expensive,
- b->raid_partial_stripes_expensive);
-
/* Find lowest common alignment_offset */
t->alignment_offset = lcm_not_zero(t->alignment_offset, alignment)
% max(t->physical_block_size, t->io_min);
/* Verify that new alignment_offset is on a logical block boundary */
if (t->alignment_offset & (t->logical_block_size - 1)) {
- t->misaligned = 1;
+ t->flags |= BLK_FLAG_MISALIGNED;
ret = -1;
}
@@ -723,16 +664,6 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
if (b->discard_granularity) {
alignment = queue_limit_discard_alignment(b, start);
- if (t->discard_granularity != 0 &&
- t->discard_alignment != alignment) {
- top = t->discard_granularity + t->discard_alignment;
- bottom = b->discard_granularity + alignment;
-
- /* Verify that top and bottom intervals line up */
- if ((max(top, bottom) % min(top, bottom)) != 0)
- t->discard_misaligned = 1;
- }
-
t->max_discard_sectors = min_not_zero(t->max_discard_sectors,
b->max_discard_sectors);
t->max_hw_discard_sectors = min_not_zero(t->max_hw_discard_sectors,
@@ -746,8 +677,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
b->max_secure_erase_sectors);
t->zone_write_granularity = max(t->zone_write_granularity,
b->zone_write_granularity);
- t->zoned = max(t->zoned, b->zoned);
- if (!t->zoned) {
+ if (!(t->features & BLK_FEAT_ZONED)) {
t->zone_write_granularity = 0;
t->max_zone_append_sectors = 0;
}
@@ -781,21 +711,65 @@ void queue_limits_stack_bdev(struct queue_limits *t, struct block_device *bdev,
EXPORT_SYMBOL_GPL(queue_limits_stack_bdev);
/**
- * blk_queue_update_dma_pad - update pad mask
- * @q: the request queue for the device
- * @mask: pad mask
+ * queue_limits_stack_integrity - stack integrity profile
+ * @t: target queue limits
+ * @b: base queue limits
*
- * Update dma pad mask.
+ * Check if the integrity profile in the @b can be stacked into the
+ * target @t. Stacking is possible if either:
*
- * Appending pad buffer to a request modifies the last entry of a
- * scatter list such that it includes the pad buffer.
- **/
-void blk_queue_update_dma_pad(struct request_queue *q, unsigned int mask)
-{
- if (mask > q->dma_pad_mask)
- q->dma_pad_mask = mask;
+ * a) does not have any integrity information stacked into it yet
+ * b) the integrity profile in @b is identical to the one in @t
+ *
+ * If @b can be stacked into @t, return %true. Else return %false and clear the
+ * integrity information in @t.
+ */
+bool queue_limits_stack_integrity(struct queue_limits *t,
+ struct queue_limits *b)
+{
+ struct blk_integrity *ti = &t->integrity;
+ struct blk_integrity *bi = &b->integrity;
+
+ if (!IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY))
+ return true;
+
+ if (!ti->tuple_size) {
+ /* inherit the settings from the first underlying device */
+ if (!(ti->flags & BLK_INTEGRITY_STACKED)) {
+ ti->flags = BLK_INTEGRITY_DEVICE_CAPABLE |
+ (bi->flags & BLK_INTEGRITY_REF_TAG);
+ ti->csum_type = bi->csum_type;
+ ti->tuple_size = bi->tuple_size;
+ ti->pi_offset = bi->pi_offset;
+ ti->interval_exp = bi->interval_exp;
+ ti->tag_size = bi->tag_size;
+ goto done;
+ }
+ if (!bi->tuple_size)
+ goto done;
+ }
+
+ if (ti->tuple_size != bi->tuple_size)
+ goto incompatible;
+ if (ti->interval_exp != bi->interval_exp)
+ goto incompatible;
+ if (ti->tag_size != bi->tag_size)
+ goto incompatible;
+ if (ti->csum_type != bi->csum_type)
+ goto incompatible;
+ if ((ti->flags & BLK_INTEGRITY_REF_TAG) !=
+ (bi->flags & BLK_INTEGRITY_REF_TAG))
+ goto incompatible;
+
+done:
+ ti->flags |= BLK_INTEGRITY_STACKED;
+ return true;
+
+incompatible:
+ memset(ti, 0, sizeof(*ti));
+ return false;
}
-EXPORT_SYMBOL(blk_queue_update_dma_pad);
+EXPORT_SYMBOL_GPL(queue_limits_stack_integrity);
/**
* blk_set_queue_depth - tell the block layer about the device queue depth
@@ -810,54 +784,11 @@ void blk_set_queue_depth(struct request_queue *q, unsigned int depth)
}
EXPORT_SYMBOL(blk_set_queue_depth);
-/**
- * blk_queue_write_cache - configure queue's write cache
- * @q: the request queue for the device
- * @wc: write back cache on or off
- * @fua: device supports FUA writes, if true
- *
- * Tell the block layer about the write cache of @q.
- */
-void blk_queue_write_cache(struct request_queue *q, bool wc, bool fua)
-{
- if (wc) {
- blk_queue_flag_set(QUEUE_FLAG_HW_WC, q);
- blk_queue_flag_set(QUEUE_FLAG_WC, q);
- } else {
- blk_queue_flag_clear(QUEUE_FLAG_HW_WC, q);
- blk_queue_flag_clear(QUEUE_FLAG_WC, q);
- }
- if (fua)
- blk_queue_flag_set(QUEUE_FLAG_FUA, q);
- else
- blk_queue_flag_clear(QUEUE_FLAG_FUA, q);
-}
-EXPORT_SYMBOL_GPL(blk_queue_write_cache);
-
-/**
- * disk_set_zoned - inidicate a zoned device
- * @disk: gendisk to configure
- */
-void disk_set_zoned(struct gendisk *disk)
-{
- struct request_queue *q = disk->queue;
-
- WARN_ON_ONCE(!IS_ENABLED(CONFIG_BLK_DEV_ZONED));
-
- /*
- * Set the zone write granularity to the device logical block
- * size by default. The driver can change this value if needed.
- */
- q->limits.zoned = true;
- blk_queue_zone_write_granularity(q, queue_logical_block_size(q));
-}
-EXPORT_SYMBOL_GPL(disk_set_zoned);
-
int bdev_alignment_offset(struct block_device *bdev)
{
struct request_queue *q = bdev_get_queue(bdev);
- if (q->limits.misaligned)
+ if (q->limits.flags & BLK_FLAG_MISALIGNED)
return -1;
if (bdev_is_partition(bdev))
return queue_limit_alignment_offset(&q->limits,
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index f0f9314ab65c..60116d13cb80 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -22,8 +22,8 @@
struct queue_sysfs_entry {
struct attribute attr;
- ssize_t (*show)(struct request_queue *, char *);
- ssize_t (*store)(struct request_queue *, const char *, size_t);
+ ssize_t (*show)(struct gendisk *disk, char *page);
+ ssize_t (*store)(struct gendisk *disk, const char *page, size_t count);
};
static ssize_t
@@ -47,18 +47,18 @@ queue_var_store(unsigned long *var, const char *page, size_t count)
return count;
}
-static ssize_t queue_requests_show(struct request_queue *q, char *page)
+static ssize_t queue_requests_show(struct gendisk *disk, char *page)
{
- return queue_var_show(q->nr_requests, page);
+ return queue_var_show(disk->queue->nr_requests, page);
}
static ssize_t
-queue_requests_store(struct request_queue *q, const char *page, size_t count)
+queue_requests_store(struct gendisk *disk, const char *page, size_t count)
{
unsigned long nr;
int ret, err;
- if (!queue_is_mq(q))
+ if (!queue_is_mq(disk->queue))
return -EINVAL;
ret = queue_var_store(&nr, page, count);
@@ -68,111 +68,91 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count)
if (nr < BLKDEV_MIN_RQ)
nr = BLKDEV_MIN_RQ;
- err = blk_mq_update_nr_requests(q, nr);
+ err = blk_mq_update_nr_requests(disk->queue, nr);
if (err)
return err;
return ret;
}
-static ssize_t queue_ra_show(struct request_queue *q, char *page)
+static ssize_t queue_ra_show(struct gendisk *disk, char *page)
{
- unsigned long ra_kb;
-
- if (!q->disk)
- return -EINVAL;
- ra_kb = q->disk->bdi->ra_pages << (PAGE_SHIFT - 10);
- return queue_var_show(ra_kb, page);
+ return queue_var_show(disk->bdi->ra_pages << (PAGE_SHIFT - 10), page);
}
static ssize_t
-queue_ra_store(struct request_queue *q, const char *page, size_t count)
+queue_ra_store(struct gendisk *disk, const char *page, size_t count)
{
unsigned long ra_kb;
ssize_t ret;
- if (!q->disk)
- return -EINVAL;
ret = queue_var_store(&ra_kb, page, count);
if (ret < 0)
return ret;
- q->disk->bdi->ra_pages = ra_kb >> (PAGE_SHIFT - 10);
+ disk->bdi->ra_pages = ra_kb >> (PAGE_SHIFT - 10);
return ret;
}
-static ssize_t queue_max_sectors_show(struct request_queue *q, char *page)
-{
- int max_sectors_kb = queue_max_sectors(q) >> 1;
-
- return queue_var_show(max_sectors_kb, page);
-}
-
-static ssize_t queue_max_segments_show(struct request_queue *q, char *page)
-{
- return queue_var_show(queue_max_segments(q), page);
-}
-
-static ssize_t queue_max_discard_segments_show(struct request_queue *q,
- char *page)
-{
- return queue_var_show(queue_max_discard_segments(q), page);
-}
-
-static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *page)
-{
- return queue_var_show(q->limits.max_integrity_segments, page);
-}
-
-static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
-{
- return queue_var_show(queue_max_segment_size(q), page);
-}
-
-static ssize_t queue_logical_block_size_show(struct request_queue *q, char *page)
-{
- return queue_var_show(queue_logical_block_size(q), page);
-}
-
-static ssize_t queue_physical_block_size_show(struct request_queue *q, char *page)
-{
- return queue_var_show(queue_physical_block_size(q), page);
-}
-
-static ssize_t queue_chunk_sectors_show(struct request_queue *q, char *page)
-{
- return queue_var_show(q->limits.chunk_sectors, page);
-}
-
-static ssize_t queue_io_min_show(struct request_queue *q, char *page)
-{
- return queue_var_show(queue_io_min(q), page);
+#define QUEUE_SYSFS_LIMIT_SHOW(_field) \
+static ssize_t queue_##_field##_show(struct gendisk *disk, char *page) \
+{ \
+ return queue_var_show(disk->queue->limits._field, page); \
+}
+
+QUEUE_SYSFS_LIMIT_SHOW(max_segments)
+QUEUE_SYSFS_LIMIT_SHOW(max_discard_segments)
+QUEUE_SYSFS_LIMIT_SHOW(max_integrity_segments)
+QUEUE_SYSFS_LIMIT_SHOW(max_segment_size)
+QUEUE_SYSFS_LIMIT_SHOW(logical_block_size)
+QUEUE_SYSFS_LIMIT_SHOW(physical_block_size)
+QUEUE_SYSFS_LIMIT_SHOW(chunk_sectors)
+QUEUE_SYSFS_LIMIT_SHOW(io_min)
+QUEUE_SYSFS_LIMIT_SHOW(io_opt)
+QUEUE_SYSFS_LIMIT_SHOW(discard_granularity)
+QUEUE_SYSFS_LIMIT_SHOW(zone_write_granularity)
+QUEUE_SYSFS_LIMIT_SHOW(virt_boundary_mask)
+QUEUE_SYSFS_LIMIT_SHOW(dma_alignment)
+QUEUE_SYSFS_LIMIT_SHOW(max_open_zones)
+QUEUE_SYSFS_LIMIT_SHOW(max_active_zones)
+QUEUE_SYSFS_LIMIT_SHOW(atomic_write_unit_min)
+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", \
+ (unsigned long long)disk->queue->limits._field << \
+ SECTOR_SHIFT); \
}
-static ssize_t queue_io_opt_show(struct request_queue *q, char *page)
-{
- return queue_var_show(queue_io_opt(q), page);
-}
+QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(max_discard_sectors)
+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)
-static ssize_t queue_discard_granularity_show(struct request_queue *q, char *page)
-{
- return queue_var_show(q->limits.discard_granularity, page);
+#define QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_KB(_field) \
+static ssize_t queue_##_field##_show(struct gendisk *disk, char *page) \
+{ \
+ return queue_var_show(disk->queue->limits._field >> 1, page); \
}
-static ssize_t queue_discard_max_hw_show(struct request_queue *q, char *page)
-{
+QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_KB(max_sectors)
+QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_KB(max_hw_sectors)
- return sprintf(page, "%llu\n",
- (unsigned long long)q->limits.max_hw_discard_sectors << 9);
+#define QUEUE_SYSFS_SHOW_CONST(_name, _val) \
+static ssize_t queue_##_name##_show(struct gendisk *disk, char *page) \
+{ \
+ return sprintf(page, "%d\n", _val); \
}
-static ssize_t queue_discard_max_show(struct request_queue *q, char *page)
-{
- return sprintf(page, "%llu\n",
- (unsigned long long)q->limits.max_discard_sectors << 9);
-}
+/* deprecated fields */
+QUEUE_SYSFS_SHOW_CONST(discard_zeroes_data, 0)
+QUEUE_SYSFS_SHOW_CONST(write_same_max, 0)
+QUEUE_SYSFS_SHOW_CONST(poll_delay, -1)
-static ssize_t queue_discard_max_store(struct request_queue *q,
- const char *page, size_t count)
+static ssize_t queue_max_discard_sectors_store(struct gendisk *disk,
+ const char *page, size_t count)
{
unsigned long max_discard_bytes;
struct queue_limits lim;
@@ -183,54 +163,34 @@ static ssize_t queue_discard_max_store(struct request_queue *q,
if (ret < 0)
return ret;
- if (max_discard_bytes & (q->limits.discard_granularity - 1))
+ if (max_discard_bytes & (disk->queue->limits.discard_granularity - 1))
return -EINVAL;
if ((max_discard_bytes >> SECTOR_SHIFT) > UINT_MAX)
return -EINVAL;
- blk_mq_freeze_queue(q);
- lim = queue_limits_start_update(q);
+ lim = queue_limits_start_update(disk->queue);
lim.max_user_discard_sectors = max_discard_bytes >> SECTOR_SHIFT;
- err = queue_limits_commit_update(q, &lim);
- blk_mq_unfreeze_queue(q);
-
+ err = queue_limits_commit_update(disk->queue, &lim);
if (err)
return err;
return ret;
}
-static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *page)
-{
- return queue_var_show(0, page);
-}
-
-static ssize_t queue_write_same_max_show(struct request_queue *q, char *page)
-{
- return queue_var_show(0, page);
-}
-
-static ssize_t queue_write_zeroes_max_show(struct request_queue *q, char *page)
+/*
+ * 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",
- (unsigned long long)q->limits.max_write_zeroes_sectors << 9);
-}
-
-static ssize_t queue_zone_write_granularity_show(struct request_queue *q,
- char *page)
-{
- return queue_var_show(queue_zone_write_granularity(q), page);
-}
-
-static ssize_t queue_zone_append_max_show(struct request_queue *q, char *page)
-{
- unsigned long long max_sectors = queue_max_zone_append_sectors(q);
-
- return sprintf(page, "%llu\n", max_sectors << SECTOR_SHIFT);
+ (u64)queue_max_zone_append_sectors(disk->queue) <<
+ SECTOR_SHIFT);
}
static ssize_t
-queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
+queue_max_sectors_store(struct gendisk *disk, const char *page, size_t count)
{
unsigned long max_sectors_kb;
struct queue_limits lim;
@@ -241,94 +201,83 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
if (ret < 0)
return ret;
- blk_mq_freeze_queue(q);
- lim = queue_limits_start_update(q);
+ lim = queue_limits_start_update(disk->queue);
lim.max_user_sectors = max_sectors_kb << 1;
- err = queue_limits_commit_update(q, &lim);
- blk_mq_unfreeze_queue(q);
+ err = queue_limits_commit_update(disk->queue, &lim);
if (err)
return err;
return ret;
}
-static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
+static ssize_t queue_feature_store(struct gendisk *disk, const char *page,
+ size_t count, blk_features_t feature)
{
- int max_hw_sectors_kb = queue_max_hw_sectors(q) >> 1;
-
- return queue_var_show(max_hw_sectors_kb, page);
-}
+ struct queue_limits lim;
+ unsigned long val;
+ ssize_t ret;
-static ssize_t queue_virt_boundary_mask_show(struct request_queue *q, char *page)
-{
- return queue_var_show(q->limits.virt_boundary_mask, page);
-}
+ ret = queue_var_store(&val, page, count);
+ if (ret < 0)
+ return ret;
-static ssize_t queue_dma_alignment_show(struct request_queue *q, char *page)
-{
- return queue_var_show(queue_dma_alignment(q), page);
+ lim = queue_limits_start_update(disk->queue);
+ if (val)
+ lim.features |= feature;
+ else
+ lim.features &= ~feature;
+ ret = queue_limits_commit_update(disk->queue, &lim);
+ if (ret)
+ return ret;
+ return count;
}
-#define QUEUE_SYSFS_BIT_FNS(name, flag, neg) \
-static ssize_t \
-queue_##name##_show(struct request_queue *q, char *page) \
+#define QUEUE_SYSFS_FEATURE(_name, _feature) \
+static ssize_t queue_##_name##_show(struct gendisk *disk, char *page) \
{ \
- int bit; \
- bit = test_bit(QUEUE_FLAG_##flag, &q->queue_flags); \
- return queue_var_show(neg ? !bit : bit, page); \
+ return sprintf(page, "%u\n", \
+ !!(disk->queue->limits.features & _feature)); \
} \
-static ssize_t \
-queue_##name##_store(struct request_queue *q, const char *page, size_t count) \
+static ssize_t queue_##_name##_store(struct gendisk *disk, \
+ const char *page, size_t count) \
{ \
- unsigned long val; \
- ssize_t ret; \
- ret = queue_var_store(&val, page, count); \
- if (ret < 0) \
- return ret; \
- if (neg) \
- val = !val; \
- \
- if (val) \
- blk_queue_flag_set(QUEUE_FLAG_##flag, q); \
- else \
- blk_queue_flag_clear(QUEUE_FLAG_##flag, q); \
- return ret; \
-}
-
-QUEUE_SYSFS_BIT_FNS(nonrot, NONROT, 1);
-QUEUE_SYSFS_BIT_FNS(random, ADD_RANDOM, 0);
-QUEUE_SYSFS_BIT_FNS(iostats, IO_STAT, 0);
-QUEUE_SYSFS_BIT_FNS(stable_writes, STABLE_WRITES, 0);
-#undef QUEUE_SYSFS_BIT_FNS
-
-static ssize_t queue_zoned_show(struct request_queue *q, char *page)
-{
- if (blk_queue_is_zoned(q))
- return sprintf(page, "host-managed\n");
- return sprintf(page, "none\n");
+ return queue_feature_store(disk, page, count, _feature); \
}
-static ssize_t queue_nr_zones_show(struct request_queue *q, char *page)
-{
- return queue_var_show(disk_nr_zones(q->disk), page);
+QUEUE_SYSFS_FEATURE(rotational, BLK_FEAT_ROTATIONAL)
+QUEUE_SYSFS_FEATURE(add_random, BLK_FEAT_ADD_RANDOM)
+QUEUE_SYSFS_FEATURE(iostats, BLK_FEAT_IO_STAT)
+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", \
+ !!(disk->queue->limits.features & _feature)); \
}
-static ssize_t queue_max_open_zones_show(struct request_queue *q, char *page)
+QUEUE_SYSFS_FEATURE_SHOW(poll, BLK_FEAT_POLL);
+QUEUE_SYSFS_FEATURE_SHOW(fua, BLK_FEAT_FUA);
+QUEUE_SYSFS_FEATURE_SHOW(dax, BLK_FEAT_DAX);
+
+static ssize_t queue_zoned_show(struct gendisk *disk, char *page)
{
- return queue_var_show(bdev_max_open_zones(q->disk->part0), page);
+ if (blk_queue_is_zoned(disk->queue))
+ return sprintf(page, "host-managed\n");
+ return sprintf(page, "none\n");
}
-static ssize_t queue_max_active_zones_show(struct request_queue *q, char *page)
+static ssize_t queue_nr_zones_show(struct gendisk *disk, char *page)
{
- return queue_var_show(bdev_max_active_zones(q->disk->part0), page);
+ return queue_var_show(disk_nr_zones(disk), page);
}
-static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
+static ssize_t queue_nomerges_show(struct gendisk *disk, char *page)
{
- return queue_var_show((blk_queue_nomerges(q) << 1) |
- blk_queue_noxmerges(q), page);
+ return queue_var_show((blk_queue_nomerges(disk->queue) << 1) |
+ blk_queue_noxmerges(disk->queue), page);
}
-static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
+static ssize_t queue_nomerges_store(struct gendisk *disk, const char *page,
size_t count)
{
unsigned long nm;
@@ -337,29 +286,30 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
if (ret < 0)
return ret;
- blk_queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
- blk_queue_flag_clear(QUEUE_FLAG_NOXMERGES, q);
+ blk_queue_flag_clear(QUEUE_FLAG_NOMERGES, disk->queue);
+ blk_queue_flag_clear(QUEUE_FLAG_NOXMERGES, disk->queue);
if (nm == 2)
- blk_queue_flag_set(QUEUE_FLAG_NOMERGES, q);
+ blk_queue_flag_set(QUEUE_FLAG_NOMERGES, disk->queue);
else if (nm)
- blk_queue_flag_set(QUEUE_FLAG_NOXMERGES, q);
+ blk_queue_flag_set(QUEUE_FLAG_NOXMERGES, disk->queue);
return ret;
}
-static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page)
+static ssize_t queue_rq_affinity_show(struct gendisk *disk, char *page)
{
- bool set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
- bool force = test_bit(QUEUE_FLAG_SAME_FORCE, &q->queue_flags);
+ bool set = test_bit(QUEUE_FLAG_SAME_COMP, &disk->queue->queue_flags);
+ bool force = test_bit(QUEUE_FLAG_SAME_FORCE, &disk->queue->queue_flags);
return queue_var_show(set << force, page);
}
static ssize_t
-queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
+queue_rq_affinity_store(struct gendisk *disk, const char *page, size_t count)
{
ssize_t ret = -EINVAL;
#ifdef CONFIG_SMP
+ struct request_queue *q = disk->queue;
unsigned long val;
ret = queue_var_store(&val, page, count);
@@ -380,38 +330,28 @@ queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
return ret;
}
-static ssize_t queue_poll_delay_show(struct request_queue *q, char *page)
-{
- return sprintf(page, "%d\n", -1);
-}
-
-static ssize_t queue_poll_delay_store(struct request_queue *q, const char *page,
+static ssize_t queue_poll_delay_store(struct gendisk *disk, const char *page,
size_t count)
{
return count;
}
-static ssize_t queue_poll_show(struct request_queue *q, char *page)
-{
- return queue_var_show(test_bit(QUEUE_FLAG_POLL, &q->queue_flags), page);
-}
-
-static ssize_t queue_poll_store(struct request_queue *q, const char *page,
+static ssize_t queue_poll_store(struct gendisk *disk, const char *page,
size_t count)
{
- if (!test_bit(QUEUE_FLAG_POLL, &q->queue_flags))
+ if (!(disk->queue->limits.features & BLK_FEAT_POLL))
return -EINVAL;
pr_info_ratelimited("writes to the poll attribute are ignored.\n");
pr_info_ratelimited("please use driver specific parameters instead.\n");
return count;
}
-static ssize_t queue_io_timeout_show(struct request_queue *q, char *page)
+static ssize_t queue_io_timeout_show(struct gendisk *disk, char *page)
{
- return sprintf(page, "%u\n", jiffies_to_msecs(q->rq_timeout));
+ return sprintf(page, "%u\n", jiffies_to_msecs(disk->queue->rq_timeout));
}
-static ssize_t queue_io_timeout_store(struct request_queue *q, const char *page,
+static ssize_t queue_io_timeout_store(struct gendisk *disk, const char *page,
size_t count)
{
unsigned int val;
@@ -421,46 +361,45 @@ static ssize_t queue_io_timeout_store(struct request_queue *q, const char *page,
if (err || val == 0)
return -EINVAL;
- blk_queue_rq_timeout(q, msecs_to_jiffies(val));
+ blk_queue_rq_timeout(disk->queue, msecs_to_jiffies(val));
return count;
}
-static ssize_t queue_wc_show(struct request_queue *q, char *page)
+static ssize_t queue_wc_show(struct gendisk *disk, char *page)
{
- if (test_bit(QUEUE_FLAG_WC, &q->queue_flags))
+ if (blk_queue_write_cache(disk->queue))
return sprintf(page, "write back\n");
-
return sprintf(page, "write through\n");
}
-static ssize_t queue_wc_store(struct request_queue *q, const char *page,
+static ssize_t queue_wc_store(struct gendisk *disk, const char *page,
size_t count)
{
+ struct queue_limits lim;
+ bool disable;
+ int err;
+
if (!strncmp(page, "write back", 10)) {
- if (!test_bit(QUEUE_FLAG_HW_WC, &q->queue_flags))
- return -EINVAL;
- blk_queue_flag_set(QUEUE_FLAG_WC, q);
+ disable = false;
} else if (!strncmp(page, "write through", 13) ||
- !strncmp(page, "none", 4)) {
- blk_queue_flag_clear(QUEUE_FLAG_WC, q);
+ !strncmp(page, "none", 4)) {
+ disable = true;
} else {
return -EINVAL;
}
+ lim = queue_limits_start_update(disk->queue);
+ if (disable)
+ lim.flags |= BLK_FLAG_WRITE_CACHE_DISABLED;
+ else
+ lim.flags &= ~BLK_FLAG_WRITE_CACHE_DISABLED;
+ err = queue_limits_commit_update(disk->queue, &lim);
+ if (err)
+ return err;
return count;
}
-static ssize_t queue_fua_show(struct request_queue *q, char *page)
-{
- return sprintf(page, "%u\n", test_bit(QUEUE_FLAG_FUA, &q->queue_flags));
-}
-
-static ssize_t queue_dax_show(struct request_queue *q, char *page)
-{
- return queue_var_show(blk_queue_dax(q), page);
-}
-
#define QUEUE_RO_ENTRY(_prefix, _name) \
static struct queue_sysfs_entry _prefix##_entry = { \
.attr = { .name = _name, .mode = 0444 }, \
@@ -491,12 +430,18 @@ QUEUE_RO_ENTRY(queue_io_opt, "optimal_io_size");
QUEUE_RO_ENTRY(queue_max_discard_segments, "max_discard_segments");
QUEUE_RO_ENTRY(queue_discard_granularity, "discard_granularity");
-QUEUE_RO_ENTRY(queue_discard_max_hw, "discard_max_hw_bytes");
-QUEUE_RW_ENTRY(queue_discard_max, "discard_max_bytes");
+QUEUE_RO_ENTRY(queue_max_hw_discard_sectors, "discard_max_hw_bytes");
+QUEUE_RW_ENTRY(queue_max_discard_sectors, "discard_max_bytes");
QUEUE_RO_ENTRY(queue_discard_zeroes_data, "discard_zeroes_data");
+QUEUE_RO_ENTRY(queue_atomic_write_max_sectors, "atomic_write_max_bytes");
+QUEUE_RO_ENTRY(queue_atomic_write_boundary_sectors,
+ "atomic_write_boundary_bytes");
+QUEUE_RO_ENTRY(queue_atomic_write_unit_max, "atomic_write_unit_max_bytes");
+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_write_zeroes_max, "write_zeroes_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_zone_write_granularity, "zone_write_granularity");
@@ -522,9 +467,9 @@ static struct queue_sysfs_entry queue_hw_sector_size_entry = {
.show = queue_logical_block_size_show,
};
-QUEUE_RW_ENTRY(queue_nonrot, "rotational");
+QUEUE_RW_ENTRY(queue_rotational, "rotational");
QUEUE_RW_ENTRY(queue_iostats, "iostats");
-QUEUE_RW_ENTRY(queue_random, "add_random");
+QUEUE_RW_ENTRY(queue_add_random, "add_random");
QUEUE_RW_ENTRY(queue_stable_writes, "stable_writes");
#ifdef CONFIG_BLK_WBT
@@ -541,20 +486,22 @@ static ssize_t queue_var_store64(s64 *var, const char *page)
return 0;
}
-static ssize_t queue_wb_lat_show(struct request_queue *q, char *page)
+static ssize_t queue_wb_lat_show(struct gendisk *disk, char *page)
{
- if (!wbt_rq_qos(q))
+ if (!wbt_rq_qos(disk->queue))
return -EINVAL;
- if (wbt_disabled(q))
+ if (wbt_disabled(disk->queue))
return sprintf(page, "0\n");
- return sprintf(page, "%llu\n", div_u64(wbt_get_min_lat(q), 1000));
+ return sprintf(page, "%llu\n",
+ div_u64(wbt_get_min_lat(disk->queue), 1000));
}
-static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page,
+static ssize_t queue_wb_lat_store(struct gendisk *disk, const char *page,
size_t count)
{
+ struct request_queue *q = disk->queue;
struct rq_qos *rqos;
ssize_t ret;
s64 val;
@@ -567,7 +514,7 @@ static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page,
rqos = wbt_rq_qos(q);
if (!rqos) {
- ret = wbt_init(q->disk);
+ ret = wbt_init(disk);
if (ret)
return ret;
}
@@ -585,13 +532,11 @@ static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page,
* ends up either enabling or disabling wbt completely. We can't
* have IO inflight if that happens.
*/
- blk_mq_freeze_queue(q);
blk_mq_quiesce_queue(q);
wbt_set_min_lat(q, val);
blk_mq_unquiesce_queue(q);
- blk_mq_unfreeze_queue(q);
return count;
}
@@ -615,14 +560,18 @@ static struct attribute *queue_attrs[] = {
&queue_io_min_entry.attr,
&queue_io_opt_entry.attr,
&queue_discard_granularity_entry.attr,
- &queue_discard_max_entry.attr,
- &queue_discard_max_hw_entry.attr,
+ &queue_max_discard_sectors_entry.attr,
+ &queue_max_hw_discard_sectors_entry.attr,
&queue_discard_zeroes_data_entry.attr,
+ &queue_atomic_write_max_sectors_entry.attr,
+ &queue_atomic_write_boundary_sectors_entry.attr,
+ &queue_atomic_write_unit_min_entry.attr,
+ &queue_atomic_write_unit_max_entry.attr,
&queue_write_same_max_entry.attr,
- &queue_write_zeroes_max_entry.attr,
+ &queue_max_write_zeroes_sectors_entry.attr,
&queue_zone_append_max_entry.attr,
&queue_zone_write_granularity_entry.attr,
- &queue_nonrot_entry.attr,
+ &queue_rotational_entry.attr,
&queue_zoned_entry.attr,
&queue_nr_zones_entry.attr,
&queue_max_open_zones_entry.attr,
@@ -630,7 +579,7 @@ static struct attribute *queue_attrs[] = {
&queue_nomerges_entry.attr,
&queue_iostats_entry.attr,
&queue_stable_writes_entry.attr,
- &queue_random_entry.attr,
+ &queue_add_random_entry.attr,
&queue_poll_entry.attr,
&queue_wc_entry.attr,
&queue_fua_entry.attr,
@@ -699,14 +648,13 @@ queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
{
struct queue_sysfs_entry *entry = to_queue(attr);
struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
- struct request_queue *q = disk->queue;
ssize_t res;
if (!entry->show)
return -EIO;
- mutex_lock(&q->sysfs_lock);
- res = entry->show(q, page);
- mutex_unlock(&q->sysfs_lock);
+ mutex_lock(&disk->queue->sysfs_lock);
+ res = entry->show(disk, page);
+ mutex_unlock(&disk->queue->sysfs_lock);
return res;
}
@@ -722,9 +670,11 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
if (!entry->store)
return -EIO;
+ blk_mq_freeze_queue(q);
mutex_lock(&q->sysfs_lock);
- res = entry->store(q, page, length);
+ res = entry->store(disk, page, length);
mutex_unlock(&q->sysfs_lock);
+ blk_mq_unfreeze_queue(q);
return res;
}
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index c1bf73f8c75d..dc6140fa3de0 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -704,6 +704,9 @@ static unsigned long tg_within_iops_limit(struct throtl_grp *tg, struct bio *bio
/* Calc approx time to dispatch */
jiffy_wait = jiffy_elapsed_rnd - jiffy_elapsed;
+
+ /* make sure at least one io can be dispatched after waiting */
+ jiffy_wait = max(jiffy_wait, HZ / iops_limit + 1);
return jiffy_wait;
}
diff --git a/block/blk-wbt.c b/block/blk-wbt.c
index 64472134dd26..6dfc659d22e2 100644
--- a/block/blk-wbt.c
+++ b/block/blk-wbt.c
@@ -37,7 +37,7 @@
enum wbt_flags {
WBT_TRACKED = 1, /* write, tracked for throttling */
WBT_READ = 2, /* read */
- WBT_KSWAPD = 4, /* write, from kswapd */
+ WBT_SWAP = 4, /* write, from swap_writepage() */
WBT_DISCARD = 8, /* discard */
WBT_NR_BITS = 4, /* number of bits */
@@ -45,7 +45,7 @@ enum wbt_flags {
enum {
WBT_RWQ_BG = 0,
- WBT_RWQ_KSWAPD,
+ WBT_RWQ_SWAP,
WBT_RWQ_DISCARD,
WBT_NUM_RWQ,
};
@@ -172,8 +172,8 @@ static bool wb_recent_wait(struct rq_wb *rwb)
static inline struct rq_wait *get_rq_wait(struct rq_wb *rwb,
enum wbt_flags wb_acct)
{
- if (wb_acct & WBT_KSWAPD)
- return &rwb->rq_wait[WBT_RWQ_KSWAPD];
+ if (wb_acct & WBT_SWAP)
+ return &rwb->rq_wait[WBT_RWQ_SWAP];
else if (wb_acct & WBT_DISCARD)
return &rwb->rq_wait[WBT_RWQ_DISCARD];
@@ -206,8 +206,8 @@ static void wbt_rqw_done(struct rq_wb *rwb, struct rq_wait *rqw,
*/
if (wb_acct & WBT_DISCARD)
limit = rwb->wb_background;
- else if (test_bit(QUEUE_FLAG_WC, &rwb->rqos.disk->queue->queue_flags) &&
- !wb_recent_wait(rwb))
+ else if (blk_queue_write_cache(rwb->rqos.disk->queue) &&
+ !wb_recent_wait(rwb))
limit = 0;
else
limit = rwb->wb_normal;
@@ -528,7 +528,7 @@ static bool close_io(struct rq_wb *rwb)
time_before(now, rwb->last_comp + HZ / 10);
}
-#define REQ_HIPRIO (REQ_SYNC | REQ_META | REQ_PRIO)
+#define REQ_HIPRIO (REQ_SYNC | REQ_META | REQ_PRIO | REQ_SWAP)
static inline unsigned int get_limit(struct rq_wb *rwb, blk_opf_t opf)
{
@@ -539,13 +539,13 @@ static inline unsigned int get_limit(struct rq_wb *rwb, blk_opf_t opf)
/*
* At this point we know it's a buffered write. If this is
- * kswapd trying to free memory, or REQ_SYNC is set, then
+ * swap trying to free memory, or REQ_SYNC is set, then
* it's WB_SYNC_ALL writeback, and we'll use the max limit for
* that. If the write is marked as a background write, then use
* the idle limit, or go to normal if we haven't had competing
* IO for a bit.
*/
- if ((opf & REQ_HIPRIO) || wb_recent_wait(rwb) || current_is_kswapd())
+ if ((opf & REQ_HIPRIO) || wb_recent_wait(rwb))
limit = rwb->rq_depth.max_depth;
else if ((opf & REQ_BACKGROUND) || close_io(rwb)) {
/*
@@ -622,8 +622,8 @@ static enum wbt_flags bio_to_wbt_flags(struct rq_wb *rwb, struct bio *bio)
if (bio_op(bio) == REQ_OP_READ) {
flags = WBT_READ;
} else if (wbt_should_throttle(bio)) {
- if (current_is_kswapd())
- flags |= WBT_KSWAPD;
+ if (bio->bi_opf & REQ_SWAP)
+ flags |= WBT_SWAP;
if (bio_op(bio) == REQ_OP_DISCARD)
flags |= WBT_DISCARD;
flags |= WBT_TRACKED;
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index 08d7dfe8bd93..af19296fa50d 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -116,24 +116,6 @@ const char *blk_zone_cond_str(enum blk_zone_cond zone_cond)
EXPORT_SYMBOL_GPL(blk_zone_cond_str);
/**
- * bdev_nr_zones - Get number of zones
- * @bdev: Target device
- *
- * Return the total number of zones of a zoned block device. For a block
- * device without zone capabilities, the number of zones is always 0.
- */
-unsigned int bdev_nr_zones(struct block_device *bdev)
-{
- sector_t zone_sectors = bdev_zone_sectors(bdev);
-
- if (!bdev_is_zoned(bdev))
- return 0;
- return (bdev_nr_sectors(bdev) + zone_sectors - 1) >>
- ilog2(zone_sectors);
-}
-EXPORT_SYMBOL_GPL(bdev_nr_zones);
-
-/**
* blkdev_report_zones - Get zones information
* @bdev: Target block device
* @sector: Sector from which to report zones
@@ -168,77 +150,6 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector,
}
EXPORT_SYMBOL_GPL(blkdev_report_zones);
-static inline unsigned long *blk_alloc_zone_bitmap(int node,
- unsigned int nr_zones)
-{
- return kcalloc_node(BITS_TO_LONGS(nr_zones), sizeof(unsigned long),
- GFP_NOIO, node);
-}
-
-static int blk_zone_need_reset_cb(struct blk_zone *zone, unsigned int idx,
- void *data)
-{
- /*
- * For an all-zones reset, ignore conventional, empty, read-only
- * and offline zones.
- */
- switch (zone->cond) {
- case BLK_ZONE_COND_NOT_WP:
- case BLK_ZONE_COND_EMPTY:
- case BLK_ZONE_COND_READONLY:
- case BLK_ZONE_COND_OFFLINE:
- return 0;
- default:
- set_bit(idx, (unsigned long *)data);
- return 0;
- }
-}
-
-static int blkdev_zone_reset_all_emulated(struct block_device *bdev)
-{
- struct gendisk *disk = bdev->bd_disk;
- sector_t capacity = bdev_nr_sectors(bdev);
- sector_t zone_sectors = bdev_zone_sectors(bdev);
- unsigned long *need_reset;
- struct bio *bio = NULL;
- sector_t sector = 0;
- int ret;
-
- need_reset = blk_alloc_zone_bitmap(disk->queue->node, disk->nr_zones);
- if (!need_reset)
- return -ENOMEM;
-
- ret = disk->fops->report_zones(disk, 0, disk->nr_zones,
- blk_zone_need_reset_cb, need_reset);
- if (ret < 0)
- goto out_free_need_reset;
-
- ret = 0;
- while (sector < capacity) {
- if (!test_bit(disk_zone_no(disk, sector), need_reset)) {
- sector += zone_sectors;
- continue;
- }
-
- bio = blk_next_bio(bio, bdev, 0, REQ_OP_ZONE_RESET | REQ_SYNC,
- GFP_KERNEL);
- bio->bi_iter.bi_sector = sector;
- sector += zone_sectors;
-
- /* This may take a while, so be nice to others */
- cond_resched();
- }
-
- if (bio) {
- ret = submit_bio_wait(bio);
- bio_put(bio);
- }
-
-out_free_need_reset:
- kfree(need_reset);
- return ret;
-}
-
static int blkdev_zone_reset_all(struct block_device *bdev)
{
struct bio bio;
@@ -265,7 +176,6 @@ static int blkdev_zone_reset_all(struct block_device *bdev)
int blkdev_zone_mgmt(struct block_device *bdev, enum req_op op,
sector_t sector, sector_t nr_sectors)
{
- struct request_queue *q = bdev_get_queue(bdev);
sector_t zone_sectors = bdev_zone_sectors(bdev);
sector_t capacity = bdev_nr_sectors(bdev);
sector_t end_sector = sector + nr_sectors;
@@ -293,16 +203,11 @@ int blkdev_zone_mgmt(struct block_device *bdev, enum req_op op,
return -EINVAL;
/*
- * In the case of a zone reset operation over all zones,
- * REQ_OP_ZONE_RESET_ALL can be used with devices supporting this
- * command. For other devices, we emulate this command behavior by
- * identifying the zones needing a reset.
+ * In the case of a zone reset operation over all zones, use
+ * REQ_OP_ZONE_RESET_ALL.
*/
- if (op == REQ_OP_ZONE_RESET && sector == 0 && nr_sectors == capacity) {
- if (!blk_queue_zone_resetall(q))
- return blkdev_zone_reset_all_emulated(bdev);
+ if (op == REQ_OP_ZONE_RESET && sector == 0 && nr_sectors == capacity)
return blkdev_zone_reset_all(bdev);
- }
while (sector < end_sector) {
bio = blk_next_bio(bio, bdev, 0, op | REQ_SYNC, GFP_KERNEL);
@@ -1573,7 +1478,7 @@ void disk_free_zone_resources(struct gendisk *disk)
mempool_destroy(disk->zone_wplugs_pool);
disk->zone_wplugs_pool = NULL;
- kfree(disk->conv_zones_bitmap);
+ bitmap_free(disk->conv_zones_bitmap);
disk->conv_zones_bitmap = NULL;
disk->zone_capacity = 0;
disk->last_zone_capacity = 0;
@@ -1650,8 +1555,22 @@ static int disk_update_zone_resources(struct gendisk *disk,
return -ENODEV;
}
+ lim = queue_limits_start_update(q);
+
+ /*
+ * Some devices can advertize zone resource limits that are larger than
+ * the number of sequential zones of the zoned block device, e.g. a
+ * small ZNS namespace. For such case, assume that the zoned device has
+ * no zone resource limits.
+ */
+ nr_seq_zones = disk->nr_zones - nr_conv_zones;
+ if (lim.max_open_zones >= nr_seq_zones)
+ lim.max_open_zones = 0;
+ if (lim.max_active_zones >= nr_seq_zones)
+ lim.max_active_zones = 0;
+
if (!disk->zone_wplugs_pool)
- return 0;
+ goto commit;
/*
* If the device has no limit on the maximum number of open and active
@@ -1660,9 +1579,6 @@ static int disk_update_zone_resources(struct gendisk *disk,
* dynamic zone write plug allocation when simultaneously writing to
* more zones than the size of the mempool.
*/
- lim = queue_limits_start_update(q);
-
- nr_seq_zones = disk->nr_zones - nr_conv_zones;
pool_size = max(lim.max_open_zones, lim.max_active_zones);
if (!pool_size)
pool_size = min(BLK_ZONE_WPLUG_DEFAULT_POOL_SIZE, nr_seq_zones);
@@ -1676,6 +1592,7 @@ static int disk_update_zone_resources(struct gendisk *disk,
lim.max_open_zones = 0;
}
+commit:
return queue_limits_commit_update(q, &lim);
}
@@ -1683,7 +1600,6 @@ static int blk_revalidate_conv_zone(struct blk_zone *zone, unsigned int idx,
struct blk_revalidate_zone_args *args)
{
struct gendisk *disk = args->disk;
- struct request_queue *q = disk->queue;
if (zone->capacity != zone->len) {
pr_warn("%s: Invalid conventional zone capacity\n",
@@ -1699,7 +1615,7 @@ static int blk_revalidate_conv_zone(struct blk_zone *zone, unsigned int idx,
if (!args->conv_zones_bitmap) {
args->conv_zones_bitmap =
- blk_alloc_zone_bitmap(q->node, args->nr_zones);
+ bitmap_zalloc(args->nr_zones, GFP_NOIO);
if (!args->conv_zones_bitmap)
return -ENOMEM;
}
diff --git a/block/blk.h b/block/blk.h
index 189bc25beb50..8e8936e97307 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -98,8 +98,8 @@ static inline bool biovec_phys_mergeable(struct request_queue *q,
struct bio_vec *vec1, struct bio_vec *vec2)
{
unsigned long mask = queue_segment_boundary(q);
- phys_addr_t addr1 = page_to_phys(vec1->bv_page) + vec1->bv_offset;
- phys_addr_t addr2 = page_to_phys(vec2->bv_page) + vec2->bv_offset;
+ phys_addr_t addr1 = bvec_phys(vec1);
+ phys_addr_t addr2 = bvec_phys(vec2);
/*
* Merging adjacent physical pages may not work correctly under KMSAN
@@ -181,9 +181,11 @@ static inline unsigned int blk_rq_get_max_segments(struct request *rq)
return queue_max_segments(rq->q);
}
-static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q,
- enum req_op op)
+static inline unsigned int blk_queue_get_max_sectors(struct request *rq)
{
+ struct request_queue *q = rq->q;
+ enum req_op op = req_op(rq);
+
if (unlikely(op == REQ_OP_DISCARD || op == REQ_OP_SECURE_ERASE))
return min(q->limits.max_discard_sectors,
UINT_MAX >> SECTOR_SHIFT);
@@ -191,6 +193,9 @@ static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q,
if (unlikely(op == REQ_OP_WRITE_ZEROES))
return q->limits.max_write_zeroes_sectors;
+ if (rq->cmd_flags & REQ_ATOMIC)
+ return q->limits.atomic_write_max_sectors;
+
return q->limits.max_sectors;
}
@@ -352,6 +357,8 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio);
enum elv_merge blk_try_merge(struct request *rq, struct bio *bio);
int blk_set_default_limits(struct queue_limits *lim);
+void blk_apply_bdi_limits(struct backing_dev_info *bdi,
+ struct queue_limits *lim);
int blk_dev_init(void);
/*
@@ -393,7 +400,7 @@ struct bio *__blk_queue_bounce(struct bio *bio, struct request_queue *q);
static inline bool blk_queue_may_bounce(struct request_queue *q)
{
return IS_ENABLED(CONFIG_BOUNCE) &&
- q->limits.bounce == BLK_BOUNCE_HIGH &&
+ (q->limits.features & BLK_FEAT_BOUNCE_HIGH) &&
max_low_pfn >= max_pfn;
}
@@ -673,4 +680,9 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
const struct blk_holder_ops *hops, struct file *bdev_file);
int bdev_permission(dev_t dev, blk_mode_t mode, void *holder);
+void blk_integrity_generate(struct bio *bio);
+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);
+
#endif /* BLK_INTERNAL_H */
diff --git a/block/elevator.c b/block/elevator.c
index f64ebd726e58..f13d552a32c8 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -709,24 +709,25 @@ static int elevator_change(struct request_queue *q, const char *elevator_name)
return ret;
}
-ssize_t elv_iosched_store(struct request_queue *q, const char *buf,
+ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
size_t count)
{
char elevator_name[ELV_NAME_MAX];
int ret;
- if (!elv_support_iosched(q))
+ if (!elv_support_iosched(disk->queue))
return count;
strscpy(elevator_name, buf, sizeof(elevator_name));
- ret = elevator_change(q, strstrip(elevator_name));
+ ret = elevator_change(disk->queue, strstrip(elevator_name));
if (!ret)
return count;
return ret;
}
-ssize_t elv_iosched_show(struct request_queue *q, char *name)
+ssize_t elv_iosched_show(struct gendisk *disk, char *name)
{
+ struct request_queue *q = disk->queue;
struct elevator_queue *eq = q->elevator;
struct elevator_type *cur = NULL, *e;
int len = 0;
diff --git a/block/elevator.h b/block/elevator.h
index e9a050a96e53..3fe18e1a8692 100644
--- a/block/elevator.h
+++ b/block/elevator.h
@@ -147,8 +147,8 @@ extern void elv_unregister(struct elevator_type *);
/*
* io scheduler sysfs switching
*/
-extern ssize_t elv_iosched_show(struct request_queue *, char *);
-extern ssize_t elv_iosched_store(struct request_queue *, const char *, size_t);
+ssize_t elv_iosched_show(struct gendisk *disk, char *page);
+ssize_t elv_iosched_store(struct gendisk *disk, const char *page, size_t count);
extern bool elv_bio_merge_ok(struct request *, struct bio *);
extern struct elevator_queue *elevator_alloc(struct request_queue *,
diff --git a/block/fops.c b/block/fops.c
index 376265935714..9825c1713a49 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -34,9 +34,12 @@ static blk_opf_t dio_bio_write_op(struct kiocb *iocb)
return opf;
}
-static bool blkdev_dio_unaligned(struct block_device *bdev, loff_t pos,
- struct iov_iter *iter)
+static bool blkdev_dio_invalid(struct block_device *bdev, loff_t pos,
+ struct iov_iter *iter, bool is_atomic)
{
+ if (is_atomic && !generic_atomic_write_valid(iter, pos))
+ return true;
+
return pos & (bdev_logical_block_size(bdev) - 1) ||
!bdev_iter_is_aligned(bdev, iter);
}
@@ -72,6 +75,8 @@ static ssize_t __blkdev_direct_IO_simple(struct kiocb *iocb,
bio.bi_iter.bi_sector = pos >> SECTOR_SHIFT;
bio.bi_write_hint = file_inode(iocb->ki_filp)->i_write_hint;
bio.bi_ioprio = iocb->ki_ioprio;
+ if (iocb->ki_flags & IOCB_ATOMIC)
+ bio.bi_opf |= REQ_ATOMIC;
ret = bio_iov_iter_get_pages(&bio, iter);
if (unlikely(ret))
@@ -343,6 +348,9 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb,
task_io_account_write(bio->bi_iter.bi_size);
}
+ if (iocb->ki_flags & IOCB_ATOMIC)
+ bio->bi_opf |= REQ_ATOMIC;
+
if (iocb->ki_flags & IOCB_NOWAIT)
bio->bi_opf |= REQ_NOWAIT;
@@ -359,12 +367,13 @@ 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_unaligned(bdev, iocb->ki_pos, iter))
+ if (blkdev_dio_invalid(bdev, iocb->ki_pos, iter, is_atomic))
return -EINVAL;
nr_pages = bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS + 1);
@@ -373,6 +382,8 @@ 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) {
+ return -EINVAL;
}
return __blkdev_direct_IO(iocb, iter, bdev, bio_max_segs(nr_pages));
}
@@ -383,10 +394,11 @@ static int blkdev_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
struct block_device *bdev = I_BDEV(inode);
loff_t isize = i_size_read(inode);
- iomap->bdev = bdev;
- iomap->offset = ALIGN_DOWN(offset, bdev_logical_block_size(bdev));
if (offset >= isize)
return -EIO;
+
+ iomap->bdev = bdev;
+ iomap->offset = ALIGN_DOWN(offset, bdev_logical_block_size(bdev));
iomap->type = IOMAP_MAPPED;
iomap->addr = iomap->offset;
iomap->length = isize - iomap->offset;
@@ -612,6 +624,9 @@ 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)
+ filp->f_mode |= FMODE_CAN_ATOMIC_WRITE;
+
ret = bdev_open(bdev, mode, filp->private_data, NULL, filp);
if (ret)
blkdev_put_no_open(bdev);
diff --git a/block/genhd.c b/block/genhd.c
index 8f1f3c6b4d67..4dc95a463505 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -524,7 +524,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
disk->part0->bd_dev = MKDEV(disk->major, disk->first_minor);
}
- disk_update_readahead(disk);
+ blk_apply_bdi_limits(disk->bdi, &disk->queue->limits);
disk_add_events(disk);
set_bit(GD_ADDED, &disk->state);
return 0;
diff --git a/block/ioctl.c b/block/ioctl.c
index d570e1695896..e8e4a4190f18 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -224,7 +224,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, blk_mode_t mode,
goto fail;
err = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL,
- BLKDEV_ZERO_NOUNMAP);
+ BLKDEV_ZERO_NOUNMAP | BLKDEV_ZERO_KILLABLE);
fail:
filemap_invalidate_unlock(bdev->bd_mapping);
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
index 94eede4fb9eb..acdc28756d9d 100644
--- a/block/mq-deadline.c
+++ b/block/mq-deadline.c
@@ -488,6 +488,20 @@ unlock:
}
/*
+ * 'depth' is a number in the range 1..INT_MAX representing a number of
+ * requests. Scale it with a factor (1 << bt->sb.shift) / q->nr_requests since
+ * 1..(1 << bt->sb.shift) is the range expected by sbitmap_get_shallow().
+ * Values larger than q->nr_requests have the same effect as q->nr_requests.
+ */
+static int dd_to_word_depth(struct blk_mq_hw_ctx *hctx, unsigned int qdepth)
+{
+ struct sbitmap_queue *bt = &hctx->sched_tags->bitmap_tags;
+ const unsigned int nrr = hctx->queue->nr_requests;
+
+ return ((qdepth << bt->sb.shift) + nrr - 1) / nrr;
+}
+
+/*
* Called by __blk_mq_alloc_request(). The shallow_depth value set by this
* function is used by __blk_mq_get_tag().
*/
@@ -503,7 +517,7 @@ static void dd_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
* Throttle asynchronous requests and writes such that these requests
* do not block the allocation of synchronous requests.
*/
- data->shallow_depth = dd->async_depth;
+ data->shallow_depth = dd_to_word_depth(data->hctx, dd->async_depth);
}
/* Called by blk_mq_update_nr_requests(). */
@@ -513,9 +527,9 @@ static void dd_depth_updated(struct blk_mq_hw_ctx *hctx)
struct deadline_data *dd = q->elevator->elevator_data;
struct blk_mq_tags *tags = hctx->sched_tags;
- dd->async_depth = max(1UL, 3 * q->nr_requests / 4);
+ dd->async_depth = q->nr_requests;
- sbitmap_queue_min_shallow_depth(&tags->bitmap_tags, dd->async_depth);
+ sbitmap_queue_min_shallow_depth(&tags->bitmap_tags, 1);
}
/* Called by blk_mq_init_hctx() and blk_mq_init_sched(). */
diff --git a/block/t10-pi.c b/block/t10-pi.c
index f4cc91156da1..425e2836f3e1 100644
--- a/block/t10-pi.c
+++ b/block/t10-pi.c
@@ -11,17 +11,23 @@
#include <linux/module.h>
#include <net/checksum.h>
#include <asm/unaligned.h>
+#include "blk.h"
+
+struct blk_integrity_iter {
+ void *prot_buf;
+ void *data_buf;
+ sector_t seed;
+ unsigned int data_size;
+ unsigned short interval;
+ const char *disk_name;
+};
-typedef __be16 (csum_fn) (__be16, void *, unsigned int);
-
-static __be16 t10_pi_crc_fn(__be16 crc, void *data, unsigned int len)
-{
- return cpu_to_be16(crc_t10dif_update(be16_to_cpu(crc), data, len));
-}
-
-static __be16 t10_pi_ip_fn(__be16 csum, void *data, unsigned int len)
+static __be16 t10_pi_csum(__be16 csum, void *data, unsigned int len,
+ unsigned char csum_type)
{
- return (__force __be16)ip_compute_csum(data, len);
+ if (csum_type == BLK_INTEGRITY_CSUM_IP)
+ return (__force __be16)ip_compute_csum(data, len);
+ return cpu_to_be16(crc_t10dif_update(be16_to_cpu(csum), data, len));
}
/*
@@ -29,48 +35,44 @@ static __be16 t10_pi_ip_fn(__be16 csum, void *data, unsigned int len)
* 16 bit app tag, 32 bit reference tag. Type 3 does not define the ref
* tag.
*/
-static blk_status_t t10_pi_generate(struct blk_integrity_iter *iter,
- csum_fn *fn, enum t10_dif_type type)
+static void t10_pi_generate(struct blk_integrity_iter *iter,
+ struct blk_integrity *bi)
{
- u8 offset = iter->pi_offset;
+ u8 offset = bi->pi_offset;
unsigned int i;
for (i = 0 ; i < iter->data_size ; i += iter->interval) {
struct t10_pi_tuple *pi = iter->prot_buf + offset;
- pi->guard_tag = fn(0, iter->data_buf, iter->interval);
+ pi->guard_tag = t10_pi_csum(0, iter->data_buf, iter->interval,
+ bi->csum_type);
if (offset)
- pi->guard_tag = fn(pi->guard_tag, iter->prot_buf,
- offset);
+ pi->guard_tag = t10_pi_csum(pi->guard_tag,
+ iter->prot_buf, offset, bi->csum_type);
pi->app_tag = 0;
- if (type == T10_PI_TYPE1_PROTECTION)
+ if (bi->flags & BLK_INTEGRITY_REF_TAG)
pi->ref_tag = cpu_to_be32(lower_32_bits(iter->seed));
else
pi->ref_tag = 0;
iter->data_buf += iter->interval;
- iter->prot_buf += iter->tuple_size;
+ iter->prot_buf += bi->tuple_size;
iter->seed++;
}
-
- return BLK_STS_OK;
}
static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,
- csum_fn *fn, enum t10_dif_type type)
+ struct blk_integrity *bi)
{
- u8 offset = iter->pi_offset;
+ u8 offset = bi->pi_offset;
unsigned int i;
- BUG_ON(type == T10_PI_TYPE0_PROTECTION);
-
for (i = 0 ; i < iter->data_size ; i += iter->interval) {
struct t10_pi_tuple *pi = iter->prot_buf + offset;
__be16 csum;
- if (type == T10_PI_TYPE1_PROTECTION ||
- type == T10_PI_TYPE2_PROTECTION) {
+ if (bi->flags & BLK_INTEGRITY_REF_TAG) {
if (pi->app_tag == T10_PI_APP_ESCAPE)
goto next;
@@ -82,15 +84,17 @@ static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,
iter->seed, be32_to_cpu(pi->ref_tag));
return BLK_STS_PROTECTION;
}
- } else if (type == T10_PI_TYPE3_PROTECTION) {
+ } else {
if (pi->app_tag == T10_PI_APP_ESCAPE &&
pi->ref_tag == T10_PI_REF_ESCAPE)
goto next;
}
- csum = fn(0, iter->data_buf, iter->interval);
+ csum = t10_pi_csum(0, iter->data_buf, iter->interval,
+ bi->csum_type);
if (offset)
- csum = fn(csum, iter->prot_buf, offset);
+ csum = t10_pi_csum(csum, iter->prot_buf, offset,
+ bi->csum_type);
if (pi->guard_tag != csum) {
pr_err("%s: guard tag error at sector %llu " \
@@ -102,33 +106,13 @@ static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,
next:
iter->data_buf += iter->interval;
- iter->prot_buf += iter->tuple_size;
+ iter->prot_buf += bi->tuple_size;
iter->seed++;
}
return BLK_STS_OK;
}
-static blk_status_t t10_pi_type1_generate_crc(struct blk_integrity_iter *iter)
-{
- return t10_pi_generate(iter, t10_pi_crc_fn, T10_PI_TYPE1_PROTECTION);
-}
-
-static blk_status_t t10_pi_type1_generate_ip(struct blk_integrity_iter *iter)
-{
- return t10_pi_generate(iter, t10_pi_ip_fn, T10_PI_TYPE1_PROTECTION);
-}
-
-static blk_status_t t10_pi_type1_verify_crc(struct blk_integrity_iter *iter)
-{
- return t10_pi_verify(iter, t10_pi_crc_fn, T10_PI_TYPE1_PROTECTION);
-}
-
-static blk_status_t t10_pi_type1_verify_ip(struct blk_integrity_iter *iter)
-{
- return t10_pi_verify(iter, t10_pi_ip_fn, T10_PI_TYPE1_PROTECTION);
-}
-
/**
* t10_pi_type1_prepare - prepare PI prior submitting request to device
* @rq: request with PI that should be prepared
@@ -141,7 +125,7 @@ static blk_status_t t10_pi_type1_verify_ip(struct blk_integrity_iter *iter)
*/
static void t10_pi_type1_prepare(struct request *rq)
{
- struct blk_integrity *bi = &rq->q->integrity;
+ struct blk_integrity *bi = &rq->q->limits.integrity;
const int tuple_sz = bi->tuple_size;
u32 ref_tag = t10_pi_ref_tag(rq);
u8 offset = bi->pi_offset;
@@ -192,7 +176,7 @@ static void t10_pi_type1_prepare(struct request *rq)
*/
static void t10_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
{
- struct blk_integrity *bi = &rq->q->integrity;
+ struct blk_integrity *bi = &rq->q->limits.integrity;
unsigned intervals = nr_bytes >> bi->interval_exp;
const int tuple_sz = bi->tuple_size;
u32 ref_tag = t10_pi_ref_tag(rq);
@@ -225,81 +209,15 @@ static void t10_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
}
}
-static blk_status_t t10_pi_type3_generate_crc(struct blk_integrity_iter *iter)
-{
- return t10_pi_generate(iter, t10_pi_crc_fn, T10_PI_TYPE3_PROTECTION);
-}
-
-static blk_status_t t10_pi_type3_generate_ip(struct blk_integrity_iter *iter)
-{
- return t10_pi_generate(iter, t10_pi_ip_fn, T10_PI_TYPE3_PROTECTION);
-}
-
-static blk_status_t t10_pi_type3_verify_crc(struct blk_integrity_iter *iter)
-{
- return t10_pi_verify(iter, t10_pi_crc_fn, T10_PI_TYPE3_PROTECTION);
-}
-
-static blk_status_t t10_pi_type3_verify_ip(struct blk_integrity_iter *iter)
-{
- return t10_pi_verify(iter, t10_pi_ip_fn, T10_PI_TYPE3_PROTECTION);
-}
-
-/* Type 3 does not have a reference tag so no remapping is required. */
-static void t10_pi_type3_prepare(struct request *rq)
-{
-}
-
-/* Type 3 does not have a reference tag so no remapping is required. */
-static void t10_pi_type3_complete(struct request *rq, unsigned int nr_bytes)
-{
-}
-
-const struct blk_integrity_profile t10_pi_type1_crc = {
- .name = "T10-DIF-TYPE1-CRC",
- .generate_fn = t10_pi_type1_generate_crc,
- .verify_fn = t10_pi_type1_verify_crc,
- .prepare_fn = t10_pi_type1_prepare,
- .complete_fn = t10_pi_type1_complete,
-};
-EXPORT_SYMBOL(t10_pi_type1_crc);
-
-const struct blk_integrity_profile t10_pi_type1_ip = {
- .name = "T10-DIF-TYPE1-IP",
- .generate_fn = t10_pi_type1_generate_ip,
- .verify_fn = t10_pi_type1_verify_ip,
- .prepare_fn = t10_pi_type1_prepare,
- .complete_fn = t10_pi_type1_complete,
-};
-EXPORT_SYMBOL(t10_pi_type1_ip);
-
-const struct blk_integrity_profile t10_pi_type3_crc = {
- .name = "T10-DIF-TYPE3-CRC",
- .generate_fn = t10_pi_type3_generate_crc,
- .verify_fn = t10_pi_type3_verify_crc,
- .prepare_fn = t10_pi_type3_prepare,
- .complete_fn = t10_pi_type3_complete,
-};
-EXPORT_SYMBOL(t10_pi_type3_crc);
-
-const struct blk_integrity_profile t10_pi_type3_ip = {
- .name = "T10-DIF-TYPE3-IP",
- .generate_fn = t10_pi_type3_generate_ip,
- .verify_fn = t10_pi_type3_verify_ip,
- .prepare_fn = t10_pi_type3_prepare,
- .complete_fn = t10_pi_type3_complete,
-};
-EXPORT_SYMBOL(t10_pi_type3_ip);
-
static __be64 ext_pi_crc64(u64 crc, void *data, unsigned int len)
{
return cpu_to_be64(crc64_rocksoft_update(crc, data, len));
}
-static blk_status_t ext_pi_crc64_generate(struct blk_integrity_iter *iter,
- enum t10_dif_type type)
+static void ext_pi_crc64_generate(struct blk_integrity_iter *iter,
+ struct blk_integrity *bi)
{
- u8 offset = iter->pi_offset;
+ u8 offset = bi->pi_offset;
unsigned int i;
for (i = 0 ; i < iter->data_size ; i += iter->interval) {
@@ -311,17 +229,15 @@ static blk_status_t ext_pi_crc64_generate(struct blk_integrity_iter *iter,
iter->prot_buf, offset);
pi->app_tag = 0;
- if (type == T10_PI_TYPE1_PROTECTION)
+ if (bi->flags & BLK_INTEGRITY_REF_TAG)
put_unaligned_be48(iter->seed, pi->ref_tag);
else
put_unaligned_be48(0ULL, pi->ref_tag);
iter->data_buf += iter->interval;
- iter->prot_buf += iter->tuple_size;
+ iter->prot_buf += bi->tuple_size;
iter->seed++;
}
-
- return BLK_STS_OK;
}
static bool ext_pi_ref_escape(u8 *ref_tag)
@@ -332,9 +248,9 @@ static bool ext_pi_ref_escape(u8 *ref_tag)
}
static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
- enum t10_dif_type type)
+ struct blk_integrity *bi)
{
- u8 offset = iter->pi_offset;
+ u8 offset = bi->pi_offset;
unsigned int i;
for (i = 0; i < iter->data_size; i += iter->interval) {
@@ -342,7 +258,7 @@ static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
u64 ref, seed;
__be64 csum;
- if (type == T10_PI_TYPE1_PROTECTION) {
+ if (bi->flags & BLK_INTEGRITY_REF_TAG) {
if (pi->app_tag == T10_PI_APP_ESCAPE)
goto next;
@@ -353,7 +269,7 @@ static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
iter->disk_name, seed, ref);
return BLK_STS_PROTECTION;
}
- } else if (type == T10_PI_TYPE3_PROTECTION) {
+ } else {
if (pi->app_tag == T10_PI_APP_ESCAPE &&
ext_pi_ref_escape(pi->ref_tag))
goto next;
@@ -374,26 +290,16 @@ static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
next:
iter->data_buf += iter->interval;
- iter->prot_buf += iter->tuple_size;
+ iter->prot_buf += bi->tuple_size;
iter->seed++;
}
return BLK_STS_OK;
}
-static blk_status_t ext_pi_type1_verify_crc64(struct blk_integrity_iter *iter)
-{
- return ext_pi_crc64_verify(iter, T10_PI_TYPE1_PROTECTION);
-}
-
-static blk_status_t ext_pi_type1_generate_crc64(struct blk_integrity_iter *iter)
-{
- return ext_pi_crc64_generate(iter, T10_PI_TYPE1_PROTECTION);
-}
-
static void ext_pi_type1_prepare(struct request *rq)
{
- struct blk_integrity *bi = &rq->q->integrity;
+ struct blk_integrity *bi = &rq->q->limits.integrity;
const int tuple_sz = bi->tuple_size;
u64 ref_tag = ext_pi_ref_tag(rq);
u8 offset = bi->pi_offset;
@@ -433,7 +339,7 @@ static void ext_pi_type1_prepare(struct request *rq)
static void ext_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
{
- struct blk_integrity *bi = &rq->q->integrity;
+ struct blk_integrity *bi = &rq->q->limits.integrity;
unsigned intervals = nr_bytes >> bi->interval_exp;
const int tuple_sz = bi->tuple_size;
u64 ref_tag = ext_pi_ref_tag(rq);
@@ -467,33 +373,105 @@ static void ext_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
}
}
-static blk_status_t ext_pi_type3_verify_crc64(struct blk_integrity_iter *iter)
+void blk_integrity_generate(struct bio *bio)
{
- return ext_pi_crc64_verify(iter, T10_PI_TYPE3_PROTECTION);
+ struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
+ struct bio_integrity_payload *bip = bio_integrity(bio);
+ struct blk_integrity_iter iter;
+ struct bvec_iter bviter;
+ struct bio_vec bv;
+
+ iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
+ iter.interval = 1 << bi->interval_exp;
+ iter.seed = bio->bi_iter.bi_sector;
+ iter.prot_buf = bvec_virt(bip->bip_vec);
+ bio_for_each_segment(bv, bio, bviter) {
+ void *kaddr = bvec_kmap_local(&bv);
+
+ iter.data_buf = kaddr;
+ iter.data_size = bv.bv_len;
+ switch (bi->csum_type) {
+ case BLK_INTEGRITY_CSUM_CRC64:
+ ext_pi_crc64_generate(&iter, bi);
+ break;
+ case BLK_INTEGRITY_CSUM_CRC:
+ case BLK_INTEGRITY_CSUM_IP:
+ t10_pi_generate(&iter, bi);
+ break;
+ default:
+ break;
+ }
+ kunmap_local(kaddr);
+ }
}
-static blk_status_t ext_pi_type3_generate_crc64(struct blk_integrity_iter *iter)
+void blk_integrity_verify(struct bio *bio)
{
- return ext_pi_crc64_generate(iter, T10_PI_TYPE3_PROTECTION);
+ struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
+ struct bio_integrity_payload *bip = bio_integrity(bio);
+ struct blk_integrity_iter iter;
+ struct bvec_iter bviter;
+ struct bio_vec bv;
+
+ /*
+ * At the moment verify is called bi_iter has been advanced during split
+ * and completion, so use the copy created during submission here.
+ */
+ iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
+ iter.interval = 1 << bi->interval_exp;
+ iter.seed = bip->bio_iter.bi_sector;
+ iter.prot_buf = bvec_virt(bip->bip_vec);
+ __bio_for_each_segment(bv, bio, bviter, bip->bio_iter) {
+ void *kaddr = bvec_kmap_local(&bv);
+ blk_status_t ret = BLK_STS_OK;
+
+ iter.data_buf = kaddr;
+ iter.data_size = bv.bv_len;
+ switch (bi->csum_type) {
+ case BLK_INTEGRITY_CSUM_CRC64:
+ ret = ext_pi_crc64_verify(&iter, bi);
+ break;
+ case BLK_INTEGRITY_CSUM_CRC:
+ case BLK_INTEGRITY_CSUM_IP:
+ ret = t10_pi_verify(&iter, bi);
+ break;
+ default:
+ break;
+ }
+ kunmap_local(kaddr);
+
+ if (ret) {
+ bio->bi_status = ret;
+ return;
+ }
+ }
}
-const struct blk_integrity_profile ext_pi_type1_crc64 = {
- .name = "EXT-DIF-TYPE1-CRC64",
- .generate_fn = ext_pi_type1_generate_crc64,
- .verify_fn = ext_pi_type1_verify_crc64,
- .prepare_fn = ext_pi_type1_prepare,
- .complete_fn = ext_pi_type1_complete,
-};
-EXPORT_SYMBOL_GPL(ext_pi_type1_crc64);
-
-const struct blk_integrity_profile ext_pi_type3_crc64 = {
- .name = "EXT-DIF-TYPE3-CRC64",
- .generate_fn = ext_pi_type3_generate_crc64,
- .verify_fn = ext_pi_type3_verify_crc64,
- .prepare_fn = t10_pi_type3_prepare,
- .complete_fn = t10_pi_type3_complete,
-};
-EXPORT_SYMBOL_GPL(ext_pi_type3_crc64);
+void blk_integrity_prepare(struct request *rq)
+{
+ struct blk_integrity *bi = &rq->q->limits.integrity;
+
+ if (!(bi->flags & BLK_INTEGRITY_REF_TAG))
+ return;
+
+ if (bi->csum_type == BLK_INTEGRITY_CSUM_CRC64)
+ ext_pi_type1_prepare(rq);
+ else
+ t10_pi_type1_prepare(rq);
+}
+
+void blk_integrity_complete(struct request *rq, unsigned int nr_bytes)
+{
+ struct blk_integrity *bi = &rq->q->limits.integrity;
+
+ if (!(bi->flags & BLK_INTEGRITY_REF_TAG))
+ return;
+
+ if (bi->csum_type == BLK_INTEGRITY_CSUM_CRC64)
+ ext_pi_type1_complete(rq, nr_bytes);
+ else
+ t10_pi_type1_complete(rq, nr_bytes);
+}
MODULE_DESCRIPTION("T10 Protection Information module");
MODULE_LICENSE("GPL");
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index 7a0dd35d62c9..64e10bad8072 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -35,6 +35,17 @@ EXPORT_PER_CPU_SYMBOL(processors);
struct acpi_processor_errata errata __read_mostly;
EXPORT_SYMBOL_GPL(errata);
+acpi_handle acpi_get_processor_handle(int cpu)
+{
+ struct acpi_processor *pr;
+
+ pr = per_cpu(processors, cpu);
+ if (pr)
+ return pr->handle;
+
+ return NULL;
+}
+
static int acpi_processor_errata_piix4(struct pci_dev *dev)
{
u8 value1 = 0;
@@ -183,20 +194,44 @@ static void __init acpi_pcc_cpufreq_init(void) {}
#endif /* CONFIG_X86 */
/* Initialization */
+static DEFINE_PER_CPU(void *, processor_device_array);
+
+static int acpi_processor_set_per_cpu(struct acpi_processor *pr,
+ struct acpi_device *device)
+{
+ BUG_ON(pr->id >= nr_cpu_ids);
+
+ /*
+ * Buggy BIOS check.
+ * ACPI id of processors can be reported wrongly by the BIOS.
+ * Don't trust it blindly
+ */
+ if (per_cpu(processor_device_array, pr->id) != NULL &&
+ per_cpu(processor_device_array, pr->id) != device) {
+ dev_warn(&device->dev,
+ "BIOS reported wrong ACPI id %d for the processor\n",
+ pr->id);
+ return -EINVAL;
+ }
+ /*
+ * processor_device_array is not cleared on errors to allow buggy BIOS
+ * checks.
+ */
+ per_cpu(processor_device_array, pr->id) = device;
+ per_cpu(processors, pr->id) = pr;
+
+ return 0;
+}
+
#ifdef CONFIG_ACPI_HOTPLUG_CPU
-static int acpi_processor_hotadd_init(struct acpi_processor *pr)
+static int acpi_processor_hotadd_init(struct acpi_processor *pr,
+ struct acpi_device *device)
{
- unsigned long long sta;
- acpi_status status;
int ret;
if (invalid_phys_cpuid(pr->phys_id))
return -ENODEV;
- status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta);
- if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
- return -ENODEV;
-
cpu_maps_update_begin();
cpus_write_lock();
@@ -204,19 +239,26 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
if (ret)
goto out;
+ ret = acpi_processor_set_per_cpu(pr, device);
+ if (ret) {
+ acpi_unmap_cpu(pr->id);
+ goto out;
+ }
+
ret = arch_register_cpu(pr->id);
if (ret) {
+ /* Leave the processor device array in place to detect buggy bios */
+ per_cpu(processors, pr->id) = NULL;
acpi_unmap_cpu(pr->id);
goto out;
}
/*
- * CPU got hot-added, but cpu_data is not initialized yet. Set a flag
- * to delay cpu_idle/throttling initialization and do it when the CPU
- * gets online for the first time.
+ * CPU got hot-added, but cpu_data is not initialized yet. Do
+ * cpu_idle/throttling initialization when the CPU gets online for
+ * the first time.
*/
pr_info("CPU%d has been hot-added\n", pr->id);
- pr->flags.need_hotplug_init = 1;
out:
cpus_write_unlock();
@@ -224,7 +266,8 @@ out:
return ret;
}
#else
-static inline int acpi_processor_hotadd_init(struct acpi_processor *pr)
+static inline int acpi_processor_hotadd_init(struct acpi_processor *pr,
+ struct acpi_device *device)
{
return -ENODEV;
}
@@ -239,6 +282,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
acpi_status status = AE_OK;
static int cpu0_initialized;
unsigned long long value;
+ int ret;
acpi_processor_errata();
@@ -315,19 +359,19 @@ static int acpi_processor_get_info(struct acpi_device *device)
}
/*
- * Extra Processor objects may be enumerated on MP systems with
- * less than the max # of CPUs. They should be ignored _iff
- * they are physically not present.
- *
- * NOTE: Even if the processor has a cpuid, it may not be present
- * because cpuid <-> apicid mapping is persistent now.
+ * This code is not called unless we know the CPU is present and
+ * enabled. The two paths are:
+ * a) Initially present CPUs on architectures that do not defer
+ * their arch_register_cpu() calls until this point.
+ * b) Hotplugged CPUs (enabled bit in _STA has transitioned from not
+ * enabled to enabled)
*/
- if (invalid_logical_cpuid(pr->id) || !cpu_present(pr->id)) {
- int ret = acpi_processor_hotadd_init(pr);
-
- if (ret)
- return ret;
- }
+ if (!get_cpu_device(pr->id))
+ ret = acpi_processor_hotadd_init(pr, device);
+ else
+ ret = acpi_processor_set_per_cpu(pr, device);
+ if (ret)
+ return ret;
/*
* On some boxes several processors use the same processor bus id.
@@ -372,8 +416,6 @@ static int acpi_processor_get_info(struct acpi_device *device)
* (cpu_data(cpu)) values, like CPU feature flags, family, model, etc.
* Such things have to be put in and set up by the processor driver's .probe().
*/
-static DEFINE_PER_CPU(void *, processor_device_array);
-
static int acpi_processor_add(struct acpi_device *device,
const struct acpi_device_id *id)
{
@@ -400,39 +442,17 @@ static int acpi_processor_add(struct acpi_device *device,
result = acpi_processor_get_info(device);
if (result) /* Processor is not physically present or unavailable */
- return 0;
-
- BUG_ON(pr->id >= nr_cpu_ids);
-
- /*
- * Buggy BIOS check.
- * ACPI id of processors can be reported wrongly by the BIOS.
- * Don't trust it blindly
- */
- if (per_cpu(processor_device_array, pr->id) != NULL &&
- per_cpu(processor_device_array, pr->id) != device) {
- dev_warn(&device->dev,
- "BIOS reported wrong ACPI id %d for the processor\n",
- pr->id);
- /* Give up, but do not abort the namespace scan. */
- goto err;
- }
- /*
- * processor_device_array is not cleared on errors to allow buggy BIOS
- * checks.
- */
- per_cpu(processor_device_array, pr->id) = device;
- per_cpu(processors, pr->id) = pr;
+ goto err_clear_driver_data;
dev = get_cpu_device(pr->id);
if (!dev) {
result = -ENODEV;
- goto err;
+ goto err_clear_per_cpu;
}
result = acpi_bind_one(dev, device);
if (result)
- goto err;
+ goto err_clear_per_cpu;
pr->dev = dev;
@@ -443,10 +463,11 @@ static int acpi_processor_add(struct acpi_device *device,
dev_err(dev, "Processor driver could not be attached\n");
acpi_unbind_one(dev);
- err:
- free_cpumask_var(pr->throttling.shared_cpu_map);
- device->driver_data = NULL;
+ err_clear_per_cpu:
per_cpu(processors, pr->id) = NULL;
+ err_clear_driver_data:
+ device->driver_data = NULL;
+ free_cpumask_var(pr->throttling.shared_cpu_map);
err_free_pr:
kfree(pr);
return result;
@@ -454,7 +475,7 @@ static int acpi_processor_add(struct acpi_device *device,
#ifdef CONFIG_ACPI_HOTPLUG_CPU
/* Removal */
-static void acpi_processor_remove(struct acpi_device *device)
+static void acpi_processor_post_eject(struct acpi_device *device)
{
struct acpi_processor *pr;
@@ -476,10 +497,6 @@ static void acpi_processor_remove(struct acpi_device *device)
device_release_driver(pr->dev);
acpi_unbind_one(pr->dev);
- /* Clean up. */
- per_cpu(processor_device_array, pr->id) = NULL;
- per_cpu(processors, pr->id) = NULL;
-
cpu_maps_update_begin();
cpus_write_lock();
@@ -487,6 +504,10 @@ static void acpi_processor_remove(struct acpi_device *device)
arch_unregister_cpu(pr->id);
acpi_unmap_cpu(pr->id);
+ /* Clean up. */
+ per_cpu(processor_device_array, pr->id) = NULL;
+ per_cpu(processors, pr->id) = NULL;
+
cpus_write_unlock();
cpu_maps_update_done();
@@ -622,7 +643,7 @@ static struct acpi_scan_handler processor_handler = {
.ids = processor_device_ids,
.attach = acpi_processor_add,
#ifdef CONFIG_ACPI_HOTPLUG_CPU
- .detach = acpi_processor_remove,
+ .post_eject = acpi_processor_post_eject,
#endif
.hotplug = {
.enabled = true,
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 726944648c9b..05ecde9eaabe 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_ACPI_AGDI) += agdi.o
-obj-$(CONFIG_ACPI_IORT) += iort.o
-obj-$(CONFIG_ACPI_GTDT) += gtdt.o
obj-$(CONFIG_ACPI_APMT) += apmt.o
+obj-$(CONFIG_ACPI_FFH) += ffh.o
+obj-$(CONFIG_ACPI_GTDT) += gtdt.o
+obj-$(CONFIG_ACPI_IORT) += iort.o
+obj-$(CONFIG_ACPI_PROCESSOR_IDLE) += cpuidle.o
obj-$(CONFIG_ARM_AMBA) += amba.o
obj-y += dma.o init.o
obj-y += thermal_cpufreq.o
diff --git a/drivers/acpi/arm64/amba.c b/drivers/acpi/arm64/amba.c
index e1f0bbb8f393..1350083bce5f 100644
--- a/drivers/acpi/arm64/amba.c
+++ b/drivers/acpi/arm64/amba.c
@@ -27,11 +27,7 @@ static const struct acpi_device_id amba_id_list[] = {
static void amba_register_dummy_clk(void)
{
- static struct clk *amba_dummy_clk;
-
- /* If clock already registered */
- if (amba_dummy_clk)
- return;
+ struct clk *amba_dummy_clk;
amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, 0, 0);
clk_register_clkdev(amba_dummy_clk, "apb_pclk", NULL);
diff --git a/arch/arm64/kernel/cpuidle.c b/drivers/acpi/arm64/cpuidle.c
index f372295207fb..801f9c450142 100644
--- a/arch/arm64/kernel/cpuidle.c
+++ b/drivers/acpi/arm64/cpuidle.c
@@ -10,9 +10,6 @@
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
#include <linux/psci.h>
-
-#ifdef CONFIG_ACPI_PROCESSOR_IDLE
-
#include <acpi/processor.h>
#define ARM64_LPI_IS_RETENTION_STATE(arch_flags) (!(arch_flags))
@@ -71,4 +68,3 @@ __cpuidle int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
return CPU_PM_CPU_IDLE_ENTER_PARAM_RCU(psci_cpu_suspend_enter,
lpi->index, state);
}
-#endif
diff --git a/drivers/acpi/arm64/ffh.c b/drivers/acpi/arm64/ffh.c
new file mode 100644
index 000000000000..877edc6557e9
--- /dev/null
+++ b/drivers/acpi/arm64/ffh.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/acpi.h>
+#include <linux/arm-smccc.h>
+#include <linux/slab.h>
+
+/*
+ * Implements ARM64 specific callbacks to support ACPI FFH Operation Region as
+ * specified in https://developer.arm.com/docs/den0048/latest
+ */
+struct acpi_ffh_data {
+ struct acpi_ffh_info info;
+ void (*invoke_ffh_fn)(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3,
+ unsigned long a4, unsigned long a5,
+ unsigned long a6, unsigned long a7,
+ struct arm_smccc_res *args,
+ struct arm_smccc_quirk *res);
+ void (*invoke_ffh64_fn)(const struct arm_smccc_1_2_regs *args,
+ struct arm_smccc_1_2_regs *res);
+};
+
+int acpi_ffh_address_space_arch_setup(void *handler_ctxt, void **region_ctxt)
+{
+ enum arm_smccc_conduit conduit;
+ struct acpi_ffh_data *ffh_ctxt;
+
+ if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
+ return -EOPNOTSUPP;
+
+ conduit = arm_smccc_1_1_get_conduit();
+ if (conduit == SMCCC_CONDUIT_NONE) {
+ pr_err("%s: invalid SMCCC conduit\n", __func__);
+ return -EOPNOTSUPP;
+ }
+
+ ffh_ctxt = kzalloc(sizeof(*ffh_ctxt), GFP_KERNEL);
+ if (!ffh_ctxt)
+ return -ENOMEM;
+
+ if (conduit == SMCCC_CONDUIT_SMC) {
+ ffh_ctxt->invoke_ffh_fn = __arm_smccc_smc;
+ ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_smc;
+ } else {
+ ffh_ctxt->invoke_ffh_fn = __arm_smccc_hvc;
+ ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_hvc;
+ }
+
+ memcpy(ffh_ctxt, handler_ctxt, sizeof(ffh_ctxt->info));
+
+ *region_ctxt = ffh_ctxt;
+ return AE_OK;
+}
+
+static bool acpi_ffh_smccc_owner_allowed(u32 fid)
+{
+ int owner = ARM_SMCCC_OWNER_NUM(fid);
+
+ if (owner == ARM_SMCCC_OWNER_STANDARD ||
+ owner == ARM_SMCCC_OWNER_SIP || owner == ARM_SMCCC_OWNER_OEM)
+ return true;
+
+ return false;
+}
+
+int acpi_ffh_address_space_arch_handler(acpi_integer *value, void *region_context)
+{
+ int ret = 0;
+ struct acpi_ffh_data *ffh_ctxt = region_context;
+
+ if (ffh_ctxt->info.offset == 0) {
+ /* SMC/HVC 32bit call */
+ struct arm_smccc_res res;
+ u32 a[8] = { 0 }, *ptr = (u32 *)value;
+
+ if (!ARM_SMCCC_IS_FAST_CALL(*ptr) || ARM_SMCCC_IS_64(*ptr) ||
+ !acpi_ffh_smccc_owner_allowed(*ptr) ||
+ ffh_ctxt->info.length > 32) {
+ ret = AE_ERROR;
+ } else {
+ int idx, len = ffh_ctxt->info.length >> 2;
+
+ for (idx = 0; idx < len; idx++)
+ a[idx] = *(ptr + idx);
+
+ ffh_ctxt->invoke_ffh_fn(a[0], a[1], a[2], a[3], a[4],
+ a[5], a[6], a[7], &res, NULL);
+ memcpy(value, &res, sizeof(res));
+ }
+
+ } else if (ffh_ctxt->info.offset == 1) {
+ /* SMC/HVC 64bit call */
+ struct arm_smccc_1_2_regs *r = (struct arm_smccc_1_2_regs *)value;
+
+ if (!ARM_SMCCC_IS_FAST_CALL(r->a0) || !ARM_SMCCC_IS_64(r->a0) ||
+ !acpi_ffh_smccc_owner_allowed(r->a0) ||
+ ffh_ctxt->info.length > sizeof(*r)) {
+ ret = AE_ERROR;
+ } else {
+ ffh_ctxt->invoke_ffh64_fn(r, r);
+ memcpy(value, r, ffh_ctxt->info.length);
+ }
+ } else {
+ ret = AE_ERROR;
+ }
+
+ return ret;
+}
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index b379401ff1c2..6ea979f76f84 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -756,6 +756,21 @@ end:
}
EXPORT_SYMBOL_GPL(battery_hook_register);
+static void devm_battery_hook_unregister(void *data)
+{
+ struct acpi_battery_hook *hook = data;
+
+ battery_hook_unregister(hook);
+}
+
+int devm_battery_hook_register(struct device *dev, struct acpi_battery_hook *hook)
+{
+ battery_hook_register(hook);
+
+ return devm_add_action_or_reset(dev, devm_battery_hook_unregister, hook);
+}
+EXPORT_SYMBOL_GPL(devm_battery_hook_register);
+
/*
* This function gets called right after the battery sysfs
* attributes have been added, so that the drivers that
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index b203cfe28550..b04b684f3190 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -90,7 +90,8 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry,
struct acpi_madt_generic_interrupt *gicc =
container_of(entry, struct acpi_madt_generic_interrupt, header);
- if (!acpi_gicc_is_usable(gicc))
+ if (!(gicc->flags &
+ (ACPI_MADT_ENABLED | ACPI_MADT_GICC_ONLINE_CAPABLE)))
return -ENODEV;
/* device_declaration means Device object in DSDT, in the
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 67db60eda370..cb52dd000b95 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -33,7 +33,6 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION("ACPI Processor Driver");
MODULE_LICENSE("GPL");
-static int acpi_processor_start(struct device *dev);
static int acpi_processor_stop(struct device *dev);
static const struct acpi_device_id processor_device_ids[] = {
@@ -47,7 +46,6 @@ static struct device_driver acpi_processor_driver = {
.name = "processor",
.bus = &cpu_subsys,
.acpi_match_table = processor_device_ids,
- .probe = acpi_processor_start,
.remove = acpi_processor_stop,
};
@@ -115,12 +113,9 @@ static int acpi_soft_cpu_online(unsigned int cpu)
* CPU got physically hotplugged and onlined for the first time:
* Initialize missing things.
*/
- if (pr->flags.need_hotplug_init) {
+ if (!pr->flags.previously_online) {
int ret;
- pr_info("Will online and init hotplugged CPU: %d\n",
- pr->id);
- pr->flags.need_hotplug_init = 0;
ret = __acpi_processor_start(device);
WARN(ret, "Failed to start CPU: %d\n", pr->id);
} else {
@@ -167,9 +162,6 @@ static int __acpi_processor_start(struct acpi_device *device)
if (!pr)
return -ENODEV;
- if (pr->flags.need_hotplug_init)
- return 0;
-
result = acpi_cppc_processor_probe(pr);
if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
dev_dbg(&device->dev, "CPPC data invalid or not present\n");
@@ -185,32 +177,21 @@ static int __acpi_processor_start(struct acpi_device *device)
status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
acpi_processor_notify, device);
- if (ACPI_SUCCESS(status))
- return 0;
+ if (!ACPI_SUCCESS(status)) {
+ result = -ENODEV;
+ goto err_thermal_exit;
+ }
+ pr->flags.previously_online = 1;
- result = -ENODEV;
- acpi_processor_thermal_exit(pr, device);
+ return 0;
+err_thermal_exit:
+ acpi_processor_thermal_exit(pr, device);
err_power_exit:
acpi_processor_power_exit(pr);
return result;
}
-static int acpi_processor_start(struct device *dev)
-{
- struct acpi_device *device = ACPI_COMPANION(dev);
- int ret;
-
- if (!device)
- return -ENODEV;
-
- /* Protect against concurrent CPU hotplug operations */
- cpu_hotplug_disable();
- ret = __acpi_processor_start(device);
- cpu_hotplug_enable();
- return ret;
-}
-
static int acpi_processor_stop(struct device *dev)
{
struct acpi_device *device = ACPI_COMPANION(dev);
@@ -279,9 +260,9 @@ static int __init acpi_processor_driver_init(void)
if (result < 0)
return result;
- result = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
- "acpi/cpu-drv:online",
- acpi_soft_cpu_online, NULL);
+ result = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+ "acpi/cpu-drv:online",
+ acpi_soft_cpu_online, NULL);
if (result < 0)
goto err;
hp_online = result;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index bd6a7857ce05..831fa4a12159 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -16,7 +16,6 @@
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/sched.h> /* need_resched() */
-#include <linux/sort.h>
#include <linux/tick.h>
#include <linux/cpuidle.h>
#include <linux/cpu.h>
@@ -386,25 +385,24 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
}
-static int acpi_cst_latency_cmp(const void *a, const void *b)
+static void acpi_cst_latency_sort(struct acpi_processor_cx *states, size_t length)
{
- const struct acpi_processor_cx *x = a, *y = b;
+ int i, j, k;
- if (!(x->valid && y->valid))
- return 0;
- if (x->latency > y->latency)
- return 1;
- if (x->latency < y->latency)
- return -1;
- return 0;
-}
-static void acpi_cst_latency_swap(void *a, void *b, int n)
-{
- struct acpi_processor_cx *x = a, *y = b;
+ for (i = 1; i < length; i++) {
+ if (!states[i].valid)
+ continue;
- if (!(x->valid && y->valid))
- return;
- swap(x->latency, y->latency);
+ for (j = i - 1, k = i; j >= 0; j--) {
+ if (!states[j].valid)
+ continue;
+
+ if (states[j].latency > states[k].latency)
+ swap(states[j].latency, states[k].latency);
+
+ k = j;
+ }
+ }
}
static int acpi_processor_power_verify(struct acpi_processor *pr)
@@ -449,10 +447,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
if (buggy_latency) {
pr_notice("FW issue: working around C-state latencies out of order\n");
- sort(&pr->power.states[1], max_cstate,
- sizeof(struct acpi_processor_cx),
- acpi_cst_latency_cmp,
- acpi_cst_latency_swap);
+ acpi_cst_latency_sort(&pr->power.states[1], max_cstate);
}
lapic_timer_propagate_broadcast(pr);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 503773707e01..0aa20623525a 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -243,13 +243,17 @@ static int acpi_scan_try_to_offline(struct acpi_device *device)
return 0;
}
-static int acpi_scan_check_and_detach(struct acpi_device *adev, void *check)
+#define ACPI_SCAN_CHECK_FLAG_STATUS BIT(0)
+#define ACPI_SCAN_CHECK_FLAG_EJECT BIT(1)
+
+static int acpi_scan_check_and_detach(struct acpi_device *adev, void *p)
{
struct acpi_scan_handler *handler = adev->handler;
+ uintptr_t flags = (uintptr_t)p;
- acpi_dev_for_each_child_reverse(adev, acpi_scan_check_and_detach, check);
+ acpi_dev_for_each_child_reverse(adev, acpi_scan_check_and_detach, p);
- if (check) {
+ if (flags & ACPI_SCAN_CHECK_FLAG_STATUS) {
acpi_bus_get_status(adev);
/*
* Skip devices that are still there and take the enabled
@@ -269,8 +273,6 @@ static int acpi_scan_check_and_detach(struct acpi_device *adev, void *check)
if (handler) {
if (handler->detach)
handler->detach(adev);
-
- adev->handler = NULL;
} else {
device_release_driver(&adev->dev);
}
@@ -280,6 +282,28 @@ static int acpi_scan_check_and_detach(struct acpi_device *adev, void *check)
*/
acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
adev->flags.initialized = false;
+
+ /* For eject this is deferred to acpi_bus_post_eject() */
+ if (!(flags & ACPI_SCAN_CHECK_FLAG_EJECT)) {
+ adev->handler = NULL;
+ acpi_device_clear_enumerated(adev);
+ }
+ return 0;
+}
+
+static int acpi_bus_post_eject(struct acpi_device *adev, void *not_used)
+{
+ struct acpi_scan_handler *handler = adev->handler;
+
+ acpi_dev_for_each_child_reverse(adev, acpi_bus_post_eject, NULL);
+
+ if (handler) {
+ if (handler->post_eject)
+ handler->post_eject(adev);
+
+ adev->handler = NULL;
+ }
+
acpi_device_clear_enumerated(adev);
return 0;
@@ -287,7 +311,9 @@ static int acpi_scan_check_and_detach(struct acpi_device *adev, void *check)
static void acpi_scan_check_subtree(struct acpi_device *adev)
{
- acpi_scan_check_and_detach(adev, (void *)true);
+ uintptr_t flags = ACPI_SCAN_CHECK_FLAG_STATUS;
+
+ acpi_scan_check_and_detach(adev, (void *)flags);
}
static int acpi_scan_hot_remove(struct acpi_device *device)
@@ -295,6 +321,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
acpi_handle handle = device->handle;
unsigned long long sta;
acpi_status status;
+ uintptr_t flags = ACPI_SCAN_CHECK_FLAG_EJECT;
if (device->handler && device->handler->hotplug.demand_offline) {
if (!acpi_scan_is_offline(device, true))
@@ -307,7 +334,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
acpi_handle_debug(handle, "Ejecting\n");
- acpi_bus_trim(device);
+ acpi_scan_check_and_detach(device, (void *)flags);
acpi_evaluate_lck(handle, 0);
/*
@@ -330,6 +357,8 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
} else if (sta & ACPI_STA_DEVICE_ENABLED) {
acpi_handle_warn(handle,
"Eject incomplete - status 0x%llx\n", sta);
+ } else {
+ acpi_bus_post_eject(device, NULL);
}
return 0;
@@ -2596,7 +2625,9 @@ EXPORT_SYMBOL(acpi_bus_scan);
*/
void acpi_bus_trim(struct acpi_device *adev)
{
- acpi_scan_check_and_detach(adev, NULL);
+ uintptr_t flags = 0;
+
+ acpi_scan_check_and_detach(adev, (void *)flags);
}
EXPORT_SYMBOL_GPL(acpi_bus_trim);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index b976e5fc3fbc..9e1b01c35070 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -198,6 +198,20 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
break;
+ case ACPI_MADT_TYPE_MULTIPROC_WAKEUP:
+ {
+ struct acpi_madt_multiproc_wakeup *p =
+ (struct acpi_madt_multiproc_wakeup *)header;
+ u64 reset_vector = 0;
+
+ if (p->version >= ACPI_MADT_MP_WAKEUP_VERSION_V1)
+ reset_vector = p->reset_vector;
+
+ pr_debug("MP Wakeup (version[%d], mailbox[%#llx], reset[%#llx])\n",
+ p->version, p->mailbox_address, reset_vector);
+ }
+ break;
+
case ACPI_MADT_TYPE_CORE_PIC:
{
struct acpi_madt_core_pic *p = (struct acpi_madt_core_pic *)header;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index bb4d30d377ae..67ce756f8dfc 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1024,7 +1024,6 @@ EXPORT_SYMBOL_GPL(ata_scsi_dma_need_drain);
int ata_scsi_dev_config(struct scsi_device *sdev, struct queue_limits *lim,
struct ata_device *dev)
{
- struct request_queue *q = sdev->request_queue;
int depth = 1;
if (!ata_id_has_unload(dev->id))
@@ -1038,7 +1037,7 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct queue_limits *lim,
sdev->sector_size = ATA_SECT_SIZE;
/* set DMA padding */
- blk_queue_update_dma_pad(q, ATA_DMA_PAD_SZ - 1);
+ lim->dma_pad_mask = ATA_DMA_PAD_SZ - 1;
/* make room for appending the drain */
lim->max_segments--;
diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c
index 3cb455a32d92..1b85e8bf4ef9 100644
--- a/drivers/ata/pata_macio.c
+++ b/drivers/ata/pata_macio.c
@@ -816,7 +816,7 @@ static int pata_macio_device_configure(struct scsi_device *sdev,
/* OHare has issues with non cache aligned DMA on some chipsets */
if (priv->kind == controller_ohare) {
lim->dma_alignment = 31;
- blk_queue_update_dma_pad(sdev->request_queue, 31);
+ lim->dma_pad_mask = 31;
/* Tell the world about it */
ata_dev_info(dev, "OHare alignment limits applied\n");
@@ -831,7 +831,7 @@ static int pata_macio_device_configure(struct scsi_device *sdev,
if (priv->kind == controller_sh_ata6 || priv->kind == controller_k2_ata6) {
/* Allright these are bad, apply restrictions */
lim->dma_alignment = 15;
- blk_queue_update_dma_pad(sdev->request_queue, 15);
+ lim->dma_pad_mask = 15;
/* We enable MWI and hack cache line size directly here, this
* is specific to this chipset and not normal values, we happen
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index c61ecb0c2ae2..b57326fd48d4 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -95,6 +95,7 @@ void unregister_cpu(struct cpu *cpu)
{
int logical_cpu = cpu->dev.id;
+ set_cpu_enabled(logical_cpu, false);
unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu));
device_unregister(&cpu->dev);
@@ -273,6 +274,13 @@ static ssize_t print_cpus_offline(struct device *dev,
}
static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
+static ssize_t print_cpus_enabled(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpu_enabled_mask));
+}
+static DEVICE_ATTR(enabled, 0444, print_cpus_enabled, NULL);
+
static ssize_t print_cpus_isolated(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -413,6 +421,7 @@ int register_cpu(struct cpu *cpu, int num)
register_cpu_under_node(num, cpu_to_node(num));
dev_pm_qos_expose_latency_limit(&cpu->dev,
PM_QOS_RESUME_LATENCY_NO_CONSTRAINT);
+ set_cpu_enabled(num, true);
return 0;
}
@@ -494,6 +503,7 @@ static struct attribute *cpu_root_attrs[] = {
&cpu_attrs[2].attr.attr,
&dev_attr_kernel_max.attr,
&dev_attr_offline.attr,
+ &dev_attr_enabled.attr,
&dev_attr_isolated.attr,
#ifdef CONFIG_NO_HZ_FULL
&dev_attr_nohz_full.attr,
@@ -558,7 +568,7 @@ static void __init cpu_dev_register_generic(void)
for_each_present_cpu(i) {
ret = arch_register_cpu(i);
- if (ret)
+ if (ret && ret != -EPROBE_DEFER)
pr_warn("register_cpu %d failed (%d)\n", i, ret);
}
}
diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c
index e42433404854..f0df2da6d522 100644
--- a/drivers/base/regmap/regcache-maple.c
+++ b/drivers/base/regmap/regcache-maple.c
@@ -132,9 +132,9 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min,
lower_index = mas.index;
lower_last = min -1;
- lower = kmemdup(entry, ((min - mas.index) *
- sizeof(unsigned long)),
- map->alloc_flags);
+ lower = kmemdup_array(entry,
+ min - mas.index, sizeof(*lower),
+ map->alloc_flags);
if (!lower) {
ret = -ENOMEM;
goto out_unlocked;
@@ -145,10 +145,9 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min,
upper_index = max + 1;
upper_last = mas.last;
- upper = kmemdup(&entry[max - mas.index + 1],
- ((mas.last - max) *
- sizeof(unsigned long)),
- map->alloc_flags);
+ upper = kmemdup_array(&entry[max - mas.index + 1],
+ mas.last - max, sizeof(*upper),
+ map->alloc_flags);
if (!upper) {
ret = -ENOMEM;
goto out_unlocked;
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 2e41cb12b8e2..7ec1ec605335 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -170,8 +170,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
* a copy of it.
*/
if (config->reg_defaults) {
- tmp_buf = kmemdup(config->reg_defaults, map->num_reg_defaults *
- sizeof(struct reg_default), GFP_KERNEL);
+ tmp_buf = kmemdup_array(config->reg_defaults, map->num_reg_defaults,
+ sizeof(*map->reg_defaults), GFP_KERNEL);
if (!tmp_buf)
return -ENOMEM;
map->reg_defaults = tmp_buf;
@@ -407,7 +407,7 @@ out:
* have gone out of sync, force writes of all the paging
* registers.
*/
- rb_for_each(node, 0, &map->range_tree, rbtree_all) {
+ rb_for_each(node, NULL, &map->range_tree, rbtree_all) {
struct regmap_range_node *this =
rb_entry(node, struct regmap_range_node, node);
diff --git a/drivers/base/regmap/regmap-ac97.c b/drivers/base/regmap/regmap-ac97.c
index b9f76bdf74a9..a561971c459c 100644
--- a/drivers/base/regmap/regmap-ac97.c
+++ b/drivers/base/regmap/regmap-ac97.c
@@ -86,4 +86,5 @@ struct regmap *__devm_regmap_init_ac97(struct snd_ac97 *ac97,
}
EXPORT_SYMBOL_GPL(__devm_regmap_init_ac97);
+MODULE_DESCRIPTION("Register map access API - AC'97 support");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index a905e955bbfc..c9b39a02278e 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -397,4 +397,5 @@ struct regmap *__devm_regmap_init_i2c(struct i2c_client *i2c,
}
EXPORT_SYMBOL_GPL(__devm_regmap_init_i2c);
+MODULE_DESCRIPTION("Register map access API - I2C support");
MODULE_LICENSE("GPL");
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 45fd13ef13fc..d3ec1345b5b5 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -305,8 +305,8 @@ static inline int read_sub_irq_data(struct regmap_irq_chip_data *data,
unsigned int b)
{
const struct regmap_irq_chip *chip = data->chip;
+ const struct regmap_irq_sub_irq_map *subreg;
struct regmap *map = data->map;
- struct regmap_irq_sub_irq_map *subreg;
unsigned int reg;
int i, ret = 0;
diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c
index be32cd4e84da..d790c7df5cac 100644
--- a/drivers/base/regmap/regmap-kunit.c
+++ b/drivers/base/regmap/regmap-kunit.c
@@ -145,9 +145,9 @@ static struct regmap *gen_regmap(struct kunit *test,
const struct regmap_test_param *param = test->param_value;
struct regmap_test_priv *priv = test->priv;
unsigned int *buf;
- struct regmap *ret;
+ struct regmap *ret = ERR_PTR(-ENOMEM);
size_t size;
- int i;
+ int i, error;
struct reg_default *defaults;
config->cache_type = param->cache;
@@ -163,7 +163,7 @@ static struct regmap *gen_regmap(struct kunit *test,
config->max_register += (BLOCK_TEST_SIZE * config->reg_stride);
}
- size = (config->max_register + 1) * sizeof(unsigned int);
+ size = array_size(config->max_register + 1, sizeof(*buf));
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return ERR_PTR(-ENOMEM);
@@ -172,15 +172,17 @@ static struct regmap *gen_regmap(struct kunit *test,
*data = kzalloc(sizeof(**data), GFP_KERNEL);
if (!(*data))
- return ERR_PTR(-ENOMEM);
+ goto out_free;
(*data)->vals = buf;
if (config->num_reg_defaults) {
- defaults = kcalloc(config->num_reg_defaults,
- sizeof(struct reg_default),
- GFP_KERNEL);
+ defaults = kunit_kcalloc(test,
+ config->num_reg_defaults,
+ sizeof(struct reg_default),
+ GFP_KERNEL);
if (!defaults)
- return ERR_PTR(-ENOMEM);
+ goto out_free;
+
config->reg_defaults = defaults;
for (i = 0; i < config->num_reg_defaults; i++) {
@@ -190,12 +192,19 @@ static struct regmap *gen_regmap(struct kunit *test,
}
ret = regmap_init_ram(priv->dev, config, *data);
- if (IS_ERR(ret)) {
- kfree(buf);
- kfree(*data);
- } else {
- kunit_add_action(test, regmap_exit_action, ret);
- }
+ if (IS_ERR(ret))
+ goto out_free;
+
+ /* This calls regmap_exit() on failure, which frees buf and *data */
+ error = kunit_add_action_or_reset(test, regmap_exit_action, ret);
+ if (error)
+ ret = ERR_PTR(error);
+
+ return ret;
+
+out_free:
+ kfree(buf);
+ kfree(*data);
return ret;
}
@@ -295,6 +304,77 @@ static void bulk_read(struct kunit *test)
KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
}
+static void multi_write(struct kunit *test)
+{
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ struct reg_sequence sequence[BLOCK_TEST_SIZE];
+ unsigned int val[BLOCK_TEST_SIZE], rval[BLOCK_TEST_SIZE];
+ int i;
+
+ config = test_regmap_config;
+
+ map = gen_regmap(test, &config, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ get_random_bytes(&val, sizeof(val));
+
+ /*
+ * Data written via the multi API can be read back with single
+ * reads.
+ */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++) {
+ sequence[i].reg = i;
+ sequence[i].def = val[i];
+ sequence[i].delay_us = 0;
+ }
+ KUNIT_EXPECT_EQ(test, 0,
+ regmap_multi_reg_write(map, sequence, BLOCK_TEST_SIZE));
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval[i]));
+
+ KUNIT_EXPECT_MEMEQ(test, val, rval, sizeof(val));
+
+ /* If using a cache the cache satisfied the read */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
+}
+
+static void multi_read(struct kunit *test)
+{
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ unsigned int regs[BLOCK_TEST_SIZE];
+ unsigned int val[BLOCK_TEST_SIZE], rval[BLOCK_TEST_SIZE];
+ int i;
+
+ config = test_regmap_config;
+
+ map = gen_regmap(test, &config, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ get_random_bytes(&val, sizeof(val));
+
+ /* Data written as single writes can be read via the multi API */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++) {
+ regs[i] = i;
+ KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, val[i]));
+ }
+ KUNIT_EXPECT_EQ(test, 0,
+ regmap_multi_reg_read(map, regs, rval, BLOCK_TEST_SIZE));
+ KUNIT_EXPECT_MEMEQ(test, val, rval, sizeof(val));
+
+ /* If using a cache the cache satisfied the read */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
+}
+
static void read_bypassed(struct kunit *test)
{
const struct regmap_test_param *param = test->param_value;
@@ -759,10 +839,9 @@ static void stress_insert(struct kunit *test)
if (IS_ERR(map))
return;
- vals = kunit_kcalloc(test, sizeof(unsigned long), config.max_register,
- GFP_KERNEL);
+ buf_sz = array_size(sizeof(*vals), config.max_register);
+ vals = kunit_kmalloc(test, buf_sz, GFP_KERNEL);
KUNIT_ASSERT_FALSE(test, vals == NULL);
- buf_sz = sizeof(unsigned long) * config.max_register;
get_random_bytes(vals, buf_sz);
@@ -1497,16 +1576,17 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
struct regmap_test_priv *priv = test->priv;
const struct regmap_test_param *param = test->param_value;
u16 *buf;
- struct regmap *ret;
- size_t size = (config->max_register + 1) * config->reg_bits / 8;
- int i;
+ struct regmap *ret = ERR_PTR(-ENOMEM);
+ int i, error;
struct reg_default *defaults;
+ size_t size;
config->cache_type = param->cache;
config->val_format_endian = param->val_endian;
config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
config->cache_type == REGCACHE_MAPLE;
+ size = array_size(config->max_register + 1, BITS_TO_BYTES(config->reg_bits));
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return ERR_PTR(-ENOMEM);
@@ -1515,15 +1595,16 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
*data = kzalloc(sizeof(**data), GFP_KERNEL);
if (!(*data))
- return ERR_PTR(-ENOMEM);
+ goto out_free;
(*data)->vals = (void *)buf;
config->num_reg_defaults = config->max_register + 1;
- defaults = kcalloc(config->num_reg_defaults,
- sizeof(struct reg_default),
- GFP_KERNEL);
+ defaults = kunit_kcalloc(test,
+ config->num_reg_defaults,
+ sizeof(struct reg_default),
+ GFP_KERNEL);
if (!defaults)
- return ERR_PTR(-ENOMEM);
+ goto out_free;
config->reg_defaults = defaults;
for (i = 0; i < config->num_reg_defaults; i++) {
@@ -1536,7 +1617,8 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
defaults[i].def = be16_to_cpu(buf[i]);
break;
default:
- return ERR_PTR(-EINVAL);
+ ret = ERR_PTR(-EINVAL);
+ goto out_free;
}
}
@@ -1548,12 +1630,19 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
config->num_reg_defaults = 0;
ret = regmap_init_raw_ram(priv->dev, config, *data);
- if (IS_ERR(ret)) {
- kfree(buf);
- kfree(*data);
- } else {
- kunit_add_action(test, regmap_exit_action, ret);
- }
+ if (IS_ERR(ret))
+ goto out_free;
+
+ /* This calls regmap_exit() on failure, which frees buf and *data */
+ error = kunit_add_action_or_reset(test, regmap_exit_action, ret);
+ if (error)
+ ret = ERR_PTR(error);
+
+ return ret;
+
+out_free:
+ kfree(buf);
+ kfree(*data);
return ret;
}
@@ -1597,7 +1686,7 @@ static void raw_read_defaults(struct kunit *test)
if (IS_ERR(map))
return;
- val_len = sizeof(*rval) * (config.max_register + 1);
+ val_len = array_size(sizeof(*rval), config.max_register + 1);
rval = kunit_kmalloc(test, val_len, GFP_KERNEL);
KUNIT_ASSERT_TRUE(test, rval != NULL);
if (!rval)
@@ -1887,6 +1976,8 @@ static struct kunit_case regmap_test_cases[] = {
KUNIT_CASE_PARAM(read_bypassed_volatile, real_cache_types_gen_params),
KUNIT_CASE_PARAM(bulk_write, regcache_types_gen_params),
KUNIT_CASE_PARAM(bulk_read, regcache_types_gen_params),
+ KUNIT_CASE_PARAM(multi_write, regcache_types_gen_params),
+ KUNIT_CASE_PARAM(multi_read, regcache_types_gen_params),
KUNIT_CASE_PARAM(write_readonly, regcache_types_gen_params),
KUNIT_CASE_PARAM(read_writeonly, regcache_types_gen_params),
KUNIT_CASE_PARAM(reg_defaults, regcache_types_gen_params),
@@ -1958,4 +2049,5 @@ static struct kunit_suite regmap_test_suite = {
};
kunit_test_suite(regmap_test_suite);
+MODULE_DESCRIPTION("Regmap KUnit tests");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap-ram.c b/drivers/base/regmap/regmap-ram.c
index 5b4cbf982a11..4e5b4518ce4d 100644
--- a/drivers/base/regmap/regmap-ram.c
+++ b/drivers/base/regmap/regmap-ram.c
@@ -83,4 +83,5 @@ struct regmap *__regmap_init_ram(struct device *dev,
}
EXPORT_SYMBOL_GPL(__regmap_init_ram);
+MODULE_DESCRIPTION("Register map access API - Memory region");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap-raw-ram.c b/drivers/base/regmap/regmap-raw-ram.c
index 69eabfb89eda..76c98814fb8a 100644
--- a/drivers/base/regmap/regmap-raw-ram.c
+++ b/drivers/base/regmap/regmap-raw-ram.c
@@ -142,4 +142,5 @@ struct regmap *__regmap_init_raw_ram(struct device *dev,
}
EXPORT_SYMBOL_GPL(__regmap_init_raw_ram);
+MODULE_DESCRIPTION("Register map access API - Memory region with raw access");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap-sccb.c b/drivers/base/regmap/regmap-sccb.c
index 986af26d88c2..12bbbb03e5f2 100644
--- a/drivers/base/regmap/regmap-sccb.c
+++ b/drivers/base/regmap/regmap-sccb.c
@@ -125,4 +125,5 @@ struct regmap *__devm_regmap_init_sccb(struct i2c_client *i2c,
}
EXPORT_SYMBOL_GPL(__devm_regmap_init_sccb);
+MODULE_DESCRIPTION("Register map access API - SCCB support");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap-slimbus.c b/drivers/base/regmap/regmap-slimbus.c
index 8075db788b39..54eb7d227cf4 100644
--- a/drivers/base/regmap/regmap-slimbus.c
+++ b/drivers/base/regmap/regmap-slimbus.c
@@ -68,4 +68,5 @@ struct regmap *__devm_regmap_init_slimbus(struct slim_device *slimbus,
}
EXPORT_SYMBOL_GPL(__devm_regmap_init_slimbus);
+MODULE_DESCRIPTION("Register map access API - SLIMbus support");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap-spi-avmm.c b/drivers/base/regmap/regmap-spi-avmm.c
index 4c2b94b3e30b..d86a06cadcdb 100644
--- a/drivers/base/regmap/regmap-spi-avmm.c
+++ b/drivers/base/regmap/regmap-spi-avmm.c
@@ -710,4 +710,5 @@ struct regmap *__devm_regmap_init_spi_avmm(struct spi_device *spi,
}
EXPORT_SYMBOL_GPL(__devm_regmap_init_spi_avmm);
+MODULE_DESCRIPTION("Register map access API - SPI AVMM support");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index 094cf2a2ca3c..14b1d88997cb 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -122,8 +122,7 @@ static const struct regmap_bus *regmap_get_spi_bus(struct spi_device *spi,
return ERR_PTR(-ENOMEM);
max_msg_size = spi_max_message_size(spi);
- reg_reserve_size = config->reg_bits / BITS_PER_BYTE
- + config->pad_bits / BITS_PER_BYTE;
+ reg_reserve_size = (config->reg_bits + config->pad_bits) / BITS_PER_BYTE;
if (max_size + reg_reserve_size > max_msg_size)
max_size -= reg_reserve_size;
diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c
index cdf12d2aa3a1..347bfe9544ce 100644
--- a/drivers/base/regmap/regmap-spmi.c
+++ b/drivers/base/regmap/regmap-spmi.c
@@ -222,4 +222,5 @@ struct regmap *__devm_regmap_init_spmi_ext(struct spmi_device *sdev,
}
EXPORT_SYMBOL_GPL(__devm_regmap_init_spmi_ext);
+MODULE_DESCRIPTION("Register map access API - SPMI support");
MODULE_LICENSE("GPL");
diff --git a/drivers/base/regmap/regmap-w1.c b/drivers/base/regmap/regmap-w1.c
index 3a8b402db852..29fd24f9c7ed 100644
--- a/drivers/base/regmap/regmap-w1.c
+++ b/drivers/base/regmap/regmap-w1.c
@@ -234,4 +234,5 @@ struct regmap *__devm_regmap_init_w1(struct device *w1_dev,
}
EXPORT_SYMBOL_GPL(__devm_regmap_init_w1);
+MODULE_DESCRIPTION("Register map access API - W1 (1-Wire) support");
MODULE_LICENSE("GPL");
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 0a34dd3c4f38..bfc6bc1eb3a4 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -2347,7 +2347,7 @@ out:
} else {
void *wval;
- wval = kmemdup(val, val_count * val_bytes, map->alloc_flags);
+ wval = kmemdup_array(val, val_count, val_bytes, map->alloc_flags);
if (!wval)
return -ENOMEM;
@@ -3101,8 +3101,53 @@ int regmap_fields_read(struct regmap_field *field, unsigned int id,
}
EXPORT_SYMBOL_GPL(regmap_fields_read);
+static int _regmap_bulk_read(struct regmap *map, unsigned int reg,
+ unsigned int *regs, void *val, size_t val_count)
+{
+ u32 *u32 = val;
+ u16 *u16 = val;
+ u8 *u8 = val;
+ int ret, i;
+
+ map->lock(map->lock_arg);
+
+ for (i = 0; i < val_count; i++) {
+ unsigned int ival;
+
+ if (regs) {
+ if (!IS_ALIGNED(regs[i], map->reg_stride)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = _regmap_read(map, regs[i], &ival);
+ } else {
+ ret = _regmap_read(map, reg + regmap_get_offset(map, i), &ival);
+ }
+ if (ret != 0)
+ goto out;
+
+ switch (map->format.val_bytes) {
+ case 4:
+ u32[i] = ival;
+ break;
+ case 2:
+ u16[i] = ival;
+ break;
+ case 1:
+ u8[i] = ival;
+ break;
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+out:
+ map->unlock(map->lock_arg);
+ return ret;
+}
+
/**
- * regmap_bulk_read() - Read multiple registers from the device
+ * regmap_bulk_read() - Read multiple sequential registers from the device
*
* @map: Register map to read from
* @reg: First register to be read from
@@ -3132,47 +3177,35 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
for (i = 0; i < val_count * val_bytes; i += val_bytes)
map->format.parse_inplace(val + i);
} else {
- u32 *u32 = val;
- u16 *u16 = val;
- u8 *u8 = val;
-
- map->lock(map->lock_arg);
-
- for (i = 0; i < val_count; i++) {
- unsigned int ival;
-
- ret = _regmap_read(map, reg + regmap_get_offset(map, i),
- &ival);
- if (ret != 0)
- goto out;
-
- switch (map->format.val_bytes) {
- case 4:
- u32[i] = ival;
- break;
- case 2:
- u16[i] = ival;
- break;
- case 1:
- u8[i] = ival;
- break;
- default:
- ret = -EINVAL;
- goto out;
- }
- }
-
-out:
- map->unlock(map->lock_arg);
+ ret = _regmap_bulk_read(map, reg, NULL, val, val_count);
}
-
if (!ret)
trace_regmap_bulk_read(map, reg, val, val_bytes * val_count);
-
return ret;
}
EXPORT_SYMBOL_GPL(regmap_bulk_read);
+/**
+ * regmap_multi_reg_read() - Read multiple non-sequential registers from the device
+ *
+ * @map: Register map to read from
+ * @regs: Array of registers to read from
+ * @val: Pointer to store read value, in native register size for device
+ * @val_count: Number of registers to read
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_multi_reg_read(struct regmap *map, unsigned int *regs, void *val,
+ size_t val_count)
+{
+ if (val_count == 0)
+ return -EINVAL;
+
+ return _regmap_bulk_read(map, 0, regs, val, val_count);
+}
+EXPORT_SYMBOL_GPL(regmap_multi_reg_read);
+
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val,
bool *change, bool force_write)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 5b9d4aaebb81..ed209f4f2798 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -354,6 +354,15 @@ config VIRTIO_BLK
This is the virtual block driver for virtio. It can be used with
QEMU based VMMs (like KVM or Xen). Say Y or M.
+config BLK_DEV_RUST_NULL
+ tristate "Rust null block driver (Experimental)"
+ depends on RUST
+ help
+ This is the Rust implementation of the null block driver. For now it
+ is only a minimal stub.
+
+ If unsure, say N.
+
config BLK_DEV_RBD
tristate "Rados block device (RBD)"
depends on INET && BLOCK
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 101612cba303..1105a2d4fdcb 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,6 +9,9 @@
# needed for trace events
ccflags-y += -I$(src)
+obj-$(CONFIG_BLK_DEV_RUST_NULL) += rnull_mod.o
+rnull_mod-y := rnull.o
+
obj-$(CONFIG_MAC_FLOPPY) += swim3.o
obj-$(CONFIG_BLK_DEV_SWIM) += swim_mod.o
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index a25414228e47..49ced65bef4c 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -232,6 +232,7 @@ static DEFINE_MUTEX(amiflop_mutex);
static unsigned long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't identify */
module_param(fd_def_df0, ulong, 0);
+MODULE_DESCRIPTION("Amiga floppy driver");
MODULE_LICENSE("GPL");
/*
@@ -1776,10 +1777,13 @@ static const struct blk_mq_ops amiflop_mq_ops = {
static int fd_alloc_disk(int drive, int system)
{
+ struct queue_limits lim = {
+ .features = BLK_FEAT_ROTATIONAL,
+ };
struct gendisk *disk;
int err;
- disk = blk_mq_alloc_disk(&unit[drive].tag_set, NULL, NULL);
+ disk = blk_mq_alloc_disk(&unit[drive].tag_set, &lim, NULL);
if (IS_ERR(disk))
return PTR_ERR(disk);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index b6dac8cee70f..2028795ec61c 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -337,6 +337,7 @@ aoeblk_gdalloc(void *vp)
struct queue_limits lim = {
.max_hw_sectors = aoe_maxsectors,
.io_opt = SZ_2M,
+ .features = BLK_FEAT_ROTATIONAL,
};
ulong flags;
int late = 0;
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index cacc4ba942a8..4ba98c6654be 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1992,9 +1992,12 @@ static const struct blk_mq_ops ataflop_mq_ops = {
static int ataflop_alloc_disk(unsigned int drive, unsigned int type)
{
+ struct queue_limits lim = {
+ .features = BLK_FEAT_ROTATIONAL,
+ };
struct gendisk *disk;
- disk = blk_mq_alloc_disk(&unit[drive].tag_set, NULL, NULL);
+ disk = blk_mq_alloc_disk(&unit[drive].tag_set, &lim, NULL);
if (IS_ERR(disk))
return PTR_ERR(disk);
@@ -2197,4 +2200,5 @@ static void __exit atari_floppy_exit(void)
module_init(atari_floppy_init)
module_exit(atari_floppy_exit)
+MODULE_DESCRIPTION("Atari floppy driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 558d8e670566..2fd1ed101748 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -296,6 +296,7 @@ static int max_part = 1;
module_param(max_part, int, 0444);
MODULE_PARM_DESC(max_part, "Num Minors to reserve between devices");
+MODULE_DESCRIPTION("Ram backed block device driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR);
MODULE_ALIAS("rd");
@@ -335,6 +336,8 @@ static int brd_alloc(int i)
.max_hw_discard_sectors = UINT_MAX,
.max_discard_segments = 1,
.discard_granularity = PAGE_SIZE,
+ .features = BLK_FEAT_SYNCHRONOUS |
+ BLK_FEAT_NOWAIT,
};
list_for_each_entry(brd, &brd_devices, brd_list)
@@ -366,10 +369,6 @@ static int brd_alloc(int i)
strscpy(disk->disk_name, buf, DISK_NAME_LEN);
set_capacity(disk, rd_size * 2);
- /* Tell the block layer that this is not a rotational device */
- blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
- blk_queue_flag_set(QUEUE_FLAG_SYNCHRONOUS, disk->queue);
- blk_queue_flag_set(QUEUE_FLAG_NOWAIT, disk->queue);
err = add_disk(disk);
if (err)
goto out_cleanup_disk;
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 113b441d4d36..f92673f05c7a 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2697,6 +2697,9 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
* connect.
*/
.max_hw_sectors = DRBD_MAX_BIO_SIZE_SAFE >> 8,
+ .features = BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA |
+ BLK_FEAT_ROTATIONAL |
+ BLK_FEAT_STABLE_WRITES,
};
device = minor_to_device(minor);
@@ -2735,9 +2738,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
sprintf(disk->disk_name, "drbd%d", minor);
disk->private_data = device;
- blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, disk->queue);
- blk_queue_write_cache(disk->queue, true, true);
-
device->md_io.page = alloc_page(GFP_KERNEL);
if (!device->md_io.page)
goto out_no_io_page;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 25c9d85667f1..3affb538b989 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4516,7 +4516,8 @@ static bool floppy_available(int drive)
static int floppy_alloc_disk(unsigned int drive, unsigned int type)
{
struct queue_limits lim = {
- .max_hw_sectors = 64,
+ .max_hw_sectors = 64,
+ .features = BLK_FEAT_ROTATIONAL,
};
struct gendisk *disk;
@@ -5016,6 +5017,7 @@ module_param(floppy, charp, 0);
module_param(FLOPPY_IRQ, int, 0);
module_param(FLOPPY_DMA, int, 0);
MODULE_AUTHOR("Alain L. Knaff");
+MODULE_DESCRIPTION("Normal floppy disk support");
MODULE_LICENSE("GPL");
/* This doesn't actually get used other than for module information */
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 1153721bc7c2..78a7bb28defe 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -211,13 +211,10 @@ static void __loop_update_dio(struct loop_device *lo, bool dio)
if (lo->lo_state == Lo_bound)
blk_mq_freeze_queue(lo->lo_queue);
lo->use_dio = use_dio;
- if (use_dio) {
- blk_queue_flag_clear(QUEUE_FLAG_NOMERGES, lo->lo_queue);
+ if (use_dio)
lo->lo_flags |= LO_FLAGS_DIRECT_IO;
- } else {
- blk_queue_flag_set(QUEUE_FLAG_NOMERGES, lo->lo_queue);
+ else
lo->lo_flags &= ~LO_FLAGS_DIRECT_IO;
- }
if (lo->lo_state == Lo_bound)
blk_mq_unfreeze_queue(lo->lo_queue);
}
@@ -939,24 +936,6 @@ static void loop_free_idle_workers_timer(struct timer_list *timer)
return loop_free_idle_workers(lo, false);
}
-static void loop_update_rotational(struct loop_device *lo)
-{
- struct file *file = lo->lo_backing_file;
- struct inode *file_inode = file->f_mapping->host;
- struct block_device *file_bdev = file_inode->i_sb->s_bdev;
- struct request_queue *q = lo->lo_queue;
- bool nonrot = true;
-
- /* not all filesystems (e.g. tmpfs) have a sb->s_bdev */
- if (file_bdev)
- nonrot = bdev_nonrot(file_bdev);
-
- if (nonrot)
- blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
- else
- blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
-}
-
/**
* loop_set_status_from_info - configure device from loop_info
* @lo: struct loop_device to configure
@@ -998,17 +977,40 @@ loop_set_status_from_info(struct loop_device *lo,
return 0;
}
-static int loop_reconfigure_limits(struct loop_device *lo, unsigned short bsize,
- bool update_discard_settings)
+static unsigned short loop_default_blocksize(struct loop_device *lo,
+ struct block_device *backing_bdev)
{
+ /* In case of direct I/O, match underlying block size */
+ if ((lo->lo_backing_file->f_flags & O_DIRECT) && backing_bdev)
+ return bdev_logical_block_size(backing_bdev);
+ return SECTOR_SIZE;
+}
+
+static int loop_reconfigure_limits(struct loop_device *lo, unsigned short 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;
+ if (S_ISBLK(inode->i_mode))
+ backing_bdev = I_BDEV(inode);
+ else if (inode->i_sb->s_bdev)
+ backing_bdev = inode->i_sb->s_bdev;
+
+ if (!bsize)
+ bsize = loop_default_blocksize(lo, backing_bdev);
+
lim = queue_limits_start_update(lo->lo_queue);
lim.logical_block_size = bsize;
lim.physical_block_size = bsize;
lim.io_min = bsize;
- if (update_discard_settings)
- loop_config_discard(lo, &lim);
+ lim.features &= ~(BLK_FEAT_WRITE_CACHE | BLK_FEAT_ROTATIONAL);
+ if (file->f_op->fsync && !(lo->lo_flags & LO_FLAGS_READ_ONLY))
+ lim.features |= BLK_FEAT_WRITE_CACHE;
+ if (backing_bdev && !bdev_nonrot(backing_bdev))
+ lim.features |= BLK_FEAT_ROTATIONAL;
+ loop_config_discard(lo, &lim);
return queue_limits_commit_update(lo->lo_queue, &lim);
}
@@ -1017,12 +1019,10 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
const struct loop_config *config)
{
struct file *file = fget(config->fd);
- struct inode *inode;
struct address_space *mapping;
int error;
loff_t size;
bool partscan;
- unsigned short bsize;
bool is_loop;
if (!file)
@@ -1055,19 +1055,12 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
goto out_unlock;
mapping = file->f_mapping;
- inode = mapping->host;
if ((config->info.lo_flags & ~LOOP_CONFIGURE_SETTABLE_FLAGS) != 0) {
error = -EINVAL;
goto out_unlock;
}
- if (config->block_size) {
- error = blk_validate_block_size(config->block_size);
- if (error)
- goto out_unlock;
- }
-
error = loop_set_status_from_info(lo, &config->info);
if (error)
goto out_unlock;
@@ -1098,22 +1091,10 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
lo->old_gfp_mask = mapping_gfp_mask(mapping);
mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
- if (!(lo->lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
- blk_queue_write_cache(lo->lo_queue, true, false);
-
- if (config->block_size)
- bsize = config->block_size;
- else if ((lo->lo_backing_file->f_flags & O_DIRECT) && inode->i_sb->s_bdev)
- /* In case of direct I/O, match underlying block size */
- bsize = bdev_logical_block_size(inode->i_sb->s_bdev);
- else
- bsize = 512;
-
- error = loop_reconfigure_limits(lo, bsize, true);
- if (WARN_ON_ONCE(error))
+ error = loop_reconfigure_limits(lo, config->block_size);
+ if (error)
goto out_unlock;
- loop_update_rotational(lo);
loop_update_dio(lo);
loop_sysfs_init(lo);
@@ -1154,22 +1135,12 @@ out_putf:
return error;
}
-static void __loop_clr_fd(struct loop_device *lo, bool release)
+static void __loop_clr_fd(struct loop_device *lo)
{
+ struct queue_limits lim;
struct file *filp;
gfp_t gfp = lo->old_gfp_mask;
- if (test_bit(QUEUE_FLAG_WC, &lo->lo_queue->queue_flags))
- blk_queue_write_cache(lo->lo_queue, false, false);
-
- /*
- * Freeze the request queue when unbinding on a live file descriptor and
- * thus an open device. When called from ->release we are guaranteed
- * that there is no I/O in progress already.
- */
- if (!release)
- blk_mq_freeze_queue(lo->lo_queue);
-
spin_lock_irq(&lo->lo_lock);
filp = lo->lo_backing_file;
lo->lo_backing_file = NULL;
@@ -1179,7 +1150,14 @@ static void __loop_clr_fd(struct loop_device *lo, bool release)
lo->lo_offset = 0;
lo->lo_sizelimit = 0;
memset(lo->lo_file_name, 0, LO_NAME_SIZE);
- loop_reconfigure_limits(lo, 512, false);
+
+ /* reset the block size to the default */
+ lim = queue_limits_start_update(lo->lo_queue);
+ lim.logical_block_size = SECTOR_SIZE;
+ lim.physical_block_size = SECTOR_SIZE;
+ lim.io_min = SECTOR_SIZE;
+ queue_limits_commit_update(lo->lo_queue, &lim);
+
invalidate_disk(lo->lo_disk);
loop_sysfs_exit(lo);
/* let user-space know about this change */
@@ -1187,8 +1165,6 @@ static void __loop_clr_fd(struct loop_device *lo, bool release)
mapping_set_gfp_mask(filp->f_mapping, gfp);
/* This is safe: open() is still holding a reference. */
module_put(THIS_MODULE);
- if (!release)
- blk_mq_unfreeze_queue(lo->lo_queue);
disk_force_media_change(lo->lo_disk);
@@ -1203,11 +1179,7 @@ static void __loop_clr_fd(struct loop_device *lo, bool release)
* must be at least one and it can only become zero when the
* current holder is released.
*/
- if (!release)
- mutex_lock(&lo->lo_disk->open_mutex);
err = bdev_disk_changed(lo->lo_disk, false);
- if (!release)
- mutex_unlock(&lo->lo_disk->open_mutex);
if (err)
pr_warn("%s: partition scan of loop%d failed (rc=%d)\n",
__func__, lo->lo_number, err);
@@ -1256,24 +1228,16 @@ static int loop_clr_fd(struct loop_device *lo)
return -ENXIO;
}
/*
- * If we've explicitly asked to tear down the loop device,
- * and it has an elevated reference count, set it for auto-teardown when
- * the last reference goes away. This stops $!~#$@ udev from
- * preventing teardown because it decided that it needs to run blkid on
- * the loopback device whenever they appear. xfstests is notorious for
- * failing tests because blkid via udev races with a losetup
- * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
- * command to fail with EBUSY.
+ * Mark the device for removing the backing device on last close.
+ * If we are the only opener, also switch the state to roundown here to
+ * prevent new openers from coming in.
*/
- if (disk_openers(lo->lo_disk) > 1) {
- lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
- loop_global_unlock(lo, true);
- return 0;
- }
- lo->lo_state = Lo_rundown;
+
+ lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
+ if (disk_openers(lo->lo_disk) == 1)
+ lo->lo_state = Lo_rundown;
loop_global_unlock(lo, true);
- __loop_clr_fd(lo, false);
return 0;
}
@@ -1500,10 +1464,6 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
if (lo->lo_state != Lo_bound)
return -ENXIO;
- err = blk_validate_block_size(arg);
- if (err)
- return err;
-
if (lo->lo_queue->limits.logical_block_size == arg)
return 0;
@@ -1511,7 +1471,7 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
invalidate_bdev(lo->lo_device);
blk_mq_freeze_queue(lo->lo_queue);
- err = loop_reconfigure_limits(lo, arg, false);
+ err = loop_reconfigure_limits(lo, arg);
loop_update_dio(lo);
blk_mq_unfreeze_queue(lo->lo_queue);
@@ -1740,25 +1700,43 @@ static int lo_compat_ioctl(struct block_device *bdev, blk_mode_t mode,
}
#endif
+static int lo_open(struct gendisk *disk, blk_mode_t mode)
+{
+ struct loop_device *lo = disk->private_data;
+ int err;
+
+ err = mutex_lock_killable(&lo->lo_mutex);
+ if (err)
+ return err;
+
+ if (lo->lo_state == Lo_deleting || lo->lo_state == Lo_rundown)
+ err = -ENXIO;
+ mutex_unlock(&lo->lo_mutex);
+ return err;
+}
+
static void lo_release(struct gendisk *disk)
{
struct loop_device *lo = disk->private_data;
+ bool need_clear = false;
if (disk_openers(disk) > 0)
return;
+ /*
+ * Clear the backing device information if this is the last close of
+ * a device that's been marked for auto clear, or on which LOOP_CLR_FD
+ * has been called.
+ */
mutex_lock(&lo->lo_mutex);
- if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR)) {
+ if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR))
lo->lo_state = Lo_rundown;
- mutex_unlock(&lo->lo_mutex);
- /*
- * In autoclear mode, stop the loop thread
- * and remove configuration after last close.
- */
- __loop_clr_fd(lo, true);
- return;
- }
+
+ need_clear = (lo->lo_state == Lo_rundown);
mutex_unlock(&lo->lo_mutex);
+
+ if (need_clear)
+ __loop_clr_fd(lo);
}
static void lo_free_disk(struct gendisk *disk)
@@ -1775,6 +1753,7 @@ static void lo_free_disk(struct gendisk *disk)
static const struct block_device_operations lo_fops = {
.owner = THIS_MODULE,
+ .open = lo_open,
.release = lo_release,
.ioctl = lo_ioctl,
#ifdef CONFIG_COMPAT
@@ -1853,6 +1832,7 @@ static const struct kernel_param_ops loop_hw_qdepth_param_ops = {
device_param_cb(hw_queue_depth, &loop_hw_qdepth_param_ops, &hw_queue_depth, 0444);
MODULE_PARM_DESC(hw_queue_depth, "Queue depth for each hardware queue. Default: " __stringify(LOOP_DEFAULT_HW_Q_DEPTH));
+MODULE_DESCRIPTION("Loopback device support");
MODULE_LICENSE("GPL");
MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
@@ -2060,14 +2040,6 @@ static int loop_add(int i)
lo->lo_queue = lo->lo_disk->queue;
/*
- * By default, we do buffer IO, so it doesn't make sense to enable
- * merge because the I/O submitted to backing file is handled page by
- * page. For directio mode, merge does help to dispatch bigger request
- * to underlayer disk. We will enable merge once directio is enabled.
- */
- blk_queue_flag_set(QUEUE_FLAG_NOMERGES, lo->lo_queue);
-
- /*
* Disable partition scanning by default. The in-kernel partition
* scanning can be requested individually per-device during its
* setup. Userspace can always add and remove partitions from all
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 43a187609ef7..c6ef0546ffc9 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -3485,8 +3485,6 @@ skip_create_disk:
goto start_service_thread;
/* Set device limits. */
- blk_queue_flag_set(QUEUE_FLAG_NONROT, dd->queue);
- blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, dd->queue);
dma_set_max_seg_size(&dd->pdev->dev, 0x400000);
/* Set the capacity of the device in 512 byte sectors. */
diff --git a/drivers/block/n64cart.c b/drivers/block/n64cart.c
index 27b2187e7a6d..b9fdeff31caf 100644
--- a/drivers/block/n64cart.c
+++ b/drivers/block/n64cart.c
@@ -150,8 +150,6 @@ static int __init n64cart_probe(struct platform_device *pdev)
set_capacity(disk, size >> SECTOR_SHIFT);
set_disk_ro(disk, 1);
- blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
-
err = add_disk(disk);
if (err)
goto out_cleanup_disk;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index b87aa80a46dd..41a90150b501 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -342,6 +342,14 @@ static int __nbd_set_size(struct nbd_device *nbd, loff_t bytesize,
lim.max_hw_discard_sectors = UINT_MAX;
else
lim.max_hw_discard_sectors = 0;
+ if (!(nbd->config->flags & NBD_FLAG_SEND_FLUSH)) {
+ lim.features &= ~(BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA);
+ } else if (nbd->config->flags & NBD_FLAG_SEND_FUA) {
+ lim.features |= BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA;
+ } else {
+ lim.features |= BLK_FEAT_WRITE_CACHE;
+ lim.features &= ~BLK_FEAT_FUA;
+ }
lim.logical_block_size = blksize;
lim.physical_block_size = blksize;
error = queue_limits_commit_update(nbd->disk->queue, &lim);
@@ -1279,19 +1287,10 @@ static void nbd_bdev_reset(struct nbd_device *nbd)
static void nbd_parse_flags(struct nbd_device *nbd)
{
- struct nbd_config *config = nbd->config;
- if (config->flags & NBD_FLAG_READ_ONLY)
+ if (nbd->config->flags & NBD_FLAG_READ_ONLY)
set_disk_ro(nbd->disk, true);
else
set_disk_ro(nbd->disk, false);
- if (config->flags & NBD_FLAG_SEND_FLUSH) {
- if (config->flags & NBD_FLAG_SEND_FUA)
- blk_queue_write_cache(nbd->disk->queue, true, true);
- else
- blk_queue_write_cache(nbd->disk->queue, true, false);
- }
- else
- blk_queue_write_cache(nbd->disk->queue, false, false);
}
static void send_disconnects(struct nbd_device *nbd)
@@ -1801,7 +1800,7 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
{
struct queue_limits lim = {
.max_hw_sectors = 65536,
- .max_user_sectors = 256,
+ .io_opt = 256 << SECTOR_SHIFT,
.max_segments = USHRT_MAX,
.max_segment_size = UINT_MAX,
};
@@ -1861,11 +1860,6 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
goto out_err_disk;
}
- /*
- * Tell the block layer that we are not a rotational device
- */
- blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
-
mutex_init(&nbd->config_lock);
refcount_set(&nbd->config_refs, 0);
/*
diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index 75f189e42f88..2f0431e42c49 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -77,7 +77,7 @@ enum {
NULL_IRQ_TIMER = 2,
};
-static bool g_virt_boundary = false;
+static bool g_virt_boundary;
module_param_named(virt_boundary, g_virt_boundary, bool, 0444);
MODULE_PARM_DESC(virt_boundary, "Require a virtual boundary for the device. Default: False");
@@ -227,7 +227,7 @@ MODULE_PARM_DESC(mbps, "Cache size in MiB for memory-backed device. Default: 0 (
static bool g_fua = true;
module_param_named(fua, g_fua, bool, 0444);
-MODULE_PARM_DESC(zoned, "Enable/disable FUA support when cache_size is used. Default: true");
+MODULE_PARM_DESC(fua, "Enable/disable FUA support when cache_size is used. Default: true");
static unsigned int g_mbps;
module_param_named(mbps, g_mbps, uint, 0444);
@@ -262,6 +262,10 @@ module_param_named(zone_append_max_sectors, g_zone_append_max_sectors, int, 0444
MODULE_PARM_DESC(zone_append_max_sectors,
"Maximum size of a zone append command (in 512B sectors). Specify 0 for zone append emulation");
+static bool g_zone_full;
+module_param_named(zone_full, g_zone_full, bool, S_IRUGO);
+MODULE_PARM_DESC(zone_full, "Initialize the sequential write required zones of a zoned device to be full. Default: false");
+
static struct nullb_device *null_alloc_dev(void);
static void null_free_dev(struct nullb_device *dev);
static void null_del_dev(struct nullb *nullb);
@@ -458,6 +462,7 @@ NULLB_DEVICE_ATTR(zone_nr_conv, uint, NULL);
NULLB_DEVICE_ATTR(zone_max_open, uint, NULL);
NULLB_DEVICE_ATTR(zone_max_active, uint, NULL);
NULLB_DEVICE_ATTR(zone_append_max_sectors, uint, NULL);
+NULLB_DEVICE_ATTR(zone_full, bool, NULL);
NULLB_DEVICE_ATTR(virt_boundary, bool, NULL);
NULLB_DEVICE_ATTR(no_sched, bool, NULL);
NULLB_DEVICE_ATTR(shared_tags, bool, NULL);
@@ -610,6 +615,7 @@ static struct configfs_attribute *nullb_device_attrs[] = {
&nullb_device_attr_zone_append_max_sectors,
&nullb_device_attr_zone_readonly,
&nullb_device_attr_zone_offline,
+ &nullb_device_attr_zone_full,
&nullb_device_attr_virt_boundary,
&nullb_device_attr_no_sched,
&nullb_device_attr_shared_tags,
@@ -700,7 +706,7 @@ static ssize_t memb_group_features_show(struct config_item *item, char *page)
"shared_tags,size,submit_queues,use_per_node_hctx,"
"virt_boundary,zoned,zone_capacity,zone_max_active,"
"zone_max_open,zone_nr_conv,zone_offline,zone_readonly,"
- "zone_size,zone_append_max_sectors\n");
+ "zone_size,zone_append_max_sectors,zone_full\n");
}
CONFIGFS_ATTR_RO(memb_group_, features);
@@ -781,6 +787,7 @@ static struct nullb_device *null_alloc_dev(void)
dev->zone_max_open = g_zone_max_open;
dev->zone_max_active = g_zone_max_active;
dev->zone_append_max_sectors = g_zone_append_max_sectors;
+ dev->zone_full = g_zone_full;
dev->virt_boundary = g_virt_boundary;
dev->no_sched = g_no_sched;
dev->shared_tags = g_shared_tags;
@@ -1824,9 +1831,6 @@ static int null_validate_conf(struct nullb_device *dev)
dev->queue_mode = NULL_Q_MQ;
}
- if (blk_validate_block_size(dev->blocksize))
- return -EINVAL;
-
if (dev->use_per_node_hctx) {
if (dev->submit_queues != nr_online_nodes)
dev->submit_queues = nr_online_nodes;
@@ -1928,6 +1932,13 @@ static int null_add_dev(struct nullb_device *dev)
goto out_cleanup_tags;
}
+ if (dev->cache_size > 0) {
+ set_bit(NULLB_DEV_FL_CACHE, &nullb->dev->flags);
+ lim.features |= BLK_FEAT_WRITE_CACHE;
+ if (dev->fua)
+ lim.features |= BLK_FEAT_FUA;
+ }
+
nullb->disk = blk_mq_alloc_disk(nullb->tag_set, &lim, nullb);
if (IS_ERR(nullb->disk)) {
rv = PTR_ERR(nullb->disk);
@@ -1940,13 +1951,7 @@ static int null_add_dev(struct nullb_device *dev)
nullb_setup_bwtimer(nullb);
}
- if (dev->cache_size > 0) {
- set_bit(NULLB_DEV_FL_CACHE, &nullb->dev->flags);
- blk_queue_write_cache(nullb->q, true, dev->fua);
- }
-
nullb->q->queuedata = nullb;
- blk_queue_flag_set(QUEUE_FLAG_NONROT, nullb->q);
rv = ida_alloc(&nullb_indexes, GFP_KERNEL);
if (rv < 0)
diff --git a/drivers/block/null_blk/null_blk.h b/drivers/block/null_blk/null_blk.h
index 3234e6c85eed..a7bb32f73ec3 100644
--- a/drivers/block/null_blk/null_blk.h
+++ b/drivers/block/null_blk/null_blk.h
@@ -101,6 +101,7 @@ struct nullb_device {
bool memory_backed; /* if data is stored in memory */
bool discard; /* if support discard */
bool zoned; /* if device is zoned */
+ bool zone_full; /* Initialize zones to be full */
bool virt_boundary; /* virtual boundary on/off for the device */
bool no_sched; /* no IO scheduler for the device */
bool shared_tags; /* share tag set between devices for blk-mq */
diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c
index f118d304f310..9bc768b2ca56 100644
--- a/drivers/block/null_blk/zoned.c
+++ b/drivers/block/null_blk/zoned.c
@@ -145,7 +145,7 @@ int null_init_zoned_dev(struct nullb_device *dev,
zone = &dev->zones[i];
null_init_zone_lock(dev, zone);
- zone->start = zone->wp = sector;
+ zone->start = sector;
if (zone->start + dev->zone_size_sects > dev_capacity_sects)
zone->len = dev_capacity_sects - zone->start;
else
@@ -153,12 +153,18 @@ int null_init_zoned_dev(struct nullb_device *dev,
zone->capacity =
min_t(sector_t, zone->len, zone_capacity_sects);
zone->type = BLK_ZONE_TYPE_SEQWRITE_REQ;
- zone->cond = BLK_ZONE_COND_EMPTY;
+ if (dev->zone_full) {
+ zone->cond = BLK_ZONE_COND_FULL;
+ zone->wp = zone->start + zone->capacity;
+ } else{
+ zone->cond = BLK_ZONE_COND_EMPTY;
+ zone->wp = zone->start;
+ }
sector += dev->zone_size_sects;
}
- lim->zoned = true;
+ lim->features |= BLK_FEAT_ZONED;
lim->chunk_sectors = dev->zone_size_sects;
lim->max_zone_append_sectors = dev->zone_append_max_sectors;
lim->max_open_zones = dev->zone_max_open;
@@ -171,9 +177,6 @@ int null_register_zoned_dev(struct nullb *nullb)
struct request_queue *q = nullb->q;
struct gendisk *disk = nullb->disk;
- blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
- disk->nr_zones = bdev_nr_zones(disk->part0);
-
pr_info("%s: using %s zone append\n",
disk->disk_name,
queue_emulates_zone_append(q) ? "emulated" : "native");
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 8a2ce8070010..7cece5884b9c 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2622,6 +2622,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
struct queue_limits lim = {
.max_hw_sectors = PACKET_MAX_SECTORS,
.logical_block_size = CD_FRAMESIZE,
+ .features = BLK_FEAT_ROTATIONAL,
};
int idx;
int ret = -ENOMEM;
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index b810ac0a5c4b..ff45ed766469 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -388,9 +388,9 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
.max_segments = -1,
.max_segment_size = dev->bounce_size,
.dma_alignment = dev->blk_size - 1,
+ .features = BLK_FEAT_WRITE_CACHE |
+ BLK_FEAT_ROTATIONAL,
};
-
- struct request_queue *queue;
struct gendisk *gendisk;
if (dev->blk_size < 512) {
@@ -447,10 +447,6 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
goto fail_free_tag_set;
}
- queue = gendisk->queue;
-
- blk_queue_write_cache(queue, true, false);
-
priv->gendisk = gendisk;
gendisk->major = ps3disk_major;
gendisk->first_minor = devidx * PS3DISK_MINORS;
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 26ff5cd2bf0a..008e850555f4 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -4949,14 +4949,12 @@ static const struct blk_mq_ops rbd_mq_ops = {
static int rbd_init_disk(struct rbd_device *rbd_dev)
{
struct gendisk *disk;
- struct request_queue *q;
unsigned int objset_bytes =
rbd_dev->layout.object_size * rbd_dev->layout.stripe_count;
struct queue_limits lim = {
.max_hw_sectors = objset_bytes >> SECTOR_SHIFT,
- .max_user_sectors = objset_bytes >> SECTOR_SHIFT,
+ .io_opt = objset_bytes,
.io_min = rbd_dev->opts->alloc_size,
- .io_opt = rbd_dev->opts->alloc_size,
.max_segments = USHRT_MAX,
.max_segment_size = UINT_MAX,
};
@@ -4980,12 +4978,14 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
lim.max_write_zeroes_sectors = objset_bytes >> SECTOR_SHIFT;
}
+ if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC))
+ lim.features |= BLK_FEAT_STABLE_WRITES;
+
disk = blk_mq_alloc_disk(&rbd_dev->tag_set, &lim, rbd_dev);
if (IS_ERR(disk)) {
err = PTR_ERR(disk);
goto out_tag_set;
}
- q = disk->queue;
snprintf(disk->disk_name, sizeof(disk->disk_name), RBD_DRV_NAME "%d",
rbd_dev->dev_id);
@@ -4997,13 +4997,6 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
disk->minors = RBD_MINORS_PER_MAJOR;
disk->fops = &rbd_bd_ops;
disk->private_data = rbd_dev;
-
- blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
- /* QUEUE_FLAG_ADD_RANDOM is off by default for blk-mq */
-
- if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC))
- blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, q);
-
rbd_dev->disk = disk;
return 0;
diff --git a/drivers/block/rnbd/rnbd-clt-sysfs.c b/drivers/block/rnbd/rnbd-clt-sysfs.c
index 39887556cf95..6ea7c12e3a87 100644
--- a/drivers/block/rnbd/rnbd-clt-sysfs.c
+++ b/drivers/block/rnbd/rnbd-clt-sysfs.c
@@ -475,7 +475,7 @@ void rnbd_clt_remove_dev_symlink(struct rnbd_clt_dev *dev)
}
}
-static struct kobj_type rnbd_dev_ktype = {
+static const struct kobj_type rnbd_dev_ktype = {
.sysfs_ops = &kobj_sysfs_ops,
.default_groups = rnbd_dev_groups,
};
diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c
index b7ffe03c6160..c34695d2eea7 100644
--- a/drivers/block/rnbd/rnbd-clt.c
+++ b/drivers/block/rnbd/rnbd-clt.c
@@ -1352,10 +1352,6 @@ static int rnbd_clt_setup_gen_disk(struct rnbd_clt_dev *dev,
if (dev->access_mode == RNBD_ACCESS_RO)
set_disk_ro(dev->gd, true);
- /*
- * Network device does not need rotational
- */
- blk_queue_flag_set(QUEUE_FLAG_NONROT, dev->queue);
err = add_disk(dev->gd);
if (err)
put_disk(dev->gd);
@@ -1389,18 +1385,18 @@ static int rnbd_client_setup_device(struct rnbd_clt_dev *dev,
le32_to_cpu(rsp->max_discard_sectors);
}
+ if (rsp->cache_policy & RNBD_WRITEBACK) {
+ lim.features |= BLK_FEAT_WRITE_CACHE;
+ if (rsp->cache_policy & RNBD_FUA)
+ lim.features |= BLK_FEAT_FUA;
+ }
+
dev->gd = blk_mq_alloc_disk(&dev->sess->tag_set, &lim, dev);
if (IS_ERR(dev->gd))
return PTR_ERR(dev->gd);
dev->queue = dev->gd->queue;
rnbd_init_mq_hw_queues(dev);
- blk_queue_flag_set(QUEUE_FLAG_SAME_COMP, dev->queue);
- blk_queue_flag_set(QUEUE_FLAG_SAME_FORCE, dev->queue);
- blk_queue_write_cache(dev->queue,
- !!(rsp->cache_policy & RNBD_WRITEBACK),
- !!(rsp->cache_policy & RNBD_FUA));
-
return rnbd_clt_setup_gen_disk(dev, rsp, idx);
}
diff --git a/drivers/block/rnbd/rnbd-srv-sysfs.c b/drivers/block/rnbd/rnbd-srv-sysfs.c
index cba6ba43c2c2..64780094442c 100644
--- a/drivers/block/rnbd/rnbd-srv-sysfs.c
+++ b/drivers/block/rnbd/rnbd-srv-sysfs.c
@@ -33,7 +33,7 @@ static void rnbd_srv_dev_release(struct kobject *kobj)
kfree(dev);
}
-static struct kobj_type dev_ktype = {
+static const struct kobj_type dev_ktype = {
.sysfs_ops = &kobj_sysfs_ops,
.release = rnbd_srv_dev_release
};
@@ -184,7 +184,7 @@ static void rnbd_srv_sess_dev_release(struct kobject *kobj)
rnbd_destroy_sess_dev(sess_dev, sess_dev->keep_id);
}
-static struct kobj_type rnbd_srv_sess_dev_ktype = {
+static const struct kobj_type rnbd_srv_sess_dev_ktype = {
.sysfs_ops = &kobj_sysfs_ops,
.release = rnbd_srv_sess_dev_release,
};
diff --git a/drivers/block/rnull.rs b/drivers/block/rnull.rs
new file mode 100644
index 000000000000..b0227cf9ddd3
--- /dev/null
+++ b/drivers/block/rnull.rs
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! This is a Rust implementation of the C null block driver.
+//!
+//! Supported features:
+//!
+//! - blk-mq interface
+//! - direct completion
+//! - block size 4k
+//!
+//! The driver is not configurable.
+
+use kernel::{
+ alloc::flags,
+ block::mq::{
+ self,
+ gen_disk::{self, GenDisk},
+ Operations, TagSet,
+ },
+ error::Result,
+ new_mutex, pr_info,
+ prelude::*,
+ sync::{Arc, Mutex},
+ types::ARef,
+};
+
+module! {
+ type: NullBlkModule,
+ name: "rnull_mod",
+ author: "Andreas Hindborg",
+ license: "GPL v2",
+}
+
+struct NullBlkModule {
+ _disk: Pin<Box<Mutex<GenDisk<NullBlkDevice>>>>,
+}
+
+impl kernel::Module for NullBlkModule {
+ fn init(_module: &'static ThisModule) -> Result<Self> {
+ pr_info!("Rust null_blk loaded\n");
+ let tagset = Arc::pin_init(TagSet::new(1, 256, 1), flags::GFP_KERNEL)?;
+
+ let disk = gen_disk::GenDiskBuilder::new()
+ .capacity_sectors(4096 << 11)
+ .logical_block_size(4096)?
+ .physical_block_size(4096)?
+ .rotational(false)
+ .build(format_args!("rnullb{}", 0), tagset)?;
+
+ let disk = Box::pin_init(new_mutex!(disk, "nullb:disk"), flags::GFP_KERNEL)?;
+
+ Ok(Self { _disk: disk })
+ }
+}
+
+struct NullBlkDevice;
+
+#[vtable]
+impl Operations for NullBlkDevice {
+ #[inline(always)]
+ fn queue_rq(rq: ARef<mq::Request<Self>>, _is_last: bool) -> Result {
+ mq::Request::end_ok(rq)
+ .map_err(|_e| kernel::error::code::EIO)
+ // We take no refcounts on the request, so we expect to be able to
+ // end the request. The request reference must be unique at this
+ // point, and so `end_ok` cannot fail.
+ .expect("Fatal error - expected to be able to end request");
+
+ Ok(())
+ }
+
+ fn commit_rqs() {}
+}
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 5286cb8e0824..2d38331ee667 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -791,6 +791,7 @@ static int probe_disk(struct vdc_port *port)
.seg_boundary_mask = PAGE_SIZE - 1,
.max_segment_size = PAGE_SIZE,
.max_segments = port->ring_cookies,
+ .features = BLK_FEAT_ROTATIONAL,
};
struct request_queue *q;
struct gendisk *g;
diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index 6731678f3a41..126f151c4f2c 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -787,6 +787,9 @@ static void swim_cleanup_floppy_disk(struct floppy_state *fs)
static int swim_floppy_init(struct swim_priv *swd)
{
+ struct queue_limits lim = {
+ .features = BLK_FEAT_ROTATIONAL,
+ };
int err;
int drive;
struct swim __iomem *base = swd->base;
@@ -820,7 +823,7 @@ static int swim_floppy_init(struct swim_priv *swd)
goto exit_put_disks;
swd->unit[drive].disk =
- blk_mq_alloc_disk(&swd->unit[drive].tag_set, NULL,
+ blk_mq_alloc_disk(&swd->unit[drive].tag_set, &lim,
&swd->unit[drive]);
if (IS_ERR(swd->unit[drive].disk)) {
blk_mq_free_tag_set(&swd->unit[drive].tag_set);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index a04756ac778e..90be1017f7bf 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -1189,6 +1189,9 @@ static int swim3_add_device(struct macio_dev *mdev, int index)
static int swim3_attach(struct macio_dev *mdev,
const struct of_device_id *match)
{
+ struct queue_limits lim = {
+ .features = BLK_FEAT_ROTATIONAL,
+ };
struct floppy_state *fs;
struct gendisk *disk;
int rc;
@@ -1210,7 +1213,7 @@ static int swim3_attach(struct macio_dev *mdev,
if (rc)
goto out_unregister;
- disk = blk_mq_alloc_disk(&fs->tag_set, NULL, fs);
+ disk = blk_mq_alloc_disk(&fs->tag_set, &lim, fs);
if (IS_ERR(disk)) {
rc = PTR_ERR(disk);
goto out_free_tag_set;
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 4e159948c912..6fb799ec0d88 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -248,8 +248,6 @@ static int ublk_dev_param_zoned_validate(const struct ublk_device *ub)
static void ublk_dev_param_zoned_apply(struct ublk_device *ub)
{
- blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, ub->ub_disk->queue);
-
ub->ub_disk->nr_zones = ublk_get_nr_zones(ub);
}
@@ -484,16 +482,8 @@ static inline unsigned ublk_pos_to_tag(loff_t pos)
static void ublk_dev_param_basic_apply(struct ublk_device *ub)
{
- struct request_queue *q = ub->ub_disk->queue;
const struct ublk_param_basic *p = &ub->params.basic;
- blk_queue_write_cache(q, p->attrs & UBLK_ATTR_VOLATILE_CACHE,
- p->attrs & UBLK_ATTR_FUA);
- if (p->attrs & UBLK_ATTR_ROTATIONAL)
- blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
- else
- blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
-
if (p->attrs & UBLK_ATTR_READ_ONLY)
set_disk_ro(ub->ub_disk, true);
@@ -2204,12 +2194,21 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
if (!IS_ENABLED(CONFIG_BLK_DEV_ZONED))
return -EOPNOTSUPP;
- lim.zoned = true;
+ 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;
}
+ if (ub->params.basic.attrs & UBLK_ATTR_VOLATILE_CACHE) {
+ lim.features |= BLK_FEAT_WRITE_CACHE;
+ if (ub->params.basic.attrs & UBLK_ATTR_FUA)
+ lim.features |= BLK_FEAT_FUA;
+ }
+
+ if (ub->params.basic.attrs & UBLK_ATTR_ROTATIONAL)
+ lim.features |= BLK_FEAT_ROTATIONAL;
+
if (wait_for_completion_interruptible(&ub->completion) != 0)
return -EINTR;
@@ -3017,4 +3016,5 @@ module_param_cb(ublks_max, &ublk_max_ublks_ops, &ublks_max, 0644);
MODULE_PARM_DESC(ublks_max, "max number of ublk devices allowed to add(default: 64)");
MODULE_AUTHOR("Ming Lei <[email protected]>");
+MODULE_DESCRIPTION("Userspace block device");
MODULE_LICENSE("GPL");
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 2351f411fa46..e3147a611151 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -728,7 +728,7 @@ static int virtblk_read_zoned_limits(struct virtio_blk *vblk,
dev_dbg(&vdev->dev, "probing host-managed zoned device\n");
- lim->zoned = true;
+ lim->features |= BLK_FEAT_ZONED;
virtio_cread(vdev, struct virtio_blk_config,
zoned.max_open_zones, &v);
@@ -1089,14 +1089,6 @@ static int virtblk_get_cache_mode(struct virtio_device *vdev)
return writeback;
}
-static void virtblk_update_cache_mode(struct virtio_device *vdev)
-{
- u8 writeback = virtblk_get_cache_mode(vdev);
- struct virtio_blk *vblk = vdev->priv;
-
- blk_queue_write_cache(vblk->disk->queue, writeback, false);
-}
-
static const char *const virtblk_cache_types[] = {
"write through", "write back"
};
@@ -1108,6 +1100,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
struct gendisk *disk = dev_to_disk(dev);
struct virtio_blk *vblk = disk->private_data;
struct virtio_device *vdev = vblk->vdev;
+ struct queue_limits lim;
int i;
BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE));
@@ -1116,7 +1109,17 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
return i;
virtio_cwrite8(vdev, offsetof(struct virtio_blk_config, wce), i);
- virtblk_update_cache_mode(vdev);
+
+ lim = queue_limits_start_update(disk->queue);
+ if (virtblk_get_cache_mode(vdev))
+ lim.features |= BLK_FEAT_WRITE_CACHE;
+ else
+ lim.features &= ~BLK_FEAT_WRITE_CACHE;
+ blk_mq_freeze_queue(disk->queue);
+ i = queue_limits_commit_update(disk->queue, &lim);
+ blk_mq_unfreeze_queue(disk->queue);
+ if (i)
+ return i;
return count;
}
@@ -1247,7 +1250,7 @@ static int virtblk_read_limits(struct virtio_blk *vblk,
struct queue_limits *lim)
{
struct virtio_device *vdev = vblk->vdev;
- u32 v, blk_size, max_size, sg_elems, opt_io_size;
+ u32 v, max_size, sg_elems, opt_io_size;
u32 max_discard_segs = 0;
u32 discard_granularity = 0;
u16 min_io_size;
@@ -1286,46 +1289,36 @@ static int virtblk_read_limits(struct virtio_blk *vblk,
lim->max_segment_size = max_size;
/* Host can optionally specify the block size of the device */
- err = virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE,
+ virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE,
struct virtio_blk_config, blk_size,
- &blk_size);
- if (!err) {
- err = blk_validate_block_size(blk_size);
- if (err) {
- dev_err(&vdev->dev,
- "virtio_blk: invalid block size: 0x%x\n",
- blk_size);
- return err;
- }
-
- lim->logical_block_size = blk_size;
- } else
- blk_size = lim->logical_block_size;
+ &lim->logical_block_size);
/* Use topology information if available */
err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
struct virtio_blk_config, physical_block_exp,
&physical_block_exp);
if (!err && physical_block_exp)
- lim->physical_block_size = blk_size * (1 << physical_block_exp);
+ lim->physical_block_size =
+ lim->logical_block_size * (1 << physical_block_exp);
err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
struct virtio_blk_config, alignment_offset,
&alignment_offset);
if (!err && alignment_offset)
- lim->alignment_offset = blk_size * alignment_offset;
+ lim->alignment_offset =
+ lim->logical_block_size * alignment_offset;
err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
struct virtio_blk_config, min_io_size,
&min_io_size);
if (!err && min_io_size)
- lim->io_min = blk_size * min_io_size;
+ lim->io_min = lim->logical_block_size * min_io_size;
err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
struct virtio_blk_config, opt_io_size,
&opt_io_size);
if (!err && opt_io_size)
- lim->io_opt = blk_size * opt_io_size;
+ lim->io_opt = lim->logical_block_size * opt_io_size;
if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) {
virtio_cread(vdev, struct virtio_blk_config,
@@ -1419,7 +1412,7 @@ static int virtblk_read_limits(struct virtio_blk *vblk,
lim->discard_granularity =
discard_granularity << SECTOR_SHIFT;
else
- lim->discard_granularity = blk_size;
+ lim->discard_granularity = lim->logical_block_size;
}
if (virtio_has_feature(vdev, VIRTIO_BLK_F_ZONED)) {
@@ -1448,7 +1441,10 @@ static int virtblk_read_limits(struct virtio_blk *vblk,
static int virtblk_probe(struct virtio_device *vdev)
{
struct virtio_blk *vblk;
- struct queue_limits lim = { };
+ struct queue_limits lim = {
+ .features = BLK_FEAT_ROTATIONAL,
+ .logical_block_size = SECTOR_SIZE,
+ };
int err, index;
unsigned int queue_depth;
@@ -1512,6 +1508,9 @@ static int virtblk_probe(struct virtio_device *vdev)
if (err)
goto out_free_tags;
+ if (virtblk_get_cache_mode(vdev))
+ lim.features |= BLK_FEAT_WRITE_CACHE;
+
vblk->disk = blk_mq_alloc_disk(&vblk->tag_set, &lim, vblk);
if (IS_ERR(vblk->disk)) {
err = PTR_ERR(vblk->disk);
@@ -1527,9 +1526,6 @@ static int virtblk_probe(struct virtio_device *vdev)
vblk->disk->fops = &virtblk_fops;
vblk->index = index;
- /* configure queue flush support */
- virtblk_update_cache_mode(vdev);
-
/* If disk is read-only in the host, the guest should obey */
if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
set_disk_ro(vblk->disk, 1);
@@ -1541,8 +1537,8 @@ static int virtblk_probe(struct virtio_device *vdev)
* All steps that follow use the VQs therefore they need to be
* placed after the virtio_device_ready() call above.
*/
- if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) && lim.zoned) {
- blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, vblk->disk->queue);
+ if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
+ (lim.features & BLK_FEAT_ZONED)) {
err = blk_revalidate_disk_zones(vblk->disk);
if (err)
goto out_cleanup_disk;
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 944576d582fb..838064593f62 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -1563,5 +1563,6 @@ static void __exit xen_blkif_fini(void)
module_exit(xen_blkif_fini);
+MODULE_DESCRIPTION("Virtual block device back-end driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("xen-backend:vbd");
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index fd7c0ff2139c..59ce113b882a 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -788,6 +788,11 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
* A barrier request a superset of FUA, so we can
* implement it the same way. (It's also a FLUSH+FUA,
* since it is guaranteed ordered WRT previous writes.)
+ *
+ * Note that can end up here with a FUA write and the
+ * flags cleared. This happens when the flag was
+ * run-time disabled after a failing I/O, and we'll
+ * simplify submit it as a normal write.
*/
if (info->feature_flush && info->feature_fua)
ring_req->operation =
@@ -795,8 +800,6 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
else if (info->feature_flush)
ring_req->operation =
BLKIF_OP_FLUSH_DISKCACHE;
- else
- ring_req->operation = 0;
}
ring_req->u.rw.nr_segments = num_grant;
if (unlikely(require_extra_req)) {
@@ -887,16 +890,6 @@ static inline void flush_requests(struct blkfront_ring_info *rinfo)
notify_remote_via_irq(rinfo->irq);
}
-static inline bool blkif_request_flush_invalid(struct request *req,
- struct blkfront_info *info)
-{
- return (blk_rq_is_passthrough(req) ||
- ((req_op(req) == REQ_OP_FLUSH) &&
- !info->feature_flush) ||
- ((req->cmd_flags & REQ_FUA) &&
- !info->feature_fua));
-}
-
static blk_status_t blkif_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *qd)
{
@@ -908,12 +901,22 @@ static blk_status_t blkif_queue_rq(struct blk_mq_hw_ctx *hctx,
rinfo = get_rinfo(info, qid);
blk_mq_start_request(qd->rq);
spin_lock_irqsave(&rinfo->ring_lock, flags);
- if (RING_FULL(&rinfo->ring))
- goto out_busy;
- if (blkif_request_flush_invalid(qd->rq, rinfo->dev_info))
- goto out_err;
+ /*
+ * Check if the backend actually supports flushes.
+ *
+ * While the block layer won't send us flushes if we don't claim to
+ * support them, the Xen protocol allows the backend to revoke support
+ * at any time. That is of course a really bad idea and dangerous, but
+ * has been allowed for 10+ years. In that case we simply clear the
+ * flags, and directly return here for an empty flush and ignore the
+ * FUA flag later on.
+ */
+ if (unlikely(req_op(qd->rq) == REQ_OP_FLUSH && !info->feature_flush))
+ goto complete;
+ if (RING_FULL(&rinfo->ring))
+ goto out_busy;
if (blkif_queue_request(qd->rq, rinfo))
goto out_busy;
@@ -921,14 +924,14 @@ static blk_status_t blkif_queue_rq(struct blk_mq_hw_ctx *hctx,
spin_unlock_irqrestore(&rinfo->ring_lock, flags);
return BLK_STS_OK;
-out_err:
- spin_unlock_irqrestore(&rinfo->ring_lock, flags);
- return BLK_STS_IOERR;
-
out_busy:
blk_mq_stop_hw_queue(hctx);
spin_unlock_irqrestore(&rinfo->ring_lock, flags);
return BLK_STS_DEV_RESOURCE;
+complete:
+ spin_unlock_irqrestore(&rinfo->ring_lock, flags);
+ blk_mq_end_request(qd->rq, BLK_STS_OK);
+ return BLK_STS_OK;
}
static void blkif_complete_rq(struct request *rq)
@@ -956,6 +959,12 @@ static void blkif_set_queue_limits(const struct blkfront_info *info,
lim->max_secure_erase_sectors = UINT_MAX;
}
+ if (info->feature_flush) {
+ lim->features |= BLK_FEAT_WRITE_CACHE;
+ if (info->feature_fua)
+ lim->features |= BLK_FEAT_FUA;
+ }
+
/* Hard sector size and max sectors impersonate the equiv. hardware. */
lim->logical_block_size = info->sector_size;
lim->physical_block_size = info->physical_sector_size;
@@ -984,8 +993,6 @@ static const char *flush_info(struct blkfront_info *info)
static void xlvbd_flush(struct blkfront_info *info)
{
- blk_queue_write_cache(info->rq, info->feature_flush ? true : false,
- info->feature_fua ? true : false);
pr_info("blkfront: %s: %s %s %s %s %s %s %s\n",
info->gd->disk_name, flush_info(info),
"persistent grants:", info->feature_persistent ?
@@ -1063,8 +1070,7 @@ static char *encode_disk_name(char *ptr, unsigned int n)
}
static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
- struct blkfront_info *info, u16 sector_size,
- unsigned int physical_sector_size)
+ struct blkfront_info *info)
{
struct queue_limits lim = {};
struct gendisk *gd;
@@ -1139,7 +1145,6 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
err = PTR_ERR(gd);
goto out_free_tag_set;
}
- blk_queue_flag_set(QUEUE_FLAG_VIRT, gd->queue);
strcpy(gd->disk_name, DEV_NAME);
ptr = encode_disk_name(gd->disk_name + sizeof(DEV_NAME) - 1, offset);
@@ -1159,8 +1164,6 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
info->rq = gd->queue;
info->gd = gd;
- info->sector_size = sector_size;
- info->physical_sector_size = physical_sector_size;
xlvbd_flush(info);
@@ -1605,8 +1608,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
blkif_req(req)->error = BLK_STS_NOTSUPP;
info->feature_discard = 0;
info->feature_secdiscard = 0;
- blk_queue_max_discard_sectors(rq, 0);
- blk_queue_max_secure_erase_sectors(rq, 0);
+ blk_queue_disable_discard(rq);
+ blk_queue_disable_secure_erase(rq);
}
break;
case BLKIF_OP_FLUSH_DISKCACHE:
@@ -1627,7 +1630,6 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
blkif_req(req)->error = BLK_STS_OK;
info->feature_fua = 0;
info->feature_flush = 0;
- xlvbd_flush(info);
}
fallthrough;
case BLKIF_OP_READ:
@@ -2315,8 +2317,6 @@ static void blkfront_gather_backend_features(struct blkfront_info *info)
static void blkfront_connect(struct blkfront_info *info)
{
unsigned long long sectors;
- unsigned long sector_size;
- unsigned int physical_sector_size;
int err, i;
struct blkfront_ring_info *rinfo;
@@ -2355,7 +2355,7 @@ static void blkfront_connect(struct blkfront_info *info)
err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
"sectors", "%llu", &sectors,
"info", "%u", &info->vdisk_info,
- "sector-size", "%lu", &sector_size,
+ "sector-size", "%lu", &info->sector_size,
NULL);
if (err) {
xenbus_dev_fatal(info->xbdev, err,
@@ -2369,9 +2369,9 @@ static void blkfront_connect(struct blkfront_info *info)
* provide this. Assume physical sector size to be the same as
* sector_size in that case.
*/
- physical_sector_size = xenbus_read_unsigned(info->xbdev->otherend,
+ info->physical_sector_size = xenbus_read_unsigned(info->xbdev->otherend,
"physical-sector-size",
- sector_size);
+ info->sector_size);
blkfront_gather_backend_features(info);
for_each_rinfo(info, rinfo, i) {
err = blkfront_setup_indirect(rinfo);
@@ -2383,8 +2383,7 @@ static void blkfront_connect(struct blkfront_info *info)
}
}
- err = xlvbd_alloc_gendisk(sectors, info, sector_size,
- physical_sector_size);
+ err = xlvbd_alloc_gendisk(sectors, info);
if (err) {
xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
info->xbdev->otherend);
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 7c5f4e4d9b50..4b7219be1bb8 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -409,4 +409,5 @@ static void __exit z2_exit(void)
module_init(z2_init);
module_exit(z2_exit);
+MODULE_DESCRIPTION("Amiga Zorro II ramdisk driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 3acd7006ad2c..efcb8d9d274c 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -2208,6 +2208,8 @@ static int zram_add(void)
#if ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE
.max_write_zeroes_sectors = UINT_MAX,
#endif
+ .features = BLK_FEAT_STABLE_WRITES |
+ BLK_FEAT_SYNCHRONOUS,
};
struct zram *zram;
int ret, device_id;
@@ -2245,10 +2247,6 @@ static int zram_add(void)
/* Actual capacity set using sysfs (/sys/block/zram<id>/disksize */
set_capacity(zram->disk, 0);
- /* zram devices sort of resembles non-rotational disks */
- blk_queue_flag_set(QUEUE_FLAG_NONROT, zram->disk->queue);
- blk_queue_flag_set(QUEUE_FLAG_SYNCHRONOUS, zram->disk->queue);
- blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, zram->disk->queue);
ret = device_add_disk(NULL, zram->disk, zram_disk_groups);
if (ret)
goto out_cleanup_disk;
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index 5b6805d87fcf..dd3c0626c72d 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -382,7 +382,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
/* The first 4 bytes indicates the Intel PCIe specific packet type */
pdata = skb_pull_data(skb, BTINTEL_PCIE_HCI_TYPE_LEN);
- if (!data) {
+ if (!pdata) {
bt_dev_err(hdev, "Corrupted packet received");
ret = -EILSEQ;
goto exit_error;
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 9d0c7e278114..9bfa9a6ad56c 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -281,7 +281,7 @@ static u8 crc8_table[CRC8_TABLE_SIZE];
/* Default configurations */
#define DEFAULT_H2C_WAKEUP_MODE WAKEUP_METHOD_BREAK
-#define DEFAULT_PS_MODE PS_MODE_DISABLE
+#define DEFAULT_PS_MODE PS_MODE_ENABLE
#define FW_INIT_BAUDRATE HCI_NXP_PRI_BAUDRATE
static struct sk_buff *nxp_drv_send_cmd(struct hci_dev *hdev, u16 opcode,
diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c
index 0c2f15235b4c..d90858ea2fe5 100644
--- a/drivers/bluetooth/hci_bcm4377.c
+++ b/drivers/bluetooth/hci_bcm4377.c
@@ -495,6 +495,10 @@ struct bcm4377_data;
* extended scanning
* broken_mws_transport_config: Set to true if the chip erroneously claims to
* support MWS Transport Configuration
+ * broken_le_ext_adv_report_phy: Set to true if this chip stuffs flags inside
+ * reserved bits of Primary/Secondary_PHY inside
+ * LE Extended Advertising Report events which
+ * have to be ignored
* send_calibration: Optional callback to send calibration data
* send_ptb: Callback to send "PTB" regulatory/calibration data
*/
@@ -513,6 +517,7 @@ struct bcm4377_hw {
unsigned long broken_ext_scan : 1;
unsigned long broken_mws_transport_config : 1;
unsigned long broken_le_coded : 1;
+ unsigned long broken_le_ext_adv_report_phy : 1;
int (*send_calibration)(struct bcm4377_data *bcm4377);
int (*send_ptb)(struct bcm4377_data *bcm4377,
@@ -716,7 +721,7 @@ static void bcm4377_handle_ack(struct bcm4377_data *bcm4377,
ring->events[msgid] = NULL;
}
- bitmap_release_region(ring->msgids, msgid, ring->n_entries);
+ bitmap_release_region(ring->msgids, msgid, 0);
unlock:
spin_unlock_irqrestore(&ring->lock, flags);
@@ -2373,6 +2378,8 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id)
set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
if (bcm4377->hw->broken_le_coded)
set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks);
+ if (bcm4377->hw->broken_le_ext_adv_report_phy)
+ set_bit(HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY, &hdev->quirks);
pci_set_drvdata(pdev, bcm4377);
hci_set_drvdata(hdev, bcm4377);
@@ -2477,6 +2484,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
.clear_pciecfg_subsystem_ctrl_bit19 = true,
.broken_mws_transport_config = true,
.broken_le_coded = true,
+ .broken_le_ext_adv_report_phy = true,
.send_calibration = bcm4387_send_calibration,
.send_ptb = bcm4378_send_ptb,
},
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 0c9c9ee56592..9a0bc86f9aac 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -2450,15 +2450,27 @@ static void qca_serdev_shutdown(struct device *dev)
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
struct hci_uart *hu = &qcadev->serdev_hu;
struct hci_dev *hdev = hu->hdev;
- struct qca_data *qca = hu->priv;
const u8 ibs_wake_cmd[] = { 0xFD };
const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 };
if (qcadev->btsoc_type == QCA_QCA6390) {
- if (test_bit(QCA_BT_OFF, &qca->flags) ||
- !test_bit(HCI_RUNNING, &hdev->flags))
+ /* The purpose of sending the VSC is to reset SOC into a initial
+ * state and the state will ensure next hdev->setup() success.
+ * if HCI_QUIRK_NON_PERSISTENT_SETUP is set, it means that
+ * hdev->setup() can do its job regardless of SoC state, so
+ * don't need to send the VSC.
+ * if HCI_SETUP is set, it means that hdev->setup() was never
+ * invoked and the SOC is already in the initial state, so
+ * don't also need to send the VSC.
+ */
+ if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks) ||
+ hci_dev_test_flag(hdev, HCI_SETUP))
return;
+ /* The serdev must be in open state when conrol logic arrives
+ * here, so also fix the use-after-free issue caused by that
+ * the serdev is flushed or wrote after it is closed.
+ */
serdev_device_write_flush(serdev);
ret = serdev_device_write_buf(serdev, ibs_wake_cmd,
sizeof(ibs_wake_cmd));
diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c
index 1e29ba76615d..ac6c7e4900f4 100644
--- a/drivers/bus/sunxi-rsb.c
+++ b/drivers/bus/sunxi-rsb.c
@@ -457,7 +457,7 @@ static void regmap_sunxi_rsb_free_ctx(void *context)
kfree(ctx);
}
-static struct regmap_bus regmap_sunxi_rsb = {
+static const struct regmap_bus regmap_sunxi_rsb = {
.reg_write = regmap_sunxi_rsb_reg_write,
.reg_read = regmap_sunxi_rsb_reg_read,
.free_context = regmap_sunxi_rsb_free_ctx,
diff --git a/drivers/bus/ts-nbus.c b/drivers/bus/ts-nbus.c
index baf22a82c47a..b8af44c5cdbd 100644
--- a/drivers/bus/ts-nbus.c
+++ b/drivers/bus/ts-nbus.c
@@ -294,7 +294,7 @@ static int ts_nbus_probe(struct platform_device *pdev)
state.duty_cycle = state.period;
state.enabled = true;
- ret = pwm_apply_state(pwm, &state);
+ ret = pwm_apply_might_sleep(pwm, &state);
if (ret < 0)
return dev_err_probe(dev, ret, "failed to configure PWM\n");
diff --git a/drivers/bus/vexpress-config.c b/drivers/bus/vexpress-config.c
index d2c7ada90186..64ee920721ee 100644
--- a/drivers/bus/vexpress-config.c
+++ b/drivers/bus/vexpress-config.c
@@ -414,4 +414,5 @@ static struct platform_driver vexpress_syscfg_driver = {
.probe = vexpress_syscfg_probe,
};
module_platform_driver(vexpress_syscfg_driver);
+MODULE_DESCRIPTION("Versatile Express configuration bus");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
index 9345ce4976d7..94abd8f632a7 100644
--- a/drivers/cache/Kconfig
+++ b/drivers/cache/Kconfig
@@ -14,4 +14,13 @@ config SIFIVE_CCACHE
help
Support for the composable cache controller on SiFive platforms.
+config STARFIVE_STARLINK_CACHE
+ bool "StarFive StarLink Cache controller"
+ depends on RISCV
+ depends on ARCH_STARFIVE
+ select RISCV_DMA_NONCOHERENT
+ select RISCV_NONSTANDARD_CACHE_OPS
+ help
+ Support for the StarLink cache controller IP from StarFive.
+
endmenu
diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
index 7657cff3bd6c..55c5e851034d 100644
--- a/drivers/cache/Makefile
+++ b/drivers/cache/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o
-obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o
+obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o
+obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o
+obj-$(CONFIG_STARFIVE_STARLINK_CACHE) += starfive_starlink_cache.o
diff --git a/drivers/cache/starfive_starlink_cache.c b/drivers/cache/starfive_starlink_cache.c
new file mode 100644
index 000000000000..24c7d078ca22
--- /dev/null
+++ b/drivers/cache/starfive_starlink_cache.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cache Management Operations for StarFive's Starlink cache controller
+ *
+ * Copyright (C) 2024 Shanghai StarFive Technology Co., Ltd.
+ *
+ * Author: Joshua Yeong <[email protected]>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/cacheflush.h>
+#include <linux/iopoll.h>
+#include <linux/of_address.h>
+
+#include <asm/dma-noncoherent.h>
+
+#define STARLINK_CACHE_FLUSH_START_ADDR 0x0
+#define STARLINK_CACHE_FLUSH_END_ADDR 0x8
+#define STARLINK_CACHE_FLUSH_CTL 0x10
+#define STARLINK_CACHE_ALIGN 0x40
+
+#define STARLINK_CACHE_ADDRESS_RANGE_MASK GENMASK(39, 0)
+#define STARLINK_CACHE_FLUSH_CTL_MODE_MASK GENMASK(2, 1)
+#define STARLINK_CACHE_FLUSH_CTL_ENABLE_MASK BIT(0)
+
+#define STARLINK_CACHE_FLUSH_CTL_CLEAN_INVALIDATE 0
+#define STARLINK_CACHE_FLUSH_CTL_MAKE_INVALIDATE 1
+#define STARLINK_CACHE_FLUSH_CTL_CLEAN_SHARED 2
+#define STARLINK_CACHE_FLUSH_POLL_DELAY_US 1
+#define STARLINK_CACHE_FLUSH_TIMEOUT_US 5000000
+
+static void __iomem *starlink_cache_base;
+
+static void starlink_cache_flush_complete(void)
+{
+ volatile void __iomem *ctl = starlink_cache_base + STARLINK_CACHE_FLUSH_CTL;
+ u64 v;
+ int ret;
+
+ ret = readq_poll_timeout_atomic(ctl, v, !(v & STARLINK_CACHE_FLUSH_CTL_ENABLE_MASK),
+ STARLINK_CACHE_FLUSH_POLL_DELAY_US,
+ STARLINK_CACHE_FLUSH_TIMEOUT_US);
+ if (ret)
+ WARN(1, "StarFive Starlink cache flush operation timeout\n");
+}
+
+static void starlink_cache_dma_cache_wback(phys_addr_t paddr, unsigned long size)
+{
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
+
+ mb();
+ writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
+ STARLINK_CACHE_FLUSH_CTL_CLEAN_SHARED),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
+
+ starlink_cache_flush_complete();
+}
+
+static void starlink_cache_dma_cache_invalidate(phys_addr_t paddr, unsigned long size)
+{
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
+
+ mb();
+ writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
+ STARLINK_CACHE_FLUSH_CTL_MAKE_INVALIDATE),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
+
+ starlink_cache_flush_complete();
+}
+
+static void starlink_cache_dma_cache_wback_inv(phys_addr_t paddr, unsigned long size)
+{
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
+
+ mb();
+ writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
+ STARLINK_CACHE_FLUSH_CTL_CLEAN_INVALIDATE),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
+
+ starlink_cache_flush_complete();
+}
+
+static const struct riscv_nonstd_cache_ops starlink_cache_ops = {
+ .wback = &starlink_cache_dma_cache_wback,
+ .inv = &starlink_cache_dma_cache_invalidate,
+ .wback_inv = &starlink_cache_dma_cache_wback_inv,
+};
+
+static const struct of_device_id starlink_cache_ids[] = {
+ { .compatible = "starfive,jh8100-starlink-cache" },
+ { /* sentinel */ }
+};
+
+static int __init starlink_cache_init(void)
+{
+ struct device_node *np;
+ u32 block_size;
+ int ret;
+
+ np = of_find_matching_node(NULL, starlink_cache_ids);
+ if (!of_device_is_available(np))
+ return -ENODEV;
+
+ ret = of_property_read_u32(np, "cache-block-size", &block_size);
+ if (ret)
+ return ret;
+
+ if (block_size % STARLINK_CACHE_ALIGN)
+ return -EINVAL;
+
+ starlink_cache_base = of_iomap(np, 0);
+ if (!starlink_cache_base)
+ return -ENOMEM;
+
+ riscv_cbom_block_size = block_size;
+ riscv_noncoherent_supported();
+ riscv_noncoherent_register_cache_ops(&starlink_cache_ops);
+
+ return 0;
+}
+arch_initcall(starlink_cache_init);
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 20c90ebb3a3f..49e4829b7264 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -3708,4 +3708,5 @@ static void __exit cdrom_exit(void)
module_init(cdrom_init);
module_exit(cdrom_exit);
+MODULE_DESCRIPTION("Uniform CD-ROM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index eefdd422ad8e..71cfe7a85913 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -744,6 +744,7 @@ static int probe_gdrom(struct platform_device *devptr)
.max_segments = 1,
/* set a large max size to get most from DMA */
.max_segment_size = 0x40000,
+ .features = BLK_FEAT_ROTATIONAL,
};
int err;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index d51fc8321d41..da32e8ed0830 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -269,8 +269,13 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
if (!devp->hd_ireqfreq)
return -EIO;
- if (count < sizeof(unsigned long))
- return -EINVAL;
+ if (in_compat_syscall()) {
+ if (count < sizeof(compat_ulong_t))
+ return -EINVAL;
+ } else {
+ if (count < sizeof(unsigned long))
+ return -EINVAL;
+ }
add_wait_queue(&devp->hd_waitqueue, &wait);
@@ -294,9 +299,16 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
schedule();
}
- retval = put_user(data, (unsigned long __user *)buf);
- if (!retval)
- retval = sizeof(unsigned long);
+ if (in_compat_syscall()) {
+ retval = put_user(data, (compat_ulong_t __user *)buf);
+ if (!retval)
+ retval = sizeof(compat_ulong_t);
+ } else {
+ retval = put_user(data, (unsigned long __user *)buf);
+ if (!retval)
+ retval = sizeof(unsigned long);
+ }
+
out:
__set_current_state(TASK_RUNNING);
remove_wait_queue(&devp->hd_waitqueue, &wait);
@@ -651,12 +663,24 @@ struct compat_hpet_info {
unsigned short hi_timer;
};
+/* 32-bit types would lead to different command codes which should be
+ * translated into 64-bit ones before passed to hpet_ioctl_common
+ */
+#define COMPAT_HPET_INFO _IOR('h', 0x03, struct compat_hpet_info)
+#define COMPAT_HPET_IRQFREQ _IOW('h', 0x6, compat_ulong_t)
+
static long
hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct hpet_info info;
int err;
+ if (cmd == COMPAT_HPET_INFO)
+ cmd = HPET_INFO;
+
+ if (cmd == COMPAT_HPET_IRQFREQ)
+ cmd = HPET_IRQFREQ;
+
mutex_lock(&hpet_mutex);
err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
mutex_unlock(&hpet_mutex);
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 4c695b0388f3..9bb142c75243 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -16,8 +16,8 @@ tpm-y += eventlog/common.o
tpm-y += eventlog/tpm1.o
tpm-y += eventlog/tpm2.o
tpm-y += tpm-buf.o
+tpm-y += tpm2-sessions.o
-tpm-$(CONFIG_TCG_TPM2_HMAC) += tpm2-sessions.o
tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o
tpm-$(CONFIG_EFI) += eventlog/efi.o
tpm-$(CONFIG_OF) += eventlog/of.o
diff --git a/drivers/char/tpm/eventlog/common.c b/drivers/char/tpm/eventlog/common.c
index 639c3f395a5a..4c0bbba64ee5 100644
--- a/drivers/char/tpm/eventlog/common.c
+++ b/drivers/char/tpm/eventlog/common.c
@@ -47,6 +47,8 @@ static int tpm_bios_measurements_open(struct inode *inode,
if (!err) {
seq = file->private_data;
seq->private = chip;
+ } else {
+ put_device(&chip->dev);
}
return err;
diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
index 907ac9956a78..2281d55df545 100644
--- a/drivers/char/tpm/tpm2-sessions.c
+++ b/drivers/char/tpm/tpm2-sessions.c
@@ -83,9 +83,6 @@
#define AES_KEY_BYTES AES_KEYSIZE_128
#define AES_KEY_BITS (AES_KEY_BYTES*8)
-static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy,
- u32 *handle, u8 *name);
-
/*
* This is the structure that carries all the auth information (like
* session handle, nonces, session key and auth) from use to use it is
@@ -148,6 +145,7 @@ struct tpm2_auth {
u8 name[AUTH_MAX_NAMES][2 + SHA512_DIGEST_SIZE];
};
+#ifdef CONFIG_TCG_TPM2_HMAC
/*
* Name Size based on TPM algorithm (assumes no hash bigger than 255)
*/
@@ -163,6 +161,226 @@ static u8 name_size(const u8 *name)
return size_map[alg] + 2;
}
+static int tpm2_parse_read_public(char *name, struct tpm_buf *buf)
+{
+ struct tpm_header *head = (struct tpm_header *)buf->data;
+ off_t offset = TPM_HEADER_SIZE;
+ u32 tot_len = be32_to_cpu(head->length);
+ u32 val;
+
+ /* we're starting after the header so adjust the length */
+ tot_len -= TPM_HEADER_SIZE;
+
+ /* skip public */
+ val = tpm_buf_read_u16(buf, &offset);
+ if (val > tot_len)
+ return -EINVAL;
+ offset += val;
+ /* name */
+ val = tpm_buf_read_u16(buf, &offset);
+ if (val != name_size(&buf->data[offset]))
+ return -EINVAL;
+ memcpy(name, &buf->data[offset], val);
+ /* forget the rest */
+ return 0;
+}
+
+static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
+{
+ struct tpm_buf buf;
+ int rc;
+
+ rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC);
+ if (rc)
+ return rc;
+
+ tpm_buf_append_u32(&buf, handle);
+ rc = tpm_transmit_cmd(chip, &buf, 0, "read public");
+ if (rc == TPM2_RC_SUCCESS)
+ rc = tpm2_parse_read_public(name, &buf);
+
+ tpm_buf_destroy(&buf);
+
+ return rc;
+}
+#endif /* CONFIG_TCG_TPM2_HMAC */
+
+/**
+ * tpm_buf_append_name() - add a handle area to the buffer
+ * @chip: the TPM chip structure
+ * @buf: The buffer to be appended
+ * @handle: The handle to be appended
+ * @name: The name of the handle (may be NULL)
+ *
+ * In order to compute session HMACs, we need to know the names of the
+ * objects pointed to by the handles. For most objects, this is simply
+ * the actual 4 byte handle or an empty buf (in these cases @name
+ * should be NULL) but for volatile objects, permanent objects and NV
+ * areas, the name is defined as the hash (according to the name
+ * algorithm which should be set to sha256) of the public area to
+ * which the two byte algorithm id has been appended. For these
+ * objects, the @name pointer should point to this. If a name is
+ * required but @name is NULL, then TPM2_ReadPublic() will be called
+ * on the handle to obtain the name.
+ *
+ * As with most tpm_buf operations, success is assumed because failure
+ * will be caused by an incorrect programming model and indicated by a
+ * kernel message.
+ */
+void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
+ u32 handle, u8 *name)
+{
+#ifdef CONFIG_TCG_TPM2_HMAC
+ enum tpm2_mso_type mso = tpm2_handle_mso(handle);
+ struct tpm2_auth *auth;
+ int slot;
+#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++;
+ return;
+ }
+
+#ifdef CONFIG_TCG_TPM2_HMAC
+ slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE) / 4;
+ if (slot >= AUTH_MAX_NAMES) {
+ dev_err(&chip->dev, "TPM: too many handles\n");
+ return;
+ }
+ auth = chip->auth;
+ WARN(auth->session != tpm_buf_length(buf),
+ "name added in wrong place\n");
+ tpm_buf_append_u32(buf, handle);
+ auth->session += 4;
+
+ if (mso == TPM2_MSO_PERSISTENT ||
+ mso == TPM2_MSO_VOLATILE ||
+ mso == TPM2_MSO_NVRAM) {
+ if (!name)
+ tpm2_read_public(chip, handle, auth->name[slot]);
+ } else {
+ if (name)
+ dev_err(&chip->dev, "TPM: Handle does not require name but one is specified\n");
+ }
+
+ auth->name_h[slot] = handle;
+ if (name)
+ memcpy(auth->name[slot], name, name_size(name));
+#endif
+}
+EXPORT_SYMBOL_GPL(tpm_buf_append_name);
+
+/**
+ * tpm_buf_append_hmac_session() - Append a TPM session element
+ * @chip: the TPM chip structure
+ * @buf: The buffer to be appended
+ * @attributes: The session attributes
+ * @passphrase: The session authority (NULL if none)
+ * @passphrase_len: The length of the session authority (0 if none)
+ *
+ * This fills in a session structure in the TPM command buffer, except
+ * for the HMAC which cannot be computed until the command buffer is
+ * complete. The type of session is controlled by the @attributes,
+ * the main ones of which are TPM2_SA_CONTINUE_SESSION which means the
+ * session won't terminate after tpm_buf_check_hmac_response(),
+ * TPM2_SA_DECRYPT which means this buffers first parameter should be
+ * encrypted with a session key and TPM2_SA_ENCRYPT, which means the
+ * response buffer's first parameter needs to be decrypted (confusing,
+ * but the defines are written from the point of view of the TPM).
+ *
+ * Any session appended by this command must be finalized by calling
+ * tpm_buf_fill_hmac_session() otherwise the HMAC will be incorrect
+ * and the TPM will reject the command.
+ *
+ * As with most tpm_buf operations, success is assumed because failure
+ * will be caused by an incorrect programming model and indicated by a
+ * kernel message.
+ */
+void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
+ u8 attributes, u8 *passphrase,
+ int passphrase_len)
+{
+#ifdef CONFIG_TCG_TPM2_HMAC
+ u8 nonce[SHA256_DIGEST_SIZE];
+ struct tpm2_auth *auth;
+ u32 len;
+#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);
+ return;
+ }
+
+#ifdef CONFIG_TCG_TPM2_HMAC
+ /*
+ * The Architecture Guide requires us to strip trailing zeros
+ * before computing the HMAC
+ */
+ while (passphrase && passphrase_len > 0 && passphrase[passphrase_len - 1] == '\0')
+ passphrase_len--;
+
+ auth = chip->auth;
+ auth->attrs = attributes;
+ auth->passphrase_len = passphrase_len;
+ if (passphrase_len)
+ memcpy(auth->passphrase, passphrase, passphrase_len);
+
+ if (auth->session != tpm_buf_length(buf)) {
+ /* we're not the first session */
+ len = get_unaligned_be32(&buf->data[auth->session]);
+ if (4 + len + auth->session != tpm_buf_length(buf)) {
+ WARN(1, "session length mismatch, cannot append");
+ return;
+ }
+
+ /* add our new session */
+ len += 9 + 2 * SHA256_DIGEST_SIZE;
+ put_unaligned_be32(len, &buf->data[auth->session]);
+ } else {
+ tpm_buf_append_u32(buf, 9 + 2 * SHA256_DIGEST_SIZE);
+ }
+
+ /* random number for our nonce */
+ get_random_bytes(nonce, sizeof(nonce));
+ memcpy(auth->our_nonce, nonce, sizeof(nonce));
+ tpm_buf_append_u32(buf, auth->handle);
+ /* our new nonce */
+ tpm_buf_append_u16(buf, SHA256_DIGEST_SIZE);
+ tpm_buf_append(buf, nonce, SHA256_DIGEST_SIZE);
+ tpm_buf_append_u8(buf, auth->attrs);
+ /* and put a placeholder for the hmac */
+ tpm_buf_append_u16(buf, SHA256_DIGEST_SIZE);
+ tpm_buf_append(buf, nonce, SHA256_DIGEST_SIZE);
+#endif
+}
+EXPORT_SYMBOL_GPL(tpm_buf_append_hmac_session);
+
+#ifdef CONFIG_TCG_TPM2_HMAC
+
+static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy,
+ u32 *handle, u8 *name);
+
/*
* It turns out the crypto hmac(sha256) is hard for us to consume
* because it assumes a fixed key and the TPM seems to change the key
@@ -344,82 +562,6 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip)
}
/**
- * tpm_buf_append_hmac_session() - Append a TPM session element
- * @chip: the TPM chip structure
- * @buf: The buffer to be appended
- * @attributes: The session attributes
- * @passphrase: The session authority (NULL if none)
- * @passphrase_len: The length of the session authority (0 if none)
- *
- * This fills in a session structure in the TPM command buffer, except
- * for the HMAC which cannot be computed until the command buffer is
- * complete. The type of session is controlled by the @attributes,
- * the main ones of which are TPM2_SA_CONTINUE_SESSION which means the
- * session won't terminate after tpm_buf_check_hmac_response(),
- * TPM2_SA_DECRYPT which means this buffers first parameter should be
- * encrypted with a session key and TPM2_SA_ENCRYPT, which means the
- * response buffer's first parameter needs to be decrypted (confusing,
- * but the defines are written from the point of view of the TPM).
- *
- * Any session appended by this command must be finalized by calling
- * tpm_buf_fill_hmac_session() otherwise the HMAC will be incorrect
- * and the TPM will reject the command.
- *
- * As with most tpm_buf operations, success is assumed because failure
- * will be caused by an incorrect programming model and indicated by a
- * kernel message.
- */
-void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
- u8 attributes, u8 *passphrase,
- int passphrase_len)
-{
- u8 nonce[SHA256_DIGEST_SIZE];
- u32 len;
- struct tpm2_auth *auth = chip->auth;
-
- /*
- * The Architecture Guide requires us to strip trailing zeros
- * before computing the HMAC
- */
- while (passphrase && passphrase_len > 0
- && passphrase[passphrase_len - 1] == '\0')
- passphrase_len--;
-
- auth->attrs = attributes;
- auth->passphrase_len = passphrase_len;
- if (passphrase_len)
- memcpy(auth->passphrase, passphrase, passphrase_len);
-
- if (auth->session != tpm_buf_length(buf)) {
- /* we're not the first session */
- len = get_unaligned_be32(&buf->data[auth->session]);
- if (4 + len + auth->session != tpm_buf_length(buf)) {
- WARN(1, "session length mismatch, cannot append");
- return;
- }
-
- /* add our new session */
- len += 9 + 2 * SHA256_DIGEST_SIZE;
- put_unaligned_be32(len, &buf->data[auth->session]);
- } else {
- tpm_buf_append_u32(buf, 9 + 2 * SHA256_DIGEST_SIZE);
- }
-
- /* random number for our nonce */
- get_random_bytes(nonce, sizeof(nonce));
- memcpy(auth->our_nonce, nonce, sizeof(nonce));
- tpm_buf_append_u32(buf, auth->handle);
- /* our new nonce */
- tpm_buf_append_u16(buf, SHA256_DIGEST_SIZE);
- tpm_buf_append(buf, nonce, SHA256_DIGEST_SIZE);
- tpm_buf_append_u8(buf, auth->attrs);
- /* and put a placeholder for the hmac */
- tpm_buf_append_u16(buf, SHA256_DIGEST_SIZE);
- tpm_buf_append(buf, nonce, SHA256_DIGEST_SIZE);
-}
-EXPORT_SYMBOL(tpm_buf_append_hmac_session);
-
-/**
* tpm_buf_fill_hmac_session() - finalize the session HMAC
* @chip: the TPM chip structure
* @buf: The buffer to be appended
@@ -449,6 +591,9 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
u8 cphash[SHA256_DIGEST_SIZE];
struct sha256_state sctx;
+ if (!auth)
+ return;
+
/* save the command code in BE format */
auth->ordinal = head->ordinal;
@@ -567,104 +712,6 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
}
EXPORT_SYMBOL(tpm_buf_fill_hmac_session);
-static int tpm2_parse_read_public(char *name, struct tpm_buf *buf)
-{
- struct tpm_header *head = (struct tpm_header *)buf->data;
- off_t offset = TPM_HEADER_SIZE;
- u32 tot_len = be32_to_cpu(head->length);
- u32 val;
-
- /* we're starting after the header so adjust the length */
- tot_len -= TPM_HEADER_SIZE;
-
- /* skip public */
- val = tpm_buf_read_u16(buf, &offset);
- if (val > tot_len)
- return -EINVAL;
- offset += val;
- /* name */
- val = tpm_buf_read_u16(buf, &offset);
- if (val != name_size(&buf->data[offset]))
- return -EINVAL;
- memcpy(name, &buf->data[offset], val);
- /* forget the rest */
- return 0;
-}
-
-static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
-{
- struct tpm_buf buf;
- int rc;
-
- rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC);
- if (rc)
- return rc;
-
- tpm_buf_append_u32(&buf, handle);
- rc = tpm_transmit_cmd(chip, &buf, 0, "read public");
- if (rc == TPM2_RC_SUCCESS)
- rc = tpm2_parse_read_public(name, &buf);
-
- tpm_buf_destroy(&buf);
-
- return rc;
-}
-
-/**
- * tpm_buf_append_name() - add a handle area to the buffer
- * @chip: the TPM chip structure
- * @buf: The buffer to be appended
- * @handle: The handle to be appended
- * @name: The name of the handle (may be NULL)
- *
- * In order to compute session HMACs, we need to know the names of the
- * objects pointed to by the handles. For most objects, this is simply
- * the actual 4 byte handle or an empty buf (in these cases @name
- * should be NULL) but for volatile objects, permanent objects and NV
- * areas, the name is defined as the hash (according to the name
- * algorithm which should be set to sha256) of the public area to
- * which the two byte algorithm id has been appended. For these
- * objects, the @name pointer should point to this. If a name is
- * required but @name is NULL, then TPM2_ReadPublic() will be called
- * on the handle to obtain the name.
- *
- * As with most tpm_buf operations, success is assumed because failure
- * will be caused by an incorrect programming model and indicated by a
- * kernel message.
- */
-void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
- u32 handle, u8 *name)
-{
- enum tpm2_mso_type mso = tpm2_handle_mso(handle);
- struct tpm2_auth *auth = chip->auth;
- int slot;
-
- slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE)/4;
- if (slot >= AUTH_MAX_NAMES) {
- dev_err(&chip->dev, "TPM: too many handles\n");
- return;
- }
- WARN(auth->session != tpm_buf_length(buf),
- "name added in wrong place\n");
- tpm_buf_append_u32(buf, handle);
- auth->session += 4;
-
- if (mso == TPM2_MSO_PERSISTENT ||
- mso == TPM2_MSO_VOLATILE ||
- mso == TPM2_MSO_NVRAM) {
- if (!name)
- tpm2_read_public(chip, handle, auth->name[slot]);
- } else {
- if (name)
- dev_err(&chip->dev, "TPM: Handle does not require name but one is specified\n");
- }
-
- auth->name_h[slot] = handle;
- if (name)
- memcpy(auth->name[slot], name, name_size(name));
-}
-EXPORT_SYMBOL(tpm_buf_append_name);
-
/**
* tpm_buf_check_hmac_response() - check the TPM return HMAC for correctness
* @chip: the TPM chip structure
@@ -705,6 +752,9 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
u32 cc = be32_to_cpu(auth->ordinal);
int parm_len, len, i, handles;
+ if (!auth)
+ return rc;
+
if (auth->session >= TPM_HEADER_SIZE) {
WARN(1, "tpm session not filled correctly\n");
goto out;
@@ -824,8 +874,13 @@ EXPORT_SYMBOL(tpm_buf_check_hmac_response);
*/
void tpm2_end_auth_session(struct tpm_chip *chip)
{
- tpm2_flush_context(chip, chip->auth->handle);
- memzero_explicit(chip->auth, sizeof(*chip->auth));
+ struct tpm2_auth *auth = chip->auth;
+
+ if (!auth)
+ return;
+
+ tpm2_flush_context(chip, auth->handle);
+ memzero_explicit(auth, sizeof(*auth));
}
EXPORT_SYMBOL(tpm2_end_auth_session);
@@ -907,6 +962,11 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
int rc;
u32 null_key;
+ if (!auth) {
+ dev_warn_once(&chip->dev, "auth session is not active\n");
+ return 0;
+ }
+
rc = tpm2_load_null(chip, &null_key);
if (rc)
goto out;
@@ -1301,3 +1361,4 @@ int tpm2_sessions_init(struct tpm_chip *chip)
return rc;
}
+#endif /* CONFIG_TCG_TPM2_HMAC */
diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c
index c9eca24bbad4..61b42c83ced8 100644
--- a/drivers/char/tpm/tpm_tis_spi_main.c
+++ b/drivers/char/tpm/tpm_tis_spi_main.c
@@ -318,6 +318,7 @@ static void tpm_tis_spi_remove(struct spi_device *dev)
}
static const struct spi_device_id tpm_tis_spi_id[] = {
+ { "attpm20p", (unsigned long)tpm_tis_spi_probe },
{ "st33htpm-spi", (unsigned long)tpm_tis_spi_probe },
{ "slb9670", (unsigned long)tpm_tis_spi_probe },
{ "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe },
diff --git a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c
index ba504e19d420..62d876e150e1 100644
--- a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c
+++ b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c
@@ -29,6 +29,7 @@ static const struct mtk_gate mfg_clks[] = {
static const struct mtk_clk_desc mfg_desc = {
.clks = mfg_clks,
.num_clks = ARRAY_SIZE(mfg_clks),
+ .need_runtime_pm = true,
};
static const struct of_device_id of_match_clk_mt8183_mfg[] = {
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index bd37ab4d1a9b..ba1d1c495bc2 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -496,14 +496,16 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
}
- devm_pm_runtime_enable(&pdev->dev);
- /*
- * Do a pm_runtime_resume_and_get() to workaround a possible
- * deadlock between clk_register() and the genpd framework.
- */
- r = pm_runtime_resume_and_get(&pdev->dev);
- if (r)
- return r;
+ if (mcd->need_runtime_pm) {
+ devm_pm_runtime_enable(&pdev->dev);
+ /*
+ * Do a pm_runtime_resume_and_get() to workaround a possible
+ * deadlock between clk_register() and the genpd framework.
+ */
+ r = pm_runtime_resume_and_get(&pdev->dev);
+ if (r)
+ return r;
+ }
/* Calculate how many clk_hw_onecell_data entries to allocate */
num_clks = mcd->num_clks + mcd->num_composite_clks;
@@ -585,7 +587,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
goto unregister_clks;
}
- pm_runtime_put(&pdev->dev);
+ if (mcd->need_runtime_pm)
+ pm_runtime_put(&pdev->dev);
return r;
@@ -618,7 +621,8 @@ free_base:
if (mcd->shared_io && base)
iounmap(base);
- pm_runtime_put(&pdev->dev);
+ if (mcd->need_runtime_pm)
+ pm_runtime_put(&pdev->dev);
return r;
}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 22096501a60a..c17fe1c2d732 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -237,6 +237,8 @@ struct mtk_clk_desc {
int (*clk_notifier_func)(struct device *dev, struct clk *clk);
unsigned int mfg_clk_idx;
+
+ bool need_runtime_pm;
};
int mtk_clk_pdev_probe(struct platform_device *pdev);
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 1bb51a058872..46369edfc07a 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -827,6 +827,14 @@ config SM_CAMCC_8550
Support for the camera clock controller on SM8550 devices.
Say Y if you want to support camera devices and camera functionality.
+config SM_CAMCC_8650
+ tristate "SM8650 Camera Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select SM_GCC_8650
+ help
+ Support for the camera clock controller on SM8650 devices.
+ Say Y if you want to support camera devices and camera functionality.
+
config SM_DISPCC_6115
tristate "SM6115 Display Clock Controller"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index dec5b6db6860..28bffa1eb8dd 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -109,6 +109,7 @@ obj-$(CONFIG_SM_CAMCC_6350) += camcc-sm6350.o
obj-$(CONFIG_SM_CAMCC_8250) += camcc-sm8250.o
obj-$(CONFIG_SM_CAMCC_8450) += camcc-sm8450.o
obj-$(CONFIG_SM_CAMCC_8550) += camcc-sm8550.o
+obj-$(CONFIG_SM_CAMCC_8650) += camcc-sm8650.o
obj-$(CONFIG_SM_DISPCC_6115) += dispcc-sm6115.o
obj-$(CONFIG_SM_DISPCC_6125) += dispcc-sm6125.o
obj-$(CONFIG_SM_DISPCC_6350) += dispcc-sm6350.o
diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c
index 5f7f537e4ecb..e8632db2c542 100644
--- a/drivers/clk/qcom/apss-ipq-pll.c
+++ b/drivers/clk/qcom/apss-ipq-pll.c
@@ -70,7 +70,6 @@ static struct clk_alpha_pll ipq_pll_stromer_plus = {
static const struct alpha_pll_config ipq5018_pll_config = {
.l = 0x2a,
.config_ctl_val = 0x4001075b,
- .config_ctl_hi_val = 0x304,
.main_output_mask = BIT(0),
.aux_output_mask = BIT(1),
.early_output_mask = BIT(3),
@@ -84,7 +83,6 @@ static const struct alpha_pll_config ipq5018_pll_config = {
static const struct alpha_pll_config ipq5332_pll_config = {
.l = 0x2d,
.config_ctl_val = 0x4001075b,
- .config_ctl_hi_val = 0x304,
.main_output_mask = BIT(0),
.aux_output_mask = BIT(1),
.early_output_mask = BIT(3),
diff --git a/drivers/clk/qcom/camcc-sm8650.c b/drivers/clk/qcom/camcc-sm8650.c
new file mode 100644
index 000000000000..1b28e086e519
--- /dev/null
+++ b/drivers/clk/qcom/camcc-sm8650.c
@@ -0,0 +1,3591 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sm8650-camcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.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_PLL1_OUT_EVEN,
+ 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_CAM_CC_PLL6_OUT_EVEN,
+ P_CAM_CC_PLL7_OUT_EVEN,
+ P_CAM_CC_PLL8_OUT_EVEN,
+ P_CAM_CC_PLL9_OUT_EVEN,
+ P_CAM_CC_PLL9_OUT_ODD,
+ P_CAM_CC_PLL10_OUT_EVEN,
+ P_SLEEP_CLK,
+};
+
+static const struct pll_vco lucid_ole_vco[] = {
+ { 249600000, 2300000000, 0 },
+};
+
+static const struct pll_vco rivian_ole_vco[] = {
+ { 777000000, 1285000000, 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 = 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_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 = "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_OLE],
+ .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_ole_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_OLE],
+ .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_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll1_config = {
+ .l = 0x31,
+ .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 = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_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 = "cam_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 clk_div_table post_div_table_cam_cc_pll1_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = {
+ .offset = 0x1000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll1_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll1_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .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 const struct alpha_pll_config 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_ole_vco,
+ .num_vco = ARRAY_SIZE(rivian_ole_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 = 0x30,
+ .alpha = 0x8aaa,
+ .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_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 = "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 = 0x3000,
+ .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_OLE],
+ .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_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll4_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .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_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 = "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 = 0x4000,
+ .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_OLE],
+ .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_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll5_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .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_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 = "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 = 0x5000,
+ .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_OLE],
+ .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_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll6_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .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_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 = "cam_cc_pll6",
+ .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_pll6_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll6_out_even = {
+ .offset = 0x6000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll6_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll6_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .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 const struct alpha_pll_config cam_cc_pll7_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .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_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 = "cam_cc_pll7",
+ .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_pll7_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll7_out_even = {
+ .offset = 0x7000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll7_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll7_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .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 const struct alpha_pll_config cam_cc_pll8_config = {
+ .l = 0x14,
+ .alpha = 0xd555,
+ .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_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 = "cam_cc_pll8",
+ .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_pll8_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll8_out_even = {
+ .offset = 0x8000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll8_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll8_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .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 const struct alpha_pll_config cam_cc_pll9_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 = 0x00008400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll9 = {
+ .offset = 0x9000,
+ .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 = "cam_cc_pll9",
+ .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_pll9_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll9_out_even = {
+ .offset = 0x9000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll9_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll9_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll9_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll9.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll9_out_odd[] = {
+ { 0x2, 3 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll9_out_odd = {
+ .offset = 0x9000,
+ .post_div_shift = 14,
+ .post_div_table = post_div_table_cam_cc_pll9_out_odd,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll9_out_odd),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll9_out_odd",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll9.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll10_config = {
+ .l = 0x30,
+ .alpha = 0x8aaa,
+ .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_pll10 = {
+ .offset = 0xa000,
+ .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 = "cam_cc_pll10",
+ .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_pll10_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll10_out_even = {
+ .offset = 0xa000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll10_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll10_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll10_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll10.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_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 },
+ { P_CAM_CC_PLL9_OUT_ODD, 4 },
+ { P_CAM_CC_PLL9_OUT_EVEN, 5 },
+};
+
+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 },
+ { .hw = &cam_cc_pll9_out_odd.clkr.hw },
+ { .hw = &cam_cc_pll9_out_even.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_PLL8_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll8_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL3_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll3_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL4_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_4[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll4_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_5[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL5_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_5[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll5_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL1_OUT_EVEN, 4 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_6[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll1_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_7[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL6_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_7[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll6_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_8[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL7_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_8[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll7_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_9[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL10_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_9[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll10_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_10[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_10[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map cam_cc_parent_map_11_ao[] = {
+ { P_BI_TCXO_AO, 0 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_11_ao[] = {
+ { .index = DT_BI_TCXO_AO },
+};
+
+static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(200000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0),
+ F(400000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0),
+ F(480000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_bps_clk_src = {
+ .cmd_rcgr = 0x10050,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_2,
+ .freq_tbl = ftbl_cam_cc_bps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_bps_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_camnoc_axi_rt_clk_src[] = {
+ F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_camnoc_axi_rt_clk_src = {
+ .cmd_rcgr = 0x1325c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_camnoc_axi_rt_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_axi_rt_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(19200000, P_BI_TCXO, 1, 0, 0),
+ F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_cci_0_clk_src = {
+ .cmd_rcgr = 0x131cc,
+ .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 = 0x131e8,
+ .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 = 0x13204,
+ .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 const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ 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_cphy_rx_clk_src = {
+ .cmd_rcgr = 0x1104c,
+ .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 const struct freq_tbl ftbl_cam_cc_cre_clk_src[] = {
+ F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAM_CC_PLL9_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_cre_clk_src = {
+ .cmd_rcgr = 0x13144,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cre_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cre_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_csi0phytimer_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = {
+ .cmd_rcgr = 0x150e0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_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 = 0x15104,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_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 = 0x15124,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_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 = 0x15144,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_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_csi4phytimer_clk_src = {
+ .cmd_rcgr = 0x15164,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi4phytimer_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_csi5phytimer_clk_src = {
+ .cmd_rcgr = 0x15184,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi5phytimer_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_csi6phytimer_clk_src = {
+ .cmd_rcgr = 0x151a4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi6phytimer_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_csi7phytimer_clk_src = {
+ .cmd_rcgr = 0x151c4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi7phytimer_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_csid_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_csid_clk_src = {
+ .cmd_rcgr = 0x13238,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csid_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(19200000, P_BI_TCXO, 1, 0, 0),
+ F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 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 = 0x10018,
+ .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(19200000, P_BI_TCXO, 1, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAM_CC_PLL9_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_icp_clk_src = {
+ .cmd_rcgr = 0x131a4,
+ .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(19200000, P_BI_TCXO, 1, 0, 0),
+ F(466000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_0_clk_src = {
+ .cmd_rcgr = 0x11018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_3,
+ .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_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_1_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(466000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_1_clk_src = {
+ .cmd_rcgr = 0x12018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_4,
+ .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_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_ife_2_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(466000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_2_clk_src = {
+ .cmd_rcgr = 0x12068,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_5,
+ .freq_tbl = ftbl_cam_cc_ife_2_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_2_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 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_csid_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 = 0x13028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_csid_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_nps_clk_src[] = {
+ F(475000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(575000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(825000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ipe_nps_clk_src = {
+ .cmd_rcgr = 0x10094,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_6,
+ .freq_tbl = ftbl_cam_cc_ipe_nps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_clk_src",
+ .parent_data = cam_cc_parent_data_6,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_jpeg_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAM_CC_PLL9_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_jpeg_clk_src = {
+ .cmd_rcgr = 0x13168,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_jpeg_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_jpeg_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_mclk0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(24000000, P_CAM_CC_PLL2_OUT_EVEN, 10, 1, 4),
+ F(68571429, P_CAM_CC_PLL2_OUT_MAIN, 14, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_mclk0_clk_src = {
+ .cmd_rcgr = 0x15000,
+ .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 = 0x1501c,
+ .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 = 0x15038,
+ .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 = 0x15054,
+ .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 struct clk_rcg2 cam_cc_mclk4_clk_src = {
+ .cmd_rcgr = 0x15070,
+ .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_mclk4_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_mclk5_clk_src = {
+ .cmd_rcgr = 0x1508c,
+ .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_mclk5_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_mclk6_clk_src = {
+ .cmd_rcgr = 0x150a8,
+ .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_mclk6_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_mclk7_clk_src = {
+ .cmd_rcgr = 0x150c4,
+ .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_mclk7_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_qdss_debug_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(75000000, P_CAM_CC_PLL0_OUT_EVEN, 8, 0, 0),
+ F(150000000, P_CAM_CC_PLL0_OUT_EVEN, 4, 0, 0),
+ F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_qdss_debug_clk_src = {
+ .cmd_rcgr = 0x1329c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_qdss_debug_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_qdss_debug_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_sfe_0_clk_src[] = {
+ F(466000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_sfe_0_clk_src = {
+ .cmd_rcgr = 0x1306c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_7,
+ .freq_tbl = ftbl_cam_cc_sfe_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_0_clk_src",
+ .parent_data = cam_cc_parent_data_7,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_7),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_sfe_1_clk_src[] = {
+ F(466000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_sfe_1_clk_src = {
+ .cmd_rcgr = 0x130bc,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_8,
+ .freq_tbl = ftbl_cam_cc_sfe_1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_1_clk_src",
+ .parent_data = cam_cc_parent_data_8,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_8),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_sfe_2_clk_src[] = {
+ F(466000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0),
+ F(594000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_sfe_2_clk_src = {
+ .cmd_rcgr = 0x1310c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_9,
+ .freq_tbl = ftbl_cam_cc_sfe_2_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_2_clk_src",
+ .parent_data = cam_cc_parent_data_9,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_9),
+ .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 = 0x132f0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_10,
+ .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_10,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_10),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_slow_ahb_clk_src = {
+ .cmd_rcgr = 0x10034,
+ .mnd_width = 0,
+ .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 = 0x132d4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_11_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_11_ao,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_11_ao),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_branch cam_cc_bps_ahb_clk = {
+ .halt_reg = 0x1004c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1004c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_bps_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_bps_clk = {
+ .halt_reg = 0x10068,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_bps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_bps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_bps_fast_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_bps_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_bps_shift_clk = {
+ .halt_reg = 0x10078,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x10078,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_bps_shift_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_camnoc_axi_nrt_clk = {
+ .halt_reg = 0x13284,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13284,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_axi_nrt_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_camnoc_axi_rt_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_axi_rt_clk = {
+ .halt_reg = 0x13274,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13274,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_axi_rt_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_camnoc_axi_rt_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 = 0x13290,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13290,
+ .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_camnoc_xo_clk = {
+ .halt_reg = 0x13294,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13294,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_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 = 0x131e4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x131e4,
+ .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 = 0x13200,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13200,
+ .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 = 0x1321c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1321c,
+ .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_core_ahb_clk = {
+ .halt_reg = 0x132d0,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x132d0,
+ .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 = 0x13220,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13220,
+ .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_bps_clk = {
+ .halt_reg = 0x10074,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10074,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_bps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_bps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_cre_clk = {
+ .halt_reg = 0x13160,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13160,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_cre_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cre_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 = 0x1322c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1322c,
+ .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 = 0x1103c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1103c,
+ .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 = 0x1203c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1203c,
+ .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_2_clk = {
+ .halt_reg = 0x1208c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1208c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ife_2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_2_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 = 0x13024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13024,
+ .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_nps_clk = {
+ .halt_reg = 0x100b8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ipe_nps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_nps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_sbi_clk = {
+ .halt_reg = 0x10104,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10104,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_sbi_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_0_clk = {
+ .halt_reg = 0x13090,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13090,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_sfe_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_sfe_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_1_clk = {
+ .halt_reg = 0x130e0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x130e0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_sfe_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_sfe_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_sfe_2_clk = {
+ .halt_reg = 0x13130,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13130,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_sfe_2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_sfe_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cre_ahb_clk = {
+ .halt_reg = 0x13164,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13164,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cre_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_cre_clk = {
+ .halt_reg = 0x1315c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1315c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cre_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cre_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 = 0x150f8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150f8,
+ .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 = 0x1511c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1511c,
+ .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 = 0x1513c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1513c,
+ .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 = 0x1515c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1515c,
+ .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_csi4phytimer_clk = {
+ .halt_reg = 0x1517c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1517c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi4phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi4phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi5phytimer_clk = {
+ .halt_reg = 0x1519c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1519c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi5phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi5phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi6phytimer_clk = {
+ .halt_reg = 0x151bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x151bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi6phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi6phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi7phytimer_clk = {
+ .halt_reg = 0x151dc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x151dc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi7phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi7phytimer_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 = 0x13250,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13250,
+ .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 = 0x15100,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15100,
+ .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 = 0x150fc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150fc,
+ .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 = 0x15120,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15120,
+ .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 = 0x15140,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15140,
+ .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 = 0x15160,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15160,
+ .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_csiphy4_clk = {
+ .halt_reg = 0x15180,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15180,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy4_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_csiphy5_clk = {
+ .halt_reg = 0x151a0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x151a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy5_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_csiphy6_clk = {
+ .halt_reg = 0x151c0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x151c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy6_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_csiphy7_clk = {
+ .halt_reg = 0x151e0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x151e0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy7_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 = 0x131c8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x131c8,
+ .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 = 0x131bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x131bc,
+ .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 = 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_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 = 0x11048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11048,
+ .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_0_shift_clk = {
+ .halt_reg = 0x11064,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x11064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_0_shift_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_ife_1_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_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 = 0x12048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x12048,
+ .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_1_shift_clk = {
+ .halt_reg = 0x1204c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1204c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_1_shift_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_ife_2_clk = {
+ .halt_reg = 0x12080,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x12080,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_2_fast_ahb_clk = {
+ .halt_reg = 0x12098,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x12098,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_2_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_2_shift_clk = {
+ .halt_reg = 0x1209c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1209c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_2_shift_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_ife_lite_ahb_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_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 = 0x1304c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1304c,
+ .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 = 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_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_nps_ahb_clk = {
+ .halt_reg = 0x100d0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100d0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_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_nps_clk = {
+ .halt_reg = 0x100ac,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_nps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_nps_fast_ahb_clk = {
+ .halt_reg = 0x100d4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_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_ipe_pps_clk = {
+ .halt_reg = 0x100bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_pps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_nps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_pps_fast_ahb_clk = {
+ .halt_reg = 0x100d8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100d8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_pps_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_ipe_shift_clk = {
+ .halt_reg = 0x100dc,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x100dc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_shift_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_jpeg_1_clk = {
+ .halt_reg = 0x1318c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1318c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_jpeg_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_jpeg_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_jpeg_clk = {
+ .halt_reg = 0x13180,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13180,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_jpeg_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_jpeg_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 = 0x15018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15018,
+ .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 = 0x15034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15034,
+ .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 = 0x15050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15050,
+ .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 = 0x1506c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1506c,
+ .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_mclk4_clk = {
+ .halt_reg = 0x15088,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15088,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk5_clk = {
+ .halt_reg = 0x150a4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk5_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk6_clk = {
+ .halt_reg = 0x150c0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk6_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk6_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk7_clk = {
+ .halt_reg = 0x150dc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150dc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk7_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk7_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_qdss_debug_clk = {
+ .halt_reg = 0x132b4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x132b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_qdss_debug_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_qdss_debug_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 = 0x132b8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x132b8,
+ .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_sbi_clk = {
+ .halt_reg = 0x100f8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100f8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sbi_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_sbi_fast_ahb_clk = {
+ .halt_reg = 0x10108,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10108,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sbi_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_sbi_shift_clk = {
+ .halt_reg = 0x1010c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1010c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sbi_shift_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_sfe_0_clk = {
+ .halt_reg = 0x13084,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13084,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_sfe_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_0_fast_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_sfe_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_0_shift_clk = {
+ .halt_reg = 0x130a0,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x130a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_0_shift_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_sfe_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_sfe_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_sfe_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_1_fast_ahb_clk = {
+ .halt_reg = 0x130ec,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x130ec,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_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_sfe_1_shift_clk = {
+ .halt_reg = 0x130f0,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x130f0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_1_shift_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_sfe_2_clk = {
+ .halt_reg = 0x13124,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13124,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_sfe_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_2_fast_ahb_clk = {
+ .halt_reg = 0x1313c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1313c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_2_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_2_shift_clk = {
+ .halt_reg = 0x13140,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x13140,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_2_shift_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_titan_top_shift_clk = {
+ .halt_reg = 0x1330c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1330c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_titan_top_shift_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 gdsc cam_cc_titan_top_gdsc = {
+ .gdscr = 0x132bc,
+ .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 gdsc cam_cc_bps_gdsc = {
+ .gdscr = 0x10004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_bps_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_ife_0_gdsc = {
+ .gdscr = 0x11004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_ife_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_ife_1_gdsc = {
+ .gdscr = 0x12004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_ife_1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_ife_2_gdsc = {
+ .gdscr = 0x12054,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_ife_2_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_ipe_0_gdsc = {
+ .gdscr = 0x10080,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_ipe_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_sbi_gdsc = {
+ .gdscr = 0x100e4,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_sbi_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_sfe_0_gdsc = {
+ .gdscr = 0x13058,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_sfe_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_sfe_1_gdsc = {
+ .gdscr = 0x130a8,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_sfe_1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_sfe_2_gdsc = {
+ .gdscr = 0x130f8,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_sfe_2_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *cam_cc_sm8650_clocks[] = {
+ [CAM_CC_BPS_AHB_CLK] = &cam_cc_bps_ahb_clk.clkr,
+ [CAM_CC_BPS_CLK] = &cam_cc_bps_clk.clkr,
+ [CAM_CC_BPS_CLK_SRC] = &cam_cc_bps_clk_src.clkr,
+ [CAM_CC_BPS_FAST_AHB_CLK] = &cam_cc_bps_fast_ahb_clk.clkr,
+ [CAM_CC_BPS_SHIFT_CLK] = &cam_cc_bps_shift_clk.clkr,
+ [CAM_CC_CAMNOC_AXI_NRT_CLK] = &cam_cc_camnoc_axi_nrt_clk.clkr,
+ [CAM_CC_CAMNOC_AXI_RT_CLK] = &cam_cc_camnoc_axi_rt_clk.clkr,
+ [CAM_CC_CAMNOC_AXI_RT_CLK_SRC] = &cam_cc_camnoc_axi_rt_clk_src.clkr,
+ [CAM_CC_CAMNOC_DCD_XO_CLK] = &cam_cc_camnoc_dcd_xo_clk.clkr,
+ [CAM_CC_CAMNOC_XO_CLK] = &cam_cc_camnoc_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_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr,
+ [CAM_CC_CPAS_AHB_CLK] = &cam_cc_cpas_ahb_clk.clkr,
+ [CAM_CC_CPAS_BPS_CLK] = &cam_cc_cpas_bps_clk.clkr,
+ [CAM_CC_CPAS_CRE_CLK] = &cam_cc_cpas_cre_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_2_CLK] = &cam_cc_cpas_ife_2_clk.clkr,
+ [CAM_CC_CPAS_IFE_LITE_CLK] = &cam_cc_cpas_ife_lite_clk.clkr,
+ [CAM_CC_CPAS_IPE_NPS_CLK] = &cam_cc_cpas_ipe_nps_clk.clkr,
+ [CAM_CC_CPAS_SBI_CLK] = &cam_cc_cpas_sbi_clk.clkr,
+ [CAM_CC_CPAS_SFE_0_CLK] = &cam_cc_cpas_sfe_0_clk.clkr,
+ [CAM_CC_CPAS_SFE_1_CLK] = &cam_cc_cpas_sfe_1_clk.clkr,
+ [CAM_CC_CPAS_SFE_2_CLK] = &cam_cc_cpas_sfe_2_clk.clkr,
+ [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr,
+ [CAM_CC_CRE_AHB_CLK] = &cam_cc_cre_ahb_clk.clkr,
+ [CAM_CC_CRE_CLK] = &cam_cc_cre_clk.clkr,
+ [CAM_CC_CRE_CLK_SRC] = &cam_cc_cre_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_CSI4PHYTIMER_CLK] = &cam_cc_csi4phytimer_clk.clkr,
+ [CAM_CC_CSI4PHYTIMER_CLK_SRC] = &cam_cc_csi4phytimer_clk_src.clkr,
+ [CAM_CC_CSI5PHYTIMER_CLK] = &cam_cc_csi5phytimer_clk.clkr,
+ [CAM_CC_CSI5PHYTIMER_CLK_SRC] = &cam_cc_csi5phytimer_clk_src.clkr,
+ [CAM_CC_CSI6PHYTIMER_CLK] = &cam_cc_csi6phytimer_clk.clkr,
+ [CAM_CC_CSI6PHYTIMER_CLK_SRC] = &cam_cc_csi6phytimer_clk_src.clkr,
+ [CAM_CC_CSI7PHYTIMER_CLK] = &cam_cc_csi7phytimer_clk.clkr,
+ [CAM_CC_CSI7PHYTIMER_CLK_SRC] = &cam_cc_csi7phytimer_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_CSIPHY4_CLK] = &cam_cc_csiphy4_clk.clkr,
+ [CAM_CC_CSIPHY5_CLK] = &cam_cc_csiphy5_clk.clkr,
+ [CAM_CC_CSIPHY6_CLK] = &cam_cc_csiphy6_clk.clkr,
+ [CAM_CC_CSIPHY7_CLK] = &cam_cc_csiphy7_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_0_SHIFT_CLK] = &cam_cc_ife_0_shift_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_1_SHIFT_CLK] = &cam_cc_ife_1_shift_clk.clkr,
+ [CAM_CC_IFE_2_CLK] = &cam_cc_ife_2_clk.clkr,
+ [CAM_CC_IFE_2_CLK_SRC] = &cam_cc_ife_2_clk_src.clkr,
+ [CAM_CC_IFE_2_FAST_AHB_CLK] = &cam_cc_ife_2_fast_ahb_clk.clkr,
+ [CAM_CC_IFE_2_SHIFT_CLK] = &cam_cc_ife_2_shift_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_NPS_AHB_CLK] = &cam_cc_ipe_nps_ahb_clk.clkr,
+ [CAM_CC_IPE_NPS_CLK] = &cam_cc_ipe_nps_clk.clkr,
+ [CAM_CC_IPE_NPS_CLK_SRC] = &cam_cc_ipe_nps_clk_src.clkr,
+ [CAM_CC_IPE_NPS_FAST_AHB_CLK] = &cam_cc_ipe_nps_fast_ahb_clk.clkr,
+ [CAM_CC_IPE_PPS_CLK] = &cam_cc_ipe_pps_clk.clkr,
+ [CAM_CC_IPE_PPS_FAST_AHB_CLK] = &cam_cc_ipe_pps_fast_ahb_clk.clkr,
+ [CAM_CC_IPE_SHIFT_CLK] = &cam_cc_ipe_shift_clk.clkr,
+ [CAM_CC_JPEG_1_CLK] = &cam_cc_jpeg_1_clk.clkr,
+ [CAM_CC_JPEG_CLK] = &cam_cc_jpeg_clk.clkr,
+ [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.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_MCLK4_CLK] = &cam_cc_mclk4_clk.clkr,
+ [CAM_CC_MCLK4_CLK_SRC] = &cam_cc_mclk4_clk_src.clkr,
+ [CAM_CC_MCLK5_CLK] = &cam_cc_mclk5_clk.clkr,
+ [CAM_CC_MCLK5_CLK_SRC] = &cam_cc_mclk5_clk_src.clkr,
+ [CAM_CC_MCLK6_CLK] = &cam_cc_mclk6_clk.clkr,
+ [CAM_CC_MCLK6_CLK_SRC] = &cam_cc_mclk6_clk_src.clkr,
+ [CAM_CC_MCLK7_CLK] = &cam_cc_mclk7_clk.clkr,
+ [CAM_CC_MCLK7_CLK_SRC] = &cam_cc_mclk7_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_PLL1] = &cam_cc_pll1.clkr,
+ [CAM_CC_PLL1_OUT_EVEN] = &cam_cc_pll1_out_even.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_PLL6] = &cam_cc_pll6.clkr,
+ [CAM_CC_PLL6_OUT_EVEN] = &cam_cc_pll6_out_even.clkr,
+ [CAM_CC_PLL7] = &cam_cc_pll7.clkr,
+ [CAM_CC_PLL7_OUT_EVEN] = &cam_cc_pll7_out_even.clkr,
+ [CAM_CC_PLL8] = &cam_cc_pll8.clkr,
+ [CAM_CC_PLL8_OUT_EVEN] = &cam_cc_pll8_out_even.clkr,
+ [CAM_CC_PLL9] = &cam_cc_pll9.clkr,
+ [CAM_CC_PLL9_OUT_EVEN] = &cam_cc_pll9_out_even.clkr,
+ [CAM_CC_PLL9_OUT_ODD] = &cam_cc_pll9_out_odd.clkr,
+ [CAM_CC_PLL10] = &cam_cc_pll10.clkr,
+ [CAM_CC_PLL10_OUT_EVEN] = &cam_cc_pll10_out_even.clkr,
+ [CAM_CC_QDSS_DEBUG_CLK] = &cam_cc_qdss_debug_clk.clkr,
+ [CAM_CC_QDSS_DEBUG_CLK_SRC] = &cam_cc_qdss_debug_clk_src.clkr,
+ [CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr,
+ [CAM_CC_SBI_CLK] = &cam_cc_sbi_clk.clkr,
+ [CAM_CC_SBI_FAST_AHB_CLK] = &cam_cc_sbi_fast_ahb_clk.clkr,
+ [CAM_CC_SBI_SHIFT_CLK] = &cam_cc_sbi_shift_clk.clkr,
+ [CAM_CC_SFE_0_CLK] = &cam_cc_sfe_0_clk.clkr,
+ [CAM_CC_SFE_0_CLK_SRC] = &cam_cc_sfe_0_clk_src.clkr,
+ [CAM_CC_SFE_0_FAST_AHB_CLK] = &cam_cc_sfe_0_fast_ahb_clk.clkr,
+ [CAM_CC_SFE_0_SHIFT_CLK] = &cam_cc_sfe_0_shift_clk.clkr,
+ [CAM_CC_SFE_1_CLK] = &cam_cc_sfe_1_clk.clkr,
+ [CAM_CC_SFE_1_CLK_SRC] = &cam_cc_sfe_1_clk_src.clkr,
+ [CAM_CC_SFE_1_FAST_AHB_CLK] = &cam_cc_sfe_1_fast_ahb_clk.clkr,
+ [CAM_CC_SFE_1_SHIFT_CLK] = &cam_cc_sfe_1_shift_clk.clkr,
+ [CAM_CC_SFE_2_CLK] = &cam_cc_sfe_2_clk.clkr,
+ [CAM_CC_SFE_2_CLK_SRC] = &cam_cc_sfe_2_clk_src.clkr,
+ [CAM_CC_SFE_2_FAST_AHB_CLK] = &cam_cc_sfe_2_fast_ahb_clk.clkr,
+ [CAM_CC_SFE_2_SHIFT_CLK] = &cam_cc_sfe_2_shift_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_TITAN_TOP_SHIFT_CLK] = &cam_cc_titan_top_shift_clk.clkr,
+ [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr,
+};
+
+static struct gdsc *cam_cc_sm8650_gdscs[] = {
+ [CAM_CC_TITAN_TOP_GDSC] = &cam_cc_titan_top_gdsc,
+ [CAM_CC_BPS_GDSC] = &cam_cc_bps_gdsc,
+ [CAM_CC_IFE_0_GDSC] = &cam_cc_ife_0_gdsc,
+ [CAM_CC_IFE_1_GDSC] = &cam_cc_ife_1_gdsc,
+ [CAM_CC_IFE_2_GDSC] = &cam_cc_ife_2_gdsc,
+ [CAM_CC_IPE_0_GDSC] = &cam_cc_ipe_0_gdsc,
+ [CAM_CC_SBI_GDSC] = &cam_cc_sbi_gdsc,
+ [CAM_CC_SFE_0_GDSC] = &cam_cc_sfe_0_gdsc,
+ [CAM_CC_SFE_1_GDSC] = &cam_cc_sfe_1_gdsc,
+ [CAM_CC_SFE_2_GDSC] = &cam_cc_sfe_2_gdsc,
+};
+
+static const struct qcom_reset_map cam_cc_sm8650_resets[] = {
+ [CAM_CC_BPS_BCR] = { 0x10000 },
+ [CAM_CC_DRV_BCR] = { 0x13310 },
+ [CAM_CC_ICP_BCR] = { 0x131a0 },
+ [CAM_CC_IFE_0_BCR] = { 0x11000 },
+ [CAM_CC_IFE_1_BCR] = { 0x12000 },
+ [CAM_CC_IFE_2_BCR] = { 0x12050 },
+ [CAM_CC_IPE_0_BCR] = { 0x1007c },
+ [CAM_CC_QDSS_DEBUG_BCR] = { 0x13298 },
+ [CAM_CC_SBI_BCR] = { 0x100e0 },
+ [CAM_CC_SFE_0_BCR] = { 0x13054 },
+ [CAM_CC_SFE_1_BCR] = { 0x130a4 },
+ [CAM_CC_SFE_2_BCR] = { 0x130f4 },
+};
+
+static const struct regmap_config cam_cc_sm8650_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1603c,
+ .fast_io = true,
+};
+
+static struct qcom_cc_desc cam_cc_sm8650_desc = {
+ .config = &cam_cc_sm8650_regmap_config,
+ .clks = cam_cc_sm8650_clocks,
+ .num_clks = ARRAY_SIZE(cam_cc_sm8650_clocks),
+ .resets = cam_cc_sm8650_resets,
+ .num_resets = ARRAY_SIZE(cam_cc_sm8650_resets),
+ .gdscs = cam_cc_sm8650_gdscs,
+ .num_gdscs = ARRAY_SIZE(cam_cc_sm8650_gdscs),
+};
+
+static const struct of_device_id cam_cc_sm8650_match_table[] = {
+ { .compatible = "qcom,sm8650-camcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cam_cc_sm8650_match_table);
+
+static int cam_cc_sm8650_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_sm8650_desc);
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
+ return PTR_ERR(regmap);
+ }
+
+ clk_lucid_ole_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config);
+ clk_lucid_ole_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_ole_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll5, regmap, &cam_cc_pll5_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll6, regmap, &cam_cc_pll6_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll7, regmap, &cam_cc_pll7_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll8, regmap, &cam_cc_pll8_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll9, regmap, &cam_cc_pll9_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll10, regmap, &cam_cc_pll10_config);
+
+ /* Keep clocks always enabled */
+ qcom_branch_set_clk_en(regmap, 0x13318); /* CAM_CC_DRV_AHB_CLK */
+ qcom_branch_set_clk_en(regmap, 0x13314); /* CAM_CC_DRV_XO_CLK */
+ qcom_branch_set_clk_en(regmap, 0x132ec); /* CAM_CC_GDSC_CLK */
+ qcom_branch_set_clk_en(regmap, 0x13308); /* CAM_CC_SLEEP_CLK */
+
+ ret = qcom_cc_really_probe(pdev, &cam_cc_sm8650_desc, regmap);
+
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
+}
+
+static struct platform_driver cam_cc_sm8650_driver = {
+ .probe = cam_cc_sm8650_probe,
+ .driver = {
+ .name = "camcc-sm8650",
+ .of_match_table = cam_cc_sm8650_match_table,
+ },
+};
+
+module_platform_driver(cam_cc_sm8650_driver);
+
+MODULE_DESCRIPTION("QTI CAMCC SM8650 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index d4227909d1fe..c51647e37df8 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -2574,6 +2574,9 @@ static int clk_alpha_pll_stromer_plus_set_rate(struct clk_hw *hw,
regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),
a >> ALPHA_BITWIDTH);
+ regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
+ PLL_ALPHA_EN, PLL_ALPHA_EN);
+
regmap_write(pll->clkr.regmap, PLL_MODE(pll), PLL_BYPASSNL);
/* Wait five micro seconds or more */
diff --git a/drivers/clk/qcom/gcc-ipq9574.c b/drivers/clk/qcom/gcc-ipq9574.c
index 0a3f846695b8..f8b9a1e93bef 100644
--- a/drivers/clk/qcom/gcc-ipq9574.c
+++ b/drivers/clk/qcom/gcc-ipq9574.c
@@ -2140,9 +2140,10 @@ static struct clk_rcg2 pcnoc_bfdcd_clk_src = {
static struct clk_branch gcc_crypto_axi_clk = {
.halt_reg = 0x16010,
+ .halt_check = BRANCH_HALT_VOTED,
.clkr = {
- .enable_reg = 0x16010,
- .enable_mask = BIT(0),
+ .enable_reg = 0xb004,
+ .enable_mask = BIT(15),
.hw.init = &(const struct clk_init_data) {
.name = "gcc_crypto_axi_clk",
.parent_hws = (const struct clk_hw *[]) {
@@ -2156,9 +2157,10 @@ static struct clk_branch gcc_crypto_axi_clk = {
static struct clk_branch gcc_crypto_ahb_clk = {
.halt_reg = 0x16014,
+ .halt_check = BRANCH_HALT_VOTED,
.clkr = {
- .enable_reg = 0x16014,
- .enable_mask = BIT(0),
+ .enable_reg = 0xb004,
+ .enable_mask = BIT(16),
.hw.init = &(const struct clk_init_data) {
.name = "gcc_crypto_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
diff --git a/drivers/clk/qcom/gcc-sm6350.c b/drivers/clk/qcom/gcc-sm6350.c
index cf4a7b6e0b23..0559a33faf00 100644
--- a/drivers/clk/qcom/gcc-sm6350.c
+++ b/drivers/clk/qcom/gcc-sm6350.c
@@ -100,8 +100,8 @@ static struct clk_alpha_pll gpll6 = {
.enable_mask = BIT(6),
.hw.init = &(struct clk_init_data){
.name = "gpll6",
- .parent_hws = (const struct clk_hw*[]){
- &gpll0.clkr.hw,
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_fixed_fabia_ops,
@@ -124,7 +124,7 @@ static struct clk_alpha_pll_postdiv gpll6_out_even = {
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll6_out_even",
.parent_hws = (const struct clk_hw*[]){
- &gpll0.clkr.hw,
+ &gpll6.clkr.hw,
},
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_fabia_ops,
@@ -139,8 +139,8 @@ static struct clk_alpha_pll gpll7 = {
.enable_mask = BIT(7),
.hw.init = &(struct clk_init_data){
.name = "gpll7",
- .parent_hws = (const struct clk_hw*[]){
- &gpll0.clkr.hw,
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_fixed_fabia_ops,
diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c
index df9618ab7eea..fa5fe4c2a2ee 100644
--- a/drivers/clk/qcom/gdsc.c
+++ b/drivers/clk/qcom/gdsc.c
@@ -363,6 +363,43 @@ static int gdsc_disable(struct generic_pm_domain *domain)
return 0;
}
+static int gdsc_set_hwmode(struct generic_pm_domain *domain, struct device *dev, bool mode)
+{
+ struct gdsc *sc = domain_to_gdsc(domain);
+ int ret;
+
+ ret = gdsc_hwctrl(sc, mode);
+ if (ret)
+ return ret;
+
+ /*
+ * Wait for the GDSC to go through a power down and
+ * up cycle. If we poll the status register before the
+ * power cycle is finished we might read incorrect values.
+ */
+ udelay(1);
+
+ /*
+ * When the GDSC is switched to HW mode, HW can disable the GDSC.
+ * When the GDSC is switched back to SW mode, the GDSC will be enabled
+ * again, hence we need to poll for GDSC to complete the power up.
+ */
+ if (!mode)
+ return gdsc_poll_status(sc, GDSC_ON);
+
+ return 0;
+}
+
+static bool gdsc_get_hwmode(struct generic_pm_domain *domain, struct device *dev)
+{
+ struct gdsc *sc = domain_to_gdsc(domain);
+ u32 val;
+
+ regmap_read(sc->regmap, sc->gdscr, &val);
+
+ return !!(val & HW_CONTROL_MASK);
+}
+
static int gdsc_init(struct gdsc *sc)
{
u32 mask, val;
@@ -451,6 +488,10 @@ static int gdsc_init(struct gdsc *sc)
sc->pd.power_off = gdsc_disable;
if (!sc->pd.power_on)
sc->pd.power_on = gdsc_enable;
+ if (sc->flags & HW_CTRL_TRIGGER) {
+ sc->pd.set_hwmode_dev = gdsc_set_hwmode;
+ sc->pd.get_hwmode_dev = gdsc_get_hwmode;
+ }
ret = pm_genpd_init(&sc->pd, NULL, !on);
if (ret)
diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h
index 803512688336..1e2779b823d1 100644
--- a/drivers/clk/qcom/gdsc.h
+++ b/drivers/clk/qcom/gdsc.h
@@ -67,6 +67,7 @@ struct gdsc {
#define ALWAYS_ON BIT(6)
#define RETAIN_FF_ENABLE BIT(7)
#define NO_RET_PERIPH BIT(8)
+#define HW_CTRL_TRIGGER BIT(9)
struct reset_controller_dev *rcdev;
unsigned int *resets;
unsigned int reset_count;
diff --git a/drivers/clk/qcom/videocc-sc7280.c b/drivers/clk/qcom/videocc-sc7280.c
index cdd59c6f60df..d55613a47ff7 100644
--- a/drivers/clk/qcom/videocc-sc7280.c
+++ b/drivers/clk/qcom/videocc-sc7280.c
@@ -236,7 +236,7 @@ static struct gdsc mvs0_gdsc = {
.name = "mvs0_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
- .flags = HW_CTRL | RETAIN_FF_ENABLE,
+ .flags = HW_CTRL_TRIGGER | RETAIN_FF_ENABLE,
};
static struct gdsc mvsc_gdsc = {
diff --git a/drivers/clk/qcom/videocc-sm8250.c b/drivers/clk/qcom/videocc-sm8250.c
index 016b596e03b3..cac10ccd362e 100644
--- a/drivers/clk/qcom/videocc-sm8250.c
+++ b/drivers/clk/qcom/videocc-sm8250.c
@@ -293,7 +293,7 @@ static struct gdsc mvs0_gdsc = {
.pd = {
.name = "mvs0_gdsc",
},
- .flags = HW_CTRL,
+ .flags = HW_CTRL_TRIGGER,
.pwrsts = PWRSTS_OFF_ON,
};
@@ -302,7 +302,7 @@ static struct gdsc mvs1_gdsc = {
.pd = {
.name = "mvs1_gdsc",
},
- .flags = HW_CTRL,
+ .flags = HW_CTRL_TRIGGER,
.pwrsts = PWRSTS_OFF_ON,
};
diff --git a/drivers/clk/qcom/videocc-sm8550.c b/drivers/clk/qcom/videocc-sm8550.c
index d73f747d2474..c601c35e6724 100644
--- a/drivers/clk/qcom/videocc-sm8550.c
+++ b/drivers/clk/qcom/videocc-sm8550.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/clk-provider.h>
@@ -10,7 +10,7 @@
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
-#include <dt-bindings/clock/qcom,sm8450-videocc.h>
+#include <dt-bindings/clock/qcom,sm8650-videocc.h>
#include "clk-alpha-pll.h"
#include "clk-branch.h"
@@ -35,7 +35,7 @@ static const struct pll_vco lucid_ole_vco[] = {
{ 249600000, 2300000000, 0 },
};
-static const struct alpha_pll_config video_cc_pll0_config = {
+static struct alpha_pll_config video_cc_pll0_config = {
.l = 0x25,
.alpha = 0x8000,
.config_ctl_val = 0x20485699,
@@ -66,7 +66,7 @@ static struct clk_alpha_pll video_cc_pll0 = {
},
};
-static const struct alpha_pll_config video_cc_pll1_config = {
+static struct alpha_pll_config video_cc_pll1_config = {
.l = 0x36,
.alpha = 0xb000,
.config_ctl_val = 0x20485699,
@@ -117,6 +117,14 @@ static const struct clk_parent_data video_cc_parent_data_1[] = {
{ .hw = &video_cc_pll1.clkr.hw },
};
+static const struct parent_map video_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+};
+
static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
@@ -126,6 +134,16 @@ static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
{ }
};
+static const struct freq_tbl ftbl_video_cc_mvs0_clk_src_sm8650[] = {
+ F(588000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(900000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1140000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1305000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1440000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1600000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
static struct clk_rcg2 video_cc_mvs0_clk_src = {
.cmd_rcgr = 0x8000,
.mnd_width = 0,
@@ -149,6 +167,15 @@ static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = {
{ }
};
+static const struct freq_tbl ftbl_video_cc_mvs1_clk_src_sm8650[] = {
+ F(840000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1110000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1350000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1500000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1650000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
static struct clk_rcg2 video_cc_mvs1_clk_src = {
.cmd_rcgr = 0x8018,
.mnd_width = 0,
@@ -164,6 +191,26 @@ static struct clk_rcg2 video_cc_mvs1_clk_src = {
},
};
+static const struct freq_tbl ftbl_video_cc_xo_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_xo_clk_src = {
+ .cmd_rcgr = 0x810c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_2,
+ .freq_tbl = ftbl_video_cc_xo_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_xo_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 struct clk_regmap_div video_cc_mvs0_div_clk_src = {
.reg = 0x80c4,
.shift = 0,
@@ -244,6 +291,26 @@ static struct clk_branch video_cc_mvs0_clk = {
},
};
+static struct clk_branch video_cc_mvs0_shift_clk = {
+ .halt_reg = 0x8128,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8128,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x8128,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_shift_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_mvs0c_clk = {
.halt_reg = 0x8064,
.halt_check = BRANCH_HALT,
@@ -262,6 +329,26 @@ static struct clk_branch video_cc_mvs0c_clk = {
},
};
+static struct clk_branch video_cc_mvs0c_shift_clk = {
+ .halt_reg = 0x812c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x812c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x812c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_shift_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_mvs1_clk = {
.halt_reg = 0x80e0,
.halt_check = BRANCH_HALT_SKIP,
@@ -282,6 +369,26 @@ static struct clk_branch video_cc_mvs1_clk = {
},
};
+static struct clk_branch video_cc_mvs1_shift_clk = {
+ .halt_reg = 0x8130,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8130,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x8130,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_shift_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_mvs1c_clk = {
.halt_reg = 0x8090,
.halt_check = BRANCH_HALT,
@@ -300,6 +407,26 @@ static struct clk_branch video_cc_mvs1c_clk = {
},
};
+static struct clk_branch video_cc_mvs1c_shift_clk = {
+ .halt_reg = 0x8134,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8134,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x8134,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1c_shift_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 gdsc video_cc_mvs0c_gdsc = {
.gdscr = 0x804c,
.en_rest_wait_val = 0x2,
@@ -363,6 +490,7 @@ static struct clk_regmap *video_cc_sm8550_clocks[] = {
[VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr,
[VIDEO_CC_PLL0] = &video_cc_pll0.clkr,
[VIDEO_CC_PLL1] = &video_cc_pll1.clkr,
+ [VIDEO_CC_XO_CLK_SRC] = NULL,
};
static struct gdsc *video_cc_sm8550_gdscs[] = {
@@ -380,6 +508,7 @@ static const struct qcom_reset_map video_cc_sm8550_resets[] = {
[CVP_VIDEO_CC_MVS1C_BCR] = { 0x8074 },
[VIDEO_CC_MVS0C_CLK_ARES] = { .reg = 0x8064, .bit = 2, .udelay = 1000 },
[VIDEO_CC_MVS1C_CLK_ARES] = { .reg = 0x8090, .bit = 2, .udelay = 1000 },
+ [VIDEO_CC_XO_CLK_ARES] = { .reg = 0x8124, .bit = 2, .udelay = 100 },
};
static const struct regmap_config video_cc_sm8550_regmap_config = {
@@ -402,6 +531,7 @@ static struct qcom_cc_desc video_cc_sm8550_desc = {
static const struct of_device_id video_cc_sm8550_match_table[] = {
{ .compatible = "qcom,sm8550-videocc" },
+ { .compatible = "qcom,sm8650-videocc" },
{ }
};
MODULE_DEVICE_TABLE(of, video_cc_sm8550_match_table);
@@ -410,6 +540,7 @@ static int video_cc_sm8550_probe(struct platform_device *pdev)
{
struct regmap *regmap;
int ret;
+ u32 sleep_clk_offset = 0x8140;
ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
@@ -425,12 +556,27 @@ static int video_cc_sm8550_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
}
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8650-videocc")) {
+ sleep_clk_offset = 0x8150;
+ video_cc_pll0_config.l = 0x1e;
+ video_cc_pll0_config.alpha = 0xa000;
+ video_cc_pll1_config.l = 0x2b;
+ video_cc_pll1_config.alpha = 0xc000;
+ video_cc_mvs0_clk_src.freq_tbl = ftbl_video_cc_mvs0_clk_src_sm8650;
+ video_cc_mvs1_clk_src.freq_tbl = ftbl_video_cc_mvs1_clk_src_sm8650;
+ video_cc_sm8550_clocks[VIDEO_CC_MVS0_SHIFT_CLK] = &video_cc_mvs0_shift_clk.clkr;
+ video_cc_sm8550_clocks[VIDEO_CC_MVS0C_SHIFT_CLK] = &video_cc_mvs0c_shift_clk.clkr;
+ video_cc_sm8550_clocks[VIDEO_CC_MVS1_SHIFT_CLK] = &video_cc_mvs1_shift_clk.clkr;
+ video_cc_sm8550_clocks[VIDEO_CC_MVS1C_SHIFT_CLK] = &video_cc_mvs1c_shift_clk.clkr;
+ video_cc_sm8550_clocks[VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr;
+ }
+
clk_lucid_ole_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config);
clk_lucid_ole_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config);
/* Keep some clocks always-on */
qcom_branch_set_clk_en(regmap, 0x80f4); /* VIDEO_CC_AHB_CLK */
- qcom_branch_set_clk_en(regmap, 0x8140); /* VIDEO_CC_SLEEP_CLK */
+ qcom_branch_set_clk_en(regmap, sleep_clk_offset); /* VIDEO_CC_SLEEP_CLK */
qcom_branch_set_clk_en(regmap, 0x8124); /* VIDEO_CC_XO_CLK */
ret = qcom_cc_really_probe(pdev, &video_cc_sm8550_desc, regmap);
diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
index ac0091b4ce24..be375ce0149c 100644
--- a/drivers/clk/sunxi-ng/ccu_common.c
+++ b/drivers/clk/sunxi-ng/ccu_common.c
@@ -132,7 +132,6 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
for (i = 0; i < desc->hw_clks->num ; i++) {
struct clk_hw *hw = desc->hw_clks->hws[i];
- struct ccu_common *common = hw_to_ccu_common(hw);
const char *name;
if (!hw)
@@ -147,14 +146,21 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
pr_err("Couldn't register clock %d - %s\n", i, name);
goto err_clk_unreg;
}
+ }
+
+ for (i = 0; i < desc->num_ccu_clks; i++) {
+ struct ccu_common *cclk = desc->ccu_clks[i];
+
+ if (!cclk)
+ continue;
- if (common->max_rate)
- clk_hw_set_rate_range(hw, common->min_rate,
- common->max_rate);
+ if (cclk->max_rate)
+ clk_hw_set_rate_range(&cclk->hw, cclk->min_rate,
+ cclk->max_rate);
else
- WARN(common->min_rate,
+ WARN(cclk->min_rate,
"No max_rate, ignoring min_rate of clock %d - %s\n",
- i, name);
+ i, clk_hw_get_name(&cclk->hw));
}
ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 34faa0320ece..95dd4660b5b6 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -134,6 +134,16 @@ config RDA_TIMER
help
Enables the support for the RDA Micro timer driver.
+config REALTEK_OTTO_TIMER
+ bool "Clocksource/timer for the Realtek Otto platform" if COMPILE_TEST
+ select TIMER_OF
+ help
+ This driver adds support for the timers found in the Realtek RTL83xx
+ and RTL93xx SoCs series. This includes chips such as RTL8380, RTL8381
+ and RTL832, as well as chips from the RTL839x series, such as RTL8390
+ RT8391, RTL8392, RTL8393 and RTL8396 and chips of the RTL930x series
+ such as RTL9301, RTL9302 or RTL9303.
+
config SUN4I_TIMER
bool "Sun4i timer driver" if COMPILE_TEST
depends on HAS_IOMEM
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 4bb856e4df55..22743785299e 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_MILBEAUT_TIMER) += timer-milbeaut.o
obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o
obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o
obj-$(CONFIG_RDA_TIMER) += timer-rda.o
+obj-$(CONFIG_REALTEK_OTTO_TIMER) += timer-rtl-otto.o
obj-$(CONFIG_ARC_TIMERS) += arc_timer.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 5bb43cc1a8df..aeafc74181f0 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1556,7 +1556,7 @@ static int __init
arch_timer_mem_frame_register(struct arch_timer_mem_frame *frame)
{
void __iomem *base;
- int ret, irq = 0;
+ int ret, irq;
if (arch_timer_mem_use_virtual)
irq = frame->virt_irq;
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index ab1c8c2b66b8..a05cfaab5f84 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -343,7 +343,7 @@ static int __init global_timer_of_register(struct device_node *np)
{
struct clk *gt_clk;
static unsigned long gt_clk_rate;
- int err = 0;
+ int err;
/*
* In A9 r2p0 the comparators for each processor with the global timer
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c
index b3ae38f36720..110347707ff9 100644
--- a/drivers/clocksource/mips-gic-timer.c
+++ b/drivers/clocksource/mips-gic-timer.c
@@ -19,6 +19,7 @@
static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device);
static int gic_timer_irq;
static unsigned int gic_frequency;
+static unsigned int gic_count_width;
static bool __read_mostly gic_clock_unstable;
static void gic_clocksource_unstable(char *reason);
@@ -186,18 +187,21 @@ static void gic_clocksource_unstable(char *reason)
static int __init __gic_clocksource_init(void)
{
- unsigned int count_width;
int ret;
/* Set clocksource mask. */
- count_width = read_gic_config() & GIC_CONFIG_COUNTBITS;
- count_width >>= __ffs(GIC_CONFIG_COUNTBITS);
- count_width *= 4;
- count_width += 32;
- gic_clocksource.mask = CLOCKSOURCE_MASK(count_width);
+ gic_count_width = read_gic_config() & GIC_CONFIG_COUNTBITS;
+ gic_count_width >>= __ffs(GIC_CONFIG_COUNTBITS);
+ gic_count_width *= 4;
+ gic_count_width += 32;
+ gic_clocksource.mask = CLOCKSOURCE_MASK(gic_count_width);
/* Calculate a somewhat reasonable rating value. */
- gic_clocksource.rating = 200 + gic_frequency / 10000000;
+ if (mips_cm_revision() >= CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ))
+ gic_clocksource.rating = 300; /* Good when frequecy is stable */
+ else
+ gic_clocksource.rating = 200;
+ gic_clocksource.rating += clamp(gic_frequency / 10000000, 0, 99);
ret = clocksource_register_hz(&gic_clocksource, gic_frequency);
if (ret < 0)
@@ -260,7 +264,7 @@ static int __init gic_clocksource_of_init(struct device_node *node)
if (mips_cm_revision() >= CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) {
sched_clock_register(mips_cm_is64 ?
gic_read_count_64 : gic_read_count_2x32,
- 64, gic_frequency);
+ gic_count_width, gic_frequency);
}
return 0;
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 26919556ef5f..b72b36e0abed 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -528,6 +528,7 @@ static void sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
{
struct sh_cmt_channel *ch = dev_id;
+ unsigned long flags;
/* clear flags */
sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) &
@@ -558,6 +559,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
ch->flags &= ~FLAG_SKIPEVENT;
+ raw_spin_lock_irqsave(&ch->lock, flags);
+
if (ch->flags & FLAG_REPROGRAM) {
ch->flags &= ~FLAG_REPROGRAM;
sh_cmt_clock_event_program_verify(ch, 1);
@@ -570,6 +573,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
ch->flags &= ~FLAG_IRQCONTEXT;
+ raw_spin_unlock_irqrestore(&ch->lock, flags);
+
return IRQ_HANDLED;
}
@@ -780,12 +785,18 @@ static int sh_cmt_clock_event_next(unsigned long delta,
struct clock_event_device *ced)
{
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
+ unsigned long flags;
BUG_ON(!clockevent_state_oneshot(ced));
+
+ raw_spin_lock_irqsave(&ch->lock, flags);
+
if (likely(ch->flags & FLAG_IRQCONTEXT))
ch->next_match_value = delta - 1;
else
- sh_cmt_set_next(ch, delta - 1);
+ __sh_cmt_set_next(ch, delta - 1);
+
+ raw_spin_unlock_irqrestore(&ch->lock, flags);
return 0;
}
diff --git a/drivers/clocksource/timer-rtl-otto.c b/drivers/clocksource/timer-rtl-otto.c
new file mode 100644
index 000000000000..8a3068b36e75
--- /dev/null
+++ b/drivers/clocksource/timer-rtl-otto.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/cpu.h>
+#include <linux/cpuhotplug.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/printk.h>
+#include <linux/sched_clock.h>
+#include "timer-of.h"
+
+#define RTTM_DATA 0x0
+#define RTTM_CNT 0x4
+#define RTTM_CTRL 0x8
+#define RTTM_INT 0xc
+
+#define RTTM_CTRL_ENABLE BIT(28)
+#define RTTM_INT_PENDING BIT(16)
+#define RTTM_INT_ENABLE BIT(20)
+
+/*
+ * The Otto platform provides multiple 28 bit timers/counters with the following
+ * operating logic. If enabled the timer counts up. Per timer one can set a
+ * maximum counter value as an end marker. If end marker is reached the timer
+ * fires an interrupt. If the timer "overflows" by reaching the end marker or
+ * by adding 1 to 0x0fffffff the counter is reset to 0. When this happens and
+ * the timer is in operating mode COUNTER it stops. In mode TIMER it will
+ * continue to count up.
+ */
+#define RTTM_CTRL_COUNTER 0
+#define RTTM_CTRL_TIMER BIT(24)
+
+#define RTTM_BIT_COUNT 28
+#define RTTM_MIN_DELTA 8
+#define RTTM_MAX_DELTA CLOCKSOURCE_MASK(28)
+
+/*
+ * Timers are derived from the LXB clock frequency. Usually this is a fixed
+ * multiple of the 25 MHz oscillator. The 930X SOC is an exception from that.
+ * Its LXB clock has only dividers and uses the switch PLL of 2.45 GHz as its
+ * base. The only meaningful frequencies we can achieve from that are 175.000
+ * MHz and 153.125 MHz. The greatest common divisor of all explained possible
+ * speeds is 3125000. Pin the timers to this 3.125 MHz reference frequency.
+ */
+#define RTTM_TICKS_PER_SEC 3125000
+
+struct rttm_cs {
+ struct timer_of to;
+ struct clocksource cs;
+};
+
+/* Simple internal register functions */
+static inline void rttm_set_counter(void __iomem *base, unsigned int counter)
+{
+ iowrite32(counter, base + RTTM_CNT);
+}
+
+static inline unsigned int rttm_get_counter(void __iomem *base)
+{
+ return ioread32(base + RTTM_CNT);
+}
+
+static inline void rttm_set_period(void __iomem *base, unsigned int period)
+{
+ iowrite32(period, base + RTTM_DATA);
+}
+
+static inline void rttm_disable_timer(void __iomem *base)
+{
+ iowrite32(0, base + RTTM_CTRL);
+}
+
+static inline void rttm_enable_timer(void __iomem *base, u32 mode, u32 divisor)
+{
+ iowrite32(RTTM_CTRL_ENABLE | mode | divisor, base + RTTM_CTRL);
+}
+
+static inline void rttm_ack_irq(void __iomem *base)
+{
+ iowrite32(ioread32(base + RTTM_INT) | RTTM_INT_PENDING, base + RTTM_INT);
+}
+
+static inline void rttm_enable_irq(void __iomem *base)
+{
+ iowrite32(RTTM_INT_ENABLE, base + RTTM_INT);
+}
+
+static inline void rttm_disable_irq(void __iomem *base)
+{
+ iowrite32(0, base + RTTM_INT);
+}
+
+/* Aggregated control functions for kernel clock framework */
+#define RTTM_DEBUG(base) \
+ pr_debug("------------- %d %p\n", \
+ smp_processor_id(), base)
+
+static irqreturn_t rttm_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *clkevt = dev_id;
+ struct timer_of *to = to_timer_of(clkevt);
+
+ rttm_ack_irq(to->of_base.base);
+ RTTM_DEBUG(to->of_base.base);
+ clkevt->event_handler(clkevt);
+
+ return IRQ_HANDLED;
+}
+
+static void rttm_stop_timer(void __iomem *base)
+{
+ rttm_disable_timer(base);
+ rttm_ack_irq(base);
+}
+
+static void rttm_start_timer(struct timer_of *to, u32 mode)
+{
+ rttm_set_counter(to->of_base.base, 0);
+ rttm_enable_timer(to->of_base.base, mode, to->of_clk.rate / RTTM_TICKS_PER_SEC);
+}
+
+static int rttm_next_event(unsigned long delta, struct clock_event_device *clkevt)
+{
+ struct timer_of *to = to_timer_of(clkevt);
+
+ RTTM_DEBUG(to->of_base.base);
+ rttm_stop_timer(to->of_base.base);
+ rttm_set_period(to->of_base.base, delta);
+ rttm_start_timer(to, RTTM_CTRL_COUNTER);
+
+ return 0;
+}
+
+static int rttm_state_oneshot(struct clock_event_device *clkevt)
+{
+ struct timer_of *to = to_timer_of(clkevt);
+
+ RTTM_DEBUG(to->of_base.base);
+ rttm_stop_timer(to->of_base.base);
+ rttm_set_period(to->of_base.base, RTTM_TICKS_PER_SEC / HZ);
+ rttm_start_timer(to, RTTM_CTRL_COUNTER);
+
+ return 0;
+}
+
+static int rttm_state_periodic(struct clock_event_device *clkevt)
+{
+ struct timer_of *to = to_timer_of(clkevt);
+
+ RTTM_DEBUG(to->of_base.base);
+ rttm_stop_timer(to->of_base.base);
+ rttm_set_period(to->of_base.base, RTTM_TICKS_PER_SEC / HZ);
+ rttm_start_timer(to, RTTM_CTRL_TIMER);
+
+ return 0;
+}
+
+static int rttm_state_shutdown(struct clock_event_device *clkevt)
+{
+ struct timer_of *to = to_timer_of(clkevt);
+
+ RTTM_DEBUG(to->of_base.base);
+ rttm_stop_timer(to->of_base.base);
+
+ return 0;
+}
+
+static void rttm_setup_timer(void __iomem *base)
+{
+ RTTM_DEBUG(base);
+ rttm_stop_timer(base);
+ rttm_set_period(base, 0);
+}
+
+static u64 rttm_read_clocksource(struct clocksource *cs)
+{
+ struct rttm_cs *rcs = container_of(cs, struct rttm_cs, cs);
+
+ return rttm_get_counter(rcs->to.of_base.base);
+}
+
+/* Module initialization part. */
+static DEFINE_PER_CPU(struct timer_of, rttm_to) = {
+ .flags = TIMER_OF_BASE | TIMER_OF_CLOCK | TIMER_OF_IRQ,
+ .of_irq = {
+ .flags = IRQF_PERCPU | IRQF_TIMER,
+ .handler = rttm_timer_interrupt,
+ },
+ .clkevt = {
+ .rating = 400,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_state_periodic = rttm_state_periodic,
+ .set_state_shutdown = rttm_state_shutdown,
+ .set_state_oneshot = rttm_state_oneshot,
+ .set_next_event = rttm_next_event
+ },
+};
+
+static int rttm_enable_clocksource(struct clocksource *cs)
+{
+ struct rttm_cs *rcs = container_of(cs, struct rttm_cs, cs);
+
+ rttm_disable_irq(rcs->to.of_base.base);
+ rttm_setup_timer(rcs->to.of_base.base);
+ rttm_enable_timer(rcs->to.of_base.base, RTTM_CTRL_TIMER,
+ rcs->to.of_clk.rate / RTTM_TICKS_PER_SEC);
+
+ return 0;
+}
+
+struct rttm_cs rttm_cs = {
+ .to = {
+ .flags = TIMER_OF_BASE | TIMER_OF_CLOCK,
+ },
+ .cs = {
+ .name = "realtek_otto_timer",
+ .rating = 400,
+ .mask = CLOCKSOURCE_MASK(RTTM_BIT_COUNT),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .read = rttm_read_clocksource,
+ }
+};
+
+static u64 notrace rttm_read_clock(void)
+{
+ return rttm_get_counter(rttm_cs.to.of_base.base);
+}
+
+static int rttm_cpu_starting(unsigned int cpu)
+{
+ struct timer_of *to = per_cpu_ptr(&rttm_to, cpu);
+
+ RTTM_DEBUG(to->of_base.base);
+ to->clkevt.cpumask = cpumask_of(cpu);
+ irq_force_affinity(to->of_irq.irq, to->clkevt.cpumask);
+ clockevents_config_and_register(&to->clkevt, RTTM_TICKS_PER_SEC,
+ RTTM_MIN_DELTA, RTTM_MAX_DELTA);
+ rttm_enable_irq(to->of_base.base);
+
+ return 0;
+}
+
+static int __init rttm_probe(struct device_node *np)
+{
+ unsigned int cpu, cpu_rollback;
+ struct timer_of *to;
+ unsigned int clkidx = num_possible_cpus();
+
+ /* Use the first n timers as per CPU clock event generators */
+ for_each_possible_cpu(cpu) {
+ to = per_cpu_ptr(&rttm_to, cpu);
+ to->of_irq.index = to->of_base.index = cpu;
+ if (timer_of_init(np, to)) {
+ pr_err("setup of timer %d failed\n", cpu);
+ goto rollback;
+ }
+ rttm_setup_timer(to->of_base.base);
+ }
+
+ /* Activate the n'th + 1 timer as a stable CPU clocksource. */
+ to = &rttm_cs.to;
+ to->of_base.index = clkidx;
+ timer_of_init(np, to);
+ if (rttm_cs.to.of_base.base && rttm_cs.to.of_clk.rate) {
+ rttm_enable_clocksource(&rttm_cs.cs);
+ clocksource_register_hz(&rttm_cs.cs, RTTM_TICKS_PER_SEC);
+ sched_clock_register(rttm_read_clock, RTTM_BIT_COUNT, RTTM_TICKS_PER_SEC);
+ } else
+ pr_err(" setup of timer %d as clocksource failed", clkidx);
+
+ return cpuhp_setup_state(CPUHP_AP_REALTEK_TIMER_STARTING,
+ "timer/realtek:online",
+ rttm_cpu_starting, NULL);
+rollback:
+ pr_err("timer registration failed\n");
+ for_each_possible_cpu(cpu_rollback) {
+ if (cpu_rollback == cpu)
+ break;
+ to = per_cpu_ptr(&rttm_to, cpu_rollback);
+ timer_of_cleanup(to);
+ }
+
+ return -EINVAL;
+}
+
+TIMER_OF_DECLARE(otto_timer, "realtek,otto-timer", rttm_probe);
diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
index 0664ef969f79..186e73d6ccb4 100644
--- a/drivers/counter/stm32-timer-cnt.c
+++ b/drivers/counter/stm32-timer-cnt.c
@@ -465,7 +465,7 @@ static int stm32_count_events_configure(struct counter_device *counter)
ret = stm32_count_capture_configure(counter, event_node->channel, true);
if (ret)
return ret;
- dier |= TIM_DIER_CC_IE(event_node->channel);
+ dier |= TIM_DIER_CCxIE(event_node->channel + 1);
break;
default:
/* should never reach this path */
@@ -478,7 +478,7 @@ static int stm32_count_events_configure(struct counter_device *counter)
/* check for disabled capture events */
for (i = 0 ; i < priv->nchannels; i++) {
- if (!(dier & TIM_DIER_CC_IE(i))) {
+ if (!(dier & TIM_DIER_CCxIE(i + 1))) {
ret = stm32_count_capture_configure(counter, i, false);
if (ret)
return ret;
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 37f1cdf46d29..4ac3a35dcd98 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -890,8 +890,10 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
if (perf->states[0].core_frequency * 1000 != freq_table[0].frequency)
pr_warn(FW_WARN "P-state 0 is not max freq\n");
- if (acpi_cpufreq_driver.set_boost)
+ if (acpi_cpufreq_driver.set_boost) {
set_boost(policy, acpi_cpufreq_driver.boost_enabled);
+ policy->boost_enabled = acpi_cpufreq_driver.boost_enabled;
+ }
return result;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a45aac17c20f..9e5060b27864 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1431,7 +1431,8 @@ static int cpufreq_online(unsigned int cpu)
}
/* Let the per-policy boost flag mirror the cpufreq_driver boost during init */
- policy->boost_enabled = cpufreq_boost_enabled() && policy_has_boost_freq(policy);
+ if (cpufreq_boost_enabled() && policy_has_boost_freq(policy))
+ policy->boost_enabled = true;
/*
* The initialization has succeeded and the policy is online.
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index ea05d9d67490..0a46b5d49d32 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -191,6 +191,7 @@ static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
case QCOM_ID_IPQ5312:
case QCOM_ID_IPQ5302:
case QCOM_ID_IPQ5300:
+ case QCOM_ID_IPQ5321:
case QCOM_ID_IPQ9514:
case QCOM_ID_IPQ9550:
case QCOM_ID_IPQ9554:
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index 784843fa2a22..3df10517a327 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -52,6 +52,14 @@ int devm_cxl_add_passthrough_decoder(struct cxl_port *port)
struct cxl_dport *dport = NULL;
int single_port_map[1];
unsigned long index;
+ struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev);
+
+ /*
+ * Capability checks are moot for passthrough decoders, support
+ * any and all possibilities.
+ */
+ cxlhdm->interleave_mask = ~0U;
+ cxlhdm->iw_cap_mask = ~0UL;
cxlsd = cxl_switch_decoder_alloc(port, 1);
if (IS_ERR(cxlsd))
@@ -79,6 +87,11 @@ static void parse_hdm_decoder_caps(struct cxl_hdm *cxlhdm)
cxlhdm->interleave_mask |= GENMASK(11, 8);
if (FIELD_GET(CXL_HDM_DECODER_INTERLEAVE_14_12, hdm_cap))
cxlhdm->interleave_mask |= GENMASK(14, 12);
+ cxlhdm->iw_cap_mask = BIT(1) | BIT(2) | BIT(4) | BIT(8);
+ if (FIELD_GET(CXL_HDM_DECODER_INTERLEAVE_3_6_12_WAY, hdm_cap))
+ cxlhdm->iw_cap_mask |= BIT(3) | BIT(6) | BIT(12);
+ if (FIELD_GET(CXL_HDM_DECODER_INTERLEAVE_16_WAY, hdm_cap))
+ cxlhdm->iw_cap_mask |= BIT(16);
}
static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c
index e69625a8d6a1..c00f3a933164 100644
--- a/drivers/cxl/core/pmem.c
+++ b/drivers/cxl/core/pmem.c
@@ -62,10 +62,14 @@ static int match_nvdimm_bridge(struct device *dev, void *data)
return is_cxl_nvdimm_bridge(dev);
}
-struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_memdev *cxlmd)
+/**
+ * cxl_find_nvdimm_bridge() - find a bridge device relative to a port
+ * @port: any descendant port of an nvdimm-bridge associated
+ * root-cxl-port
+ */
+struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_port *port)
{
- struct cxl_root *cxl_root __free(put_cxl_root) =
- find_cxl_root(cxlmd->endpoint);
+ struct cxl_root *cxl_root __free(put_cxl_root) = find_cxl_root(port);
struct device *dev;
if (!cxl_root)
@@ -242,18 +246,20 @@ static void cxlmd_release_nvdimm(void *_cxlmd)
/**
* devm_cxl_add_nvdimm() - add a bridge between a cxl_memdev and an nvdimm
+ * @parent_port: parent port for the (to be added) @cxlmd endpoint port
* @cxlmd: cxl_memdev instance that will perform LIBNVDIMM operations
*
* Return: 0 on success negative error code on failure.
*/
-int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd)
+int devm_cxl_add_nvdimm(struct cxl_port *parent_port,
+ struct cxl_memdev *cxlmd)
{
struct cxl_nvdimm_bridge *cxl_nvb;
struct cxl_nvdimm *cxl_nvd;
struct device *dev;
int rc;
- cxl_nvb = cxl_find_nvdimm_bridge(cxlmd);
+ cxl_nvb = cxl_find_nvdimm_bridge(parent_port);
if (!cxl_nvb)
return -ENODEV;
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 3c2b6144be23..538ebd5a64fd 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -1101,6 +1101,26 @@ static int cxl_port_attach_region(struct cxl_port *port,
}
cxld = cxl_rr->decoder;
+ /*
+ * the number of targets should not exceed the target_count
+ * of the decoder
+ */
+ if (is_switch_decoder(&cxld->dev)) {
+ struct cxl_switch_decoder *cxlsd;
+
+ cxlsd = to_cxl_switch_decoder(&cxld->dev);
+ if (cxl_rr->nr_targets > cxlsd->nr_targets) {
+ dev_dbg(&cxlr->dev,
+ "%s:%s %s add: %s:%s @ %d overflows targets: %d\n",
+ dev_name(port->uport_dev), dev_name(&port->dev),
+ dev_name(&cxld->dev), dev_name(&cxlmd->dev),
+ dev_name(&cxled->cxld.dev), pos,
+ cxlsd->nr_targets);
+ rc = -ENXIO;
+ goto out_erase;
+ }
+ }
+
rc = cxl_rr_ep_add(cxl_rr, cxled);
if (rc) {
dev_dbg(&cxlr->dev,
@@ -1210,6 +1230,50 @@ static int check_last_peer(struct cxl_endpoint_decoder *cxled,
return 0;
}
+static int check_interleave_cap(struct cxl_decoder *cxld, int iw, int ig)
+{
+ struct cxl_port *port = to_cxl_port(cxld->dev.parent);
+ struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev);
+ unsigned int interleave_mask;
+ u8 eiw;
+ u16 eig;
+ int high_pos, low_pos;
+
+ if (!test_bit(iw, &cxlhdm->iw_cap_mask))
+ return -ENXIO;
+ /*
+ * Per CXL specification r3.1(8.2.4.20.13 Decoder Protection),
+ * if eiw < 8:
+ * DPAOFFSET[51: eig + 8] = HPAOFFSET[51: eig + 8 + eiw]
+ * DPAOFFSET[eig + 7: 0] = HPAOFFSET[eig + 7: 0]
+ *
+ * when the eiw is 0, all the bits of HPAOFFSET[51: 0] are used, the
+ * interleave bits are none.
+ *
+ * if eiw >= 8:
+ * DPAOFFSET[51: eig + 8] = HPAOFFSET[51: eig + eiw] / 3
+ * DPAOFFSET[eig + 7: 0] = HPAOFFSET[eig + 7: 0]
+ *
+ * when the eiw is 8, all the bits of HPAOFFSET[51: 0] are used, the
+ * interleave bits are none.
+ */
+ ways_to_eiw(iw, &eiw);
+ if (eiw == 0 || eiw == 8)
+ return 0;
+
+ granularity_to_eig(ig, &eig);
+ if (eiw > 8)
+ high_pos = eiw + eig - 1;
+ else
+ high_pos = eiw + eig + 7;
+ low_pos = eig + 8;
+ interleave_mask = GENMASK(high_pos, low_pos);
+ if (interleave_mask & ~cxlhdm->interleave_mask)
+ return -ENXIO;
+
+ return 0;
+}
+
static int cxl_port_setup_targets(struct cxl_port *port,
struct cxl_region *cxlr,
struct cxl_endpoint_decoder *cxled)
@@ -1360,6 +1424,15 @@ static int cxl_port_setup_targets(struct cxl_port *port,
return -ENXIO;
}
} else {
+ rc = check_interleave_cap(cxld, iw, ig);
+ if (rc) {
+ dev_dbg(&cxlr->dev,
+ "%s:%s iw: %d ig: %d is not supported\n",
+ dev_name(port->uport_dev),
+ dev_name(&port->dev), iw, ig);
+ return rc;
+ }
+
cxld->interleave_ways = iw;
cxld->interleave_granularity = ig;
cxld->hpa_range = (struct range) {
@@ -1796,6 +1869,15 @@ static int cxl_region_attach(struct cxl_region *cxlr,
struct cxl_dport *dport;
int rc = -ENXIO;
+ rc = check_interleave_cap(&cxled->cxld, p->interleave_ways,
+ p->interleave_granularity);
+ if (rc) {
+ dev_dbg(&cxlr->dev, "%s iw: %d ig: %d is not supported\n",
+ dev_name(&cxled->cxld.dev), p->interleave_ways,
+ p->interleave_granularity);
+ return rc;
+ }
+
if (cxled->mode != cxlr->mode) {
dev_dbg(&cxlr->dev, "%s region mode: %d mismatch: %d\n",
dev_name(&cxled->cxld.dev), cxlr->mode, cxled->mode);
@@ -2688,22 +2770,33 @@ static int __cxl_dpa_to_region(struct device *dev, void *arg)
{
struct cxl_dpa_to_region_context *ctx = arg;
struct cxl_endpoint_decoder *cxled;
+ struct cxl_region *cxlr;
u64 dpa = ctx->dpa;
if (!is_endpoint_decoder(dev))
return 0;
cxled = to_cxl_endpoint_decoder(dev);
- if (!cxled->dpa_res || !resource_size(cxled->dpa_res))
+ if (!cxled || !cxled->dpa_res || !resource_size(cxled->dpa_res))
return 0;
if (dpa > cxled->dpa_res->end || dpa < cxled->dpa_res->start)
return 0;
- dev_dbg(dev, "dpa:0x%llx mapped in region:%s\n", dpa,
- dev_name(&cxled->cxld.region->dev));
+ /*
+ * Stop the region search (return 1) when an endpoint mapping is
+ * found. The region may not be fully constructed so offering
+ * the cxlr in the context structure is not guaranteed.
+ */
+ cxlr = cxled->cxld.region;
+ if (cxlr)
+ dev_dbg(dev, "dpa:0x%llx mapped in region:%s\n", dpa,
+ dev_name(&cxlr->dev));
+ else
+ dev_dbg(dev, "dpa:0x%llx mapped in endpoint:%s\n", dpa,
+ dev_name(dev));
- ctx->cxlr = cxled->cxld.region;
+ ctx->cxlr = cxlr;
return 1;
}
@@ -2847,7 +2940,7 @@ static int cxl_pmem_region_alloc(struct cxl_region *cxlr)
* bridge for one device is the same for all.
*/
if (i == 0) {
- cxl_nvb = cxl_find_nvdimm_bridge(cxlmd);
+ cxl_nvb = cxl_find_nvdimm_bridge(cxlmd->endpoint);
if (!cxl_nvb)
return -ENODEV;
cxlr->cxl_nvb = cxl_nvb;
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 603c0120cff8..a6613a6f8923 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -47,6 +47,8 @@ extern const struct nvdimm_security_ops *cxl_security_ops;
#define CXL_HDM_DECODER_TARGET_COUNT_MASK GENMASK(7, 4)
#define CXL_HDM_DECODER_INTERLEAVE_11_8 BIT(8)
#define CXL_HDM_DECODER_INTERLEAVE_14_12 BIT(9)
+#define CXL_HDM_DECODER_INTERLEAVE_3_6_12_WAY BIT(11)
+#define CXL_HDM_DECODER_INTERLEAVE_16_WAY BIT(12)
#define CXL_HDM_DECODER_CTRL_OFFSET 0x4
#define CXL_HDM_DECODER_ENABLE BIT(1)
#define CXL_HDM_DECODER0_BASE_LOW_OFFSET(i) (0x20 * (i) + 0x10)
@@ -855,8 +857,8 @@ struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev);
bool is_cxl_nvdimm(struct device *dev);
bool is_cxl_nvdimm_bridge(struct device *dev);
-int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd);
-struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_memdev *cxlmd);
+int devm_cxl_add_nvdimm(struct cxl_port *parent_port, struct cxl_memdev *cxlmd);
+struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_port *port);
#ifdef CONFIG_CXL_REGION
bool is_cxl_pmem_region(struct device *dev);
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 19aba81cdf13..af8169ccdbc0 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -395,9 +395,9 @@ enum cxl_devtype {
/**
* struct cxl_dpa_perf - DPA performance property entry
- * @dpa_range - range for DPA address
- * @coord - QoS performance data (i.e. latency, bandwidth)
- * @qos_class - QoS Class cookies
+ * @dpa_range: range for DPA address
+ * @coord: QoS performance data (i.e. latency, bandwidth)
+ * @qos_class: QoS Class cookies
*/
struct cxl_dpa_perf {
struct range dpa_range;
@@ -464,13 +464,14 @@ struct cxl_dev_state {
* @active_persistent_bytes: sum of hard + soft persistent
* @next_volatile_bytes: volatile capacity change pending device reset
* @next_persistent_bytes: persistent capacity change pending device reset
+ * @ram_perf: performance data entry matched to RAM partition
+ * @pmem_perf: performance data entry matched to PMEM partition
* @event: event log driver state
* @poison: poison driver state info
* @security: security driver state info
* @fw: firmware upload / activation state
+ * @mbox_wait: RCU wait for mbox send completely
* @mbox_send: @dev specific transport for transmitting mailbox commands
- * @ram_perf: performance data entry matched to RAM partition
- * @pmem_perf: performance data entry matched to PMEM partition
*
* See CXL 3.0 8.2.9.8.2 Capacity Configuration and Label Storage for
* details on capacity parameters.
@@ -851,11 +852,21 @@ static inline void cxl_mem_active_dec(void)
int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd);
+/**
+ * struct cxl_hdm - HDM Decoder registers and cached / decoded capabilities
+ * @regs: mapped registers, see devm_cxl_setup_hdm()
+ * @decoder_count: number of decoders for this port
+ * @target_count: for switch decoders, max downstream port targets
+ * @interleave_mask: interleave granularity capability, see check_interleave_cap()
+ * @iw_cap_mask: bitmask of supported interleave ways, see check_interleave_cap()
+ * @port: mapped cxl_port, see devm_cxl_setup_hdm()
+ */
struct cxl_hdm {
struct cxl_component_regs regs;
unsigned int decoder_count;
unsigned int target_count;
unsigned int interleave_mask;
+ unsigned long iw_cap_mask;
struct cxl_port *port;
};
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 0c79d9ce877c..2f1b49bfe162 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -152,6 +152,15 @@ static int cxl_mem_probe(struct device *dev)
return -ENXIO;
}
+ if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM)) {
+ rc = devm_cxl_add_nvdimm(parent_port, cxlmd);
+ if (rc) {
+ if (rc == -ENODEV)
+ dev_info(dev, "PMEM disabled by platform\n");
+ return rc;
+ }
+ }
+
if (dport->rch)
endpoint_parent = parent_port->uport_dev;
else
@@ -174,14 +183,6 @@ unlock:
if (rc)
return rc;
- if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM)) {
- rc = devm_cxl_add_nvdimm(cxlmd);
- if (rc == -ENODEV)
- dev_info(dev, "PMEM disabled by platform\n");
- else
- return rc;
- }
-
/*
* The kernel may be operating out of CXL memory on this device,
* there is no spec defined way to determine whether this device
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 9c09893695b7..4edfb83ffbee 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -54,11 +54,13 @@ obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac_mod.o
layerscape_edac_mod-y := fsl_ddr_edac.o layerscape_edac.o
obj-$(CONFIG_EDAC_LAYERSCAPE) += layerscape_edac_mod.o
-skx_edac-y := skx_common.o skx_base.o
-obj-$(CONFIG_EDAC_SKX) += skx_edac.o
+skx_edac_common-y := skx_common.o
-i10nm_edac-y := skx_common.o i10nm_base.o
-obj-$(CONFIG_EDAC_I10NM) += i10nm_edac.o
+skx_edac-y := skx_base.o
+obj-$(CONFIG_EDAC_SKX) += skx_edac.o skx_edac_common.o
+
+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_PPC4XX) += ppc4xx_edac.o
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index a17f3c0cdfa6..ddfbdb66b794 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -20,7 +20,6 @@ static inline u32 get_umc_reg(struct amd64_pvt *pvt, u32 reg)
return reg;
switch (reg) {
- case UMCCH_ADDR_CFG: return UMCCH_ADDR_CFG_DDR5;
case UMCCH_ADDR_MASK_SEC: return UMCCH_ADDR_MASK_SEC_DDR5;
case UMCCH_DIMM_CFG: return UMCCH_DIMM_CFG_DDR5;
}
@@ -1341,22 +1340,15 @@ static void umc_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
static void umc_dump_misc_regs(struct amd64_pvt *pvt)
{
struct amd64_umc *umc;
- u32 i, tmp, umc_base;
+ u32 i;
for_each_umc(i) {
- umc_base = get_umc_base(i);
umc = &pvt->umc[i];
edac_dbg(1, "UMC%d DIMM cfg: 0x%x\n", i, umc->dimm_cfg);
edac_dbg(1, "UMC%d UMC cfg: 0x%x\n", i, umc->umc_cfg);
edac_dbg(1, "UMC%d SDP ctrl: 0x%x\n", i, umc->sdp_ctrl);
edac_dbg(1, "UMC%d ECC ctrl: 0x%x\n", i, umc->ecc_ctrl);
-
- amd_smn_read(pvt->mc_node_id, umc_base + UMCCH_ECC_BAD_SYMBOL, &tmp);
- edac_dbg(1, "UMC%d ECC bad symbol: 0x%x\n", i, tmp);
-
- amd_smn_read(pvt->mc_node_id, umc_base + UMCCH_UMC_CAP, &tmp);
- edac_dbg(1, "UMC%d UMC cap: 0x%x\n", i, tmp);
edac_dbg(1, "UMC%d UMC cap high: 0x%x\n", i, umc->umc_cap_hi);
edac_dbg(1, "UMC%d ECC capable: %s, ChipKill ECC capable: %s\n",
@@ -1369,14 +1361,6 @@ static void umc_dump_misc_regs(struct amd64_pvt *pvt)
edac_dbg(1, "UMC%d x16 DIMMs present: %s\n",
i, (umc->dimm_cfg & BIT(7)) ? "yes" : "no");
- if (umc->dram_type == MEM_LRDDR4 || umc->dram_type == MEM_LRDDR5) {
- amd_smn_read(pvt->mc_node_id,
- umc_base + get_umc_reg(pvt, UMCCH_ADDR_CFG),
- &tmp);
- edac_dbg(1, "UMC%d LRDIMM %dx rank multiply\n",
- i, 1 << ((tmp >> 4) & 0x3));
- }
-
umc_debug_display_dimm_sizes(pvt, i);
}
}
@@ -1454,6 +1438,7 @@ static void umc_read_base_mask(struct amd64_pvt *pvt)
u32 *base, *base_sec;
u32 *mask, *mask_sec;
int cs, umc;
+ u32 tmp;
for_each_umc(umc) {
umc_base_reg = get_umc_base(umc) + UMCCH_BASE_ADDR;
@@ -1466,13 +1451,17 @@ static void umc_read_base_mask(struct amd64_pvt *pvt)
base_reg = umc_base_reg + (cs * 4);
base_reg_sec = umc_base_reg_sec + (cs * 4);
- if (!amd_smn_read(pvt->mc_node_id, base_reg, base))
+ if (!amd_smn_read(pvt->mc_node_id, base_reg, &tmp)) {
+ *base = tmp;
edac_dbg(0, " DCSB%d[%d]=0x%08x reg: 0x%x\n",
umc, cs, *base, base_reg);
+ }
- if (!amd_smn_read(pvt->mc_node_id, base_reg_sec, base_sec))
+ if (!amd_smn_read(pvt->mc_node_id, base_reg_sec, &tmp)) {
+ *base_sec = tmp;
edac_dbg(0, " DCSB_SEC%d[%d]=0x%08x reg: 0x%x\n",
umc, cs, *base_sec, base_reg_sec);
+ }
}
umc_mask_reg = get_umc_base(umc) + UMCCH_ADDR_MASK;
@@ -1485,13 +1474,17 @@ static void umc_read_base_mask(struct amd64_pvt *pvt)
mask_reg = umc_mask_reg + (cs * 4);
mask_reg_sec = umc_mask_reg_sec + (cs * 4);
- if (!amd_smn_read(pvt->mc_node_id, mask_reg, mask))
+ if (!amd_smn_read(pvt->mc_node_id, mask_reg, &tmp)) {
+ *mask = tmp;
edac_dbg(0, " DCSM%d[%d]=0x%08x reg: 0x%x\n",
umc, cs, *mask, mask_reg);
+ }
- if (!amd_smn_read(pvt->mc_node_id, mask_reg_sec, mask_sec))
+ if (!amd_smn_read(pvt->mc_node_id, mask_reg_sec, &tmp)) {
+ *mask_sec = tmp;
edac_dbg(0, " DCSM_SEC%d[%d]=0x%08x reg: 0x%x\n",
umc, cs, *mask_sec, mask_reg_sec);
+ }
}
}
}
@@ -2910,7 +2903,7 @@ static void umc_read_mc_regs(struct amd64_pvt *pvt)
{
u8 nid = pvt->mc_node_id;
struct amd64_umc *umc;
- u32 i, umc_base;
+ u32 i, tmp, umc_base;
/* Read registers from each UMC */
for_each_umc(i) {
@@ -2918,11 +2911,20 @@ static void umc_read_mc_regs(struct amd64_pvt *pvt)
umc_base = get_umc_base(i);
umc = &pvt->umc[i];
- amd_smn_read(nid, umc_base + get_umc_reg(pvt, UMCCH_DIMM_CFG), &umc->dimm_cfg);
- amd_smn_read(nid, umc_base + UMCCH_UMC_CFG, &umc->umc_cfg);
- amd_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &umc->sdp_ctrl);
- amd_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &umc->ecc_ctrl);
- amd_smn_read(nid, umc_base + UMCCH_UMC_CAP_HI, &umc->umc_cap_hi);
+ if (!amd_smn_read(nid, umc_base + get_umc_reg(pvt, UMCCH_DIMM_CFG), &tmp))
+ umc->dimm_cfg = tmp;
+
+ if (!amd_smn_read(nid, umc_base + UMCCH_UMC_CFG, &tmp))
+ umc->umc_cfg = tmp;
+
+ if (!amd_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &tmp))
+ umc->sdp_ctrl = tmp;
+
+ if (!amd_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &tmp))
+ umc->ecc_ctrl = tmp;
+
+ if (!amd_smn_read(nid, umc_base + UMCCH_UMC_CAP_HI, &tmp))
+ umc->umc_cap_hi = tmp;
}
}
@@ -3651,16 +3653,21 @@ static void gpu_read_mc_regs(struct amd64_pvt *pvt)
{
u8 nid = pvt->mc_node_id;
struct amd64_umc *umc;
- u32 i, umc_base;
+ u32 i, tmp, umc_base;
/* Read registers from each UMC */
for_each_umc(i) {
umc_base = gpu_get_umc_base(pvt, i, 0);
umc = &pvt->umc[i];
- amd_smn_read(nid, umc_base + UMCCH_UMC_CFG, &umc->umc_cfg);
- amd_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &umc->sdp_ctrl);
- amd_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &umc->ecc_ctrl);
+ if (!amd_smn_read(nid, umc_base + UMCCH_UMC_CFG, &tmp))
+ umc->umc_cfg = tmp;
+
+ if (!amd_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &tmp))
+ umc->sdp_ctrl = tmp;
+
+ if (!amd_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &tmp))
+ umc->ecc_ctrl = tmp;
}
}
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index b879b12971e7..17228d07de4c 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -256,15 +256,11 @@
#define UMCCH_ADDR_MASK 0x20
#define UMCCH_ADDR_MASK_SEC 0x28
#define UMCCH_ADDR_MASK_SEC_DDR5 0x30
-#define UMCCH_ADDR_CFG 0x30
-#define UMCCH_ADDR_CFG_DDR5 0x40
#define UMCCH_DIMM_CFG 0x80
#define UMCCH_DIMM_CFG_DDR5 0x90
#define UMCCH_UMC_CFG 0x100
#define UMCCH_SDP_CTRL 0x104
#define UMCCH_ECC_CTRL 0x14C
-#define UMCCH_ECC_BAD_SYMBOL 0xD90
-#define UMCCH_UMC_CAP 0xDF0
#define UMCCH_UMC_CAP_HI 0xDF4
/* UMC CH bitfields */
diff --git a/drivers/edac/dmc520_edac.c b/drivers/edac/dmc520_edac.c
index 4e30b989a1a4..5e52d31db3b8 100644
--- a/drivers/edac/dmc520_edac.c
+++ b/drivers/edac/dmc520_edac.c
@@ -480,7 +480,6 @@ static int dmc520_edac_probe(struct platform_device *pdev)
struct mem_ctl_info *mci;
void __iomem *reg_base;
u32 irq_mask_all = 0;
- struct resource *res;
struct device *dev;
int ret, idx, irq;
u32 reg_val;
@@ -505,8 +504,7 @@ static int dmc520_edac_probe(struct platform_device *pdev)
}
/* Initialize dmc520 edac */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- reg_base = devm_ioremap_resource(dev, res);
+ reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg_base))
return PTR_ERR(reg_base);
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index cf2b618c1ada..1eb0136c6fbd 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -547,7 +547,7 @@ static int __init ghes_edac_init(void)
return -ENODEV;
if (list_empty(ghes_devs)) {
- pr_info("GHES probing device list is empty");
+ pr_info("GHES probing device list is empty\n");
return -ENODEV;
}
diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
index 3fd22a1eb1a9..24dd896d9a9d 100644
--- a/drivers/edac/i10nm_base.c
+++ b/drivers/edac/i10nm_base.c
@@ -942,16 +942,16 @@ static struct res_config gnr_cfg = {
};
static const struct x86_cpu_id i10nm_cpuids[] = {
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPINGS(0x0, 0x3), &i10nm_cfg0),
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPINGS(0x4, 0xf), &i10nm_cfg1),
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_X, X86_STEPPINGS(0x0, 0x3), &i10nm_cfg0),
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_X, X86_STEPPINGS(0x4, 0xf), &i10nm_cfg1),
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ICELAKE_D, X86_STEPPINGS(0x0, 0xf), &i10nm_cfg1),
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(SAPPHIRERAPIDS_X, X86_STEPPINGS(0x0, 0xf), &spr_cfg),
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(EMERALDRAPIDS_X, X86_STEPPINGS(0x0, 0xf), &spr_cfg),
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(GRANITERAPIDS_X, X86_STEPPINGS(0x0, 0xf), &gnr_cfg),
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ATOM_CRESTMONT_X, X86_STEPPINGS(0x0, 0xf), &gnr_cfg),
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ATOM_CRESTMONT, X86_STEPPINGS(0x0, 0xf), &gnr_cfg),
+ X86_MATCH_VFM_STEPPINGS(INTEL_ATOM_TREMONT_D, X86_STEPPINGS(0x0, 0x3), &i10nm_cfg0),
+ X86_MATCH_VFM_STEPPINGS(INTEL_ATOM_TREMONT_D, X86_STEPPINGS(0x4, 0xf), &i10nm_cfg1),
+ X86_MATCH_VFM_STEPPINGS(INTEL_ICELAKE_X, X86_STEPPINGS(0x0, 0x3), &i10nm_cfg0),
+ X86_MATCH_VFM_STEPPINGS(INTEL_ICELAKE_X, X86_STEPPINGS(0x4, 0xf), &i10nm_cfg1),
+ X86_MATCH_VFM_STEPPINGS(INTEL_ICELAKE_D, X86_STEPPINGS(0x0, 0xf), &i10nm_cfg1),
+ X86_MATCH_VFM_STEPPINGS(INTEL_SAPPHIRERAPIDS_X, X86_STEPPINGS(0x0, 0xf), &spr_cfg),
+ X86_MATCH_VFM_STEPPINGS(INTEL_EMERALDRAPIDS_X, X86_STEPPINGS(0x0, 0xf), &spr_cfg),
+ X86_MATCH_VFM_STEPPINGS(INTEL_GRANITERAPIDS_X, X86_STEPPINGS(0x0, 0xf), &gnr_cfg),
+ X86_MATCH_VFM_STEPPINGS(INTEL_ATOM_CRESTMONT_X, X86_STEPPINGS(0x0, 0xf), &gnr_cfg),
+ X86_MATCH_VFM_STEPPINGS(INTEL_ATOM_CRESTMONT, X86_STEPPINGS(0x0, 0xf), &gnr_cfg),
{}
};
MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
diff --git a/drivers/edac/igen6_edac.c b/drivers/edac/igen6_edac.c
index dbe9fe5f2ca6..0fe75eed8973 100644
--- a/drivers/edac/igen6_edac.c
+++ b/drivers/edac/igen6_edac.c
@@ -258,6 +258,11 @@ static struct work_struct ecclog_work;
#define DID_MTL_P_SKU2 0x7d02
#define DID_MTL_P_SKU3 0x7d14
+/* Compute die IDs for Arrow Lake-UH with IBECC */
+#define DID_ARL_UH_SKU1 0x7d06
+#define DID_ARL_UH_SKU2 0x7d20
+#define DID_ARL_UH_SKU3 0x7d30
+
static int get_mchbar(struct pci_dev *pdev, u64 *mchbar)
{
union {
@@ -597,6 +602,9 @@ static const struct pci_device_id igen6_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, DID_MTL_P_SKU1), (kernel_ulong_t)&mtl_p_cfg },
{ PCI_VDEVICE(INTEL, DID_MTL_P_SKU2), (kernel_ulong_t)&mtl_p_cfg },
{ PCI_VDEVICE(INTEL, DID_MTL_P_SKU3), (kernel_ulong_t)&mtl_p_cfg },
+ { 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 },
{ },
};
MODULE_DEVICE_TABLE(pci, igen6_pci_tbl);
diff --git a/drivers/edac/layerscape_edac.c b/drivers/edac/layerscape_edac.c
index d2f895033280..0d42c1238908 100644
--- a/drivers/edac/layerscape_edac.c
+++ b/drivers/edac/layerscape_edac.c
@@ -69,6 +69,7 @@ static void __exit fsl_ddr_mc_exit(void)
module_exit(fsl_ddr_mc_exit);
+MODULE_DESCRIPTION("Freescale Layerscape EDAC driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("NXP Semiconductor");
module_param(edac_op_state, int, 0444);
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index e8945d4adbad..d0266cbcbeda 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -704,6 +704,7 @@ static void __exit mpc85xx_mc_exit(void)
module_exit(mpc85xx_mc_exit);
+MODULE_DESCRIPTION("Freescale MPC85xx Memory Controller EDAC driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Montavista Software, Inc.");
module_param(edac_op_state, int, 0444);
diff --git a/drivers/edac/octeon_edac-l2c.c b/drivers/edac/octeon_edac-l2c.c
index 919095d10528..2adb9c8093f8 100644
--- a/drivers/edac/octeon_edac-l2c.c
+++ b/drivers/edac/octeon_edac-l2c.c
@@ -201,5 +201,6 @@ static struct platform_driver octeon_l2c_driver = {
};
module_platform_driver(octeon_l2c_driver);
+MODULE_DESCRIPTION("Cavium Octeon Secondary Caches (L2C) EDAC driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ralf Baechle <[email protected]>");
diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c
index 18615cbcd9ea..4112c2ee34b8 100644
--- a/drivers/edac/octeon_edac-lmc.c
+++ b/drivers/edac/octeon_edac-lmc.c
@@ -319,5 +319,6 @@ static struct platform_driver octeon_lmc_edac_driver = {
};
module_platform_driver(octeon_lmc_edac_driver);
+MODULE_DESCRIPTION("Cavium Octeon DRAM Memory Controller (LMC) EDAC driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ralf Baechle <[email protected]>");
diff --git a/drivers/edac/octeon_edac-pc.c b/drivers/edac/octeon_edac-pc.c
index b8404cc7b65f..d9eeb40d2784 100644
--- a/drivers/edac/octeon_edac-pc.c
+++ b/drivers/edac/octeon_edac-pc.c
@@ -137,5 +137,6 @@ static struct platform_driver co_cache_error_driver = {
};
module_platform_driver(co_cache_error_driver);
+MODULE_DESCRIPTION("Cavium Octeon Primary Caches EDAC driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ralf Baechle <[email protected]>");
diff --git a/drivers/edac/octeon_edac-pci.c b/drivers/edac/octeon_edac-pci.c
index 108ad9493cfb..4d368af2c5f0 100644
--- a/drivers/edac/octeon_edac-pci.c
+++ b/drivers/edac/octeon_edac-pci.c
@@ -104,5 +104,6 @@ static struct platform_driver octeon_pci_driver = {
};
module_platform_driver(octeon_pci_driver);
+MODULE_DESCRIPTION("Cavium Octeon PCI Controller EDAC driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ralf Baechle <[email protected]>");
diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c
index 2afcd148fcf8..f93f2f2b1cf2 100644
--- a/drivers/edac/pnd2_edac.c
+++ b/drivers/edac/pnd2_edac.c
@@ -1511,8 +1511,8 @@ static struct dunit_ops dnv_ops = {
};
static const struct x86_cpu_id pnd2_cpuids[] = {
- X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &apl_ops),
- X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D, &dnv_ops),
+ X86_MATCH_VFM(INTEL_ATOM_GOLDMONT, &apl_ops),
+ X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_D, &dnv_ops),
{ }
};
MODULE_DEVICE_TABLE(x86cpu, pnd2_cpuids);
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 26cca5a9322d..cbc92d3683e6 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -3546,13 +3546,13 @@ fail0:
}
static const struct x86_cpu_id sbridge_cpuids[] = {
- X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, &pci_dev_descr_sbridge_table),
- X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X, &pci_dev_descr_ibridge_table),
- X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X, &pci_dev_descr_haswell_table),
- X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X, &pci_dev_descr_broadwell_table),
- X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D, &pci_dev_descr_broadwell_table),
- X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &pci_dev_descr_knl_table),
- X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &pci_dev_descr_knl_table),
+ X86_MATCH_VFM(INTEL_SANDYBRIDGE_X, &pci_dev_descr_sbridge_table),
+ X86_MATCH_VFM(INTEL_IVYBRIDGE_X, &pci_dev_descr_ibridge_table),
+ X86_MATCH_VFM(INTEL_HASWELL_X, &pci_dev_descr_haswell_table),
+ X86_MATCH_VFM(INTEL_BROADWELL_X, &pci_dev_descr_broadwell_table),
+ X86_MATCH_VFM(INTEL_BROADWELL_D, &pci_dev_descr_broadwell_table),
+ X86_MATCH_VFM(INTEL_XEON_PHI_KNL, &pci_dev_descr_knl_table),
+ X86_MATCH_VFM(INTEL_XEON_PHI_KNM, &pci_dev_descr_knl_table),
{ }
};
MODULE_DEVICE_TABLE(x86cpu, sbridge_cpuids);
diff --git a/drivers/edac/skx_base.c b/drivers/edac/skx_base.c
index 0a862336a7ce..af3fa807acdb 100644
--- a/drivers/edac/skx_base.c
+++ b/drivers/edac/skx_base.c
@@ -164,7 +164,7 @@ static struct res_config skx_cfg = {
};
static const struct x86_cpu_id skx_cpuids[] = {
- X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(SKYLAKE_X, X86_STEPPINGS(0x0, 0xf), &skx_cfg),
+ X86_MATCH_VFM_STEPPINGS(INTEL_SKYLAKE_X, X86_STEPPINGS(0x0, 0xf), &skx_cfg),
{ }
};
MODULE_DEVICE_TABLE(x86cpu, skx_cpuids);
diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c
index 27996b7924c8..8d18099fd528 100644
--- a/drivers/edac/skx_common.c
+++ b/drivers/edac/skx_common.c
@@ -48,7 +48,7 @@ static u64 skx_tolm, skx_tohm;
static LIST_HEAD(dev_edac_list);
static bool skx_mem_cfg_2lm;
-int __init skx_adxl_get(void)
+int skx_adxl_get(void)
{
const char * const *names;
int i, j;
@@ -110,12 +110,14 @@ err:
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(skx_adxl_get);
-void __exit skx_adxl_put(void)
+void skx_adxl_put(void)
{
kfree(adxl_values);
kfree(adxl_msg);
}
+EXPORT_SYMBOL_GPL(skx_adxl_put);
static bool skx_adxl_decode(struct decoded_addr *res, bool error_in_1st_level_mem)
{
@@ -187,12 +189,14 @@ void skx_set_mem_cfg(bool mem_cfg_2lm)
{
skx_mem_cfg_2lm = mem_cfg_2lm;
}
+EXPORT_SYMBOL_GPL(skx_set_mem_cfg);
void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log)
{
driver_decode = decode;
skx_show_retry_rd_err_log = show_retry_log;
}
+EXPORT_SYMBOL_GPL(skx_set_decode);
int skx_get_src_id(struct skx_dev *d, int off, u8 *id)
{
@@ -206,6 +210,7 @@ int skx_get_src_id(struct skx_dev *d, int off, u8 *id)
*id = GET_BITFIELD(reg, 12, 14);
return 0;
}
+EXPORT_SYMBOL_GPL(skx_get_src_id);
int skx_get_node_id(struct skx_dev *d, u8 *id)
{
@@ -219,6 +224,7 @@ int skx_get_node_id(struct skx_dev *d, u8 *id)
*id = GET_BITFIELD(reg, 0, 2);
return 0;
}
+EXPORT_SYMBOL_GPL(skx_get_node_id);
static int get_width(u32 mtr)
{
@@ -284,6 +290,7 @@ int skx_get_all_bus_mappings(struct res_config *cfg, struct list_head **list)
*list = &dev_edac_list;
return ndev;
}
+EXPORT_SYMBOL_GPL(skx_get_all_bus_mappings);
int skx_get_hi_lo(unsigned int did, int off[], u64 *tolm, u64 *tohm)
{
@@ -323,6 +330,7 @@ fail:
pci_dev_put(pdev);
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(skx_get_hi_lo);
static int skx_get_dimm_attr(u32 reg, int lobit, int hibit, int add,
int minval, int maxval, const char *name)
@@ -394,6 +402,7 @@ int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
return 1;
}
+EXPORT_SYMBOL_GPL(skx_get_dimm_info);
int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,
int chan, int dimmno, const char *mod_str)
@@ -442,6 +451,7 @@ unknown_size:
return (size == 0 || size == ~0ull) ? 0 : 1;
}
+EXPORT_SYMBOL_GPL(skx_get_nvdimm_info);
int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev,
const char *ctl_name, const char *mod_str,
@@ -512,6 +522,7 @@ fail0:
imc->mci = NULL;
return rc;
}
+EXPORT_SYMBOL_GPL(skx_register_mci);
static void skx_unregister_mci(struct skx_imc *imc)
{
@@ -688,6 +699,7 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
mce->kflags |= MCE_HANDLED_EDAC;
return NOTIFY_DONE;
}
+EXPORT_SYMBOL_GPL(skx_mce_check_error);
void skx_remove(void)
{
@@ -725,3 +737,8 @@ void skx_remove(void)
kfree(d);
}
}
+EXPORT_SYMBOL_GPL(skx_remove);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Tony Luck");
+MODULE_DESCRIPTION("MC Driver for Intel server processors");
diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h
index b6d3607dffe2..11faf1db4fa4 100644
--- a/drivers/edac/skx_common.h
+++ b/drivers/edac/skx_common.h
@@ -231,8 +231,8 @@ typedef int (*get_dimm_config_f)(struct mem_ctl_info *mci,
typedef bool (*skx_decode_f)(struct decoded_addr *res);
typedef void (*skx_show_retry_log_f)(struct decoded_addr *res, char *msg, int len, bool scrub_err);
-int __init skx_adxl_get(void);
-void __exit skx_adxl_put(void);
+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);
diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c
index fab9891e569a..75c04dfc3962 100644
--- a/drivers/edac/thunderx_edac.c
+++ b/drivers/edac/thunderx_edac.c
@@ -35,12 +35,6 @@ enum {
ERR_UNKNOWN = 3,
};
-#define MAX_SYNDROME_REGS 4
-
-struct error_syndrome {
- u64 reg[MAX_SYNDROME_REGS];
-};
-
struct error_descr {
int type;
u64 mask;
diff --git a/drivers/firmware/arm_ffa/Makefile b/drivers/firmware/arm_ffa/Makefile
index 9d9f37523200..168990a7e792 100644
--- a/drivers/firmware/arm_ffa/Makefile
+++ b/drivers/firmware/arm_ffa/Makefile
@@ -2,5 +2,7 @@
ffa-bus-y = bus.o
ffa-driver-y = driver.o
ffa-transport-$(CONFIG_ARM_FFA_SMCCC) += smccc.o
-ffa-module-objs := $(ffa-bus-y) $(ffa-driver-y) $(ffa-transport-y)
-obj-$(CONFIG_ARM_FFA_TRANSPORT) = ffa-module.o
+ffa-core-objs := $(ffa-bus-y)
+ffa-module-objs := $(ffa-driver-y) $(ffa-transport-y)
+obj-$(CONFIG_ARM_FFA_TRANSPORT) = ffa-core.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa-module.o
diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c
index 2f557e90f2eb..0c83931485f6 100644
--- a/drivers/firmware/arm_ffa/bus.c
+++ b/drivers/firmware/arm_ffa/bus.c
@@ -30,12 +30,11 @@ static int ffa_device_match(struct device *dev, struct device_driver *drv)
while (!uuid_is_null(&id_table->uuid)) {
/*
* FF-A v1.0 doesn't provide discovery of UUIDs, just the
- * partition IDs, so fetch the partitions IDs for this
- * id_table UUID and assign the UUID to the device if the
- * partition ID matches
+ * partition IDs, so match it unconditionally here and handle
+ * it via the installed bus notifier during driver binding.
*/
if (uuid_is_null(&ffa_dev->uuid))
- ffa_device_match_uuid(ffa_dev, &id_table->uuid);
+ return 1;
if (uuid_equal(&ffa_dev->uuid, &id_table->uuid))
return 1;
@@ -50,6 +49,10 @@ static int ffa_device_probe(struct device *dev)
struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
struct ffa_device *ffa_dev = to_ffa_dev(dev);
+ /* UUID can be still NULL with FF-A v1.0, so just skip probing them */
+ if (uuid_is_null(&ffa_dev->uuid))
+ return -ENODEV;
+
return ffa_drv->probe(ffa_dev);
}
@@ -232,14 +235,21 @@ void ffa_device_unregister(struct ffa_device *ffa_dev)
}
EXPORT_SYMBOL_GPL(ffa_device_unregister);
-int arm_ffa_bus_init(void)
+static int __init arm_ffa_bus_init(void)
{
return bus_register(&ffa_bus_type);
}
+subsys_initcall(arm_ffa_bus_init);
-void arm_ffa_bus_exit(void)
+static void __exit arm_ffa_bus_exit(void)
{
ffa_devices_unregister();
bus_unregister(&ffa_bus_type);
ida_destroy(&ffa_bus_id);
}
+module_exit(arm_ffa_bus_exit);
+
+MODULE_ALIAS("ffa-core");
+MODULE_AUTHOR("Sudeep Holla <[email protected]>");
+MODULE_DESCRIPTION("ARM FF-A bus");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/arm_ffa/common.h b/drivers/firmware/arm_ffa/common.h
index d6eccf1fd3f6..9c6425a81d0d 100644
--- a/drivers/firmware/arm_ffa/common.h
+++ b/drivers/firmware/arm_ffa/common.h
@@ -14,8 +14,6 @@ typedef struct arm_smccc_1_2_regs ffa_value_t;
typedef void (ffa_fn)(ffa_value_t, ffa_value_t *);
-int arm_ffa_bus_init(void);
-void arm_ffa_bus_exit(void);
bool ffa_device_is_valid(struct ffa_device *ffa_dev);
void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid);
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 1609247cfafc..7ba98c7af2e9 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1224,14 +1224,6 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
int count, idx;
struct ffa_partition_info *pbuf, *tpbuf;
- /*
- * FF-A v1.1 provides UUID for each partition as part of the discovery
- * API, the discovered UUID must be populated in the device's UUID and
- * there is no need to copy the same from the driver table.
- */
- if (drv_info->version > FFA_VERSION_1_0)
- return;
-
count = ffa_partition_probe(uuid, &pbuf);
if (count <= 0)
return;
@@ -1242,6 +1234,35 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
kfree(pbuf);
}
+static int
+ffa_bus_notifier(struct notifier_block *nb, unsigned long action, void *data)
+{
+ struct device *dev = data;
+ struct ffa_device *fdev = to_ffa_dev(dev);
+
+ if (action == BUS_NOTIFY_BIND_DRIVER) {
+ struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
+ const struct ffa_device_id *id_table= ffa_drv->id_table;
+
+ /*
+ * FF-A v1.1 provides UUID for each partition as part of the
+ * discovery API, the discovered UUID must be populated in the
+ * device's UUID and there is no need to workaround by copying
+ * the same from the driver table.
+ */
+ if (uuid_is_null(&fdev->uuid))
+ ffa_device_match_uuid(fdev, &id_table->uuid);
+
+ return NOTIFY_OK;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ffa_bus_nb = {
+ .notifier_call = ffa_bus_notifier,
+};
+
static int ffa_setup_partitions(void)
{
int count, idx, ret;
@@ -1250,6 +1271,12 @@ static int ffa_setup_partitions(void)
struct ffa_dev_part_info *info;
struct ffa_partition_info *pbuf, *tpbuf;
+ if (drv_info->version == FFA_VERSION_1_0) {
+ ret = bus_register_notifier(&ffa_bus_type, &ffa_bus_nb);
+ if (ret)
+ pr_err("Failed to register FF-A bus notifiers\n");
+ }
+
count = ffa_partition_probe(&uuid_null, &pbuf);
if (count <= 0) {
pr_info("%s: No partitions found, error %d\n", __func__, count);
@@ -1261,7 +1288,7 @@ static int ffa_setup_partitions(void)
import_uuid(&uuid, (u8 *)tpbuf->uuid);
/* Note that if the UUID will be uuid_null, that will require
- * ffa_device_match() to find the UUID of this partition id
+ * ffa_bus_notifier() to find the UUID of this partition id
* with help of ffa_device_match_uuid(). FF-A v1.1 and above
* provides UUID here for each partition as part of the
* discovery API and the same is passed.
@@ -1581,14 +1608,9 @@ static int __init ffa_init(void)
if (ret)
return ret;
- ret = arm_ffa_bus_init();
- if (ret)
- return ret;
-
drv_info = kzalloc(sizeof(*drv_info), GFP_KERNEL);
if (!drv_info) {
- ret = -ENOMEM;
- goto ffa_bus_exit;
+ return -ENOMEM;
}
ret = ffa_version_check(&drv_info->version);
@@ -1649,11 +1671,9 @@ free_pages:
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
free_drv_info:
kfree(drv_info);
-ffa_bus_exit:
- arm_ffa_bus_exit();
return ret;
}
-subsys_initcall(ffa_init);
+module_init(ffa_init);
static void __exit ffa_exit(void)
{
@@ -1663,7 +1683,6 @@ static void __exit ffa_exit(void)
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
kfree(drv_info);
- arm_ffa_bus_exit();
}
module_exit(ffa_exit);
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index b5ac25dbc1ca..4b8c5250cdb5 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -326,6 +326,7 @@ void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem);
bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer);
bool shmem_channel_free(struct scmi_shared_mem __iomem *shmem);
+bool shmem_channel_intr_enabled(struct scmi_shared_mem __iomem *shmem);
/* declarations for message passing transports */
struct scmi_msg_payld;
diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c
index 615a3b2ad83d..0219a12e3209 100644
--- a/drivers/firmware/arm_scmi/mailbox.c
+++ b/drivers/firmware/arm_scmi/mailbox.c
@@ -21,6 +21,7 @@
* @cl: Mailbox Client
* @chan: Transmit/Receive mailbox uni/bi-directional channel
* @chan_receiver: Optional Receiver mailbox unidirectional channel
+ * @chan_platform_receiver: Optional Platform Receiver mailbox unidirectional channel
* @cinfo: SCMI channel info
* @shmem: Transmit/Receive shared memory area
*/
@@ -28,6 +29,7 @@ struct scmi_mailbox {
struct mbox_client cl;
struct mbox_chan *chan;
struct mbox_chan *chan_receiver;
+ struct mbox_chan *chan_platform_receiver;
struct scmi_chan_info *cinfo;
struct scmi_shared_mem __iomem *shmem;
};
@@ -91,6 +93,8 @@ static bool mailbox_chan_available(struct device_node *of_node, int idx)
* for replies on the a2p channel. Set as zero if not present.
* @p2a_chan: A reference to the optional p2a channel.
* Set as zero if not present.
+ * @p2a_rx_chan: A reference to the optional p2a completion channel.
+ * Set as zero if not present.
*
* At first, validate the transport configuration as described in terms of
* 'mboxes' and 'shmem', then determin which mailbox channel indexes are
@@ -98,8 +102,8 @@ static bool mailbox_chan_available(struct device_node *of_node, int idx)
*
* Return: 0 on Success or error
*/
-static int mailbox_chan_validate(struct device *cdev,
- int *a2p_rx_chan, int *p2a_chan)
+static int mailbox_chan_validate(struct device *cdev, int *a2p_rx_chan,
+ int *p2a_chan, int *p2a_rx_chan)
{
int num_mb, num_sh, ret = 0;
struct device_node *np = cdev->of_node;
@@ -109,8 +113,9 @@ static int mailbox_chan_validate(struct device *cdev,
dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh);
/* Bail out if mboxes and shmem descriptors are inconsistent */
- if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 3 ||
- (num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2)) {
+ if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 4 ||
+ (num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2) ||
+ (num_mb == 4 && num_sh != 2)) {
dev_warn(cdev,
"Invalid channel descriptor for '%s' - mbs:%d shm:%d\n",
of_node_full_name(np), num_mb, num_sh);
@@ -139,6 +144,7 @@ static int mailbox_chan_validate(struct device *cdev,
case 1:
*a2p_rx_chan = 0;
*p2a_chan = 0;
+ *p2a_rx_chan = 0;
break;
case 2:
if (num_sh == 2) {
@@ -148,10 +154,17 @@ static int mailbox_chan_validate(struct device *cdev,
*a2p_rx_chan = 1;
*p2a_chan = 0;
}
+ *p2a_rx_chan = 0;
break;
case 3:
*a2p_rx_chan = 1;
*p2a_chan = 2;
+ *p2a_rx_chan = 0;
+ break;
+ case 4:
+ *a2p_rx_chan = 1;
+ *p2a_chan = 2;
+ *p2a_rx_chan = 3;
break;
}
}
@@ -166,12 +179,12 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
struct device *cdev = cinfo->dev;
struct scmi_mailbox *smbox;
struct device_node *shmem;
- int ret, a2p_rx_chan, p2a_chan, idx = tx ? 0 : 1;
+ int ret, a2p_rx_chan, p2a_chan, p2a_rx_chan, idx = tx ? 0 : 1;
struct mbox_client *cl;
resource_size_t size;
struct resource res;
- ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan);
+ ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan, &p2a_rx_chan);
if (ret)
return ret;
@@ -229,6 +242,17 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
}
}
+ if (!tx && p2a_rx_chan) {
+ smbox->chan_platform_receiver = mbox_request_channel(cl, p2a_rx_chan);
+ if (IS_ERR(smbox->chan_platform_receiver)) {
+ ret = PTR_ERR(smbox->chan_platform_receiver);
+ if (ret != -EPROBE_DEFER)
+ dev_err(cdev, "failed to request SCMI P2A Receiver mailbox\n");
+ return ret;
+ }
+ }
+
+
cinfo->transport_info = smbox;
smbox->cinfo = cinfo;
@@ -243,9 +267,11 @@ static int mailbox_chan_free(int id, void *p, void *data)
if (smbox && !IS_ERR(smbox->chan)) {
mbox_free_channel(smbox->chan);
mbox_free_channel(smbox->chan_receiver);
+ mbox_free_channel(smbox->chan_platform_receiver);
cinfo->transport_info = NULL;
smbox->chan = NULL;
smbox->chan_receiver = NULL;
+ smbox->chan_platform_receiver = NULL;
smbox->cinfo = NULL;
}
@@ -300,8 +326,27 @@ static void mailbox_fetch_notification(struct scmi_chan_info *cinfo,
static void mailbox_clear_channel(struct scmi_chan_info *cinfo)
{
struct scmi_mailbox *smbox = cinfo->transport_info;
+ struct mbox_chan *intr_chan;
+ int ret;
shmem_clear_channel(smbox->shmem);
+
+ if (!shmem_channel_intr_enabled(smbox->shmem))
+ return;
+
+ if (smbox->chan_platform_receiver)
+ intr_chan = smbox->chan_platform_receiver;
+ else if (smbox->chan)
+ intr_chan = smbox->chan;
+ else
+ return;
+
+ ret = mbox_send_message(intr_chan, NULL);
+ /* mbox_send_message returns non-negative value on success, so reset */
+ if (ret > 0)
+ ret = 0;
+
+ mbox_client_txdone(intr_chan, ret);
}
static bool
diff --git a/drivers/firmware/arm_scmi/scmi_power_control.c b/drivers/firmware/arm_scmi/scmi_power_control.c
index 6eb7d2a4b6b1..21f467a92942 100644
--- a/drivers/firmware/arm_scmi/scmi_power_control.c
+++ b/drivers/firmware/arm_scmi/scmi_power_control.c
@@ -50,6 +50,7 @@
#include <linux/reboot.h>
#include <linux/scmi_protocol.h>
#include <linux/slab.h>
+#include <linux/suspend.h>
#include <linux/time64.h>
#include <linux/timer.h>
#include <linux/types.h>
@@ -78,6 +79,7 @@ enum scmi_syspower_state {
* @reboot_nb: A notifier_block optionally used to track reboot progress
* @forceful_work: A worker used to trigger a forceful transition once a
* graceful has timed out.
+ * @suspend_work: A worker used to trigger system suspend
*/
struct scmi_syspower_conf {
struct device *dev;
@@ -90,6 +92,7 @@ struct scmi_syspower_conf {
struct notifier_block reboot_nb;
struct delayed_work forceful_work;
+ struct work_struct suspend_work;
};
#define userspace_nb_to_sconf(x) \
@@ -249,6 +252,9 @@ static void scmi_request_graceful_transition(struct scmi_syspower_conf *sc,
case SCMI_SYSTEM_WARMRESET:
orderly_reboot();
break;
+ case SCMI_SYSTEM_SUSPEND:
+ schedule_work(&sc->suspend_work);
+ break;
default:
break;
}
@@ -277,7 +283,8 @@ static int scmi_userspace_notifier(struct notifier_block *nb,
struct scmi_system_power_state_notifier_report *er = data;
struct scmi_syspower_conf *sc = userspace_nb_to_sconf(nb);
- if (er->system_state >= SCMI_SYSTEM_POWERUP) {
+ if (er->system_state >= SCMI_SYSTEM_MAX ||
+ er->system_state == SCMI_SYSTEM_POWERUP) {
dev_err(sc->dev, "Ignoring unsupported system_state: 0x%X\n",
er->system_state);
return NOTIFY_DONE;
@@ -315,6 +322,16 @@ static int scmi_userspace_notifier(struct notifier_block *nb,
return NOTIFY_OK;
}
+static void scmi_suspend_work_func(struct work_struct *work)
+{
+ struct scmi_syspower_conf *sc =
+ container_of(work, struct scmi_syspower_conf, suspend_work);
+
+ pm_suspend(PM_SUSPEND_MEM);
+
+ sc->state = SCMI_SYSPOWER_IDLE;
+}
+
static int scmi_syspower_probe(struct scmi_device *sdev)
{
int ret;
@@ -338,6 +355,8 @@ static int scmi_syspower_probe(struct scmi_device *sdev)
sc->userspace_nb.notifier_call = &scmi_userspace_notifier;
sc->dev = &sdev->dev;
+ INIT_WORK(&sc->suspend_work, scmi_suspend_work_func);
+
return handle->notify_ops->devm_event_notifier_register(sdev,
SCMI_PROTOCOL_SYSTEM,
SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER,
diff --git a/drivers/firmware/arm_scmi/shmem.c b/drivers/firmware/arm_scmi/shmem.c
index 8bf495bcad09..b74e5a740f2c 100644
--- a/drivers/firmware/arm_scmi/shmem.c
+++ b/drivers/firmware/arm_scmi/shmem.c
@@ -128,3 +128,8 @@ bool shmem_channel_free(struct scmi_shared_mem __iomem *shmem)
return (ioread32(&shmem->channel_status) &
SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
}
+
+bool shmem_channel_intr_enabled(struct scmi_shared_mem __iomem *shmem)
+{
+ return ioread32(&shmem->flags) & SCMI_SHMEM_FLAG_INTR_ENABLED;
+}
diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c
index 0d139e4de37c..8a347b938406 100644
--- a/drivers/firmware/cirrus/cs_dsp.c
+++ b/drivers/firmware/cirrus/cs_dsp.c
@@ -1107,9 +1107,16 @@ struct cs_dsp_coeff_parsed_coeff {
int len;
};
-static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
+static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, unsigned int avail,
+ const u8 **str)
{
- int length;
+ int length, total_field_len;
+
+ /* String fields are at least one __le32 */
+ if (sizeof(__le32) > avail) {
+ *pos = NULL;
+ return 0;
+ }
switch (bytes) {
case 1:
@@ -1122,10 +1129,16 @@ static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
return 0;
}
+ total_field_len = ((length + bytes) + 3) & ~0x03;
+ if ((unsigned int)total_field_len > avail) {
+ *pos = NULL;
+ return 0;
+ }
+
if (str)
*str = *pos + bytes;
- *pos += ((length + bytes) + 3) & ~0x03;
+ *pos += total_field_len;
return length;
}
@@ -1150,71 +1163,134 @@ static int cs_dsp_coeff_parse_int(int bytes, const u8 **pos)
return val;
}
-static inline void cs_dsp_coeff_parse_alg(struct cs_dsp *dsp, const u8 **data,
- struct cs_dsp_coeff_parsed_alg *blk)
+static int cs_dsp_coeff_parse_alg(struct cs_dsp *dsp,
+ const struct wmfw_region *region,
+ struct cs_dsp_coeff_parsed_alg *blk)
{
const struct wmfw_adsp_alg_data *raw;
+ unsigned int data_len = le32_to_cpu(region->len);
+ unsigned int pos;
+ const u8 *tmp;
+
+ raw = (const struct wmfw_adsp_alg_data *)region->data;
switch (dsp->fw_ver) {
case 0:
case 1:
- raw = (const struct wmfw_adsp_alg_data *)*data;
- *data = raw->data;
+ if (sizeof(*raw) > data_len)
+ return -EOVERFLOW;
blk->id = le32_to_cpu(raw->id);
blk->name = raw->name;
- blk->name_len = strlen(raw->name);
+ blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
blk->ncoeff = le32_to_cpu(raw->ncoeff);
+
+ pos = sizeof(*raw);
break;
default:
- blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), data);
- blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), data,
+ if (sizeof(raw->id) > data_len)
+ return -EOVERFLOW;
+
+ tmp = region->data;
+ blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), &tmp);
+ pos = tmp - region->data;
+
+ tmp = &region->data[pos];
+ blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
&blk->name);
- cs_dsp_coeff_parse_string(sizeof(u16), data, NULL);
- blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), data);
+ if (!tmp)
+ return -EOVERFLOW;
+
+ pos = tmp - region->data;
+ cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
+ if (!tmp)
+ return -EOVERFLOW;
+
+ pos = tmp - region->data;
+ if (sizeof(raw->ncoeff) > (data_len - pos))
+ return -EOVERFLOW;
+
+ blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), &tmp);
+ pos += sizeof(raw->ncoeff);
break;
}
+ if ((int)blk->ncoeff < 0)
+ return -EOVERFLOW;
+
cs_dsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
cs_dsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
cs_dsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);
+
+ return pos;
}
-static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
- struct cs_dsp_coeff_parsed_coeff *blk)
+static int cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp,
+ const struct wmfw_region *region,
+ unsigned int pos,
+ struct cs_dsp_coeff_parsed_coeff *blk)
{
const struct wmfw_adsp_coeff_data *raw;
+ unsigned int data_len = le32_to_cpu(region->len);
+ unsigned int blk_len, blk_end_pos;
const u8 *tmp;
- int length;
+
+ raw = (const struct wmfw_adsp_coeff_data *)&region->data[pos];
+ if (sizeof(raw->hdr) > (data_len - pos))
+ return -EOVERFLOW;
+
+ blk_len = le32_to_cpu(raw->hdr.size);
+ if (blk_len > S32_MAX)
+ return -EOVERFLOW;
+
+ if (blk_len > (data_len - pos - sizeof(raw->hdr)))
+ return -EOVERFLOW;
+
+ blk_end_pos = pos + sizeof(raw->hdr) + blk_len;
+
+ blk->offset = le16_to_cpu(raw->hdr.offset);
+ blk->mem_type = le16_to_cpu(raw->hdr.type);
switch (dsp->fw_ver) {
case 0:
case 1:
- raw = (const struct wmfw_adsp_coeff_data *)*data;
- *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
+ if (sizeof(*raw) > (data_len - pos))
+ return -EOVERFLOW;
- blk->offset = le16_to_cpu(raw->hdr.offset);
- blk->mem_type = le16_to_cpu(raw->hdr.type);
blk->name = raw->name;
- blk->name_len = strlen(raw->name);
+ blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
blk->ctl_type = le16_to_cpu(raw->ctl_type);
blk->flags = le16_to_cpu(raw->flags);
blk->len = le32_to_cpu(raw->len);
break;
default:
- tmp = *data;
- blk->offset = cs_dsp_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
- blk->mem_type = cs_dsp_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
- length = cs_dsp_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
- blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp,
+ pos += sizeof(raw->hdr);
+ tmp = &region->data[pos];
+ blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
&blk->name);
- cs_dsp_coeff_parse_string(sizeof(u8), &tmp, NULL);
- cs_dsp_coeff_parse_string(sizeof(u16), &tmp, NULL);
+ if (!tmp)
+ return -EOVERFLOW;
+
+ pos = tmp - region->data;
+ cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos, NULL);
+ if (!tmp)
+ return -EOVERFLOW;
+
+ pos = tmp - region->data;
+ cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
+ if (!tmp)
+ return -EOVERFLOW;
+
+ pos = tmp - region->data;
+ if (sizeof(raw->ctl_type) + sizeof(raw->flags) + sizeof(raw->len) >
+ (data_len - pos))
+ return -EOVERFLOW;
+
blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
+ pos += sizeof(raw->ctl_type);
blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp);
+ pos += sizeof(raw->flags);
blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp);
-
- *data = *data + sizeof(raw->hdr) + length;
break;
}
@@ -1224,6 +1300,8 @@ static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
cs_dsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
cs_dsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
cs_dsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);
+
+ return blk_end_pos;
}
static int cs_dsp_check_coeff_flags(struct cs_dsp *dsp,
@@ -1247,12 +1325,16 @@ static int cs_dsp_parse_coeff(struct cs_dsp *dsp,
struct cs_dsp_alg_region alg_region = {};
struct cs_dsp_coeff_parsed_alg alg_blk;
struct cs_dsp_coeff_parsed_coeff coeff_blk;
- const u8 *data = region->data;
- int i, ret;
+ int i, pos, ret;
+
+ pos = cs_dsp_coeff_parse_alg(dsp, region, &alg_blk);
+ if (pos < 0)
+ return pos;
- cs_dsp_coeff_parse_alg(dsp, &data, &alg_blk);
for (i = 0; i < alg_blk.ncoeff; i++) {
- cs_dsp_coeff_parse_coeff(dsp, &data, &coeff_blk);
+ pos = cs_dsp_coeff_parse_coeff(dsp, region, pos, &coeff_blk);
+ if (pos < 0)
+ return pos;
switch (coeff_blk.ctl_type) {
case WMFW_CTL_TYPE_BYTES:
@@ -1321,6 +1403,10 @@ static unsigned int cs_dsp_adsp1_parse_sizes(struct cs_dsp *dsp,
const struct wmfw_adsp1_sizes *adsp1_sizes;
adsp1_sizes = (void *)&firmware->data[pos];
+ if (sizeof(*adsp1_sizes) > firmware->size - pos) {
+ cs_dsp_err(dsp, "%s: file truncated\n", file);
+ return 0;
+ }
cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm),
@@ -1337,6 +1423,10 @@ static unsigned int cs_dsp_adsp2_parse_sizes(struct cs_dsp *dsp,
const struct wmfw_adsp2_sizes *adsp2_sizes;
adsp2_sizes = (void *)&firmware->data[pos];
+ if (sizeof(*adsp2_sizes) > firmware->size - pos) {
+ cs_dsp_err(dsp, "%s: file truncated\n", file);
+ return 0;
+ }
cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym),
@@ -1376,7 +1466,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
struct regmap *regmap = dsp->regmap;
unsigned int pos = 0;
const struct wmfw_header *header;
- const struct wmfw_adsp1_sizes *adsp1_sizes;
const struct wmfw_footer *footer;
const struct wmfw_region *region;
const struct cs_dsp_region *mem;
@@ -1392,10 +1481,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
ret = -EINVAL;
- pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
- if (pos >= firmware->size) {
- cs_dsp_err(dsp, "%s: file too short, %zu bytes\n",
- file, firmware->size);
+ if (sizeof(*header) >= firmware->size) {
+ ret = -EOVERFLOW;
goto out_fw;
}
@@ -1423,22 +1510,36 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
pos = sizeof(*header);
pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
+ if ((pos == 0) || (sizeof(*footer) > firmware->size - pos)) {
+ ret = -EOVERFLOW;
+ goto out_fw;
+ }
footer = (void *)&firmware->data[pos];
pos += sizeof(*footer);
if (le32_to_cpu(header->len) != pos) {
- cs_dsp_err(dsp, "%s: unexpected header length %d\n",
- file, le32_to_cpu(header->len));
+ ret = -EOVERFLOW;
goto out_fw;
}
cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file,
le64_to_cpu(footer->timestamp));
- while (pos < firmware->size &&
- sizeof(*region) < firmware->size - pos) {
+ while (pos < firmware->size) {
+ /* Is there enough data for a complete block header? */
+ if (sizeof(*region) > firmware->size - pos) {
+ ret = -EOVERFLOW;
+ goto out_fw;
+ }
+
region = (void *)&(firmware->data[pos]);
+
+ if (le32_to_cpu(region->len) > firmware->size - pos - sizeof(*region)) {
+ ret = -EOVERFLOW;
+ goto out_fw;
+ }
+
region_name = "Unknown";
reg = 0;
text = NULL;
@@ -1495,16 +1596,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
regions, le32_to_cpu(region->len), offset,
region_name);
- if (le32_to_cpu(region->len) >
- firmware->size - pos - sizeof(*region)) {
- cs_dsp_err(dsp,
- "%s.%d: %s region len %d bytes exceeds file length %zu\n",
- file, regions, region_name,
- le32_to_cpu(region->len), firmware->size);
- ret = -EINVAL;
- goto out_fw;
- }
-
if (text) {
memcpy(text, region->data, le32_to_cpu(region->len));
cs_dsp_info(dsp, "%s: %s\n", file, text);
@@ -1555,6 +1646,9 @@ out_fw:
cs_dsp_buf_free(&buf_list);
kfree(text);
+ if (ret == -EOVERFLOW)
+ cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
+
return ret;
}
@@ -2122,10 +2216,20 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
pos = le32_to_cpu(hdr->len);
blocks = 0;
- while (pos < firmware->size &&
- sizeof(*blk) < firmware->size - pos) {
+ while (pos < firmware->size) {
+ /* Is there enough data for a complete block header? */
+ if (sizeof(*blk) > firmware->size - pos) {
+ ret = -EOVERFLOW;
+ goto out_fw;
+ }
+
blk = (void *)(&firmware->data[pos]);
+ if (le32_to_cpu(blk->len) > firmware->size - pos - sizeof(*blk)) {
+ ret = -EOVERFLOW;
+ goto out_fw;
+ }
+
type = le16_to_cpu(blk->type);
offset = le16_to_cpu(blk->offset);
version = le32_to_cpu(blk->ver) >> 8;
@@ -2222,17 +2326,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
}
if (reg) {
- if (le32_to_cpu(blk->len) >
- firmware->size - pos - sizeof(*blk)) {
- cs_dsp_err(dsp,
- "%s.%d: %s region len %d bytes exceeds file length %zu\n",
- file, blocks, region_name,
- le32_to_cpu(blk->len),
- firmware->size);
- ret = -EINVAL;
- goto out_fw;
- }
-
buf = cs_dsp_buf_alloc(blk->data,
le32_to_cpu(blk->len),
&buf_list);
@@ -2272,6 +2365,10 @@ out_fw:
regmap_async_complete(regmap);
cs_dsp_buf_free(&buf_list);
kfree(text);
+
+ if (ret == -EOVERFLOW)
+ cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
+
return ret;
}
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 06f0428a723c..1f32d6cf98d6 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -76,7 +76,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \
lib-$(CONFIG_ARM) += arm32-stub.o
lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o
-lib-$(CONFIG_X86) += x86-stub.o
+lib-$(CONFIG_X86) += x86-stub.o smbios.o
lib-$(CONFIG_X86_64) += x86-5lvl.o
lib-$(CONFIG_RISCV) += kaslr.o riscv.o riscv-stub.o
lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index 452b7ccd330e..2c3869356147 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -21,7 +21,6 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
efi_loaded_image_t *image,
efi_handle_t image_handle)
{
- efi_status_t status;
unsigned long kernel_size, kernel_codesize, kernel_memsize;
if (image->image_base != _text) {
@@ -39,15 +38,9 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
*reserve_size = kernel_memsize;
*image_addr = (unsigned long)_text;
- status = efi_kaslr_relocate_kernel(image_addr,
- reserve_addr, reserve_size,
- kernel_size, kernel_codesize,
- kernel_memsize,
- efi_kaslr_get_phys_seed(image_handle));
- if (status != EFI_SUCCESS)
- return status;
-
- return EFI_SUCCESS;
+ return efi_kaslr_relocate_kernel(image_addr, reserve_addr, reserve_size,
+ kernel_size, kernel_codesize, kernel_memsize,
+ efi_kaslr_get_phys_seed(image_handle));
}
asmlinkage void primary_entry(void);
diff --git a/drivers/firmware/efi/libstub/arm64.c b/drivers/firmware/efi/libstub/arm64.c
index 446e35eaf3d9..e57cd3de0a00 100644
--- a/drivers/firmware/efi/libstub/arm64.c
+++ b/drivers/firmware/efi/libstub/arm64.c
@@ -39,8 +39,7 @@ static bool system_needs_vamap(void)
static char const emag[] = "eMAG";
default:
- version = efi_get_smbios_string(&record->header, 4,
- processor_version);
+ version = efi_get_smbios_string(record, processor_version);
if (!version || (strncmp(version, altra, sizeof(altra) - 1) &&
strncmp(version, emag, sizeof(emag) - 1)))
break;
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 27abb4ce0291..d33ccbc4a2c6 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1204,14 +1204,13 @@ struct efi_smbios_type4_record {
u16 thread_enabled;
};
-#define efi_get_smbios_string(__record, __type, __name) ({ \
- int off = offsetof(struct efi_smbios_type ## __type ## _record, \
- __name); \
- __efi_get_smbios_string((__record), __type, off); \
+#define efi_get_smbios_string(__record, __field) ({ \
+ __typeof__(__record) __rec = __record; \
+ __efi_get_smbios_string(&__rec->header, &__rec->__field); \
})
const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
- u8 type, int offset);
+ const u8 *offset);
void efi_remap_image(unsigned long image_base, unsigned alloc_size,
unsigned long code_size);
diff --git a/drivers/firmware/efi/libstub/kaslr.c b/drivers/firmware/efi/libstub/kaslr.c
index 1a9808012abd..6318c40bda38 100644
--- a/drivers/firmware/efi/libstub/kaslr.c
+++ b/drivers/firmware/efi/libstub/kaslr.c
@@ -18,8 +18,6 @@
*/
u32 efi_kaslr_get_phys_seed(efi_handle_t image_handle)
{
- efi_status_t status;
- u32 phys_seed;
efi_guid_t li_fixed_proto = LINUX_EFI_LOADED_IMAGE_FIXED_GUID;
void *p;
@@ -32,18 +30,20 @@ u32 efi_kaslr_get_phys_seed(efi_handle_t image_handle)
&li_fixed_proto, &p) == EFI_SUCCESS) {
efi_info("Image placement fixed by loader\n");
} else {
+ efi_status_t status;
+ u32 phys_seed;
+
status = efi_get_random_bytes(sizeof(phys_seed),
(u8 *)&phys_seed);
- if (status == EFI_SUCCESS) {
+ if (status == EFI_SUCCESS)
return phys_seed;
- } else if (status == EFI_NOT_FOUND) {
+
+ if (status == EFI_NOT_FOUND)
efi_info("EFI_RNG_PROTOCOL unavailable\n");
- efi_nokaslr = true;
- } else if (status != EFI_SUCCESS) {
- efi_err("efi_get_random_bytes() failed (0x%lx)\n",
- status);
- efi_nokaslr = true;
- }
+ else
+ efi_err("efi_get_random_bytes() failed (0x%lx)\n", status);
+
+ efi_nokaslr = true;
}
return 0;
diff --git a/drivers/firmware/efi/libstub/relocate.c b/drivers/firmware/efi/libstub/relocate.c
index bf6fbd5d22a1..d694bcfa1074 100644
--- a/drivers/firmware/efi/libstub/relocate.c
+++ b/drivers/firmware/efi/libstub/relocate.c
@@ -48,7 +48,7 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
unsigned long m = (unsigned long)map->map;
u64 start, end;
- desc = efi_early_memdesc_ptr(m, map->desc_size, i);
+ desc = efi_memdesc_ptr(m, map->desc_size, i);
if (desc->type != EFI_CONVENTIONAL_MEMORY)
continue;
diff --git a/drivers/firmware/efi/libstub/smbios.c b/drivers/firmware/efi/libstub/smbios.c
index c217de2cc8d5..f31410d7e7e1 100644
--- a/drivers/firmware/efi/libstub/smbios.c
+++ b/drivers/firmware/efi/libstub/smbios.c
@@ -6,20 +6,31 @@
#include "efistub.h"
-typedef struct efi_smbios_protocol efi_smbios_protocol_t;
-
-struct efi_smbios_protocol {
- efi_status_t (__efiapi *add)(efi_smbios_protocol_t *, efi_handle_t,
- u16 *, struct efi_smbios_record *);
- efi_status_t (__efiapi *update_string)(efi_smbios_protocol_t *, u16 *,
- unsigned long *, u8 *);
- efi_status_t (__efiapi *remove)(efi_smbios_protocol_t *, u16);
- efi_status_t (__efiapi *get_next)(efi_smbios_protocol_t *, u16 *, u8 *,
- struct efi_smbios_record **,
- efi_handle_t *);
-
- u8 major_version;
- u8 minor_version;
+typedef union efi_smbios_protocol efi_smbios_protocol_t;
+
+union efi_smbios_protocol {
+ struct {
+ efi_status_t (__efiapi *add)(efi_smbios_protocol_t *, efi_handle_t,
+ u16 *, struct efi_smbios_record *);
+ efi_status_t (__efiapi *update_string)(efi_smbios_protocol_t *, u16 *,
+ unsigned long *, u8 *);
+ efi_status_t (__efiapi *remove)(efi_smbios_protocol_t *, u16);
+ efi_status_t (__efiapi *get_next)(efi_smbios_protocol_t *, u16 *, u8 *,
+ struct efi_smbios_record **,
+ efi_handle_t *);
+
+ u8 major_version;
+ u8 minor_version;
+ };
+ struct {
+ u32 add;
+ u32 update_string;
+ u32 remove;
+ u32 get_next;
+
+ u8 major_version;
+ u8 minor_version;
+ } mixed_mode;
};
const struct efi_smbios_record *efi_get_smbios_record(u8 type)
@@ -38,7 +49,7 @@ const struct efi_smbios_record *efi_get_smbios_record(u8 type)
}
const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
- u8 type, int offset)
+ const u8 *offset)
{
const u8 *strtable;
@@ -46,7 +57,7 @@ const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
return NULL;
strtable = (u8 *)record + record->length;
- for (int i = 1; i < ((u8 *)record)[offset]; i++) {
+ for (int i = 1; i < *offset; i++) {
int len = strlen(strtable);
if (!len)
diff --git a/drivers/firmware/efi/libstub/unaccepted_memory.c b/drivers/firmware/efi/libstub/unaccepted_memory.c
index 9a655f30ba47..c295ea3a6efc 100644
--- a/drivers/firmware/efi/libstub/unaccepted_memory.c
+++ b/drivers/firmware/efi/libstub/unaccepted_memory.c
@@ -29,7 +29,7 @@ efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc,
efi_memory_desc_t *d;
unsigned long m = (unsigned long)map->map;
- d = efi_early_memdesc_ptr(m, map->desc_size, i);
+ d = efi_memdesc_ptr(m, map->desc_size, i);
if (d->type != EFI_UNACCEPTED_MEMORY)
continue;
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 1983fd3bf392..078055b054e3 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -225,6 +225,68 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
}
}
+static bool apple_match_product_name(void)
+{
+ static const char type1_product_matches[][15] = {
+ "MacBookPro11,3",
+ "MacBookPro11,5",
+ "MacBookPro13,3",
+ "MacBookPro14,3",
+ "MacBookPro15,1",
+ "MacBookPro15,3",
+ "MacBookPro16,1",
+ "MacBookPro16,4",
+ };
+ const struct efi_smbios_type1_record *record;
+ const u8 *product;
+
+ record = (struct efi_smbios_type1_record *)efi_get_smbios_record(1);
+ if (!record)
+ return false;
+
+ product = efi_get_smbios_string(record, product_name);
+ if (!product)
+ return false;
+
+ for (int i = 0; i < ARRAY_SIZE(type1_product_matches); i++) {
+ if (!strcmp(product, type1_product_matches[i]))
+ return true;
+ }
+
+ return false;
+}
+
+static void apple_set_os(void)
+{
+ struct {
+ unsigned long version;
+ efi_status_t (__efiapi *set_os_version)(const char *);
+ efi_status_t (__efiapi *set_os_vendor)(const char *);
+ } *set_os;
+ efi_status_t status;
+
+ if (!efi_is_64bit() || !apple_match_product_name())
+ return;
+
+ status = efi_bs_call(locate_protocol, &APPLE_SET_OS_PROTOCOL_GUID, NULL,
+ (void **)&set_os);
+ if (status != EFI_SUCCESS)
+ return;
+
+ if (set_os->version >= 2) {
+ status = set_os->set_os_vendor("Apple Inc.");
+ if (status != EFI_SUCCESS)
+ efi_err("Failed to set OS vendor via apple_set_os\n");
+ }
+
+ if (set_os->version > 0) {
+ /* The version being set doesn't seem to matter */
+ status = set_os->set_os_version("Mac OS X 10.9");
+ if (status != EFI_SUCCESS)
+ efi_err("Failed to set OS version via apple_set_os\n");
+ }
+}
+
efi_status_t efi_adjust_memory_range_protection(unsigned long start,
unsigned long size)
{
@@ -335,9 +397,12 @@ static const efi_char16_t apple[] = L"Apple";
static void setup_quirks(struct boot_params *boot_params)
{
- if (IS_ENABLED(CONFIG_APPLE_PROPERTIES) &&
- !memcmp(efistub_fw_vendor(), apple, sizeof(apple)))
- retrieve_apple_device_properties(boot_params);
+ if (!memcmp(efistub_fw_vendor(), apple, sizeof(apple))) {
+ if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
+ retrieve_apple_device_properties(boot_params);
+
+ apple_set_os();
+ }
}
/*
@@ -476,9 +541,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_status_t status;
char *cmdline_ptr;
- if (efi_is_native())
- memset(_bss, 0, _ebss - _bss);
-
efi_system_table = sys_table_arg;
/* Check if we were booted by the EFI firmware */
@@ -501,16 +563,13 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
/* Convert unicode cmdline to ascii */
cmdline_ptr = efi_convert_cmdline(image, &options_size);
if (!cmdline_ptr)
- goto fail;
+ efi_exit(handle, EFI_OUT_OF_RESOURCES);
efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr,
&boot_params.ext_cmd_line_ptr);
efi_stub_entry(handle, sys_table_arg, &boot_params);
/* not reached */
-
-fail:
- efi_exit(handle, status);
}
static void add_e820ext(struct boot_params *params,
@@ -555,7 +614,7 @@ setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_s
m |= (u64)efi->efi_memmap_hi << 32;
#endif
- d = efi_early_memdesc_ptr(m, efi->efi_memdesc_size, i);
+ d = efi_memdesc_ptr(m, efi->efi_memdesc_size, i);
switch (d->type) {
case EFI_RESERVED_TYPE:
case EFI_RUNTIME_SERVICES_CODE:
@@ -781,7 +840,7 @@ static const char *cmdline_memmap_override;
static efi_status_t parse_options(const char *cmdline)
{
static const char opts[][14] = {
- "mem=", "memmap=", "efi_fake_mem=", "hugepages="
+ "mem=", "memmap=", "hugepages="
};
for (int i = 0; i < ARRAY_SIZE(opts); i++) {
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index ab85bf8e165a..164203429fa7 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -164,7 +164,7 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm,
bool valid;
char buf[64];
- valid = entry_is_valid((void *)tbl->entry + i * tbl->desc_size,
+ valid = entry_is_valid(efi_memdesc_ptr(tbl->entry, tbl->desc_size, i),
&md);
size = md.num_pages << EFI_PAGE_SHIFT;
if (efi_enabled(EFI_DBG) || !valid)
diff --git a/drivers/firmware/google/cbmem.c b/drivers/firmware/google/cbmem.c
index 6f810d720f4d..66042160b361 100644
--- a/drivers/firmware/google/cbmem.c
+++ b/drivers/firmware/google/cbmem.c
@@ -131,4 +131,5 @@ static struct coreboot_driver cbmem_entry_driver = {
module_coreboot_driver(cbmem_entry_driver);
MODULE_AUTHOR("Jack Rosenthal <[email protected]>");
+MODULE_DESCRIPTION("Driver for exporting CBMEM entries in sysfs");
MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c
index fa7752f6e89b..a4e3bbd556a3 100644
--- a/drivers/firmware/google/coreboot_table.c
+++ b/drivers/firmware/google/coreboot_table.c
@@ -255,4 +255,5 @@ module_init(coreboot_table_driver_init);
module_exit(coreboot_table_driver_exit);
MODULE_AUTHOR("Google, Inc.");
+MODULE_DESCRIPTION("Module providing coreboot table access");
MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/google/framebuffer-coreboot.c b/drivers/firmware/google/framebuffer-coreboot.c
index 07c458bf64ec..daadd71d8ddd 100644
--- a/drivers/firmware/google/framebuffer-coreboot.c
+++ b/drivers/firmware/google/framebuffer-coreboot.c
@@ -97,4 +97,5 @@ static struct coreboot_driver framebuffer_driver = {
module_coreboot_driver(framebuffer_driver);
MODULE_AUTHOR("Samuel Holland <[email protected]>");
+MODULE_DESCRIPTION("Memory based framebuffer accessed through coreboot table");
MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c
index 96ea1fa76d35..d304913314e4 100644
--- a/drivers/firmware/google/gsmi.c
+++ b/drivers/firmware/google/gsmi.c
@@ -1090,4 +1090,5 @@ module_init(gsmi_init);
module_exit(gsmi_exit);
MODULE_AUTHOR("Google, Inc.");
+MODULE_DESCRIPTION("EFI SMI interface for Google platforms");
MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/google/memconsole-coreboot.c b/drivers/firmware/google/memconsole-coreboot.c
index 24c97a70aa80..c5f08617aa8d 100644
--- a/drivers/firmware/google/memconsole-coreboot.c
+++ b/drivers/firmware/google/memconsole-coreboot.c
@@ -113,4 +113,5 @@ static struct coreboot_driver memconsole_driver = {
module_coreboot_driver(memconsole_driver);
MODULE_AUTHOR("Google, Inc.");
+MODULE_DESCRIPTION("Memory based BIOS console accessed through coreboot table");
MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/google/memconsole-x86-legacy.c b/drivers/firmware/google/memconsole-x86-legacy.c
index 3d3c4f6b8194..a0974c376985 100644
--- a/drivers/firmware/google/memconsole-x86-legacy.c
+++ b/drivers/firmware/google/memconsole-x86-legacy.c
@@ -154,4 +154,5 @@ module_init(memconsole_x86_init);
module_exit(memconsole_x86_exit);
MODULE_AUTHOR("Google, Inc.");
+MODULE_DESCRIPTION("EBDA specific parts of the memory based BIOS console.");
MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/google/memconsole.c b/drivers/firmware/google/memconsole.c
index 44d314ad69e4..b9d99fe1ff0f 100644
--- a/drivers/firmware/google/memconsole.c
+++ b/drivers/firmware/google/memconsole.c
@@ -50,4 +50,5 @@ void memconsole_exit(void)
EXPORT_SYMBOL(memconsole_exit);
MODULE_AUTHOR("Google, Inc.");
+MODULE_DESCRIPTION("Architecture-independent parts of the memory based BIOS console");
MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c
index 8e4216714b29..1749529f63d4 100644
--- a/drivers/firmware/google/vpd.c
+++ b/drivers/firmware/google/vpd.c
@@ -323,4 +323,5 @@ static struct coreboot_driver vpd_driver = {
module_coreboot_driver(vpd_driver);
MODULE_AUTHOR("Google, Inc.");
+MODULE_DESCRIPTION("Driver for exporting Vital Product Data content to sysfs");
MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
index 5d7f62fe1d5f..f25a9746249b 100644
--- a/drivers/firmware/meson/meson_sm.c
+++ b/drivers/firmware/meson/meson_sm.c
@@ -340,4 +340,5 @@ static struct platform_driver meson_sm_driver = {
},
};
module_platform_driver_probe(meson_sm_driver, meson_sm_probe);
+MODULE_DESCRIPTION("Amlogic Secure Monitor driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/microchip/mpfs-auto-update.c b/drivers/firmware/microchip/mpfs-auto-update.c
index 835a19a7a3a0..30de47895b1c 100644
--- a/drivers/firmware/microchip/mpfs-auto-update.c
+++ b/drivers/firmware/microchip/mpfs-auto-update.c
@@ -9,6 +9,7 @@
*
* Author: Conor Dooley <[email protected]>
*/
+#include <linux/cleanup.h>
#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <linux/math.h>
@@ -71,8 +72,9 @@
#define AUTO_UPDATE_UPGRADE_DIRECTORY (AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_UPGRADE_INDEX)
#define AUTO_UPDATE_BLANK_DIRECTORY (AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_BLANK_INDEX)
#define AUTO_UPDATE_DIRECTORY_SIZE SZ_1K
-#define AUTO_UPDATE_RESERVED_SIZE SZ_1M
-#define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_RESERVED_SIZE)
+#define AUTO_UPDATE_INFO_BASE AUTO_UPDATE_DIRECTORY_SIZE
+#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
@@ -86,6 +88,17 @@ struct mpfs_auto_update_priv {
bool cancel_request;
};
+static bool mpfs_auto_update_is_bitstream_info(const u8 *data, u32 size)
+{
+ if (size < 4)
+ return false;
+
+ if (data[0] == 0x4d && data[1] == 0x43 && data[2] == 0x48 && data[3] == 0x50)
+ return true;
+
+ return false;
+}
+
static enum fw_upload_err mpfs_auto_update_prepare(struct fw_upload *fw_uploader, const u8 *data,
u32 size)
{
@@ -162,28 +175,17 @@ static enum fw_upload_err mpfs_auto_update_poll_complete(struct fw_upload *fw_up
static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader)
{
struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
- struct mpfs_mss_response *response;
- struct mpfs_mss_msg *message;
- u32 *response_msg;
+ u32 *response_msg __free(kfree) =
+ kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL);
+ struct mpfs_mss_response *response __free(kfree) =
+ kzalloc(sizeof(struct mpfs_mss_response), GFP_KERNEL);
+ struct mpfs_mss_msg *message __free(kfree) =
+ kzalloc(sizeof(struct mpfs_mss_msg), GFP_KERNEL);
int ret;
- response_msg = devm_kzalloc(priv->dev, AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg),
- GFP_KERNEL);
- if (!response_msg)
+ if (!response_msg || !response || !message)
return -ENOMEM;
- response = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_response), GFP_KERNEL);
- if (!response) {
- ret = -ENOMEM;
- goto free_response_msg;
- }
-
- message = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_msg), GFP_KERNEL);
- if (!message) {
- ret = -ENOMEM;
- goto free_response;
- }
-
/*
* The system controller can verify that an image in the flash is valid.
* Rather than duplicate the check in this driver, call the relevant
@@ -205,31 +207,25 @@ static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader)
ret = mpfs_blocking_transaction(priv->sys_controller, message);
if (ret | response->resp_status) {
dev_warn(priv->dev, "Verification of Upgrade Image failed!\n");
- ret = ret ? ret : -EBADMSG;
- goto free_message;
+ return ret ? ret : -EBADMSG;
}
dev_info(priv->dev, "Verification of Upgrade Image passed!\n");
-free_message:
- devm_kfree(priv->dev, message);
-free_response:
- devm_kfree(priv->dev, response);
-free_response_msg:
- devm_kfree(priv->dev, response_msg);
-
- return ret;
+ return 0;
}
-static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv, char *buffer,
+static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv,
u32 image_address, loff_t directory_address)
{
struct erase_info erase;
- size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE;
+ size_t erase_size = round_up(AUTO_UPDATE_DIRECTORY_SIZE, (u64)priv->flash->erasesize);
size_t bytes_written = 0, bytes_read = 0;
+ char *buffer __free(kfree) = kzalloc(erase_size, GFP_KERNEL);
int ret;
- erase_size = round_up(erase_size, (u64)priv->flash->erasesize);
+ if (!buffer)
+ return -ENOMEM;
erase.addr = AUTO_UPDATE_DIRECTORY_BASE;
erase.len = erase_size;
@@ -275,7 +271,7 @@ static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv
return ret;
if (bytes_written != erase_size)
- return ret;
+ return -EIO;
return 0;
}
@@ -285,26 +281,36 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
{
struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
struct erase_info erase;
- char *buffer;
loff_t directory_address = AUTO_UPDATE_UPGRADE_DIRECTORY;
size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE;
size_t bytes_written = 0;
+ bool is_info = mpfs_auto_update_is_bitstream_info(data, size);
u32 image_address;
int ret;
erase_size = round_up(erase_size, (u64)priv->flash->erasesize);
- image_address = AUTO_UPDATE_BITSTREAM_BASE +
- AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream;
-
- buffer = devm_kzalloc(priv->dev, erase_size, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
+ if (is_info)
+ image_address = AUTO_UPDATE_INFO_BASE;
+ else
+ image_address = AUTO_UPDATE_BITSTREAM_BASE +
+ AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream;
- ret = mpfs_auto_update_set_image_address(priv, buffer, image_address, directory_address);
- if (ret) {
- dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret);
- goto out;
+ /*
+ * For bitstream info, the descriptor is written to a fixed offset,
+ * so there is no need to set the image address.
+ */
+ if (!is_info) {
+ ret = mpfs_auto_update_set_image_address(priv, image_address, directory_address);
+ if (ret) {
+ dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret);
+ return ret;
+ }
+ } else {
+ if (size > AUTO_UPDATE_INFO_SIZE) {
+ dev_err(priv->dev, "bitstream info exceeds permitted size\n");
+ return -ENOSPC;
+ }
}
/*
@@ -318,7 +324,7 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
dev_info(priv->dev, "Erasing the flash at address (0x%x)\n", image_address);
ret = mtd_erase(priv->flash, &erase);
if (ret)
- goto out;
+ return ret;
/*
* No parsing etc of the bitstream is required. The system controller
@@ -328,18 +334,15 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
dev_info(priv->dev, "Writing the image to the flash at address (0x%x)\n", image_address);
ret = mtd_write(priv->flash, (loff_t)image_address, size, &bytes_written, data);
if (ret)
- goto out;
+ return ret;
- if (bytes_written != size) {
- ret = -EIO;
- goto out;
- }
+ if (bytes_written != size)
+ return -EIO;
*written = bytes_written;
+ dev_info(priv->dev, "Wrote 0x%zx bytes to the flash\n", bytes_written);
-out:
- devm_kfree(priv->dev, buffer);
- return ret;
+ return 0;
}
static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader, const u8 *data,
@@ -362,6 +365,9 @@ static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader,
goto out;
}
+ if (mpfs_auto_update_is_bitstream_info(data, size))
+ goto out;
+
ret = mpfs_auto_update_verify_image(fw_uploader);
if (ret)
err = FW_UPLOAD_ERR_FW_INVALID;
@@ -381,23 +387,15 @@ static const struct fw_upload_ops mpfs_auto_update_ops = {
static int mpfs_auto_update_available(struct mpfs_auto_update_priv *priv)
{
- struct mpfs_mss_response *response;
- struct mpfs_mss_msg *message;
- u32 *response_msg;
+ u32 *response_msg __free(kfree) =
+ kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL);
+ struct mpfs_mss_response *response __free(kfree) =
+ kzalloc(sizeof(struct mpfs_mss_response), GFP_KERNEL);
+ struct mpfs_mss_msg *message __free(kfree) =
+ kzalloc(sizeof(struct mpfs_mss_msg), GFP_KERNEL);
int ret;
- response_msg = devm_kzalloc(priv->dev,
- AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg),
- GFP_KERNEL);
- if (!response_msg)
- return -ENOMEM;
-
- response = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_response), GFP_KERNEL);
- if (!response)
- return -ENOMEM;
-
- message = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_msg), GFP_KERNEL);
- if (!message)
+ if (!response_msg || !response || !message)
return -ENOMEM;
/*
diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig
index 3f05d9854ddf..7f6eb4174734 100644
--- a/drivers/firmware/qcom/Kconfig
+++ b/drivers/firmware/qcom/Kconfig
@@ -7,8 +7,39 @@
menu "Qualcomm firmware drivers"
config QCOM_SCM
+ select QCOM_TZMEM
tristate
+config QCOM_TZMEM
+ tristate
+ select GENERIC_ALLOCATOR
+
+choice
+ prompt "TrustZone interface memory allocator mode"
+ default QCOM_TZMEM_MODE_GENERIC
+ help
+ Selects the mode of the memory allocator providing memory buffers of
+ suitable format for sharing with the TrustZone. If in doubt, select
+ 'Generic'.
+
+config QCOM_TZMEM_MODE_GENERIC
+ bool "Generic"
+ help
+ Use the generic allocator mode. The memory is page-aligned, non-cachable
+ and physically contiguous.
+
+config QCOM_TZMEM_MODE_SHMBRIDGE
+ bool "SHM Bridge"
+ help
+ Use Qualcomm Shared Memory Bridge. The memory has the same alignment as
+ in the 'Generic' allocator but is also explicitly marked as an SHM Bridge
+ buffer.
+
+ With this selected, all buffers passed to the TrustZone must be allocated
+ using the TZMem allocator or else the TrustZone will refuse to use them.
+
+endchoice
+
config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
bool "Qualcomm download mode enabled by default"
depends on QCOM_SCM
diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile
index c9f12ee8224a..0be40a1abc13 100644
--- a/drivers/firmware/qcom/Makefile
+++ b/drivers/firmware/qcom/Makefile
@@ -5,5 +5,6 @@
obj-$(CONFIG_QCOM_SCM) += qcom-scm.o
qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
+obj-$(CONFIG_QCOM_TZMEM) += qcom_tzmem.o
obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o
obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o
diff --git a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
index bc550ad0dbe0..6fefa4fe80e8 100644
--- a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
+++ b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
@@ -13,11 +13,14 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/ucs2_string.h>
#include <linux/firmware/qcom/qcom_qseecom.h>
+#include <linux/firmware/qcom/qcom_scm.h>
+#include <linux/firmware/qcom/qcom_tzmem.h>
/* -- Qualcomm "uefisecapp" interface definitions. -------------------------- */
@@ -272,6 +275,7 @@ struct qsee_rsp_uefi_query_variable_info {
struct qcuefi_client {
struct qseecom_client *client;
struct efivars efivars;
+ struct qcom_tzmem_pool *mempool;
};
static struct device *qcuefi_dev(struct qcuefi_client *qcuefi)
@@ -293,12 +297,11 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
{
struct qsee_req_uefi_get_variable *req_data;
struct qsee_rsp_uefi_get_variable *rsp_data;
+ void *cmd_buf __free(qcom_tzmem) = NULL;
unsigned long buffer_size = *data_size;
- efi_status_t efi_status = EFI_SUCCESS;
unsigned long name_length;
- dma_addr_t cmd_buf_dma;
+ efi_status_t efi_status;
size_t cmd_buf_size;
- void *cmd_buf;
size_t guid_offs;
size_t name_offs;
size_t req_size;
@@ -333,11 +336,9 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
__reqdata_offs(rsp_size, &rsp_offs)
);
- cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
- if (!cmd_buf) {
- efi_status = EFI_OUT_OF_RESOURCES;
- goto out;
- }
+ cmd_buf = qcom_tzmem_alloc(qcuefi->mempool, cmd_buf_size, GFP_KERNEL);
+ if (!cmd_buf)
+ return EFI_OUT_OF_RESOURCES;
req_data = cmd_buf + req_offs;
rsp_data = cmd_buf + rsp_offs;
@@ -351,30 +352,22 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
req_data->length = req_size;
status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length);
- if (status < 0) {
- efi_status = EFI_INVALID_PARAMETER;
- goto out_free;
- }
+ if (status < 0)
+ return EFI_INVALID_PARAMETER;
memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
status = qcom_qseecom_app_send(qcuefi->client,
- cmd_buf_dma + req_offs, req_size,
- cmd_buf_dma + rsp_offs, rsp_size);
- if (status) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ cmd_buf + req_offs, req_size,
+ cmd_buf + rsp_offs, rsp_size);
+ if (status)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->command_id != QSEE_CMD_UEFI_GET_VARIABLE) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->command_id != QSEE_CMD_UEFI_GET_VARIABLE)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->length < sizeof(*rsp_data)) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->length < sizeof(*rsp_data))
+ return EFI_DEVICE_ERROR;
if (rsp_data->status) {
dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
@@ -388,18 +381,14 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
*attributes = rsp_data->attributes;
}
- goto out_free;
+ return qsee_uefi_status_to_efi(rsp_data->status);
}
- if (rsp_data->length > rsp_size) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->length > rsp_size)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->data_offset + rsp_data->data_size > rsp_data->length) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->data_offset + rsp_data->data_size > rsp_data->length)
+ return EFI_DEVICE_ERROR;
/*
* Note: We need to set attributes and data size even if the buffer is
@@ -422,22 +411,15 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
if (attributes)
*attributes = rsp_data->attributes;
- if (buffer_size == 0 && !data) {
- efi_status = EFI_SUCCESS;
- goto out_free;
- }
+ if (buffer_size == 0 && !data)
+ return EFI_SUCCESS;
- if (buffer_size < rsp_data->data_size) {
- efi_status = EFI_BUFFER_TOO_SMALL;
- goto out_free;
- }
+ if (buffer_size < rsp_data->data_size)
+ return EFI_BUFFER_TOO_SMALL;
memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size);
-out_free:
- qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
-out:
- return efi_status;
+ return EFI_SUCCESS;
}
static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const efi_char16_t *name,
@@ -446,11 +428,9 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
{
struct qsee_req_uefi_set_variable *req_data;
struct qsee_rsp_uefi_set_variable *rsp_data;
- efi_status_t efi_status = EFI_SUCCESS;
+ void *cmd_buf __free(qcom_tzmem) = NULL;
unsigned long name_length;
- dma_addr_t cmd_buf_dma;
size_t cmd_buf_size;
- void *cmd_buf;
size_t name_offs;
size_t guid_offs;
size_t data_offs;
@@ -486,11 +466,9 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
__reqdata_offs(sizeof(*rsp_data), &rsp_offs)
);
- cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
- if (!cmd_buf) {
- efi_status = EFI_OUT_OF_RESOURCES;
- goto out;
- }
+ cmd_buf = qcom_tzmem_alloc(qcuefi->mempool, cmd_buf_size, GFP_KERNEL);
+ if (!cmd_buf)
+ return EFI_OUT_OF_RESOURCES;
req_data = cmd_buf + req_offs;
rsp_data = cmd_buf + rsp_offs;
@@ -506,10 +484,8 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
req_data->length = req_size;
status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length);
- if (status < 0) {
- efi_status = EFI_INVALID_PARAMETER;
- goto out_free;
- }
+ if (status < 0)
+ return EFI_INVALID_PARAMETER;
memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
@@ -517,33 +493,24 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
memcpy(((void *)req_data) + req_data->data_offset, data, req_data->data_size);
status = qcom_qseecom_app_send(qcuefi->client,
- cmd_buf_dma + req_offs, req_size,
- cmd_buf_dma + rsp_offs, sizeof(*rsp_data));
- if (status) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ cmd_buf + req_offs, req_size,
+ cmd_buf + rsp_offs, sizeof(*rsp_data));
+ if (status)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->command_id != QSEE_CMD_UEFI_SET_VARIABLE) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->command_id != QSEE_CMD_UEFI_SET_VARIABLE)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->length != sizeof(*rsp_data)) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->length != sizeof(*rsp_data))
+ return EFI_DEVICE_ERROR;
if (rsp_data->status) {
dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
__func__, rsp_data->status);
- efi_status = qsee_uefi_status_to_efi(rsp_data->status);
+ return qsee_uefi_status_to_efi(rsp_data->status);
}
-out_free:
- qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
-out:
- return efi_status;
+ return EFI_SUCCESS;
}
static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
@@ -552,10 +519,9 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
{
struct qsee_req_uefi_get_next_variable *req_data;
struct qsee_rsp_uefi_get_next_variable *rsp_data;
- efi_status_t efi_status = EFI_SUCCESS;
- dma_addr_t cmd_buf_dma;
+ void *cmd_buf __free(qcom_tzmem) = NULL;
+ efi_status_t efi_status;
size_t cmd_buf_size;
- void *cmd_buf;
size_t guid_offs;
size_t name_offs;
size_t req_size;
@@ -587,11 +553,9 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
__reqdata_offs(rsp_size, &rsp_offs)
);
- cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
- if (!cmd_buf) {
- efi_status = EFI_OUT_OF_RESOURCES;
- goto out;
- }
+ cmd_buf = qcom_tzmem_alloc(qcuefi->mempool, cmd_buf_size, GFP_KERNEL);
+ if (!cmd_buf)
+ return EFI_OUT_OF_RESOURCES;
req_data = cmd_buf + req_offs;
rsp_data = cmd_buf + rsp_offs;
@@ -606,28 +570,20 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name,
*name_size / sizeof(*name));
- if (status < 0) {
- efi_status = EFI_INVALID_PARAMETER;
- goto out_free;
- }
+ if (status < 0)
+ return EFI_INVALID_PARAMETER;
status = qcom_qseecom_app_send(qcuefi->client,
- cmd_buf_dma + req_offs, req_size,
- cmd_buf_dma + rsp_offs, rsp_size);
- if (status) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ cmd_buf + req_offs, req_size,
+ cmd_buf + rsp_offs, rsp_size);
+ if (status)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->command_id != QSEE_CMD_UEFI_GET_NEXT_VARIABLE) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->command_id != QSEE_CMD_UEFI_GET_NEXT_VARIABLE)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->length < sizeof(*rsp_data)) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->length < sizeof(*rsp_data))
+ return EFI_DEVICE_ERROR;
if (rsp_data->status) {
dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
@@ -642,53 +598,40 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
if (efi_status == EFI_BUFFER_TOO_SMALL)
*name_size = rsp_data->name_size;
- goto out_free;
+ return efi_status;
}
- if (rsp_data->length > rsp_size) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->length > rsp_size)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->name_offset + rsp_data->name_size > rsp_data->length) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->name_offset + rsp_data->name_size > rsp_data->length)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->guid_offset + rsp_data->guid_size > rsp_data->length) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->guid_offset + rsp_data->guid_size > rsp_data->length)
+ return EFI_DEVICE_ERROR;
if (rsp_data->name_size > *name_size) {
*name_size = rsp_data->name_size;
- efi_status = EFI_BUFFER_TOO_SMALL;
- goto out_free;
+ return EFI_BUFFER_TOO_SMALL;
}
- if (rsp_data->guid_size != sizeof(*guid)) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->guid_size != sizeof(*guid))
+ return EFI_DEVICE_ERROR;
memcpy(guid, ((void *)rsp_data) + rsp_data->guid_offset, rsp_data->guid_size);
status = ucs2_strscpy(name, ((void *)rsp_data) + rsp_data->name_offset,
rsp_data->name_size / sizeof(*name));
*name_size = rsp_data->name_size;
- if (status < 0) {
+ if (status < 0)
/*
* Return EFI_DEVICE_ERROR here because the buffer size should
* have already been validated above, causing this function to
* bail with EFI_BUFFER_TOO_SMALL.
*/
- efi_status = EFI_DEVICE_ERROR;
- }
+ return EFI_DEVICE_ERROR;
-out_free:
- qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
-out:
- return efi_status;
+ return EFI_SUCCESS;
}
static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi, u32 attr,
@@ -697,10 +640,8 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
{
struct qsee_req_uefi_query_variable_info *req_data;
struct qsee_rsp_uefi_query_variable_info *rsp_data;
- efi_status_t efi_status = EFI_SUCCESS;
- dma_addr_t cmd_buf_dma;
+ void *cmd_buf __free(qcom_tzmem) = NULL;
size_t cmd_buf_size;
- void *cmd_buf;
size_t req_offs;
size_t rsp_offs;
int status;
@@ -710,11 +651,9 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
__reqdata_offs(sizeof(*rsp_data), &rsp_offs)
);
- cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
- if (!cmd_buf) {
- efi_status = EFI_OUT_OF_RESOURCES;
- goto out;
- }
+ cmd_buf = qcom_tzmem_alloc(qcuefi->mempool, cmd_buf_size, GFP_KERNEL);
+ if (!cmd_buf)
+ return EFI_OUT_OF_RESOURCES;
req_data = cmd_buf + req_offs;
rsp_data = cmd_buf + rsp_offs;
@@ -724,28 +663,21 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
req_data->length = sizeof(*req_data);
status = qcom_qseecom_app_send(qcuefi->client,
- cmd_buf_dma + req_offs, sizeof(*req_data),
- cmd_buf_dma + rsp_offs, sizeof(*rsp_data));
- if (status) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ cmd_buf + req_offs, sizeof(*req_data),
+ cmd_buf + rsp_offs, sizeof(*rsp_data));
+ if (status)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->command_id != QSEE_CMD_UEFI_QUERY_VARIABLE_INFO) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->command_id != QSEE_CMD_UEFI_QUERY_VARIABLE_INFO)
+ return EFI_DEVICE_ERROR;
- if (rsp_data->length != sizeof(*rsp_data)) {
- efi_status = EFI_DEVICE_ERROR;
- goto out_free;
- }
+ if (rsp_data->length != sizeof(*rsp_data))
+ return EFI_DEVICE_ERROR;
if (rsp_data->status) {
dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
__func__, rsp_data->status);
- efi_status = qsee_uefi_status_to_efi(rsp_data->status);
- goto out_free;
+ return qsee_uefi_status_to_efi(rsp_data->status);
}
if (storage_space)
@@ -757,10 +689,7 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
if (max_variable_size)
*max_variable_size = rsp_data->max_variable_size;
-out_free:
- qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
-out:
- return efi_status;
+ return EFI_SUCCESS;
}
/* -- Global efivar interface. ---------------------------------------------- */
@@ -871,6 +800,7 @@ static const struct efivar_operations qcom_efivar_ops = {
static int qcom_uefisecapp_probe(struct auxiliary_device *aux_dev,
const struct auxiliary_device_id *aux_dev_id)
{
+ struct qcom_tzmem_pool_config pool_config;
struct qcuefi_client *qcuefi;
int status;
@@ -889,6 +819,16 @@ static int qcom_uefisecapp_probe(struct auxiliary_device *aux_dev,
if (status)
qcuefi_set_reference(NULL);
+ memset(&pool_config, 0, sizeof(pool_config));
+ pool_config.initial_size = SZ_4K;
+ pool_config.policy = QCOM_TZMEM_POLICY_MULTIPLIER;
+ pool_config.increment = 2;
+ pool_config.max_size = SZ_256K;
+
+ qcuefi->mempool = devm_qcom_tzmem_pool_new(&aux_dev->dev, &pool_config);
+ if (IS_ERR(qcuefi->mempool))
+ return PTR_ERR(qcuefi->mempool);
+
return status;
}
diff --git a/drivers/firmware/qcom/qcom_scm-smc.c b/drivers/firmware/qcom/qcom_scm-smc.c
index 16cf88acfa8e..dca5f3f1883b 100644
--- a/drivers/firmware/qcom/qcom_scm-smc.c
+++ b/drivers/firmware/qcom/qcom_scm-smc.c
@@ -2,6 +2,7 @@
/* Copyright (c) 2015,2019 The Linux Foundation. All rights reserved.
*/
+#include <linux/cleanup.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/delay.h>
@@ -9,6 +10,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/firmware/qcom/qcom_scm.h>
+#include <linux/firmware/qcom/qcom_tzmem.h>
#include <linux/arm-smccc.h>
#include <linux/dma-mapping.h>
@@ -150,11 +152,10 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
enum qcom_scm_convention qcom_convention,
struct qcom_scm_res *res, bool atomic)
{
+ struct qcom_tzmem_pool *mempool = qcom_scm_get_tzmem_pool();
int arglen = desc->arginfo & 0xf;
int i, ret;
- dma_addr_t args_phys = 0;
- void *args_virt = NULL;
- size_t alloc_len;
+ void *args_virt __free(qcom_tzmem) = NULL;
gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL;
u32 smccc_call_type = atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL;
u32 qcom_smccc_convention = (qcom_convention == SMC_CONVENTION_ARM_32) ?
@@ -172,9 +173,9 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
smc.args[i + SCM_SMC_FIRST_REG_IDX] = desc->args[i];
if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) {
- alloc_len = SCM_SMC_N_EXT_ARGS * sizeof(u64);
- args_virt = kzalloc(PAGE_ALIGN(alloc_len), flag);
-
+ args_virt = qcom_tzmem_alloc(mempool,
+ SCM_SMC_N_EXT_ARGS * sizeof(u64),
+ flag);
if (!args_virt)
return -ENOMEM;
@@ -192,25 +193,10 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
SCM_SMC_FIRST_EXT_IDX]);
}
- args_phys = dma_map_single(dev, args_virt, alloc_len,
- DMA_TO_DEVICE);
-
- if (dma_mapping_error(dev, args_phys)) {
- kfree(args_virt);
- return -ENOMEM;
- }
-
- smc.args[SCM_SMC_LAST_REG_IDX] = args_phys;
+ smc.args[SCM_SMC_LAST_REG_IDX] = qcom_tzmem_to_phys(args_virt);
}
- /* ret error check follows after args_virt cleanup*/
ret = __scm_smc_do(dev, &smc, &smc_res, atomic);
-
- if (args_virt) {
- dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
- kfree(args_virt);
- }
-
if (ret)
return ret;
diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 68f4df7e6c3c..00c379a3cceb 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -6,12 +6,15 @@
#include <linux/arm-smccc.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/cpumask.h>
#include <linux/dma-mapping.h>
+#include <linux/err.h>
#include <linux/export.h>
#include <linux/firmware/qcom/qcom_scm.h>
+#include <linux/firmware/qcom/qcom_tzmem.h>
#include <linux/init.h>
#include <linux/interconnect.h>
#include <linux/interrupt.h>
@@ -20,11 +23,14 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
+#include <linux/sizes.h>
#include <linux/types.h>
#include "qcom_scm.h"
+#include "qcom_tzmem.h"
static bool download_mode = IS_ENABLED(CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT);
module_param(download_mode, bool, 0);
@@ -43,6 +49,8 @@ struct qcom_scm {
int scm_vote_count;
u64 dload_mode_addr;
+
+ struct qcom_tzmem_pool *mempool;
};
struct qcom_scm_current_perm_info {
@@ -114,7 +122,6 @@ static const u8 qcom_scm_cpu_warm_bits[QCOM_SCM_BOOT_MAX_CPUS] = {
};
#define QCOM_SMC_WAITQ_FLAG_WAKE_ONE BIT(0)
-#define QCOM_SMC_WAITQ_FLAG_WAKE_ALL BIT(1)
#define QCOM_DLOAD_MASK GENMASK(5, 4)
#define QCOM_DLOAD_NODUMP 0
@@ -198,6 +205,11 @@ static void qcom_scm_bw_disable(void)
enum qcom_scm_convention qcom_scm_convention = SMC_CONVENTION_UNKNOWN;
static DEFINE_SPINLOCK(scm_query_lock);
+struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void)
+{
+ return __scm->mempool;
+}
+
static enum qcom_scm_convention __get_convention(void)
{
unsigned long flags;
@@ -570,6 +582,13 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size,
* During the scm call memory protection will be enabled for the meta
* data blob, so make sure it's physically contiguous, 4K aligned and
* non-cachable to avoid XPU violations.
+ *
+ * For PIL calls the hypervisor creates SHM Bridges for the blob
+ * buffers on behalf of Linux so we must not do it ourselves hence
+ * not using the TZMem allocator here.
+ *
+ * If we pass a buffer that is already part of an SHM Bridge to this
+ * call, it will fail.
*/
mdata_buf = dma_alloc_coherent(__scm->dev, size, &mdata_phys,
GFP_KERNEL);
@@ -1008,14 +1027,13 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
struct qcom_scm_mem_map_info *mem_to_map;
phys_addr_t mem_to_map_phys;
phys_addr_t dest_phys;
- dma_addr_t ptr_phys;
+ phys_addr_t ptr_phys;
size_t mem_to_map_sz;
size_t dest_sz;
size_t src_sz;
size_t ptr_sz;
int next_vm;
__le32 *src;
- void *ptr;
int ret, i, b;
u64 srcvm_bits = *srcvm;
@@ -1025,10 +1043,13 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) +
ALIGN(dest_sz, SZ_64);
- ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_phys, GFP_KERNEL);
+ void *ptr __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
+ ptr_sz, GFP_KERNEL);
if (!ptr)
return -ENOMEM;
+ ptr_phys = qcom_tzmem_to_phys(ptr);
+
/* Fill source vmid detail */
src = ptr;
i = 0;
@@ -1057,7 +1078,6 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
ret = __qcom_scm_assign_mem(__scm->dev, mem_to_map_phys, mem_to_map_sz,
ptr_phys, src_sz, dest_phys, dest_sz);
- dma_free_coherent(__scm->dev, ptr_sz, ptr, ptr_phys);
if (ret) {
dev_err(__scm->dev,
"Assign memory protection call failed %d\n", ret);
@@ -1205,32 +1225,21 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
.args[4] = data_unit_size,
.owner = ARM_SMCCC_OWNER_SIP,
};
- void *keybuf;
- dma_addr_t key_phys;
- int ret;
- /*
- * 'key' may point to vmalloc()'ed memory, but we need to pass a
- * physical address that's been properly flushed. The sanctioned way to
- * do this is by using the DMA API. But as is best practice for crypto
- * keys, we also must wipe the key after use. This makes kmemdup() +
- * dma_map_single() not clearly correct, since the DMA API can use
- * bounce buffers. Instead, just use dma_alloc_coherent(). Programming
- * keys is normally rare and thus not performance-critical.
- */
+ int ret;
- keybuf = dma_alloc_coherent(__scm->dev, key_size, &key_phys,
- GFP_KERNEL);
+ void *keybuf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
+ key_size,
+ GFP_KERNEL);
if (!keybuf)
return -ENOMEM;
memcpy(keybuf, key, key_size);
- desc.args[1] = key_phys;
+ desc.args[1] = qcom_tzmem_to_phys(keybuf);
ret = qcom_scm_call(__scm->dev, &desc, NULL);
memzero_explicit(keybuf, key_size);
- dma_free_coherent(__scm->dev, key_size, keybuf, key_phys);
return ret;
}
EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key);
@@ -1342,6 +1351,66 @@ bool qcom_scm_lmh_dcvsh_available(void)
}
EXPORT_SYMBOL_GPL(qcom_scm_lmh_dcvsh_available);
+int qcom_scm_shm_bridge_enable(void)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_MP,
+ .cmd = QCOM_SCM_MP_SHM_BRIDGE_ENABLE,
+ .owner = ARM_SMCCC_OWNER_SIP
+ };
+
+ struct qcom_scm_res res;
+
+ if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_MP,
+ QCOM_SCM_MP_SHM_BRIDGE_ENABLE))
+ return -EOPNOTSUPP;
+
+ return qcom_scm_call(__scm->dev, &desc, &res) ?: res.result[0];
+}
+EXPORT_SYMBOL_GPL(qcom_scm_shm_bridge_enable);
+
+int qcom_scm_shm_bridge_create(struct device *dev, u64 pfn_and_ns_perm_flags,
+ u64 ipfn_and_s_perm_flags, u64 size_and_flags,
+ u64 ns_vmids, u64 *handle)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_MP,
+ .cmd = QCOM_SCM_MP_SHM_BRIDGE_CREATE,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ .args[0] = pfn_and_ns_perm_flags,
+ .args[1] = ipfn_and_s_perm_flags,
+ .args[2] = size_and_flags,
+ .args[3] = ns_vmids,
+ .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL,
+ QCOM_SCM_VAL, QCOM_SCM_VAL),
+ };
+
+ struct qcom_scm_res res;
+ int ret;
+
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+
+ if (handle && !ret)
+ *handle = res.result[1];
+
+ return ret ?: res.result[0];
+}
+EXPORT_SYMBOL_GPL(qcom_scm_shm_bridge_create);
+
+int qcom_scm_shm_bridge_delete(struct device *dev, u64 handle)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_MP,
+ .cmd = QCOM_SCM_MP_SHM_BRIDGE_DELETE,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ .args[0] = handle,
+ .arginfo = QCOM_SCM_ARGS(1, QCOM_SCM_VAL),
+ };
+
+ return qcom_scm_call(__scm->dev, &desc, NULL);
+}
+EXPORT_SYMBOL_GPL(qcom_scm_shm_bridge_delete);
+
int qcom_scm_lmh_profile_change(u32 profile_id)
{
struct qcom_scm_desc desc = {
@@ -1359,8 +1428,6 @@ EXPORT_SYMBOL_GPL(qcom_scm_lmh_profile_change);
int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val,
u64 limit_node, u32 node_id, u64 version)
{
- dma_addr_t payload_phys;
- u32 *payload_buf;
int ret, payload_size = 5 * sizeof(u32);
struct qcom_scm_desc desc = {
@@ -1375,7 +1442,9 @@ int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val,
.owner = ARM_SMCCC_OWNER_SIP,
};
- payload_buf = dma_alloc_coherent(__scm->dev, payload_size, &payload_phys, GFP_KERNEL);
+ u32 *payload_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
+ payload_size,
+ GFP_KERNEL);
if (!payload_buf)
return -ENOMEM;
@@ -1385,15 +1454,28 @@ int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val,
payload_buf[3] = 1;
payload_buf[4] = payload_val;
- desc.args[0] = payload_phys;
+ desc.args[0] = qcom_tzmem_to_phys(payload_buf);
ret = qcom_scm_call(__scm->dev, &desc, NULL);
- dma_free_coherent(__scm->dev, payload_size, payload_buf, payload_phys);
return ret;
}
EXPORT_SYMBOL_GPL(qcom_scm_lmh_dcvsh);
+int qcom_scm_gpu_init_regs(u32 gpu_req)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_GPU,
+ .cmd = QCOM_SCM_SVC_GPU_INIT_REGS,
+ .arginfo = QCOM_SCM_ARGS(1),
+ .args[0] = gpu_req,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+
+ return qcom_scm_call(__scm->dev, &desc, NULL);
+}
+EXPORT_SYMBOL_GPL(qcom_scm_gpu_init_regs);
+
static int qcom_scm_find_dload_address(struct device *dev, u64 *addr)
{
struct device_node *tcsr;
@@ -1545,37 +1627,27 @@ int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id)
unsigned long app_name_len = strlen(app_name);
struct qcom_scm_desc desc = {};
struct qcom_scm_qseecom_resp res = {};
- dma_addr_t name_buf_phys;
- char *name_buf;
int status;
if (app_name_len >= name_buf_size)
return -EINVAL;
- name_buf = kzalloc(name_buf_size, GFP_KERNEL);
+ char *name_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool,
+ name_buf_size,
+ GFP_KERNEL);
if (!name_buf)
return -ENOMEM;
memcpy(name_buf, app_name, app_name_len);
- name_buf_phys = dma_map_single(__scm->dev, name_buf, name_buf_size, DMA_TO_DEVICE);
- status = dma_mapping_error(__scm->dev, name_buf_phys);
- if (status) {
- kfree(name_buf);
- dev_err(__scm->dev, "qseecom: failed to map dma address\n");
- return status;
- }
-
desc.owner = QSEECOM_TZ_OWNER_QSEE_OS;
desc.svc = QSEECOM_TZ_SVC_APP_MGR;
desc.cmd = QSEECOM_TZ_CMD_APP_LOOKUP;
desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL);
- desc.args[0] = name_buf_phys;
+ desc.args[0] = qcom_tzmem_to_phys(name_buf);
desc.args[1] = app_name_len;
status = qcom_scm_qseecom_call(&desc, &res);
- dma_unmap_single(__scm->dev, name_buf_phys, name_buf_size, DMA_TO_DEVICE);
- kfree(name_buf);
if (status)
return status;
@@ -1597,9 +1669,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id);
/**
* qcom_scm_qseecom_app_send() - Send to and receive data from a given QSEE app.
* @app_id: The ID of the target app.
- * @req: DMA address of the request buffer sent to the app.
+ * @req: Request buffer sent to the app (must be TZ memory)
* @req_size: Size of the request buffer.
- * @rsp: DMA address of the response buffer, written to by the app.
+ * @rsp: Response buffer, written to by the app (must be TZ memory)
* @rsp_size: Size of the response buffer.
*
* Sends a request to the QSEE app associated with the given ID and read back
@@ -1610,13 +1682,18 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id);
*
* Return: Zero on success, nonzero on failure.
*/
-int qcom_scm_qseecom_app_send(u32 app_id, dma_addr_t req, size_t req_size,
- dma_addr_t rsp, size_t rsp_size)
+int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size,
+ void *rsp, size_t rsp_size)
{
struct qcom_scm_qseecom_resp res = {};
struct qcom_scm_desc desc = {};
+ phys_addr_t req_phys;
+ phys_addr_t rsp_phys;
int status;
+ req_phys = qcom_tzmem_to_phys(req);
+ rsp_phys = qcom_tzmem_to_phys(rsp);
+
desc.owner = QSEECOM_TZ_OWNER_TZ_APPS;
desc.svc = QSEECOM_TZ_SVC_APP_ID_PLACEHOLDER;
desc.cmd = QSEECOM_TZ_CMD_APP_SEND;
@@ -1624,9 +1701,9 @@ int qcom_scm_qseecom_app_send(u32 app_id, dma_addr_t req, size_t req_size,
QCOM_SCM_RW, QCOM_SCM_VAL,
QCOM_SCM_RW, QCOM_SCM_VAL);
desc.args[0] = app_id;
- desc.args[1] = req;
+ desc.args[1] = req_phys;
desc.args[2] = req_size;
- desc.args[3] = rsp;
+ desc.args[3] = rsp_phys;
desc.args[4] = rsp_size;
status = qcom_scm_qseecom_call(&desc, &res);
@@ -1649,6 +1726,8 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
{ .compatible = "lenovo,flex-5g" },
{ .compatible = "lenovo,thinkpad-x13s", },
{ .compatible = "qcom,sc8180x-primus" },
+ { .compatible = "qcom,x1e80100-crd" },
+ { .compatible = "qcom,x1e80100-qcp" },
{ }
};
@@ -1793,9 +1872,8 @@ static irqreturn_t qcom_scm_irq_handler(int irq, void *data)
goto out;
}
- if (flags != QCOM_SMC_WAITQ_FLAG_WAKE_ONE &&
- flags != QCOM_SMC_WAITQ_FLAG_WAKE_ALL) {
- dev_err(scm->dev, "Invalid flags found for wq_ctx: %u\n", flags);
+ if (flags != QCOM_SMC_WAITQ_FLAG_WAKE_ONE) {
+ dev_err(scm->dev, "Invalid flags received for wq_ctx: %u\n", flags);
goto out;
}
@@ -1810,6 +1888,7 @@ out:
static int qcom_scm_probe(struct platform_device *pdev)
{
+ struct qcom_tzmem_pool_config pool_config;
struct qcom_scm *scm;
int irq, ret;
@@ -1885,6 +1964,26 @@ static int qcom_scm_probe(struct platform_device *pdev)
if (of_property_read_bool(pdev->dev.of_node, "qcom,sdi-enabled"))
qcom_scm_disable_sdi();
+ ret = of_reserved_mem_device_init(__scm->dev);
+ if (ret && ret != -ENODEV)
+ return dev_err_probe(__scm->dev, ret,
+ "Failed to setup the reserved memory region for TZ mem\n");
+
+ ret = qcom_tzmem_enable(__scm->dev);
+ if (ret)
+ return dev_err_probe(__scm->dev, ret,
+ "Failed to enable the TrustZone memory allocator\n");
+
+ memset(&pool_config, 0, sizeof(pool_config));
+ pool_config.initial_size = 0;
+ pool_config.policy = QCOM_TZMEM_POLICY_ON_DEMAND;
+ pool_config.max_size = SZ_256K;
+
+ __scm->mempool = devm_qcom_tzmem_pool_new(__scm->dev, &pool_config);
+ if (IS_ERR(__scm->mempool))
+ return dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool),
+ "Failed to create the SCM memory pool\n");
+
/*
* Initialize the QSEECOM interface.
*
diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h
index 4532907e8489..685b8f59e7a6 100644
--- a/drivers/firmware/qcom/qcom_scm.h
+++ b/drivers/firmware/qcom/qcom_scm.h
@@ -5,6 +5,7 @@
#define __QCOM_SCM_INT_H
struct device;
+struct qcom_tzmem_pool;
enum qcom_scm_convention {
SMC_CONVENTION_UNKNOWN,
@@ -78,6 +79,8 @@ int scm_legacy_call_atomic(struct device *dev, const struct qcom_scm_desc *desc,
int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
struct qcom_scm_res *res);
+struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void);
+
#define QCOM_SCM_SVC_BOOT 0x01
#define QCOM_SCM_BOOT_SET_ADDR 0x01
#define QCOM_SCM_BOOT_TERMINATE_PC 0x02
@@ -113,6 +116,9 @@ int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
#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_SHM_BRIDGE_ENABLE 0x1c
+#define QCOM_SCM_MP_SHM_BRIDGE_DELETE 0x1d
+#define QCOM_SCM_MP_SHM_BRIDGE_CREATE 0x1e
#define QCOM_SCM_SVC_OCMEM 0x0f
#define QCOM_SCM_OCMEM_LOCK_CMD 0x01
@@ -138,6 +144,9 @@ int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
#define QCOM_SCM_WAITQ_RESUME 0x02
#define QCOM_SCM_WAITQ_GET_WQ_CTX 0x03
+#define QCOM_SCM_SVC_GPU 0x28
+#define QCOM_SCM_SVC_GPU_INIT_REGS 0x01
+
/* common error codes */
#define QCOM_SCM_V2_EBUSY -12
#define QCOM_SCM_ENOMEM -5
diff --git a/drivers/firmware/qcom/qcom_tzmem.c b/drivers/firmware/qcom/qcom_tzmem.c
new file mode 100644
index 000000000000..17948cfc82e7
--- /dev/null
+++ b/drivers/firmware/qcom/qcom_tzmem.c
@@ -0,0 +1,469 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Memory allocator for buffers shared with the TrustZone.
+ *
+ * Copyright (C) 2023-2024 Linaro Ltd.
+ */
+
+#include <linux/bug.h>
+#include <linux/cleanup.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/firmware/qcom/qcom_tzmem.h>
+#include <linux/genalloc.h>
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/radix-tree.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include "qcom_tzmem.h"
+
+struct qcom_tzmem_area {
+ struct list_head list;
+ void *vaddr;
+ dma_addr_t paddr;
+ size_t size;
+ void *priv;
+};
+
+struct qcom_tzmem_pool {
+ struct gen_pool *genpool;
+ struct list_head areas;
+ enum qcom_tzmem_policy policy;
+ size_t increment;
+ size_t max_size;
+ spinlock_t lock;
+};
+
+struct qcom_tzmem_chunk {
+ phys_addr_t paddr;
+ size_t size;
+ struct qcom_tzmem_pool *owner;
+};
+
+static struct device *qcom_tzmem_dev;
+static RADIX_TREE(qcom_tzmem_chunks, GFP_ATOMIC);
+static DEFINE_SPINLOCK(qcom_tzmem_chunks_lock);
+
+#if IS_ENABLED(CONFIG_QCOM_TZMEM_MODE_GENERIC)
+
+static int qcom_tzmem_init(void)
+{
+ return 0;
+}
+
+static int qcom_tzmem_init_area(struct qcom_tzmem_area *area)
+{
+ return 0;
+}
+
+static void qcom_tzmem_cleanup_area(struct qcom_tzmem_area *area)
+{
+
+}
+
+#elif IS_ENABLED(CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE)
+
+#include <linux/firmware/qcom/qcom_scm.h>
+#include <linux/of.h>
+
+#define QCOM_SHM_BRIDGE_NUM_VM_SHIFT 9
+
+static bool qcom_tzmem_using_shm_bridge;
+
+/* List of machines that are known to not support SHM bridge correctly. */
+static const char *const qcom_tzmem_blacklist[] = {
+ "qcom,sc8180x",
+ "qcom,sdm845", /* reset in rmtfs memory assignment */
+ "qcom,sm8150", /* reset in rmtfs memory assignment */
+ NULL
+};
+
+static int qcom_tzmem_init(void)
+{
+ const char *const *platform;
+ int ret;
+
+ for (platform = qcom_tzmem_blacklist; *platform; platform++) {
+ if (of_machine_is_compatible(*platform))
+ goto notsupp;
+ }
+
+ ret = qcom_scm_shm_bridge_enable();
+ if (ret == -EOPNOTSUPP)
+ goto notsupp;
+
+ if (!ret)
+ qcom_tzmem_using_shm_bridge = true;
+
+ return ret;
+
+notsupp:
+ dev_info(qcom_tzmem_dev, "SHM Bridge not supported\n");
+ return 0;
+}
+
+static int qcom_tzmem_init_area(struct qcom_tzmem_area *area)
+{
+ u64 pfn_and_ns_perm, ipfn_and_s_perm, size_and_flags;
+ int ret;
+
+ if (!qcom_tzmem_using_shm_bridge)
+ return 0;
+
+ pfn_and_ns_perm = (u64)area->paddr | QCOM_SCM_PERM_RW;
+ ipfn_and_s_perm = (u64)area->paddr | QCOM_SCM_PERM_RW;
+ size_and_flags = area->size | (1 << QCOM_SHM_BRIDGE_NUM_VM_SHIFT);
+
+ u64 *handle __free(kfree) = kzalloc(sizeof(*handle), GFP_KERNEL);
+ if (!handle)
+ return -ENOMEM;
+
+ ret = qcom_scm_shm_bridge_create(qcom_tzmem_dev, pfn_and_ns_perm,
+ ipfn_and_s_perm, size_and_flags,
+ QCOM_SCM_VMID_HLOS, handle);
+ if (ret)
+ return ret;
+
+ area->priv = no_free_ptr(handle);
+
+ return 0;
+}
+
+static void qcom_tzmem_cleanup_area(struct qcom_tzmem_area *area)
+{
+ u64 *handle = area->priv;
+
+ if (!qcom_tzmem_using_shm_bridge)
+ return;
+
+ qcom_scm_shm_bridge_delete(qcom_tzmem_dev, *handle);
+ kfree(handle);
+}
+
+#endif /* CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE */
+
+static int qcom_tzmem_pool_add_memory(struct qcom_tzmem_pool *pool,
+ size_t size, gfp_t gfp)
+{
+ int ret;
+
+ struct qcom_tzmem_area *area __free(kfree) = kzalloc(sizeof(*area),
+ gfp);
+ if (!area)
+ return -ENOMEM;
+
+ area->size = PAGE_ALIGN(size);
+
+ area->vaddr = dma_alloc_coherent(qcom_tzmem_dev, area->size,
+ &area->paddr, gfp);
+ if (!area->vaddr)
+ return -ENOMEM;
+
+ ret = qcom_tzmem_init_area(area);
+ if (ret) {
+ dma_free_coherent(qcom_tzmem_dev, area->size,
+ area->vaddr, area->paddr);
+ return ret;
+ }
+
+ ret = gen_pool_add_virt(pool->genpool, (unsigned long)area->vaddr,
+ (phys_addr_t)area->paddr, size, -1);
+ if (ret) {
+ dma_free_coherent(qcom_tzmem_dev, area->size,
+ area->vaddr, area->paddr);
+ return ret;
+ }
+
+ scoped_guard(spinlock_irqsave, &pool->lock)
+ list_add_tail(&area->list, &pool->areas);
+
+ area = NULL;
+ return 0;
+}
+
+/**
+ * qcom_tzmem_pool_new() - Create a new TZ memory pool.
+ * @config: Pool configuration.
+ *
+ * Create a new pool of memory suitable for sharing with the TrustZone.
+ *
+ * Must not be used in atomic context.
+ *
+ * Return: New memory pool address or ERR_PTR() on error.
+ */
+struct qcom_tzmem_pool *
+qcom_tzmem_pool_new(const struct qcom_tzmem_pool_config *config)
+{
+ int ret = -ENOMEM;
+
+ might_sleep();
+
+ switch (config->policy) {
+ case QCOM_TZMEM_POLICY_STATIC:
+ if (!config->initial_size)
+ return ERR_PTR(-EINVAL);
+ break;
+ case QCOM_TZMEM_POLICY_MULTIPLIER:
+ if (!config->increment)
+ return ERR_PTR(-EINVAL);
+ break;
+ case QCOM_TZMEM_POLICY_ON_DEMAND:
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ struct qcom_tzmem_pool *pool __free(kfree) = kzalloc(sizeof(*pool),
+ GFP_KERNEL);
+ if (!pool)
+ return ERR_PTR(-ENOMEM);
+
+ pool->genpool = gen_pool_create(PAGE_SHIFT, -1);
+ if (!pool->genpool)
+ return ERR_PTR(-ENOMEM);
+
+ gen_pool_set_algo(pool->genpool, gen_pool_best_fit, NULL);
+
+ pool->policy = config->policy;
+ pool->increment = config->increment;
+ pool->max_size = config->max_size;
+ INIT_LIST_HEAD(&pool->areas);
+ spin_lock_init(&pool->lock);
+
+ if (config->initial_size) {
+ ret = qcom_tzmem_pool_add_memory(pool, config->initial_size,
+ GFP_KERNEL);
+ if (ret) {
+ gen_pool_destroy(pool->genpool);
+ return ERR_PTR(ret);
+ }
+ }
+
+ return_ptr(pool);
+}
+EXPORT_SYMBOL_GPL(qcom_tzmem_pool_new);
+
+/**
+ * qcom_tzmem_pool_free() - Destroy a TZ memory pool and free all resources.
+ * @pool: Memory pool to free.
+ *
+ * Must not be called if any of the allocated chunks has not been freed.
+ * Must not be used in atomic context.
+ */
+void qcom_tzmem_pool_free(struct qcom_tzmem_pool *pool)
+{
+ struct qcom_tzmem_area *area, *next;
+ struct qcom_tzmem_chunk *chunk;
+ struct radix_tree_iter iter;
+ bool non_empty = false;
+ void __rcu **slot;
+
+ might_sleep();
+
+ if (!pool)
+ return;
+
+ scoped_guard(spinlock_irqsave, &qcom_tzmem_chunks_lock) {
+ radix_tree_for_each_slot(slot, &qcom_tzmem_chunks, &iter, 0) {
+ chunk = radix_tree_deref_slot_protected(slot,
+ &qcom_tzmem_chunks_lock);
+
+ if (chunk->owner == pool)
+ non_empty = true;
+ }
+ }
+
+ WARN(non_empty, "Freeing TZ memory pool with memory still allocated");
+
+ list_for_each_entry_safe(area, next, &pool->areas, list) {
+ list_del(&area->list);
+ qcom_tzmem_cleanup_area(area);
+ dma_free_coherent(qcom_tzmem_dev, area->size,
+ area->vaddr, area->paddr);
+ kfree(area);
+ }
+
+ gen_pool_destroy(pool->genpool);
+ kfree(pool);
+}
+EXPORT_SYMBOL_GPL(qcom_tzmem_pool_free);
+
+static void devm_qcom_tzmem_pool_free(void *data)
+{
+ struct qcom_tzmem_pool *pool = data;
+
+ qcom_tzmem_pool_free(pool);
+}
+
+/**
+ * devm_qcom_tzmem_pool_new() - Managed variant of qcom_tzmem_pool_new().
+ * @dev: Device managing this resource.
+ * @config: Pool configuration.
+ *
+ * Must not be used in atomic context.
+ *
+ * Return: Address of the managed pool or ERR_PTR() on failure.
+ */
+struct qcom_tzmem_pool *
+devm_qcom_tzmem_pool_new(struct device *dev,
+ const struct qcom_tzmem_pool_config *config)
+{
+ struct qcom_tzmem_pool *pool;
+ int ret;
+
+ pool = qcom_tzmem_pool_new(config);
+ if (IS_ERR(pool))
+ return pool;
+
+ ret = devm_add_action_or_reset(dev, devm_qcom_tzmem_pool_free, pool);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return pool;
+}
+EXPORT_SYMBOL_GPL(devm_qcom_tzmem_pool_new);
+
+static bool qcom_tzmem_try_grow_pool(struct qcom_tzmem_pool *pool,
+ size_t requested, gfp_t gfp)
+{
+ size_t current_size = gen_pool_size(pool->genpool);
+
+ if (pool->max_size && (current_size + requested) > pool->max_size)
+ return false;
+
+ switch (pool->policy) {
+ case QCOM_TZMEM_POLICY_STATIC:
+ return false;
+ case QCOM_TZMEM_POLICY_MULTIPLIER:
+ requested = current_size * pool->increment;
+ break;
+ case QCOM_TZMEM_POLICY_ON_DEMAND:
+ break;
+ }
+
+ return !qcom_tzmem_pool_add_memory(pool, requested, gfp);
+}
+
+/**
+ * qcom_tzmem_alloc() - Allocate a memory chunk suitable for sharing with TZ.
+ * @pool: TZ memory pool from which to allocate memory.
+ * @size: Number of bytes to allocate.
+ * @gfp: GFP flags.
+ *
+ * Can be used in any context.
+ *
+ * Return:
+ * Address of the allocated buffer or NULL if no more memory can be allocated.
+ * The buffer must be released using qcom_tzmem_free().
+ */
+void *qcom_tzmem_alloc(struct qcom_tzmem_pool *pool, size_t size, gfp_t gfp)
+{
+ unsigned long vaddr;
+ int ret;
+
+ if (!size)
+ return NULL;
+
+ size = PAGE_ALIGN(size);
+
+ struct qcom_tzmem_chunk *chunk __free(kfree) = kzalloc(sizeof(*chunk),
+ gfp);
+ if (!chunk)
+ return NULL;
+
+again:
+ vaddr = gen_pool_alloc(pool->genpool, size);
+ if (!vaddr) {
+ if (qcom_tzmem_try_grow_pool(pool, size, gfp))
+ goto again;
+
+ return NULL;
+ }
+
+ chunk->paddr = gen_pool_virt_to_phys(pool->genpool, vaddr);
+ chunk->size = size;
+ chunk->owner = pool;
+
+ scoped_guard(spinlock_irqsave, &qcom_tzmem_chunks_lock) {
+ ret = radix_tree_insert(&qcom_tzmem_chunks, vaddr, chunk);
+ if (ret) {
+ gen_pool_free(pool->genpool, vaddr, size);
+ return NULL;
+ }
+
+ chunk = NULL;
+ }
+
+ return (void *)vaddr;
+}
+EXPORT_SYMBOL_GPL(qcom_tzmem_alloc);
+
+/**
+ * qcom_tzmem_free() - Release a buffer allocated from a TZ memory pool.
+ * @vaddr: Virtual address of the buffer.
+ *
+ * Can be used in any context.
+ */
+void qcom_tzmem_free(void *vaddr)
+{
+ struct qcom_tzmem_chunk *chunk;
+
+ scoped_guard(spinlock_irqsave, &qcom_tzmem_chunks_lock)
+ chunk = radix_tree_delete_item(&qcom_tzmem_chunks,
+ (unsigned long)vaddr, NULL);
+
+ if (!chunk) {
+ WARN(1, "Virtual address %p not owned by TZ memory allocator",
+ vaddr);
+ return;
+ }
+
+ scoped_guard(spinlock_irqsave, &chunk->owner->lock)
+ gen_pool_free(chunk->owner->genpool, (unsigned long)vaddr,
+ chunk->size);
+ kfree(chunk);
+}
+EXPORT_SYMBOL_GPL(qcom_tzmem_free);
+
+/**
+ * qcom_tzmem_to_phys() - Map the virtual address of a TZ buffer to physical.
+ * @vaddr: Virtual address of the buffer allocated from a TZ memory pool.
+ *
+ * Can be used in any context. The address must have been returned by a call
+ * to qcom_tzmem_alloc().
+ *
+ * Returns: Physical address of the buffer.
+ */
+phys_addr_t qcom_tzmem_to_phys(void *vaddr)
+{
+ struct qcom_tzmem_chunk *chunk;
+
+ guard(spinlock_irqsave)(&qcom_tzmem_chunks_lock);
+
+ chunk = radix_tree_lookup(&qcom_tzmem_chunks, (unsigned long)vaddr);
+ if (!chunk)
+ return 0;
+
+ return chunk->paddr;
+}
+EXPORT_SYMBOL_GPL(qcom_tzmem_to_phys);
+
+int qcom_tzmem_enable(struct device *dev)
+{
+ if (qcom_tzmem_dev)
+ return -EBUSY;
+
+ qcom_tzmem_dev = dev;
+
+ return qcom_tzmem_init();
+}
+EXPORT_SYMBOL_GPL(qcom_tzmem_enable);
+
+MODULE_DESCRIPTION("TrustZone memory allocator for Qualcomm firmware drivers");
+MODULE_AUTHOR("Bartosz Golaszewski <[email protected]>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/qcom/qcom_tzmem.h b/drivers/firmware/qcom/qcom_tzmem.h
new file mode 100644
index 000000000000..8fa8a3eb940e
--- /dev/null
+++ b/drivers/firmware/qcom/qcom_tzmem.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023-2024 Linaro Ltd.
+ */
+
+#ifndef __QCOM_TZMEM_PRIV_H
+#define __QCOM_TZMEM_PRIV_H
+
+struct device;
+
+int qcom_tzmem_enable(struct device *dev);
+
+#endif /* __QCOM_TZMEM_PRIV_H */
diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
index 880ffcb50088..921f61507ae8 100644
--- a/drivers/firmware/sysfb.c
+++ b/drivers/firmware/sysfb.c
@@ -101,8 +101,10 @@ static __init struct device *sysfb_parent_dev(const struct screen_info *si)
if (IS_ERR(pdev)) {
return ERR_CAST(pdev);
} else if (pdev) {
- if (!sysfb_pci_dev_is_enabled(pdev))
+ if (!sysfb_pci_dev_is_enabled(pdev)) {
+ pci_dev_put(pdev);
return ERR_PTR(-ENODEV);
+ }
return &pdev->dev;
}
@@ -137,7 +139,7 @@ static __init int sysfb_init(void)
if (compatible) {
pd = sysfb_create_simplefb(si, &mode, parent);
if (!IS_ERR(pd))
- goto unlock_mutex;
+ goto put_device;
}
/* if the FB is incompatible, create a legacy framebuffer device */
@@ -155,7 +157,7 @@ static __init int sysfb_init(void)
pd = platform_device_alloc(name, 0);
if (!pd) {
ret = -ENOMEM;
- goto unlock_mutex;
+ goto put_device;
}
pd->dev.parent = parent;
@@ -170,9 +172,11 @@ static __init int sysfb_init(void)
if (ret)
goto err;
- goto unlock_mutex;
+ goto put_device;
err:
platform_device_put(pd);
+put_device:
+ put_device(parent);
unlock_mutex:
mutex_unlock(&disable_lock);
return ret;
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index ef3a8214d002..5846c60220f5 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -4,7 +4,7 @@
*
* Communication protocol with TI SCI hardware
* The system works in a message response protocol
- * See: http://processors.wiki.ti.com/index.php/TISCI for details
+ * See: https://software-dl.ti.com/tisci/esd/latest/index.html for details
*
* Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
*/
diff --git a/drivers/firmware/turris-mox-rwtm.c b/drivers/firmware/turris-mox-rwtm.c
index 31d962cdd6eb..3e7f186d239a 100644
--- a/drivers/firmware/turris-mox-rwtm.c
+++ b/drivers/firmware/turris-mox-rwtm.c
@@ -2,7 +2,7 @@
/*
* Turris Mox rWTM firmware driver
*
- * Copyright (C) 2019 Marek Behún <[email protected]>
+ * Copyright (C) 2019, 2024 Marek Behún <[email protected]>
*/
#include <linux/armada-37xx-rwtm-mailbox.h>
@@ -174,6 +174,9 @@ static void mox_rwtm_rx_callback(struct mbox_client *cl, void *data)
struct mox_rwtm *rwtm = dev_get_drvdata(cl->dev);
struct armada_37xx_rwtm_rx_msg *msg = data;
+ if (completion_done(&rwtm->cmd_done))
+ return;
+
rwtm->reply = *msg;
complete(&rwtm->cmd_done);
}
@@ -199,9 +202,8 @@ static int mox_get_board_info(struct mox_rwtm *rwtm)
if (ret < 0)
return ret;
- ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
- if (ret < 0)
- return ret;
+ if (!wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2))
+ return -ETIMEDOUT;
ret = mox_get_status(MBOX_CMD_BOARD_INFO, reply->retval);
if (ret == -ENODATA) {
@@ -235,9 +237,8 @@ static int mox_get_board_info(struct mox_rwtm *rwtm)
if (ret < 0)
return ret;
- ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
- if (ret < 0)
- return ret;
+ if (!wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2))
+ return -ETIMEDOUT;
ret = mox_get_status(MBOX_CMD_ECDSA_PUB_KEY, reply->retval);
if (ret == -ENODATA) {
@@ -274,9 +275,8 @@ static int check_get_random_support(struct mox_rwtm *rwtm)
if (ret < 0)
return ret;
- ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
- if (ret < 0)
- return ret;
+ if (!wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2))
+ return -ETIMEDOUT;
return mox_get_status(MBOX_CMD_GET_RANDOM, rwtm->reply.retval);
}
@@ -499,6 +499,7 @@ static int turris_mox_rwtm_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rwtm);
mutex_init(&rwtm->busy);
+ init_completion(&rwtm->cmd_done);
rwtm->mbox_client.dev = dev;
rwtm->mbox_client.rx_callback = mox_rwtm_rx_callback;
@@ -512,8 +513,6 @@ static int turris_mox_rwtm_probe(struct platform_device *pdev)
goto remove_files;
}
- init_completion(&rwtm->cmd_done);
-
ret = mox_get_board_info(rwtm);
if (ret < 0)
dev_warn(dev, "Cannot read board information: %i\n", ret);
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 9bc45357e1a8..add8acf66a9c 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -41,9 +41,6 @@
/* IOCTL/QUERY feature payload size */
#define FEATURE_PAYLOAD_SIZE 2
-/* Firmware feature check version mask */
-#define FIRMWARE_VERSION_MASK GENMASK(15, 0)
-
static bool feature_check_enabled;
static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
static u32 ioctl_features[FEATURE_PAYLOAD_SIZE];
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 1c28a48915bb..58f43bcced7c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -219,7 +219,7 @@ config GPIO_BCM_XGS_IPROC
config GPIO_BRCMSTB
tristate "BRCMSTB GPIO support"
default y if (ARCH_BRCMSTB || BMIPS_GENERIC)
- depends on OF_GPIO && (ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST)
+ depends on OF_GPIO && (ARCH_BRCMSTB || ARCH_BCM2835 || BMIPS_GENERIC || COMPILE_TEST)
select GPIO_GENERIC
select IRQ_DOMAIN
help
@@ -1891,4 +1891,35 @@ config GPIO_SIM
endmenu
+menu "GPIO Debugging utilities"
+
+config GPIO_SLOPPY_LOGIC_ANALYZER
+ tristate "Sloppy GPIO logic analyzer"
+ depends on (GPIOLIB || COMPILE_TEST) && CPUSETS && DEBUG_FS && EXPERT
+ help
+ This option enables support for a sloppy logic analyzer using polled
+ GPIOs. Use the 'tools/gpio/gpio-sloppy-logic-analyzer' script with
+ this driver. The script will make it easier to use and will also
+ isolate a CPU for the polling task. Note that this is a last resort
+ analyzer which can be affected by latencies, non-deterministic code
+ paths, or NMIs. However, for e.g. remote development, it may be useful
+ to get a first view and aid further debugging.
+
+ If this driver is built as a module it will be called
+ 'gpio-sloppy-logic-analyzer'.
+
+config GPIO_VIRTUSER
+ tristate "GPIO Virtual User Testing Module"
+ select DEBUG_FS
+ select CONFIGFS_FS
+ select IRQ_WORK
+ help
+ Say Y here to enable the configurable, configfs-based virtual GPIO
+ consumer testing driver.
+
+ This driver is aimed as a helper in spotting any regressions in
+ hot-unplug handling in GPIOLIB.
+
+endmenu
+
endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index e2a53013780e..64dd6d9d730d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -150,6 +150,7 @@ obj-$(CONFIG_GPIO_SIFIVE) += gpio-sifive.o
obj-$(CONFIG_GPIO_SIM) += gpio-sim.o
obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o
obj-$(CONFIG_GPIO_SL28CPLD) += gpio-sl28cpld.o
+obj-$(CONFIG_GPIO_SLOPPY_LOGIC_ANALYZER) += gpio-sloppy-logic-analyzer.o
obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o
obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
obj-$(CONFIG_GPIO_SPRD) += gpio-sprd.o
@@ -181,6 +182,7 @@ obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o
obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
+obj-$(CONFIG_GPIO_VIRTUSER) += gpio-virtuser.o
obj-$(CONFIG_GPIO_VIRTIO) += gpio-virtio.o
obj-$(CONFIG_GPIO_VISCONTI) += gpio-visconti.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
diff --git a/drivers/gpio/gpio-amd8111.c b/drivers/gpio/gpio-amd8111.c
index 6f3ded619c8b..3377667a28de 100644
--- a/drivers/gpio/gpio-amd8111.c
+++ b/drivers/gpio/gpio-amd8111.c
@@ -195,8 +195,10 @@ static int __init amd_gpio_init(void)
found:
err = pci_read_config_dword(pdev, 0x58, &gp.pmbase);
- if (err)
+ if (err) {
+ err = pcibios_err_to_errno(err);
goto out;
+ }
err = -EIO;
gp.pmbase &= 0x0000FF00;
if (gp.pmbase == 0)
diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c
index f0c0c0f77eb0..6211d99a5770 100644
--- a/drivers/gpio/gpio-ath79.c
+++ b/drivers/gpio/gpio-ath79.c
@@ -273,8 +273,6 @@ static int ath79_gpio_probe(struct platform_device *pdev)
dev_err(dev, "bgpio_init failed\n");
return err;
}
- /* Use base 0 to stay compatible with legacy platforms */
- ctrl->gc.base = 0;
/* Optional interrupt setup */
if (!np || of_property_read_bool(np, "interrupt-controller")) {
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
index 94f6fefc011b..5fb357d7b78a 100644
--- a/drivers/gpio/gpio-mc33880.c
+++ b/drivers/gpio/gpio-mc33880.c
@@ -99,7 +99,7 @@ static int mc33880_probe(struct spi_device *spi)
mc->spi = spi;
- mc->chip.label = DRIVER_NAME,
+ mc->chip.label = DRIVER_NAME;
mc->chip.set = mc33880_set;
mc->chip.base = pdata->base;
mc->chip.ngpio = PIN_NUMBER;
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 71e1af7c2184..d89e78f0ead3 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -619,8 +619,6 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,
ret = gpiochip_get_ngpios(gc, dev);
if (ret)
gc->ngpio = gc->bgpio_bits;
- else
- gc->bgpio_bits = roundup_pow_of_two(round_up(gc->ngpio, 8));
ret = bgpio_setup_io(gc, dat, set, clr, flags);
if (ret)
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 732a6964748c..8baf3edd5274 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -1315,6 +1315,7 @@ static const struct of_device_id pca953x_dt_ids[] = {
{ .compatible = "ti,tca6408", .data = OF_953X( 8, PCA_INT), },
{ .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), },
{ .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), },
+ { .compatible = "ti,tca9535", .data = OF_953X(16, PCA_INT), },
{ .compatible = "ti,tca9538", .data = OF_953X( 8, PCA_INT), },
{ .compatible = "ti,tca9539", .data = OF_953X(16, PCA_INT), },
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
index 01ed2517e9fd..ec7fb9220a47 100644
--- a/drivers/gpio/gpio-rdc321x.c
+++ b/drivers/gpio/gpio-rdc321x.c
@@ -102,7 +102,7 @@ static int rdc_gpio_config(struct gpio_chip *chip,
unlock:
spin_unlock(&gpch->lock);
- return err;
+ return pcibios_err_to_errno(err);
}
/* configure GPIO pin as input */
@@ -170,13 +170,13 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
rdc321x_gpio_dev->reg1_data_base,
&rdc321x_gpio_dev->data_reg[0]);
if (err)
- return err;
+ return pcibios_err_to_errno(err);
err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
rdc321x_gpio_dev->reg2_data_base,
&rdc321x_gpio_dev->data_reg[1]);
if (err)
- return err;
+ return pcibios_err_to_errno(err);
dev_info(&pdev->dev, "registering %d GPIOs\n",
rdc321x_gpio_dev->chip.ngpio);
diff --git a/drivers/gpio/gpio-sim.c b/drivers/gpio/gpio-sim.c
index 2ed5cbe7c8a8..dcca1d7f173e 100644
--- a/drivers/gpio/gpio-sim.c
+++ b/drivers/gpio/gpio-sim.c
@@ -7,6 +7,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/array_size.h>
#include <linux/bitmap.h>
#include <linux/cleanup.h>
#include <linux/completion.h>
@@ -20,7 +21,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irq_sim.h>
-#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/minmax.h>
@@ -227,6 +227,27 @@ static void gpio_sim_free(struct gpio_chip *gc, unsigned int offset)
}
}
+static int gpio_sim_irq_requested(struct irq_domain *domain,
+ irq_hw_number_t hwirq, void *data)
+{
+ struct gpio_sim_chip *chip = data;
+
+ return gpiochip_lock_as_irq(&chip->gc, hwirq);
+}
+
+static void gpio_sim_irq_released(struct irq_domain *domain,
+ irq_hw_number_t hwirq, void *data)
+{
+ struct gpio_sim_chip *chip = data;
+
+ gpiochip_unlock_as_irq(&chip->gc, hwirq);
+}
+
+static const struct irq_sim_ops gpio_sim_irq_sim_ops = {
+ .irq_sim_irq_requested = gpio_sim_irq_requested,
+ .irq_sim_irq_released = gpio_sim_irq_released,
+};
+
static void gpio_sim_dbg_show(struct seq_file *seq, struct gpio_chip *gc)
{
struct gpio_sim_chip *chip = gpiochip_get_data(gc);
@@ -308,13 +329,6 @@ static ssize_t gpio_sim_sysfs_pull_store(struct device *dev,
return len;
}
-static void gpio_sim_mutex_destroy(void *data)
-{
- struct mutex *lock = data;
-
- mutex_destroy(lock);
-}
-
static void gpio_sim_put_device(void *data)
{
struct device *dev = data;
@@ -450,7 +464,9 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
if (!chip->pull_map)
return -ENOMEM;
- chip->irq_sim = devm_irq_domain_create_sim(dev, swnode, num_lines);
+ chip->irq_sim = devm_irq_domain_create_sim_full(dev, swnode, num_lines,
+ &gpio_sim_irq_sim_ops,
+ chip);
if (IS_ERR(chip->irq_sim))
return PTR_ERR(chip->irq_sim);
@@ -458,9 +474,7 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
if (ret)
return ret;
- mutex_init(&chip->lock);
- ret = devm_add_action_or_reset(dev, gpio_sim_mutex_destroy,
- &chip->lock);
+ ret = devm_mutex_init(dev, &chip->lock);
if (ret)
return ret;
@@ -581,19 +595,19 @@ static int gpio_sim_bus_notifier_call(struct notifier_block *nb,
snprintf(devname, sizeof(devname), "gpio-sim.%u", simdev->id);
- if (strcmp(dev_name(dev), devname) == 0) {
- if (action == BUS_NOTIFY_BOUND_DRIVER)
- simdev->driver_bound = true;
- else if (action == BUS_NOTIFY_DRIVER_NOT_BOUND)
- simdev->driver_bound = false;
- else
- return NOTIFY_DONE;
+ if (!device_match_name(dev, devname))
+ return NOTIFY_DONE;
- complete(&simdev->probe_completion);
- return NOTIFY_OK;
- }
+ if (action == BUS_NOTIFY_BOUND_DRIVER)
+ simdev->driver_bound = true;
+ else if (action == BUS_NOTIFY_DRIVER_NOT_BOUND)
+ simdev->driver_bound = false;
+ else
+ return NOTIFY_DONE;
+
+ complete(&simdev->probe_completion);
- return NOTIFY_DONE;
+ return NOTIFY_OK;
}
static struct gpio_sim_device *to_gpio_sim_device(struct config_item *item)
diff --git a/drivers/gpio/gpio-sloppy-logic-analyzer.c b/drivers/gpio/gpio-sloppy-logic-analyzer.c
new file mode 100644
index 000000000000..aed6d1f6cfc3
--- /dev/null
+++ b/drivers/gpio/gpio-sloppy-logic-analyzer.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Sloppy logic analyzer using GPIOs (to be run on an isolated CPU)
+ *
+ * Use the 'gpio-sloppy-logic-analyzer' script in the 'tools/gpio' folder for
+ * easier usage and further documentation. Note that this is a last resort
+ * analyzer which can be affected by latencies and non-deterministic code
+ * paths. However, for e.g. remote development, it may be useful to get a first
+ * view and aid further debugging.
+ *
+ * Copyright (C) Wolfram Sang <[email protected]>
+ * Copyright (C) Renesas Electronics Corporation
+ */
+
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/ktime.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/sizes.h>
+#include <linux/timekeeping.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+
+#define GPIO_LA_NAME "gpio-sloppy-logic-analyzer"
+#define GPIO_LA_DEFAULT_BUF_SIZE SZ_256K
+/* can be increased but then we need to extend the u8 buffers */
+#define GPIO_LA_MAX_PROBES 8
+#define GPIO_LA_NUM_TESTS 1024
+
+struct gpio_la_poll_priv {
+ struct mutex blob_lock; /* serialize access to the blob (data) */
+ u32 buf_idx;
+ struct gpio_descs *descs;
+ unsigned long delay_ns;
+ unsigned long acq_delay;
+ struct debugfs_blob_wrapper blob;
+ struct dentry *debug_dir;
+ struct dentry *blob_dent;
+ struct debugfs_blob_wrapper meta;
+ struct device *dev;
+ unsigned int trig_len;
+ u8 *trig_data;
+};
+
+static struct dentry *gpio_la_poll_debug_dir;
+
+static __always_inline int gpio_la_get_array(struct gpio_descs *d, unsigned long *sptr)
+{
+ int ret;
+
+ ret = gpiod_get_array_value(d->ndescs, d->desc, d->info, sptr);
+ if (ret == 0 && fatal_signal_pending(current))
+ ret = -EINTR;
+
+ return ret;
+}
+
+static int fops_capture_set(void *data, u64 val)
+{
+ struct gpio_la_poll_priv *priv = data;
+ u8 *la_buf = priv->blob.data;
+ unsigned long state = 0; /* zeroed because GPIO arrays are bitfields */
+ unsigned long delay;
+ ktime_t start_time;
+ unsigned int i;
+ int ret;
+
+ if (!val)
+ return 0;
+
+ if (!la_buf)
+ return -ENOMEM;
+
+ if (!priv->delay_ns)
+ return -EINVAL;
+
+ mutex_lock(&priv->blob_lock);
+ if (priv->blob_dent) {
+ debugfs_remove(priv->blob_dent);
+ priv->blob_dent = NULL;
+ }
+
+ priv->buf_idx = 0;
+
+ local_irq_disable();
+ preempt_disable_notrace();
+
+ /* Measure delay of reading GPIOs */
+ start_time = ktime_get();
+ for (i = 0; i < GPIO_LA_NUM_TESTS; i++) {
+ ret = gpio_la_get_array(priv->descs, &state);
+ if (ret)
+ goto out;
+ }
+
+ priv->acq_delay = ktime_sub(ktime_get(), start_time) / GPIO_LA_NUM_TESTS;
+ if (priv->delay_ns < priv->acq_delay) {
+ ret = -ERANGE;
+ goto out;
+ }
+
+ delay = priv->delay_ns - priv->acq_delay;
+
+ /* Wait for triggers */
+ for (i = 0; i < priv->trig_len; i += 2) {
+ do {
+ ret = gpio_la_get_array(priv->descs, &state);
+ if (ret)
+ goto out;
+
+ ndelay(delay);
+ } while ((state & priv->trig_data[i]) != priv->trig_data[i + 1]);
+ }
+
+ /* With triggers, final state is also the first sample */
+ if (priv->trig_len)
+ la_buf[priv->buf_idx++] = state;
+
+ /* Sample */
+ while (priv->buf_idx < priv->blob.size) {
+ ret = gpio_la_get_array(priv->descs, &state);
+ if (ret)
+ goto out;
+
+ la_buf[priv->buf_idx++] = state;
+ ndelay(delay);
+ }
+out:
+ preempt_enable_notrace();
+ local_irq_enable();
+ if (ret)
+ dev_err(priv->dev, "couldn't read GPIOs: %d\n", ret);
+
+ kfree(priv->trig_data);
+ priv->trig_data = NULL;
+ priv->trig_len = 0;
+
+ priv->blob_dent = debugfs_create_blob("sample_data", 0400, priv->debug_dir, &priv->blob);
+ mutex_unlock(&priv->blob_lock);
+
+ return ret;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_capture, NULL, fops_capture_set, "%llu\n");
+
+static int fops_buf_size_get(void *data, u64 *val)
+{
+ struct gpio_la_poll_priv *priv = data;
+
+ *val = priv->blob.size;
+
+ return 0;
+}
+
+static int fops_buf_size_set(void *data, u64 val)
+{
+ struct gpio_la_poll_priv *priv = data;
+ int ret = 0;
+ void *p;
+
+ if (!val)
+ return -EINVAL;
+
+ mutex_lock(&priv->blob_lock);
+
+ vfree(priv->blob.data);
+ p = vzalloc(val);
+ if (!p) {
+ val = 0;
+ ret = -ENOMEM;
+ }
+
+ priv->blob.data = p;
+ priv->blob.size = val;
+
+ mutex_unlock(&priv->blob_lock);
+ return ret;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_buf_size, fops_buf_size_get, fops_buf_size_set, "%llu\n");
+
+static int trigger_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, NULL, inode->i_private);
+}
+
+static ssize_t trigger_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *offset)
+{
+ struct seq_file *m = file->private_data;
+ struct gpio_la_poll_priv *priv = m->private;
+ char *buf;
+
+ /* upper limit is arbitrary but should be less than PAGE_SIZE */
+ if (count > 2048 || count & 1)
+ return -EINVAL;
+
+ buf = memdup_user(ubuf, count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ priv->trig_data = buf;
+ priv->trig_len = count;
+
+ return count;
+}
+
+static const struct file_operations fops_trigger = {
+ .owner = THIS_MODULE,
+ .open = trigger_open,
+ .write = trigger_write,
+ .llseek = no_llseek,
+ .release = single_release,
+};
+
+static int gpio_la_poll_probe(struct platform_device *pdev)
+{
+ struct gpio_la_poll_priv *priv;
+ struct device *dev = &pdev->dev;
+ const char *devname = dev_name(dev);
+ const char *gpio_names[GPIO_LA_MAX_PROBES];
+ char *meta = NULL;
+ unsigned int i, meta_len = 0;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ devm_mutex_init(dev, &priv->blob_lock);
+
+ fops_buf_size_set(priv, GPIO_LA_DEFAULT_BUF_SIZE);
+
+ priv->descs = devm_gpiod_get_array(dev, "probe", GPIOD_IN);
+ if (IS_ERR(priv->descs))
+ return PTR_ERR(priv->descs);
+
+ /* artificial limit to keep 1 byte per sample for now */
+ if (priv->descs->ndescs > GPIO_LA_MAX_PROBES)
+ return -EFBIG;
+
+ ret = device_property_read_string_array(dev, "probe-names", gpio_names,
+ priv->descs->ndescs);
+ if (ret >= 0 && ret != priv->descs->ndescs)
+ ret = -EBADR;
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "error naming the GPIOs");
+
+ for (i = 0; i < priv->descs->ndescs; i++) {
+ unsigned int add_len;
+ char *new_meta, *consumer_name;
+
+ if (gpiod_cansleep(priv->descs->desc[i]))
+ return -EREMOTE;
+
+ consumer_name = kasprintf(GFP_KERNEL, "%s: %s", devname, gpio_names[i]);
+ if (!consumer_name)
+ return -ENOMEM;
+ gpiod_set_consumer_name(priv->descs->desc[i], consumer_name);
+ kfree(consumer_name);
+
+ /* '10' is length of 'probe00=\n\0' */
+ add_len = strlen(gpio_names[i]) + 10;
+
+ new_meta = devm_krealloc(dev, meta, meta_len + add_len, GFP_KERNEL);
+ if (!new_meta)
+ return -ENOMEM;
+
+ meta = new_meta;
+ meta_len += snprintf(meta + meta_len, add_len, "probe%02u=%s\n",
+ i + 1, gpio_names[i]);
+ }
+
+ platform_set_drvdata(pdev, priv);
+ priv->dev = dev;
+
+ priv->meta.data = meta;
+ priv->meta.size = meta_len;
+ priv->debug_dir = debugfs_create_dir(devname, gpio_la_poll_debug_dir);
+ debugfs_create_blob("meta_data", 0400, priv->debug_dir, &priv->meta);
+ debugfs_create_ulong("delay_ns", 0600, priv->debug_dir, &priv->delay_ns);
+ debugfs_create_ulong("delay_ns_acquisition", 0400, priv->debug_dir, &priv->acq_delay);
+ debugfs_create_file_unsafe("buf_size", 0600, priv->debug_dir, priv, &fops_buf_size);
+ debugfs_create_file_unsafe("capture", 0200, priv->debug_dir, priv, &fops_capture);
+ debugfs_create_file_unsafe("trigger", 0200, priv->debug_dir, priv, &fops_trigger);
+
+ return 0;
+}
+
+static void gpio_la_poll_remove(struct platform_device *pdev)
+{
+ struct gpio_la_poll_priv *priv = platform_get_drvdata(pdev);
+
+ mutex_lock(&priv->blob_lock);
+ debugfs_remove_recursive(priv->debug_dir);
+ mutex_unlock(&priv->blob_lock);
+}
+
+static const struct of_device_id gpio_la_poll_of_match[] = {
+ { .compatible = GPIO_LA_NAME },
+ { }
+};
+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,
+ .driver = {
+ .name = GPIO_LA_NAME,
+ .of_match_table = gpio_la_poll_of_match,
+ }
+};
+
+static int __init gpio_la_poll_init(void)
+{
+ gpio_la_poll_debug_dir = debugfs_create_dir(GPIO_LA_NAME, NULL);
+
+ return platform_driver_register(&gpio_la_poll_device_driver);
+}
+/*
+ * Non-strict pin controllers can read GPIOs while being muxed to something else.
+ * To support that, we need to claim GPIOs before further pinmuxing happens. So,
+ * we probe early using 'late_initcall'
+ */
+late_initcall(gpio_la_poll_init);
+
+static void __exit gpio_la_poll_exit(void)
+{
+ platform_driver_unregister(&gpio_la_poll_device_driver);
+ debugfs_remove_recursive(gpio_la_poll_debug_dir);
+}
+module_exit(gpio_la_poll_exit);
+
+MODULE_AUTHOR("Wolfram Sang <[email protected]>");
+MODULE_DESCRIPTION("Sloppy logic analyzer using GPIOs");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c
index 6e1a2581e6ae..3a90a3a1caea 100644
--- a/drivers/gpio/gpio-syscon.c
+++ b/drivers/gpio/gpio-syscon.c
@@ -208,6 +208,7 @@ static int syscon_gpio_probe(struct platform_device *pdev)
struct syscon_gpio_priv *priv;
struct device_node *np = dev->of_node;
int ret;
+ bool use_parent_regmap = false;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -216,24 +217,28 @@ static int syscon_gpio_probe(struct platform_device *pdev)
priv->data = of_device_get_match_data(dev);
priv->syscon = syscon_regmap_lookup_by_phandle(np, "gpio,syscon-dev");
- if (IS_ERR(priv->syscon) && np->parent)
+ if (IS_ERR(priv->syscon) && np->parent) {
priv->syscon = syscon_node_to_regmap(np->parent);
+ use_parent_regmap = true;
+ }
if (IS_ERR(priv->syscon))
return PTR_ERR(priv->syscon);
- ret = of_property_read_u32_index(np, "gpio,syscon-dev", 1,
- &priv->dreg_offset);
- if (ret)
- dev_err(dev, "can't read the data register offset!\n");
+ if (!use_parent_regmap) {
+ ret = of_property_read_u32_index(np, "gpio,syscon-dev", 1,
+ &priv->dreg_offset);
+ if (ret)
+ dev_err(dev, "can't read the data register offset!\n");
- priv->dreg_offset <<= 3;
+ priv->dreg_offset <<= 3;
- ret = of_property_read_u32_index(np, "gpio,syscon-dev", 2,
- &priv->dir_reg_offset);
- if (ret)
- dev_dbg(dev, "can't read the dir register offset!\n");
+ ret = of_property_read_u32_index(np, "gpio,syscon-dev", 2,
+ &priv->dir_reg_offset);
+ if (ret)
+ dev_dbg(dev, "can't read the dir register offset!\n");
- priv->dir_reg_offset <<= 3;
+ priv->dir_reg_offset <<= 3;
+ }
priv->chip.parent = dev;
priv->chip.owner = THIS_MODULE;
diff --git a/drivers/gpio/gpio-virtuser.c b/drivers/gpio/gpio-virtuser.c
new file mode 100644
index 000000000000..0e0d55da4f01
--- /dev/null
+++ b/drivers/gpio/gpio-virtuser.c
@@ -0,0 +1,1807 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Configurable virtual GPIO consumer module.
+ *
+ * Copyright (C) 2023-2024 Bartosz Golaszewski <[email protected]>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/array_size.h>
+#include <linux/atomic.h>
+#include <linux/bitmap.h>
+#include <linux/cleanup.h>
+#include <linux/completion.h>
+#include <linux/configfs.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/irq_work.h>
+#include <linux/limits.h>
+#include <linux/list.h>
+#include <linux/lockdep.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/overflow.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+#include <linux/types.h>
+
+#define GPIO_VIRTUSER_NAME_BUF_LEN 32
+
+static DEFINE_IDA(gpio_virtuser_ida);
+static struct dentry *gpio_virtuser_dbg_root;
+
+struct gpio_virtuser_attr_data {
+ union {
+ struct gpio_desc *desc;
+ struct gpio_descs *descs;
+ };
+ struct dentry *dbgfs_dir;
+};
+
+struct gpio_virtuser_line_array_data {
+ struct gpio_virtuser_attr_data ad;
+};
+
+struct gpio_virtuser_line_data {
+ struct gpio_virtuser_attr_data ad;
+ char consumer[GPIO_VIRTUSER_NAME_BUF_LEN];
+ struct mutex consumer_lock;
+ unsigned int debounce;
+ atomic_t irq;
+ atomic_t irq_count;
+};
+
+struct gpio_virtuser_dbgfs_attr_descr {
+ const char *name;
+ const struct file_operations *fops;
+};
+
+struct gpio_virtuser_irq_work_context {
+ struct irq_work work;
+ struct completion work_completion;
+ union {
+ struct {
+ struct gpio_desc *desc;
+ int dir;
+ int val;
+ int ret;
+ };
+ struct {
+ struct gpio_descs *descs;
+ unsigned long *values;
+ };
+ };
+};
+
+static struct gpio_virtuser_irq_work_context *
+to_gpio_virtuser_irq_work_context(struct irq_work *work)
+{
+ return container_of(work, struct gpio_virtuser_irq_work_context, work);
+}
+
+static void
+gpio_virtuser_init_irq_work_context(struct gpio_virtuser_irq_work_context *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ init_completion(&ctx->work_completion);
+}
+
+static void
+gpio_virtuser_irq_work_queue_sync(struct gpio_virtuser_irq_work_context *ctx)
+{
+ irq_work_queue(&ctx->work);
+ wait_for_completion(&ctx->work_completion);
+}
+
+static void gpio_virtuser_dbgfs_emit_value_array(char *buf,
+ unsigned long *values,
+ size_t num_values)
+{
+ size_t i;
+
+ for (i = 0; i < num_values; i++)
+ buf[i] = test_bit(i, values) ? '1' : '0';
+
+ buf[i++] = '\n';
+}
+
+static void gpio_virtuser_get_value_array_atomic(struct irq_work *work)
+{
+ struct gpio_virtuser_irq_work_context *ctx =
+ to_gpio_virtuser_irq_work_context(work);
+ struct gpio_descs *descs = ctx->descs;
+
+ ctx->ret = gpiod_get_array_value(descs->ndescs, descs->desc,
+ descs->info, ctx->values);
+ complete(&ctx->work_completion);
+}
+
+static int gpio_virtuser_get_array_value(struct gpio_descs *descs,
+ unsigned long *values, bool atomic)
+{
+ struct gpio_virtuser_irq_work_context ctx;
+
+ if (!atomic)
+ return gpiod_get_array_value_cansleep(descs->ndescs,
+ descs->desc,
+ descs->info, values);
+
+ gpio_virtuser_init_irq_work_context(&ctx);
+ ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_get_value_array_atomic);
+ ctx.descs = descs;
+ ctx.values = values;
+
+ gpio_virtuser_irq_work_queue_sync(&ctx);
+
+ return ctx.ret;
+}
+
+static ssize_t gpio_virtuser_value_array_do_read(struct file *file,
+ char __user *user_buf,
+ size_t size, loff_t *ppos,
+ bool atomic)
+{
+ struct gpio_virtuser_line_data *data = file->private_data;
+ struct gpio_descs *descs = data->ad.descs;
+ size_t bufsize;
+ int ret;
+
+ unsigned long *values __free(bitmap) = bitmap_zalloc(descs->ndescs,
+ GFP_KERNEL);
+ if (!values)
+ return -ENOMEM;
+
+ ret = gpio_virtuser_get_array_value(descs, values, atomic);
+ if (ret)
+ return ret;
+
+ bufsize = descs->ndescs + 2;
+
+ char *buf __free(kfree) = kzalloc(bufsize, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ gpio_virtuser_dbgfs_emit_value_array(buf, values, descs->ndescs);
+
+ return simple_read_from_buffer(user_buf, size, ppos, buf,
+ descs->ndescs + 1);
+}
+
+static int gpio_virtuser_dbgfs_parse_value_array(const char *buf,
+ size_t len,
+ unsigned long *values)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (buf[i] == '0')
+ clear_bit(i, values);
+ else if (buf[i] == '1')
+ set_bit(i, values);
+ else
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void gpio_virtuser_set_value_array_atomic(struct irq_work *work)
+{
+ struct gpio_virtuser_irq_work_context *ctx =
+ to_gpio_virtuser_irq_work_context(work);
+ struct gpio_descs *descs = ctx->descs;
+
+ ctx->ret = gpiod_set_array_value(descs->ndescs, descs->desc,
+ descs->info, ctx->values);
+ complete(&ctx->work_completion);
+}
+
+static int gpio_virtuser_set_array_value(struct gpio_descs *descs,
+ unsigned long *values, bool atomic)
+{
+ struct gpio_virtuser_irq_work_context ctx;
+
+ if (!atomic)
+ return gpiod_set_array_value_cansleep(descs->ndescs,
+ descs->desc,
+ descs->info, values);
+
+ gpio_virtuser_init_irq_work_context(&ctx);
+ ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_set_value_array_atomic);
+ ctx.descs = descs;
+ ctx.values = values;
+
+ gpio_virtuser_irq_work_queue_sync(&ctx);
+
+ return ctx.ret;
+}
+
+static ssize_t gpio_virtuser_value_array_do_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos,
+ bool atomic)
+{
+ struct gpio_virtuser_line_data *data = file->private_data;
+ struct gpio_descs *descs = data->ad.descs;
+ int ret;
+
+ if (count - 1 != descs->ndescs)
+ return -EINVAL;
+
+ char *buf __free(kfree) = kzalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = simple_write_to_buffer(buf, count, ppos, user_buf, count);
+ if (ret < 0)
+ return ret;
+
+ unsigned long *values __free(bitmap) = bitmap_zalloc(descs->ndescs,
+ GFP_KERNEL);
+ if (!values)
+ return -ENOMEM;
+
+ ret = gpio_virtuser_dbgfs_parse_value_array(buf, count - 1, values);
+ if (ret)
+ return ret;
+
+ ret = gpio_virtuser_set_array_value(descs, values, atomic);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static ssize_t gpio_virtuser_value_array_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return gpio_virtuser_value_array_do_read(file, user_buf, count, ppos,
+ false);
+}
+
+static ssize_t gpio_virtuser_value_array_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return gpio_virtuser_value_array_do_write(file, user_buf, count, ppos,
+ false);
+}
+
+static const struct file_operations gpio_virtuser_value_array_fops = {
+ .read = gpio_virtuser_value_array_read,
+ .write = gpio_virtuser_value_array_write,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t
+gpio_virtuser_value_array_atomic_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return gpio_virtuser_value_array_do_read(file, user_buf, count, ppos,
+ true);
+}
+
+static ssize_t
+gpio_virtuser_value_array_atomic_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return gpio_virtuser_value_array_do_write(file, user_buf, count, ppos,
+ true);
+}
+
+static const struct file_operations gpio_virtuser_value_array_atomic_fops = {
+ .read = gpio_virtuser_value_array_atomic_read,
+ .write = gpio_virtuser_value_array_atomic_write,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static void gpio_virtuser_do_get_direction_atomic(struct irq_work *work)
+{
+ struct gpio_virtuser_irq_work_context *ctx =
+ to_gpio_virtuser_irq_work_context(work);
+
+ ctx->ret = gpiod_get_direction(ctx->desc);
+ complete(&ctx->work_completion);
+}
+
+static int gpio_virtuser_get_direction_atomic(struct gpio_desc *desc)
+{
+ struct gpio_virtuser_irq_work_context ctx;
+
+ gpio_virtuser_init_irq_work_context(&ctx);
+ ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_do_get_direction_atomic);
+ ctx.desc = desc;
+
+ gpio_virtuser_irq_work_queue_sync(&ctx);
+
+ return ctx.ret;
+}
+
+static ssize_t gpio_virtuser_direction_do_read(struct file *file,
+ char __user *user_buf,
+ size_t size, loff_t *ppos,
+ bool atomic)
+{
+ struct gpio_virtuser_line_data *data = file->private_data;
+ struct gpio_desc *desc = data->ad.desc;
+ char buf[32];
+ int dir;
+
+ if (!atomic)
+ dir = gpiod_get_direction(desc);
+ else
+ dir = gpio_virtuser_get_direction_atomic(desc);
+ if (dir < 0)
+ return dir;
+
+ snprintf(buf, sizeof(buf), "%s\n", dir ? "input" : "output");
+
+ return simple_read_from_buffer(user_buf, size, ppos, buf, strlen(buf));
+}
+
+static int gpio_virtuser_set_direction(struct gpio_desc *desc, int dir, int val)
+{
+ if (dir)
+ return gpiod_direction_input(desc);
+
+ return gpiod_direction_output(desc, val);
+}
+
+static void gpio_virtuser_do_set_direction_atomic(struct irq_work *work)
+{
+ struct gpio_virtuser_irq_work_context *ctx =
+ to_gpio_virtuser_irq_work_context(work);
+
+ ctx->ret = gpio_virtuser_set_direction(ctx->desc, ctx->dir, ctx->val);
+ complete(&ctx->work_completion);
+}
+
+static int gpio_virtuser_set_direction_atomic(struct gpio_desc *desc,
+ int dir, int val)
+{
+ struct gpio_virtuser_irq_work_context ctx;
+
+ gpio_virtuser_init_irq_work_context(&ctx);
+ ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_do_set_direction_atomic);
+ ctx.desc = desc;
+ ctx.dir = dir;
+ ctx.val = val;
+
+ gpio_virtuser_irq_work_queue_sync(&ctx);
+
+ return ctx.ret;
+}
+
+static ssize_t gpio_virtuser_direction_do_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos,
+ bool atomic)
+{
+ struct gpio_virtuser_line_data *data = file->private_data;
+ struct gpio_desc *desc = data->ad.desc;
+ char buf[32], *trimmed;
+ int ret, dir, val = 0;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf), ppos, user_buf, count);
+ if (ret < 0)
+ return ret;
+
+ trimmed = strim(buf);
+
+ if (strcmp(trimmed, "input") == 0) {
+ dir = 1;
+ } else if (strcmp(trimmed, "output-high") == 0) {
+ dir = 0;
+ val = 1;
+ } else if (strcmp(trimmed, "output-low") == 0) {
+ dir = val = 0;
+ } else {
+ return -EINVAL;
+ }
+
+ if (!atomic)
+ ret = gpio_virtuser_set_direction(desc, dir, val);
+ else
+ ret = gpio_virtuser_set_direction_atomic(desc, dir, val);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static ssize_t gpio_virtuser_direction_read(struct file *file,
+ char __user *user_buf,
+ size_t size, loff_t *ppos)
+{
+ return gpio_virtuser_direction_do_read(file, user_buf, size, ppos,
+ false);
+}
+
+static ssize_t gpio_virtuser_direction_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return gpio_virtuser_direction_do_write(file, user_buf, count, ppos,
+ false);
+}
+
+static const struct file_operations gpio_virtuser_direction_fops = {
+ .read = gpio_virtuser_direction_read,
+ .write = gpio_virtuser_direction_write,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t gpio_virtuser_direction_atomic_read(struct file *file,
+ char __user *user_buf,
+ size_t size, loff_t *ppos)
+{
+ return gpio_virtuser_direction_do_read(file, user_buf, size, ppos,
+ true);
+}
+
+static ssize_t gpio_virtuser_direction_atomic_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return gpio_virtuser_direction_do_write(file, user_buf, count, ppos,
+ true);
+}
+
+static const struct file_operations gpio_virtuser_direction_atomic_fops = {
+ .read = gpio_virtuser_direction_atomic_read,
+ .write = gpio_virtuser_direction_atomic_write,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static int gpio_virtuser_value_get(void *data, u64 *val)
+{
+ struct gpio_virtuser_line_data *ld = data;
+ int ret;
+
+ ret = gpiod_get_value_cansleep(ld->ad.desc);
+ if (ret < 0)
+ return ret;
+
+ *val = ret;
+
+ return 0;
+}
+
+static int gpio_virtuser_value_set(void *data, u64 val)
+{
+ struct gpio_virtuser_line_data *ld = data;
+
+ if (val > 1)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(ld->ad.desc, (int)val);
+
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_value_fops,
+ gpio_virtuser_value_get,
+ gpio_virtuser_value_set,
+ "%llu\n");
+
+static void gpio_virtuser_get_value_atomic(struct irq_work *work)
+{
+ struct gpio_virtuser_irq_work_context *ctx =
+ to_gpio_virtuser_irq_work_context(work);
+
+ ctx->val = gpiod_get_value(ctx->desc);
+ complete(&ctx->work_completion);
+}
+
+static int gpio_virtuser_value_atomic_get(void *data, u64 *val)
+{
+ struct gpio_virtuser_line_data *ld = data;
+ struct gpio_virtuser_irq_work_context ctx;
+
+ gpio_virtuser_init_irq_work_context(&ctx);
+ ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_get_value_atomic);
+ ctx.desc = ld->ad.desc;
+
+ gpio_virtuser_irq_work_queue_sync(&ctx);
+
+ if (ctx.val < 0)
+ return ctx.val;
+
+ *val = ctx.val;
+
+ return 0;
+}
+
+static void gpio_virtuser_set_value_atomic(struct irq_work *work)
+{
+ struct gpio_virtuser_irq_work_context *ctx =
+ to_gpio_virtuser_irq_work_context(work);
+
+ gpiod_set_value(ctx->desc, ctx->val);
+ complete(&ctx->work_completion);
+}
+
+static int gpio_virtuser_value_atomic_set(void *data, u64 val)
+{
+ struct gpio_virtuser_line_data *ld = data;
+ struct gpio_virtuser_irq_work_context ctx;
+
+ if (val > 1)
+ return -EINVAL;
+
+ gpio_virtuser_init_irq_work_context(&ctx);
+ ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_set_value_atomic);
+ ctx.desc = ld->ad.desc;
+ ctx.val = (int)val;
+
+ gpio_virtuser_irq_work_queue_sync(&ctx);
+
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_value_atomic_fops,
+ gpio_virtuser_value_atomic_get,
+ gpio_virtuser_value_atomic_set,
+ "%llu\n");
+
+static int gpio_virtuser_debounce_get(void *data, u64 *val)
+{
+ struct gpio_virtuser_line_data *ld = data;
+
+ *val = READ_ONCE(ld->debounce);
+
+ return 0;
+}
+
+static int gpio_virtuser_debounce_set(void *data, u64 val)
+{
+ struct gpio_virtuser_line_data *ld = data;
+ int ret;
+
+ if (val > UINT_MAX)
+ return -E2BIG;
+
+ ret = gpiod_set_debounce(ld->ad.desc, (unsigned int)val);
+ if (ret)
+ /* Don't propagate errno unknown to user-space. */
+ return ret == -ENOTSUPP ? -EOPNOTSUPP : ret;
+
+ WRITE_ONCE(ld->debounce, (unsigned int)val);
+
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_debounce_fops,
+ gpio_virtuser_debounce_get,
+ gpio_virtuser_debounce_set,
+ "%llu\n");
+
+static ssize_t gpio_virtuser_consumer_read(struct file *file,
+ char __user *user_buf,
+ size_t size, loff_t *ppos)
+{
+ struct gpio_virtuser_line_data *data = file->private_data;
+ char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 1];
+ ssize_t ret;
+
+ memset(buf, 0x0, sizeof(buf));
+
+ scoped_guard(mutex, &data->consumer_lock)
+ ret = snprintf(buf, sizeof(buf), "%s\n", data->consumer);
+
+ return simple_read_from_buffer(user_buf, size, ppos, buf, ret);
+}
+
+static ssize_t gpio_virtuser_consumer_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct gpio_virtuser_line_data *data = file->private_data;
+ char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2];
+ int ret;
+
+ ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos,
+ user_buf, count);
+ if (ret < 0)
+ return ret;
+
+ buf[strlen(buf) - 1] = '\0';
+
+ ret = gpiod_set_consumer_name(data->ad.desc, buf);
+ if (ret)
+ return ret;
+
+ scoped_guard(mutex, &data->consumer_lock)
+ strscpy(data->consumer, buf, sizeof(data->consumer));
+
+ return count;
+}
+
+static const struct file_operations gpio_virtuser_consumer_fops = {
+ .read = gpio_virtuser_consumer_read,
+ .write = gpio_virtuser_consumer_write,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static int gpio_virtuser_interrupts_get(void *data, u64 *val)
+{
+ struct gpio_virtuser_line_data *ld = data;
+
+ *val = atomic_read(&ld->irq_count);
+
+ return 0;
+}
+
+static irqreturn_t gpio_virtuser_irq_handler(int irq, void *data)
+{
+ struct gpio_virtuser_line_data *ld = data;
+
+ atomic_inc(&ld->irq_count);
+
+ return IRQ_HANDLED;
+}
+
+static int gpio_virtuser_interrupts_set(void *data, u64 val)
+{
+ struct gpio_virtuser_line_data *ld = data;
+ int irq, ret;
+
+ if (val > 1)
+ return -EINVAL;
+
+ if (val) {
+ irq = gpiod_to_irq(ld->ad.desc);
+ if (irq < 0)
+ return irq;
+
+ ret = request_threaded_irq(irq, NULL,
+ gpio_virtuser_irq_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ ld->consumer, data);
+ if (ret)
+ return ret;
+
+ atomic_set(&ld->irq, irq);
+ } else {
+ irq = atomic_xchg(&ld->irq, 0);
+ free_irq(irq, ld);
+ }
+
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_interrupts_fops,
+ gpio_virtuser_interrupts_get,
+ gpio_virtuser_interrupts_set,
+ "%llu\n");
+
+static const struct gpio_virtuser_dbgfs_attr_descr
+gpio_virtuser_line_array_dbgfs_attrs[] = {
+ {
+ .name = "values",
+ .fops = &gpio_virtuser_value_array_fops,
+ },
+ {
+ .name = "values_atomic",
+ .fops = &gpio_virtuser_value_array_atomic_fops,
+ },
+};
+
+static const struct gpio_virtuser_dbgfs_attr_descr
+gpio_virtuser_line_dbgfs_attrs[] = {
+ {
+ .name = "direction",
+ .fops = &gpio_virtuser_direction_fops,
+ },
+ {
+ .name = "direction_atomic",
+ .fops = &gpio_virtuser_direction_atomic_fops,
+ },
+ {
+ .name = "value",
+ .fops = &gpio_virtuser_value_fops,
+ },
+ {
+ .name = "value_atomic",
+ .fops = &gpio_virtuser_value_atomic_fops,
+ },
+ {
+ .name = "debounce",
+ .fops = &gpio_virtuser_debounce_fops,
+ },
+ {
+ .name = "consumer",
+ .fops = &gpio_virtuser_consumer_fops,
+ },
+ {
+ .name = "interrupts",
+ .fops = &gpio_virtuser_interrupts_fops,
+ },
+};
+
+static int gpio_virtuser_create_debugfs_attrs(
+ const struct gpio_virtuser_dbgfs_attr_descr *attr,
+ size_t num_attrs, struct dentry *parent, void *data)
+{
+ struct dentry *ret;
+ size_t i;
+
+ for (i = 0; i < num_attrs; i++, attr++) {
+ ret = debugfs_create_file(attr->name, 0644, parent, data,
+ attr->fops);
+ if (IS_ERR(ret))
+ return PTR_ERR(ret);
+ }
+
+ return 0;
+}
+
+static int gpio_virtuser_dbgfs_init_line_array_attrs(struct device *dev,
+ struct gpio_descs *descs,
+ const char *id,
+ struct dentry *dbgfs_entry)
+{
+ struct gpio_virtuser_line_array_data *data;
+ char *name;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->ad.descs = descs;
+
+ name = devm_kasprintf(dev, GFP_KERNEL, "gpiod:%s", id);
+ if (!name)
+ return -ENOMEM;
+
+ data->ad.dbgfs_dir = debugfs_create_dir(name, dbgfs_entry);
+ if (IS_ERR(data->ad.dbgfs_dir))
+ return PTR_ERR(data->ad.dbgfs_dir);
+
+ return gpio_virtuser_create_debugfs_attrs(
+ gpio_virtuser_line_array_dbgfs_attrs,
+ ARRAY_SIZE(gpio_virtuser_line_array_dbgfs_attrs),
+ data->ad.dbgfs_dir, data);
+}
+
+static int gpio_virtuser_dbgfs_init_line_attrs(struct device *dev,
+ struct gpio_desc *desc,
+ const char *id,
+ unsigned int index,
+ struct dentry *dbgfs_entry)
+{
+ struct gpio_virtuser_line_data *data;
+ char *name;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->ad.desc = desc;
+ sprintf(data->consumer, id);
+ atomic_set(&data->irq, 0);
+ atomic_set(&data->irq_count, 0);
+
+ name = devm_kasprintf(dev, GFP_KERNEL, "gpiod:%s:%u", id, index);
+ if (!name)
+ return -ENOMEM;
+
+ ret = devm_mutex_init(dev, &data->consumer_lock);
+ if (ret)
+ return ret;
+
+ data->ad.dbgfs_dir = debugfs_create_dir(name, dbgfs_entry);
+ if (IS_ERR(data->ad.dbgfs_dir))
+ return PTR_ERR(data->ad.dbgfs_dir);
+
+ return gpio_virtuser_create_debugfs_attrs(
+ gpio_virtuser_line_dbgfs_attrs,
+ ARRAY_SIZE(gpio_virtuser_line_dbgfs_attrs),
+ data->ad.dbgfs_dir, data);
+}
+
+static void gpio_virtuser_debugfs_remove(void *data)
+{
+ struct dentry *dbgfs_entry = data;
+
+ debugfs_remove_recursive(dbgfs_entry);
+}
+
+static int gpio_virtuser_prop_is_gpio(struct property *prop)
+{
+ char *dash = strrchr(prop->name, '-');
+
+ return dash && strcmp(dash, "-gpios") == 0;
+}
+
+/*
+ * If this is an OF-based system, then we iterate over properties and consider
+ * all whose names end in "-gpios". For configfs we expect an additional string
+ * array property - "gpio-virtuser,ids" - containing the list of all GPIO IDs
+ * to request.
+ */
+static int gpio_virtuser_count_ids(struct device *dev)
+{
+ struct device_node *of_node = dev_of_node(dev);
+ struct property *prop;
+ int ret = 0;
+
+ if (!of_node)
+ return device_property_string_array_count(dev,
+ "gpio-virtuser,ids");
+
+ for_each_property_of_node(of_node, prop) {
+ if (gpio_virtuser_prop_is_gpio(prop))
+ ++ret;
+ }
+
+ return ret;
+}
+
+static int gpio_virtuser_get_ids(struct device *dev, const char **ids,
+ int num_ids)
+{
+ struct device_node *of_node = dev_of_node(dev);
+ struct property *prop;
+ size_t pos = 0, diff;
+ char *dash, *tmp;
+
+ if (!of_node)
+ return device_property_read_string_array(dev,
+ "gpio-virtuser,ids",
+ ids, num_ids);
+
+ for_each_property_of_node(of_node, prop) {
+ if (!gpio_virtuser_prop_is_gpio(prop))
+ continue;
+
+ dash = strrchr(prop->name, '-');
+ diff = dash - prop->name;
+
+ tmp = devm_kmemdup(dev, prop->name, diff + 1,
+ GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ tmp[diff] = '\0';
+ ids[pos++] = tmp;
+ }
+
+ return 0;
+}
+
+static int gpio_virtuser_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct dentry *dbgfs_entry;
+ struct gpio_descs *descs;
+ int ret, num_ids = 0, i;
+ const char **ids;
+ unsigned int j;
+
+ num_ids = gpio_virtuser_count_ids(dev);
+ if (num_ids < 0)
+ return dev_err_probe(dev, num_ids,
+ "Failed to get the number of GPIOs to request\n");
+
+ if (num_ids == 0)
+ return dev_err_probe(dev, -EINVAL, "No GPIO IDs specified\n");
+
+ ids = devm_kcalloc(dev, num_ids, sizeof(*ids), GFP_KERNEL);
+ if (!ids)
+ return -ENOMEM;
+
+ ret = gpio_virtuser_get_ids(dev, ids, num_ids);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "Failed to get the IDs of GPIOs to request\n");
+
+ dbgfs_entry = debugfs_create_dir(dev_name(dev), gpio_virtuser_dbg_root);
+ ret = devm_add_action_or_reset(dev, gpio_virtuser_debugfs_remove,
+ dbgfs_entry);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < num_ids; i++) {
+ descs = devm_gpiod_get_array(dev, ids[i], GPIOD_ASIS);
+ if (IS_ERR(descs))
+ return dev_err_probe(dev, PTR_ERR(descs),
+ "Failed to request the '%s' GPIOs\n",
+ ids[i]);
+
+ ret = gpio_virtuser_dbgfs_init_line_array_attrs(dev, descs,
+ ids[i],
+ dbgfs_entry);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to setup the debugfs array interface for the '%s' GPIOs\n",
+ ids[i]);
+
+ for (j = 0; j < descs->ndescs; j++) {
+ ret = gpio_virtuser_dbgfs_init_line_attrs(dev,
+ descs->desc[j], ids[i],
+ j, dbgfs_entry);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to setup the debugfs line interface for the '%s' GPIOs\n",
+ ids[i]);
+ }
+ }
+
+ return 0;
+}
+
+static const struct of_device_id gpio_virtuser_of_match[] = {
+ { .compatible = "gpio-virtuser" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gpio_virtuser_of_match);
+
+static struct platform_driver gpio_virtuser_driver = {
+ .driver = {
+ .name = "gpio-virtuser",
+ .of_match_table = gpio_virtuser_of_match,
+ },
+ .probe = gpio_virtuser_probe,
+};
+
+struct gpio_virtuser_device {
+ struct config_group group;
+
+ struct platform_device *pdev;
+ int id;
+ struct mutex lock;
+
+ struct notifier_block bus_notifier;
+ struct completion probe_completion;
+ bool driver_bound;
+
+ struct gpiod_lookup_table *lookup_table;
+
+ struct list_head lookup_list;
+};
+
+static int gpio_virtuser_bus_notifier_call(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct gpio_virtuser_device *vdev;
+ struct device *dev = data;
+ char devname[32];
+
+ vdev = container_of(nb, struct gpio_virtuser_device, bus_notifier);
+ snprintf(devname, sizeof(devname), "gpio-virtuser.%d", vdev->id);
+
+ if (!device_match_name(dev, devname))
+ return NOTIFY_DONE;
+
+ switch (action) {
+ case BUS_NOTIFY_BOUND_DRIVER:
+ vdev->driver_bound = true;
+ break;
+ case BUS_NOTIFY_DRIVER_NOT_BOUND:
+ vdev->driver_bound = false;
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+
+ complete(&vdev->probe_completion);
+ return NOTIFY_OK;
+}
+
+static struct gpio_virtuser_device *
+to_gpio_virtuser_device(struct config_item *item)
+{
+ struct config_group *group = to_config_group(item);
+
+ return container_of(group, struct gpio_virtuser_device, group);
+}
+
+static bool
+gpio_virtuser_device_is_live(struct gpio_virtuser_device *dev)
+{
+ lockdep_assert_held(&dev->lock);
+
+ return !!dev->pdev;
+}
+
+struct gpio_virtuser_lookup {
+ struct config_group group;
+
+ struct gpio_virtuser_device *parent;
+ struct list_head siblings;
+
+ char *con_id;
+
+ struct list_head entry_list;
+};
+
+static struct gpio_virtuser_lookup *
+to_gpio_virtuser_lookup(struct config_item *item)
+{
+ struct config_group *group = to_config_group(item);
+
+ return container_of(group, struct gpio_virtuser_lookup, group);
+}
+
+struct gpio_virtuser_lookup_entry {
+ struct config_group group;
+
+ struct gpio_virtuser_lookup *parent;
+ struct list_head siblings;
+
+ char *key;
+ /* Can be negative to indicate lookup by name. */
+ int offset;
+ enum gpio_lookup_flags flags;
+};
+
+static struct gpio_virtuser_lookup_entry *
+to_gpio_virtuser_lookup_entry(struct config_item *item)
+{
+ struct config_group *group = to_config_group(item);
+
+ return container_of(group, struct gpio_virtuser_lookup_entry, group);
+}
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_key_show(struct config_item *item, char *page)
+{
+ struct gpio_virtuser_lookup_entry *entry =
+ to_gpio_virtuser_lookup_entry(item);
+ struct gpio_virtuser_device *dev = entry->parent->parent;
+
+ guard(mutex)(&dev->lock);
+
+ return sprintf(page, "%s\n", entry->key ?: "");
+}
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_key_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct gpio_virtuser_lookup_entry *entry =
+ to_gpio_virtuser_lookup_entry(item);
+ struct gpio_virtuser_device *dev = entry->parent->parent;
+
+ char *key __free(kfree) = kstrndup(skip_spaces(page), count,
+ GFP_KERNEL);
+ if (!key)
+ return -ENOMEM;
+
+ strim(key);
+
+ guard(mutex)(&dev->lock);
+
+ if (gpio_virtuser_device_is_live(dev))
+ return -EBUSY;
+
+ kfree(entry->key);
+ entry->key = no_free_ptr(key);
+
+ return count;
+}
+
+CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, key);
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_offset_show(struct config_item *item,
+ char *page)
+{
+ struct gpio_virtuser_lookup_entry *entry =
+ to_gpio_virtuser_lookup_entry(item);
+ struct gpio_virtuser_device *dev = entry->parent->parent;
+ unsigned int offset;
+
+ scoped_guard(mutex, &dev->lock)
+ offset = entry->offset;
+
+ return sprintf(page, "%d\n", offset);
+}
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_offset_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct gpio_virtuser_lookup_entry *entry =
+ to_gpio_virtuser_lookup_entry(item);
+ struct gpio_virtuser_device *dev = entry->parent->parent;
+ int offset, ret;
+
+ ret = kstrtoint(page, 0, &offset);
+ if (ret)
+ return ret;
+
+ /*
+ * Negative number here means: 'key' represents a line name to lookup.
+ * Non-negative means: 'key' represents the label of the chip with
+ * the 'offset' value representing the line within that chip.
+ *
+ * GPIOLIB uses the U16_MAX value to indicate lookup by line name so
+ * the greatest offset we can accept is (U16_MAX - 1).
+ */
+ if (offset > (U16_MAX - 1))
+ return -EINVAL;
+
+ guard(mutex)(&dev->lock);
+
+ if (gpio_virtuser_device_is_live(dev))
+ return -EBUSY;
+
+ entry->offset = offset;
+
+ return count;
+}
+
+CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, offset);
+
+static enum gpio_lookup_flags
+gpio_virtuser_lookup_get_flags(struct config_item *item)
+{
+ struct gpio_virtuser_lookup_entry *entry =
+ to_gpio_virtuser_lookup_entry(item);
+ struct gpio_virtuser_device *dev = entry->parent->parent;
+
+ guard(mutex)(&dev->lock);
+
+ return entry->flags;
+}
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_drive_show(struct config_item *item, char *page)
+{
+ enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item);
+ const char *repr;
+
+ if (flags & GPIO_OPEN_DRAIN)
+ repr = "open-drain";
+ else if (flags & GPIO_OPEN_SOURCE)
+ repr = "open-source";
+ else
+ repr = "push-pull";
+
+ return sprintf(page, "%s\n", repr);
+}
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_drive_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct gpio_virtuser_lookup_entry *entry =
+ to_gpio_virtuser_lookup_entry(item);
+ struct gpio_virtuser_device *dev = entry->parent->parent;
+
+ guard(mutex)(&dev->lock);
+
+ if (gpio_virtuser_device_is_live(dev))
+ return -EBUSY;
+
+ if (sysfs_streq(page, "push-pull")) {
+ entry->flags &= ~(GPIO_OPEN_DRAIN | GPIO_OPEN_SOURCE);
+ } else if (sysfs_streq(page, "open-drain")) {
+ entry->flags &= ~GPIO_OPEN_SOURCE;
+ entry->flags |= GPIO_OPEN_DRAIN;
+ } else if (sysfs_streq(page, "open-source")) {
+ entry->flags &= ~GPIO_OPEN_DRAIN;
+ entry->flags |= GPIO_OPEN_SOURCE;
+ } else {
+ count = -EINVAL;
+ }
+
+ return count;
+}
+
+CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, drive);
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_pull_show(struct config_item *item, char *page)
+{
+ enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item);
+ const char *repr;
+
+ if (flags & GPIO_PULL_UP)
+ repr = "pull-up";
+ else if (flags & GPIO_PULL_DOWN)
+ repr = "pull-down";
+ else if (flags & GPIO_PULL_DISABLE)
+ repr = "pull-disabled";
+ else
+ repr = "as-is";
+
+ return sprintf(page, "%s\n", repr);
+}
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_pull_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct gpio_virtuser_lookup_entry *entry =
+ to_gpio_virtuser_lookup_entry(item);
+ struct gpio_virtuser_device *dev = entry->parent->parent;
+
+ guard(mutex)(&dev->lock);
+
+ if (gpio_virtuser_device_is_live(dev))
+ return -EBUSY;
+
+ if (sysfs_streq(page, "pull-up")) {
+ entry->flags &= ~(GPIO_PULL_DOWN | GPIO_PULL_DISABLE);
+ entry->flags |= GPIO_PULL_UP;
+ } else if (sysfs_streq(page, "pull-down")) {
+ entry->flags &= ~(GPIO_PULL_UP | GPIO_PULL_DISABLE);
+ entry->flags |= GPIO_PULL_DOWN;
+ } else if (sysfs_streq(page, "pull-disabled")) {
+ entry->flags &= ~(GPIO_PULL_UP | GPIO_PULL_DOWN);
+ entry->flags |= GPIO_PULL_DISABLE;
+ } else if (sysfs_streq(page, "as-is")) {
+ entry->flags &= ~(GPIO_PULL_UP | GPIO_PULL_DOWN |
+ GPIO_PULL_DISABLE);
+ } else {
+ count = -EINVAL;
+ }
+
+ return count;
+}
+
+CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, pull);
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_active_low_show(struct config_item *item,
+ char *page)
+{
+ enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item);
+
+ return sprintf(page, "%c\n", flags & GPIO_ACTIVE_LOW ? '1' : '0');
+}
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_active_low_store(struct config_item *item,
+ const char *page,
+ size_t count)
+{
+ struct gpio_virtuser_lookup_entry *entry =
+ to_gpio_virtuser_lookup_entry(item);
+ struct gpio_virtuser_device *dev = entry->parent->parent;
+ bool active_low;
+ int ret;
+
+ ret = kstrtobool(page, &active_low);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&dev->lock);
+
+ if (gpio_virtuser_device_is_live(dev))
+ return -EBUSY;
+
+ if (active_low)
+ entry->flags |= GPIO_ACTIVE_LOW;
+ else
+ entry->flags &= ~GPIO_ACTIVE_LOW;
+
+ return count;
+}
+
+CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, active_low);
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_transitory_show(struct config_item *item,
+ char *page)
+{
+ enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item);
+
+ return sprintf(page, "%c\n", flags & GPIO_TRANSITORY ? '1' : '0');
+}
+
+static ssize_t
+gpio_virtuser_lookup_entry_config_transitory_store(struct config_item *item,
+ const char *page,
+ size_t count)
+{
+ struct gpio_virtuser_lookup_entry *entry =
+ to_gpio_virtuser_lookup_entry(item);
+ struct gpio_virtuser_device *dev = entry->parent->parent;
+ bool transitory;
+ int ret;
+
+ ret = kstrtobool(page, &transitory);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&dev->lock);
+
+ if (gpio_virtuser_device_is_live(dev))
+ return -EBUSY;
+
+ if (transitory)
+ entry->flags |= GPIO_TRANSITORY;
+ else
+ entry->flags &= ~GPIO_TRANSITORY;
+
+ return count;
+}
+
+CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, transitory);
+
+static struct configfs_attribute *gpio_virtuser_lookup_entry_config_attrs[] = {
+ &gpio_virtuser_lookup_entry_config_attr_key,
+ &gpio_virtuser_lookup_entry_config_attr_offset,
+ &gpio_virtuser_lookup_entry_config_attr_drive,
+ &gpio_virtuser_lookup_entry_config_attr_pull,
+ &gpio_virtuser_lookup_entry_config_attr_active_low,
+ &gpio_virtuser_lookup_entry_config_attr_transitory,
+ NULL
+};
+
+static ssize_t
+gpio_virtuser_device_config_dev_name_show(struct config_item *item,
+ char *page)
+{
+ struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item);
+ struct platform_device *pdev;
+
+ guard(mutex)(&dev->lock);
+
+ pdev = dev->pdev;
+ if (pdev)
+ return sprintf(page, "%s\n", dev_name(&pdev->dev));
+
+ return sprintf(page, "gpio-sim.%d\n", dev->id);
+}
+
+CONFIGFS_ATTR_RO(gpio_virtuser_device_config_, dev_name);
+
+static ssize_t gpio_virtuser_device_config_live_show(struct config_item *item,
+ char *page)
+{
+ struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item);
+ bool live;
+
+ scoped_guard(mutex, &dev->lock)
+ live = gpio_virtuser_device_is_live(dev);
+
+ return sprintf(page, "%c\n", live ? '1' : '0');
+}
+
+static size_t
+gpio_virtuser_get_lookup_count(struct gpio_virtuser_device *dev)
+{
+ struct gpio_virtuser_lookup *lookup;
+ size_t count = 0;
+
+ lockdep_assert_held(&dev->lock);
+
+ list_for_each_entry(lookup, &dev->lookup_list, siblings)
+ count += list_count_nodes(&lookup->entry_list);
+
+ return count;
+}
+
+static int
+gpio_virtuser_make_lookup_table(struct gpio_virtuser_device *dev)
+{
+ size_t num_entries = gpio_virtuser_get_lookup_count(dev);
+ struct gpio_virtuser_lookup_entry *entry;
+ struct gpio_virtuser_lookup *lookup;
+ struct gpiod_lookup *curr;
+ unsigned int i = 0;
+
+ lockdep_assert_held(&dev->lock);
+
+ struct gpiod_lookup_table *table __free(kfree) =
+ kzalloc(struct_size(table, table, num_entries + 1), GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ table->dev_id = kasprintf(GFP_KERNEL, "gpio-virtuser.%d", dev->id);
+ if (!table->dev_id)
+ return -ENOMEM;
+
+ list_for_each_entry(lookup, &dev->lookup_list, siblings) {
+ list_for_each_entry(entry, &lookup->entry_list, siblings) {
+ curr = &table->table[i];
+
+ curr->con_id = lookup->con_id;
+ curr->idx = i;
+ curr->key = entry->key;
+ curr->chip_hwnum = entry->offset < 0 ?
+ U16_MAX : entry->offset;
+ curr->flags = entry->flags;
+ i++;
+ }
+ }
+
+ gpiod_add_lookup_table(table);
+ dev->lookup_table = no_free_ptr(table);
+
+ return 0;
+}
+
+static struct fwnode_handle *
+gpio_virtuser_make_device_swnode(struct gpio_virtuser_device *dev)
+{
+ struct property_entry properties[2];
+ struct gpio_virtuser_lookup *lookup;
+ unsigned int i = 0;
+ size_t num_ids;
+
+ memset(properties, 0, sizeof(properties));
+
+ num_ids = list_count_nodes(&dev->lookup_list);
+ char **ids __free(kfree) = kcalloc(num_ids + 1, sizeof(*ids),
+ GFP_KERNEL);
+ if (!ids)
+ return ERR_PTR(-ENOMEM);
+
+ list_for_each_entry(lookup, &dev->lookup_list, siblings)
+ ids[i++] = lookup->con_id;
+
+ properties[0] = PROPERTY_ENTRY_STRING_ARRAY_LEN("gpio-virtuser,ids",
+ ids, num_ids);
+
+ return fwnode_create_software_node(properties, NULL);
+}
+
+static int
+gpio_virtuser_device_activate(struct gpio_virtuser_device *dev)
+{
+ struct platform_device_info pdevinfo;
+ struct fwnode_handle *swnode;
+ struct platform_device *pdev;
+ int ret;
+
+ lockdep_assert_held(&dev->lock);
+
+ if (list_empty(&dev->lookup_list))
+ return -ENODATA;
+
+ swnode = gpio_virtuser_make_device_swnode(dev);
+ if (IS_ERR(swnode))
+ return PTR_ERR(swnode);
+
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ pdevinfo.name = "gpio-virtuser";
+ pdevinfo.id = dev->id;
+ pdevinfo.fwnode = swnode;
+
+ ret = gpio_virtuser_make_lookup_table(dev);
+ if (ret) {
+ fwnode_remove_software_node(swnode);
+ return ret;
+ }
+
+ reinit_completion(&dev->probe_completion);
+ dev->driver_bound = false;
+ bus_register_notifier(&platform_bus_type, &dev->bus_notifier);
+
+ pdev = platform_device_register_full(&pdevinfo);
+ if (IS_ERR(pdev)) {
+ bus_unregister_notifier(&platform_bus_type, &dev->bus_notifier);
+ fwnode_remove_software_node(swnode);
+ return PTR_ERR(pdev);
+ }
+
+ wait_for_completion(&dev->probe_completion);
+ bus_unregister_notifier(&platform_bus_type, &dev->bus_notifier);
+
+ if (!dev->driver_bound) {
+ platform_device_unregister(pdev);
+ fwnode_remove_software_node(swnode);
+ return -ENXIO;
+ }
+
+ dev->pdev = pdev;
+
+ return 0;
+}
+
+static void
+gpio_virtuser_device_deactivate(struct gpio_virtuser_device *dev)
+{
+ struct fwnode_handle *swnode;
+
+ lockdep_assert_held(&dev->lock);
+
+ swnode = dev_fwnode(&dev->pdev->dev);
+ platform_device_unregister(dev->pdev);
+ fwnode_remove_software_node(swnode);
+ dev->pdev = NULL;
+ gpiod_remove_lookup_table(dev->lookup_table);
+ kfree(dev->lookup_table);
+}
+
+static ssize_t
+gpio_virtuser_device_config_live_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item);
+ int ret = 0;
+ bool live;
+
+ ret = kstrtobool(page, &live);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&dev->lock);
+
+ if (live == gpio_virtuser_device_is_live(dev))
+ return -EPERM;
+
+ if (live)
+ ret = gpio_virtuser_device_activate(dev);
+ else
+ gpio_virtuser_device_deactivate(dev);
+
+ return ret ?: count;
+}
+
+CONFIGFS_ATTR(gpio_virtuser_device_config_, live);
+
+static struct configfs_attribute *gpio_virtuser_device_config_attrs[] = {
+ &gpio_virtuser_device_config_attr_dev_name,
+ &gpio_virtuser_device_config_attr_live,
+ NULL
+};
+
+static void
+gpio_virtuser_lookup_entry_config_group_release(struct config_item *item)
+{
+ struct gpio_virtuser_lookup_entry *entry =
+ to_gpio_virtuser_lookup_entry(item);
+ struct gpio_virtuser_device *dev = entry->parent->parent;
+
+ guard(mutex)(&dev->lock);
+
+ list_del(&entry->siblings);
+
+ kfree(entry->key);
+ kfree(entry);
+}
+
+static struct
+configfs_item_operations gpio_virtuser_lookup_entry_config_item_ops = {
+ .release = gpio_virtuser_lookup_entry_config_group_release,
+};
+
+static const struct
+config_item_type gpio_virtuser_lookup_entry_config_group_type = {
+ .ct_item_ops = &gpio_virtuser_lookup_entry_config_item_ops,
+ .ct_attrs = gpio_virtuser_lookup_entry_config_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *
+gpio_virtuser_make_lookup_entry_group(struct config_group *group,
+ const char *name)
+{
+ struct gpio_virtuser_lookup *lookup =
+ to_gpio_virtuser_lookup(&group->cg_item);
+ struct gpio_virtuser_device *dev = lookup->parent;
+
+ guard(mutex)(&dev->lock);
+
+ if (gpio_virtuser_device_is_live(dev))
+ return ERR_PTR(-EBUSY);
+
+ struct gpio_virtuser_lookup_entry *entry __free(kfree) =
+ kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return ERR_PTR(-ENOMEM);
+
+ config_group_init_type_name(&entry->group, name,
+ &gpio_virtuser_lookup_entry_config_group_type);
+ entry->flags = GPIO_LOOKUP_FLAGS_DEFAULT;
+ entry->parent = lookup;
+ list_add_tail(&entry->siblings, &lookup->entry_list);
+
+ return &no_free_ptr(entry)->group;
+}
+
+static void gpio_virtuser_lookup_config_group_release(struct config_item *item)
+{
+ struct gpio_virtuser_lookup *lookup = to_gpio_virtuser_lookup(item);
+ struct gpio_virtuser_device *dev = lookup->parent;
+
+ guard(mutex)(&dev->lock);
+
+ list_del(&lookup->siblings);
+
+ kfree(lookup->con_id);
+ kfree(lookup);
+}
+
+static struct configfs_item_operations gpio_virtuser_lookup_config_item_ops = {
+ .release = gpio_virtuser_lookup_config_group_release,
+};
+
+static struct
+configfs_group_operations gpio_virtuser_lookup_config_group_ops = {
+ .make_group = gpio_virtuser_make_lookup_entry_group,
+};
+
+static const struct config_item_type gpio_virtuser_lookup_config_group_type = {
+ .ct_group_ops = &gpio_virtuser_lookup_config_group_ops,
+ .ct_item_ops = &gpio_virtuser_lookup_config_item_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *
+gpio_virtuser_make_lookup_group(struct config_group *group, const char *name)
+{
+ struct gpio_virtuser_device *dev =
+ to_gpio_virtuser_device(&group->cg_item);
+
+ if (strlen(name) > (GPIO_VIRTUSER_NAME_BUF_LEN - 1))
+ return ERR_PTR(-E2BIG);
+
+ guard(mutex)(&dev->lock);
+
+ if (gpio_virtuser_device_is_live(dev))
+ return ERR_PTR(-EBUSY);
+
+ struct gpio_virtuser_lookup *lookup __free(kfree) =
+ kzalloc(sizeof(*lookup), GFP_KERNEL);
+ if (!lookup)
+ return ERR_PTR(-ENOMEM);
+
+ lookup->con_id = kstrdup(name, GFP_KERNEL);
+ if (!lookup->con_id)
+ return ERR_PTR(-ENOMEM);
+
+ config_group_init_type_name(&lookup->group, name,
+ &gpio_virtuser_lookup_config_group_type);
+ INIT_LIST_HEAD(&lookup->entry_list);
+ lookup->parent = dev;
+ list_add_tail(&lookup->siblings, &dev->lookup_list);
+
+ return &no_free_ptr(lookup)->group;
+}
+
+static void gpio_virtuser_device_config_group_release(struct config_item *item)
+{
+ struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item);
+
+ guard(mutex)(&dev->lock);
+
+ if (gpio_virtuser_device_is_live(dev))
+ gpio_virtuser_device_deactivate(dev);
+
+ mutex_destroy(&dev->lock);
+ ida_free(&gpio_virtuser_ida, dev->id);
+ kfree(dev);
+}
+
+static struct configfs_item_operations gpio_virtuser_device_config_item_ops = {
+ .release = gpio_virtuser_device_config_group_release,
+};
+
+static struct configfs_group_operations gpio_virtuser_device_config_group_ops = {
+ .make_group = gpio_virtuser_make_lookup_group,
+};
+
+static const struct config_item_type gpio_virtuser_device_config_group_type = {
+ .ct_group_ops = &gpio_virtuser_device_config_group_ops,
+ .ct_item_ops = &gpio_virtuser_device_config_item_ops,
+ .ct_attrs = gpio_virtuser_device_config_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *
+gpio_virtuser_config_make_device_group(struct config_group *group,
+ const char *name)
+{
+ struct gpio_virtuser_device *dev __free(kfree) = kzalloc(sizeof(*dev),
+ GFP_KERNEL);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ dev->id = ida_alloc(&gpio_virtuser_ida, GFP_KERNEL);
+ if (dev->id < 0)
+ return ERR_PTR(dev->id);
+
+ config_group_init_type_name(&dev->group, name,
+ &gpio_virtuser_device_config_group_type);
+ mutex_init(&dev->lock);
+ INIT_LIST_HEAD(&dev->lookup_list);
+ dev->bus_notifier.notifier_call = gpio_virtuser_bus_notifier_call;
+ init_completion(&dev->probe_completion);
+
+ return &no_free_ptr(dev)->group;
+}
+
+static struct configfs_group_operations gpio_virtuser_config_group_ops = {
+ .make_group = gpio_virtuser_config_make_device_group,
+};
+
+static const struct config_item_type gpio_virtuser_config_type = {
+ .ct_group_ops = &gpio_virtuser_config_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct configfs_subsystem gpio_virtuser_config_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "gpio-virtuser",
+ .ci_type = &gpio_virtuser_config_type,
+ },
+ },
+};
+
+static int __init gpio_virtuser_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&gpio_virtuser_driver);
+ if (ret) {
+ pr_err("Failed to register the platform driver: %d\n", ret);
+ return ret;
+ }
+
+ config_group_init(&gpio_virtuser_config_subsys.su_group);
+ mutex_init(&gpio_virtuser_config_subsys.su_mutex);
+ ret = configfs_register_subsystem(&gpio_virtuser_config_subsys);
+ if (ret) {
+ pr_err("Failed to register the '%s' configfs subsystem: %d\n",
+ gpio_virtuser_config_subsys.su_group.cg_item.ci_namebuf,
+ ret);
+ goto err_plat_drv_unreg;
+ }
+
+ gpio_virtuser_dbg_root = debugfs_create_dir("gpio-virtuser", NULL);
+ if (IS_ERR(gpio_virtuser_dbg_root)) {
+ ret = PTR_ERR(gpio_virtuser_dbg_root);
+ pr_err("Failed to create the debugfs tree: %d\n", ret);
+ goto err_configfs_unreg;
+ }
+
+ return 0;
+
+err_configfs_unreg:
+ configfs_unregister_subsystem(&gpio_virtuser_config_subsys);
+err_plat_drv_unreg:
+ mutex_destroy(&gpio_virtuser_config_subsys.su_mutex);
+ platform_driver_unregister(&gpio_virtuser_driver);
+
+ return ret;
+}
+module_init(gpio_virtuser_init);
+
+static void __exit gpio_virtuser_exit(void)
+{
+ configfs_unregister_subsystem(&gpio_virtuser_config_subsys);
+ mutex_destroy(&gpio_virtuser_config_subsys.su_mutex);
+ platform_driver_unregister(&gpio_virtuser_driver);
+ debugfs_remove_recursive(gpio_virtuser_dbg_root);
+}
+module_exit(gpio_virtuser_exit);
+
+MODULE_AUTHOR("Bartosz Golaszewski <[email protected]>");
+MODULE_DESCRIPTION("Virtual GPIO consumer module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index bb063b81cee6..69cd2be9c7f3 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -976,7 +976,7 @@ __acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int
int i;
/* Try first from _DSD */
- for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
+ for (i = 0; i < gpio_suffix_count; i++) {
if (con_id) {
snprintf(propname, sizeof(propname), "%s-%s",
con_id, gpio_suffixes[i]);
@@ -1453,7 +1453,7 @@ int acpi_gpio_count(const struct fwnode_handle *fwnode, const char *con_id)
unsigned int i;
/* Try first from _DSD */
- for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
+ for (i = 0; i < gpio_suffix_count; i++) {
if (con_id)
snprintf(propname, sizeof(propname), "%s-%s",
con_id, gpio_suffixes[i]);
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index 5639abce6ec5..ef08b23a56e2 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -1132,6 +1132,14 @@ static void edge_detector_stop(struct line *line)
/* do not change line->level - see comment in debounced_value() */
}
+static int edge_detector_fifo_init(struct linereq *req)
+{
+ if (kfifo_initialized(&req->events))
+ return 0;
+
+ return kfifo_alloc(&req->events, req->event_buffer_size, GFP_KERNEL);
+}
+
static int edge_detector_setup(struct line *line,
struct gpio_v2_line_config *lc,
unsigned int line_idx, u64 edflags)
@@ -1143,9 +1151,8 @@ static int edge_detector_setup(struct line *line,
char *label;
eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
- if (eflags && !kfifo_initialized(&line->req->events)) {
- ret = kfifo_alloc(&line->req->events,
- line->req->event_buffer_size, GFP_KERNEL);
+ if (eflags) {
+ ret = edge_detector_fifo_init(line->req);
if (ret)
return ret;
}
@@ -1197,8 +1204,6 @@ static int edge_detector_update(struct line *line,
struct gpio_v2_line_config *lc,
unsigned int line_idx, u64 edflags)
{
- u64 eflags;
- int ret;
u64 active_edflags = READ_ONCE(line->edflags);
unsigned int debounce_period_us =
gpio_v2_line_config_debounce_period(lc, line_idx);
@@ -1214,14 +1219,9 @@ static int edge_detector_update(struct line *line,
* ensure event fifo is initialised if edge detection
* is now enabled.
*/
- eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
- if (eflags && !kfifo_initialized(&line->req->events)) {
- ret = kfifo_alloc(&line->req->events,
- line->req->event_buffer_size,
- GFP_KERNEL);
- if (ret)
- return ret;
- }
+ if (edflags & GPIO_V2_LINE_EDGE_FLAGS)
+ return edge_detector_fifo_init(line->req);
+
return 0;
}
@@ -1648,16 +1648,15 @@ static ssize_t linereq_read(struct file *file, char __user *buf,
return ret;
}
- ret = kfifo_out(&lr->events, &le, 1);
- }
- if (ret != 1) {
- /*
- * This should never happen - we were holding the
- * lock from the moment we learned the fifo is no
- * longer empty until now.
- */
- ret = -EIO;
- break;
+ if (kfifo_out(&lr->events, &le, 1) != 1) {
+ /*
+ * This should never happen - we hold the
+ * lock from the moment we learned the fifo
+ * is no longer empty until now.
+ */
+ WARN(1, "failed to read from non-empty kfifo");
+ return -EIO;
+ }
}
if (copy_to_user(buf + bytes_read, &le, sizeof(le)))
@@ -1780,6 +1779,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
mutex_init(&lr->config_mutex);
init_waitqueue_head(&lr->wait);
+ INIT_KFIFO(lr->events);
lr->event_buffer_size = ulr.event_buffer_size;
if (lr->event_buffer_size == 0)
lr->event_buffer_size = ulr.num_lines * 16;
@@ -2000,16 +2000,15 @@ static ssize_t lineevent_read(struct file *file, char __user *buf,
return ret;
}
- ret = kfifo_out(&le->events, &ge, 1);
- }
- if (ret != 1) {
- /*
- * This should never happen - we were holding the lock
- * from the moment we learned the fifo is no longer
- * empty until now.
- */
- ret = -EIO;
- break;
+ if (kfifo_out(&le->events, &ge, 1) != 1) {
+ /*
+ * This should never happen - we hold the
+ * lock from the moment we learned the fifo
+ * is no longer empty until now.
+ */
+ WARN(1, "failed to read from non-empty kfifo");
+ return -EIO;
+ }
}
if (copy_to_user(buf + bytes_read, &ge, ge_size))
@@ -2712,12 +2711,15 @@ static ssize_t lineinfo_watch_read(struct file *file, char __user *buf,
if (count < event_size)
return -EINVAL;
#endif
- ret = kfifo_out(&cdev->events, &event, 1);
- }
- if (ret != 1) {
- ret = -EIO;
- break;
- /* We should never get here. See lineevent_read(). */
+ if (kfifo_out(&cdev->events, &event, 1) != 1) {
+ /*
+ * This should never happen - we hold the
+ * lock from the moment we learned the fifo
+ * is no longer empty until now.
+ */
+ WARN(1, "failed to read from non-empty kfifo");
+ return -EIO;
+ }
}
#ifdef CONFIG_GPIO_CDEV_V1
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index d75f6ee37028..f6af5e7be4d1 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -103,7 +103,7 @@ int of_gpio_count(const struct fwnode_handle *fwnode, const char *con_id)
if (ret > 0)
return ret;
- for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
+ for (i = 0; i < gpio_suffix_count; i++) {
if (con_id)
snprintf(propname, sizeof(propname), "%s-%s",
con_id, gpio_suffixes[i]);
@@ -203,6 +203,24 @@ static void of_gpio_try_fixup_polarity(const struct device_node *np,
*/
{ "qi,lb60", "rb-gpios", true },
#endif
+#if IS_ENABLED(CONFIG_PCI_LANTIQ)
+ /*
+ * According to the PCI specification, the RST# pin is an
+ * active-low signal. However, most of the device trees that
+ * have been widely used for a long time incorrectly describe
+ * reset GPIO as active-high, and were also using wrong name
+ * for the property.
+ */
+ { "lantiq,pci-xway", "gpio-reset", false },
+#endif
+#if IS_ENABLED(CONFIG_TOUCHSCREEN_TSC2005)
+ /*
+ * DTS for Nokia N900 incorrectly specified "active high"
+ * polarity for the reset line, while the chip actually
+ * treats it as "active low".
+ */
+ { "ti,tsc2005", "reset-gpios", false },
+#endif
};
unsigned int i;
@@ -504,9 +522,9 @@ static struct gpio_desc *of_find_gpio_rename(struct device_node *np,
{ "reset", "reset-n-io", "marvell,nfc-uart" },
{ "reset", "reset-n-io", "mrvl,nfc-uart" },
#endif
-#if !IS_ENABLED(CONFIG_PCI_LANTIQ)
+#if IS_ENABLED(CONFIG_PCI_LANTIQ)
/* MIPS Lantiq PCI */
- { "reset", "gpios-reset", "lantiq,pci-xway" },
+ { "reset", "gpio-reset", "lantiq,pci-xway" },
#endif
/*
@@ -676,7 +694,7 @@ struct gpio_desc *of_find_gpio(struct device_node *np, const char *con_id,
unsigned int i;
/* Try GPIO property "foo-gpios" and "foo-gpio" */
- for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
+ for (i = 0; i < gpio_suffix_count; i++) {
if (con_id)
snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id,
gpio_suffixes[i]);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index fa62367ee929..edaeee53db75 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/acpi.h>
+#include <linux/array_size.h>
#include <linux/bitmap.h>
#include <linux/cleanup.h>
#include <linux/compat.h>
@@ -17,6 +18,7 @@
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/module.h>
+#include <linux/nospec.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/seq_file.h>
@@ -88,6 +90,9 @@ DEFINE_STATIC_SRCU(gpio_devices_srcu);
static DEFINE_MUTEX(gpio_machine_hogs_mutex);
static LIST_HEAD(gpio_machine_hogs);
+const char *const gpio_suffixes[] = { "gpios", "gpio" };
+const size_t gpio_suffix_count = ARRAY_SIZE(gpio_suffixes);
+
static void gpiochip_free_hogs(struct gpio_chip *gc);
static int gpiochip_add_irqchip(struct gpio_chip *gc,
struct lock_class_key *lock_key,
@@ -105,16 +110,16 @@ const char *gpiod_get_label(struct gpio_desc *desc)
unsigned long flags;
flags = READ_ONCE(desc->flags);
- if (test_bit(FLAG_USED_AS_IRQ, &flags) &&
- !test_bit(FLAG_REQUESTED, &flags))
- return "interrupt";
-
- if (!test_bit(FLAG_REQUESTED, &flags))
- return NULL;
label = srcu_dereference_check(desc->label, &desc->gdev->desc_srcu,
srcu_read_lock_held(&desc->gdev->desc_srcu));
+ if (test_bit(FLAG_USED_AS_IRQ, &flags))
+ return label->str ?: "interrupt";
+
+ if (!test_bit(FLAG_REQUESTED, &flags))
+ return NULL;
+
return label->str;
}
@@ -174,7 +179,6 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc,
{
return gpio_device_get_desc(gc->gpiodev, hwnum);
}
-EXPORT_SYMBOL_GPL(gpiochip_get_desc);
/**
* gpio_device_get_desc() - get the GPIO descriptor corresponding to the given
@@ -198,7 +202,7 @@ gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum)
if (hwnum >= gdev->ngpio)
return ERR_PTR(-EINVAL);
- return &gdev->descs[hwnum];
+ return &gdev->descs[array_index_nospec(hwnum, gdev->ngpio)];
}
EXPORT_SYMBOL_GPL(gpio_device_get_desc);
@@ -485,7 +489,7 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name)
* 1. Non-unique names are still accepted,
* 2. Name collisions within the same GPIO chip are not reported.
*/
-static int gpiochip_set_desc_names(struct gpio_chip *gc)
+static void gpiochip_set_desc_names(struct gpio_chip *gc)
{
struct gpio_device *gdev = gc->gpiodev;
int i;
@@ -504,8 +508,6 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)
/* Then add all names to the GPIO descriptors */
for (i = 0; i != gc->ngpio; ++i)
gdev->descs[i].name = gc->names[i];
-
- return 0;
}
/*
@@ -999,11 +1001,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
INIT_LIST_HEAD(&gdev->pin_ranges);
#endif
- if (gc->names) {
- ret = gpiochip_set_desc_names(gc);
- if (ret)
- goto err_cleanup_desc_srcu;
- }
+ if (gc->names)
+ gpiochip_set_desc_names(gc);
+
ret = gpiochip_set_names(gc);
if (ret)
goto err_cleanup_desc_srcu;
@@ -4798,11 +4798,11 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)
for_each_gpio_desc(gc, desc) {
guard(srcu)(&desc->gdev->desc_srcu);
- if (test_bit(FLAG_REQUESTED, &desc->flags)) {
+ is_irq = test_bit(FLAG_USED_AS_IRQ, &desc->flags);
+ if (is_irq || test_bit(FLAG_REQUESTED, &desc->flags)) {
gpiod_get_direction(desc);
is_out = test_bit(FLAG_IS_OUT, &desc->flags);
value = gpio_chip_get_value(gc, desc);
- is_irq = test_bit(FLAG_USED_AS_IRQ, &desc->flags);
active_low = test_bit(FLAG_ACTIVE_LOW, &desc->flags);
seq_printf(s, " gpio-%-3u (%-20.20s|%-20.20s) %s %s %s%s\n",
gpio, desc->name ?: "", gpiod_get_label(desc),
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 48e086c2f416..4de0bf1a62d3 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -90,7 +90,8 @@ static inline struct gpio_device *to_gpio_device(struct device *dev)
}
/* gpio suffixes used for ACPI and device tree lookup */
-static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" };
+extern const char *const gpio_suffixes[];
+extern const size_t gpio_suffix_count;
/**
* struct gpio_array - Opaque descriptor for a structure of GPIO array attributes
@@ -242,6 +243,7 @@ int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce);
int gpiod_hog(struct gpio_desc *desc, const char *name,
unsigned long lflags, enum gpiod_flags dflags);
int gpiochip_get_ngpios(struct gpio_chip *gc, struct device *dev);
+struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum);
const char *gpiod_get_label(struct gpio_desc *desc);
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index ec888fc6ead8..916b6b8cf7d9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -1093,6 +1093,21 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
unsigned int i;
int r;
+ /*
+ * We can't use gang submit on with reserved VMIDs when the VM changes
+ * can't be invalidated by more than one engine at the same time.
+ */
+ if (p->gang_size > 1 && !p->adev->vm_manager.concurrent_flush) {
+ for (i = 0; i < p->gang_size; ++i) {
+ struct drm_sched_entity *entity = p->entities[i];
+ struct drm_gpu_scheduler *sched = entity->rq->sched;
+ struct amdgpu_ring *ring = to_amdgpu_ring(sched);
+
+ if (amdgpu_vmid_uses_reserved(vm, ring->vm_hub))
+ return -EINVAL;
+ }
+ }
+
r = amdgpu_vm_clear_freed(adev, vm, NULL);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index 3d7fcdeaf8cf..e8f6e4dbc5a4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -406,7 +406,7 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
if (r || !idle)
goto error;
- if (vm->reserved_vmid[vmhub] || (enforce_isolation && (vmhub == AMDGPU_GFXHUB(0)))) {
+ if (amdgpu_vmid_uses_reserved(vm, vmhub)) {
r = amdgpu_vmid_grab_reserved(vm, ring, job, &id, fence);
if (r || !id)
goto error;
@@ -456,6 +456,19 @@ error:
return r;
}
+/*
+ * amdgpu_vmid_uses_reserved - check if a VM will use a reserved VMID
+ * @vm: the VM to check
+ * @vmhub: the VMHUB which will be used
+ *
+ * Returns: True if the VM will use a reserved VMID.
+ */
+bool amdgpu_vmid_uses_reserved(struct amdgpu_vm *vm, unsigned int vmhub)
+{
+ return vm->reserved_vmid[vmhub] ||
+ (enforce_isolation && (vmhub == AMDGPU_GFXHUB(0)));
+}
+
int amdgpu_vmid_alloc_reserved(struct amdgpu_device *adev,
unsigned vmhub)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
index fa8c42c83d5d..240fa6751260 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
@@ -78,6 +78,7 @@ void amdgpu_pasid_free_delayed(struct dma_resv *resv,
bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
struct amdgpu_vmid *id);
+bool amdgpu_vmid_uses_reserved(struct amdgpu_vm *vm, unsigned int vmhub);
int amdgpu_vmid_alloc_reserved(struct amdgpu_device *adev,
unsigned vmhub);
void amdgpu_vmid_free_reserved(struct amdgpu_device *adev,
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 e9ac20bed0f2..a622aca8c649 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -11181,6 +11181,49 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
return ret;
}
+static void parse_edid_displayid_vrr(struct drm_connector *connector,
+ struct edid *edid)
+{
+ u8 *edid_ext = NULL;
+ int i;
+ int j = 0;
+ u16 min_vfreq;
+ u16 max_vfreq;
+
+ if (edid == NULL || edid->extensions == 0)
+ return;
+
+ /* Find DisplayID extension */
+ for (i = 0; i < edid->extensions; i++) {
+ edid_ext = (void *)(edid + (i + 1));
+ if (edid_ext[0] == DISPLAYID_EXT)
+ break;
+ }
+
+ if (edid_ext == NULL)
+ return;
+
+ while (j < EDID_LENGTH) {
+ /* Get dynamic video timing range from DisplayID if available */
+ if (EDID_LENGTH - j > 13 && edid_ext[j] == 0x25 &&
+ (edid_ext[j+1] & 0xFE) == 0 && (edid_ext[j+2] == 9)) {
+ min_vfreq = edid_ext[j+9];
+ if (edid_ext[j+1] & 7)
+ max_vfreq = edid_ext[j+10] + ((edid_ext[j+11] & 3) << 8);
+ else
+ max_vfreq = edid_ext[j+10];
+
+ if (max_vfreq && min_vfreq) {
+ connector->display_info.monitor_range.max_vfreq = max_vfreq;
+ connector->display_info.monitor_range.min_vfreq = min_vfreq;
+
+ return;
+ }
+ }
+ j++;
+ }
+}
+
static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector,
struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
{
@@ -11302,6 +11345,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
if (!adev->dm.freesync_module)
goto update;
+ /* Some eDP panels only have the refresh rate range info in DisplayID */
+ if ((connector->display_info.monitor_range.min_vfreq == 0 ||
+ connector->display_info.monitor_range.max_vfreq == 0))
+ parse_edid_displayid_vrr(connector, edid);
+
if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT ||
sink->sink_signal == SIGNAL_TYPE_EDP)) {
bool edid_check_required = false;
@@ -11309,9 +11357,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
if (is_dp_capable_without_timing_msa(adev->dm.dc,
amdgpu_dm_connector)) {
if (edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ) {
- freesync_capable = true;
amdgpu_dm_connector->min_vfreq = connector->display_info.monitor_range.min_vfreq;
amdgpu_dm_connector->max_vfreq = connector->display_info.monitor_range.max_vfreq;
+ if (amdgpu_dm_connector->max_vfreq -
+ amdgpu_dm_connector->min_vfreq > 10)
+ freesync_capable = true;
} else {
edid_check_required = edid->version > 1 ||
(edid->version == 1 &&
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
index 6c84b0fa40f4..0782a34689a0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
@@ -3364,6 +3364,9 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
&mode_lib->vba.UrgentBurstFactorLumaPre[k],
&mode_lib->vba.UrgentBurstFactorChromaPre[k],
&mode_lib->vba.NotUrgentLatencyHidingPre[k]);
+
+ v->cursor_bw_pre[k] = mode_lib->vba.NumberOfCursors[k] * mode_lib->vba.CursorWidth[k][0] * mode_lib->vba.CursorBPP[k][0] /
+ 8.0 / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * v->VRatioPreY[i][j][k];
}
{
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
index a41812598ce8..8ecc972dbffd 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
@@ -234,6 +234,7 @@ void dml2_init_socbb_params(struct dml2_context *dml2, const struct dc *in_dc, s
out->round_trip_ping_latency_dcfclk_cycles = 106;
out->smn_latency_us = 2;
out->dispclk_dppclk_vco_speed_mhz = 3600;
+ out->pct_ideal_dram_bw_after_urgent_pixel_only = 65.0;
break;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c
index 0f8b3336e26d..cbd1c1f26b7a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c
@@ -294,7 +294,7 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont
context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = (unsigned int)in_ctx->v20.dml_core_ctx.mp.DCFCLKDeepSleep * 1000;
context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
- if (in_ctx->v20.dml_core_ctx.ms.support.FCLKChangeSupport[in_ctx->v20.scratch.mode_support_params.out_lowest_state_idx] == dml_fclock_change_unsupported)
+ if (in_ctx->v20.dml_core_ctx.ms.support.FCLKChangeSupport[0] == dml_fclock_change_unsupported)
context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = false;
else
context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = true;
diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h
index 571691837200..09cbc3afd6d8 100644
--- a/drivers/gpu/drm/amd/include/atomfirmware.h
+++ b/drivers/gpu/drm/amd/include/atomfirmware.h
@@ -734,7 +734,7 @@ struct atom_gpio_pin_lut_v2_1
{
struct atom_common_table_header table_header;
/*the real number of this included in the structure is calcualted by using the (whole structure size - the header size)/size of atom_gpio_pin_lut */
- struct atom_gpio_pin_assignment gpio_pin[8];
+ struct atom_gpio_pin_assignment gpio_pin[];
};
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index ea271f62b214..ec0b7f3d889c 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -401,7 +401,7 @@ struct adv7511 {
#ifdef CONFIG_DRM_I2C_ADV7511_CEC
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511);
-void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
+int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
#else
static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
{
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
index 44451a9658a3..2e9c88a2b5ed 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
@@ -119,7 +119,7 @@ static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf)
cec_received_msg(adv7511->cec_adap, &msg);
}
-void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
+int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
{
unsigned int offset = adv7511->info->reg_cec_offset;
const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY |
@@ -131,16 +131,19 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
unsigned int rx_status;
int rx_order[3] = { -1, -1, -1 };
int i;
+ int irq_status = IRQ_NONE;
- if (irq1 & irq_tx_mask)
+ if (irq1 & irq_tx_mask) {
adv_cec_tx_raw_status(adv7511, irq1);
+ irq_status = IRQ_HANDLED;
+ }
if (!(irq1 & irq_rx_mask))
- return;
+ return irq_status;
if (regmap_read(adv7511->regmap_cec,
ADV7511_REG_CEC_RX_STATUS + offset, &rx_status))
- return;
+ return irq_status;
/*
* ADV7511_REG_CEC_RX_STATUS[5:0] contains the reception order of RX
@@ -172,6 +175,8 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
adv7511_cec_rx(adv7511, rx_buf);
}
+
+ return IRQ_HANDLED;
}
static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 66ccb61e2a66..c8d2c4a157b2 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -469,6 +469,8 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
{
unsigned int irq0, irq1;
int ret;
+ int cec_status = IRQ_NONE;
+ int irq_status = IRQ_NONE;
ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
if (ret < 0)
@@ -478,29 +480,31 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
if (ret < 0)
return ret;
- /* If there is no IRQ to handle, exit indicating no IRQ data */
- if (!(irq0 & (ADV7511_INT0_HPD | ADV7511_INT0_EDID_READY)) &&
- !(irq1 & ADV7511_INT1_DDC_ERROR))
- return -ENODATA;
-
regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
- if (process_hpd && irq0 & ADV7511_INT0_HPD && adv7511->bridge.encoder)
+ if (process_hpd && irq0 & ADV7511_INT0_HPD && adv7511->bridge.encoder) {
schedule_work(&adv7511->hpd_work);
+ irq_status = IRQ_HANDLED;
+ }
if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
adv7511->edid_read = true;
if (adv7511->i2c_main->irq)
wake_up_all(&adv7511->wq);
+ irq_status = IRQ_HANDLED;
}
#ifdef CONFIG_DRM_I2C_ADV7511_CEC
- adv7511_cec_irq_process(adv7511, irq1);
+ cec_status = adv7511_cec_irq_process(adv7511, irq1);
#endif
- return 0;
+ /* If there is no IRQ to handle, exit indicating no IRQ data */
+ if (irq_status == IRQ_HANDLED || cec_status == IRQ_HANDLED)
+ return IRQ_HANDLED;
+
+ return IRQ_NONE;
}
static irqreturn_t adv7511_irq_handler(int irq, void *devid)
@@ -509,7 +513,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid)
int ret;
ret = adv7511_irq_process(adv7511, true);
- return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
+ return ret < 0 ? IRQ_NONE : ret;
}
/* -----------------------------------------------------------------------------
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c
index 97e579c33d84..1e200d815e1a 100644
--- a/drivers/gpu/drm/drm_fbdev_generic.c
+++ b/drivers/gpu/drm/drm_fbdev_generic.c
@@ -84,7 +84,8 @@ static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
sizes->surface_width, sizes->surface_height,
sizes->surface_bpp);
- format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
+ format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp,
+ sizes->surface_depth);
buffer = drm_client_framebuffer_create(client, sizes->surface_width,
sizes->surface_height, format);
if (IS_ERR(buffer))
diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
index 2166208a961d..3860a8ce1e2d 100644
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -420,13 +420,20 @@ static const struct dmi_system_id orientation_data[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"),
},
.driver_data = (void *)&lcd1280x1920_rightside_up,
- }, { /* Valve Steam Deck */
+ }, { /* Valve Steam Deck (Jupiter) */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
},
.driver_data = (void *)&lcd800x1280_rightside_up,
+ }, { /* Valve Steam Deck (Galileo) */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galileo"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
+ },
+ .driver_data = (void *)&lcd800x1280_rightside_up,
}, { /* VIOS LTH17 */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"),
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index f08a6803dc18..3adc2c9ab72d 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -311,6 +311,9 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
if (mode_dev->panel_fixed_mode != NULL) {
struct drm_display_mode *mode =
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+ if (!mode)
+ return 0;
+
drm_mode_probed_add(connector, mode);
return 1;
}
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index 8486de230ec9..8d1be94a443b 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -504,6 +504,9 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector)
if (mode_dev->panel_fixed_mode != NULL) {
struct drm_display_mode *mode =
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+ if (!mode)
+ return 0;
+
drm_mode_probed_add(connector, mode);
return 1;
}
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 3c3fc53376ce..6bff169fa8d4 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2088,6 +2088,9 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port,
u32 ln0, ln1, pin_assignment;
u8 width;
+ if (DISPLAY_VER(dev_priv) >= 14)
+ return;
+
if (!intel_encoder_is_tc(&dig_port->base) ||
intel_tc_port_in_tbt_alt_mode(dig_port))
return;
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 17a5cca007e2..4bd0baa2a4f5 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -250,29 +250,20 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
if (ret)
goto free_drm;
ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_0);
- if (ret) {
- meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
- goto free_drm;
- }
+ if (ret)
+ goto free_canvas_osd1;
ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_1);
- if (ret) {
- meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
- meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
- goto free_drm;
- }
+ if (ret)
+ goto free_canvas_vd1_0;
ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_2);
- if (ret) {
- meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
- meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
- meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1);
- goto free_drm;
- }
+ if (ret)
+ goto free_canvas_vd1_1;
priv->vsync_irq = platform_get_irq(pdev, 0);
ret = drm_vblank_init(drm, 1);
if (ret)
- goto free_drm;
+ goto free_canvas_vd1_2;
/* Assign limits per soc revision/package */
for (i = 0 ; i < ARRAY_SIZE(meson_drm_soc_attrs) ; ++i) {
@@ -288,11 +279,11 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
*/
ret = drm_aperture_remove_framebuffers(&meson_driver);
if (ret)
- goto free_drm;
+ goto free_canvas_vd1_2;
ret = drmm_mode_config_init(drm);
if (ret)
- goto free_drm;
+ goto free_canvas_vd1_2;
drm->mode_config.max_width = 3840;
drm->mode_config.max_height = 2160;
drm->mode_config.funcs = &meson_mode_config_funcs;
@@ -307,7 +298,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
if (priv->afbcd.ops) {
ret = priv->afbcd.ops->init(priv);
if (ret)
- goto free_drm;
+ goto free_canvas_vd1_2;
}
/* Encoder Initialization */
@@ -371,6 +362,14 @@ uninstall_irq:
exit_afbcd:
if (priv->afbcd.ops)
priv->afbcd.ops->exit(priv);
+free_canvas_vd1_2:
+ meson_canvas_free(priv->canvas, priv->canvas_id_vd1_2);
+free_canvas_vd1_1:
+ meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1);
+free_canvas_vd1_0:
+ meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
+free_canvas_osd1:
+ meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
free_drm:
drm_dev_put(drm);
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 856b3ef5edb8..0c71d761d378 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1001,6 +1001,9 @@ nouveau_connector_get_modes(struct drm_connector *connector)
struct drm_display_mode *mode;
mode = drm_mode_duplicate(dev, nv_connector->native_mode);
+ if (!mode)
+ return 0;
+
drm_mode_probed_add(connector, mode);
ret = 1;
}
diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
index b8a84f26b3ef..b5e7b919f241 100644
--- a/drivers/gpu/drm/panthor/panthor_drv.c
+++ b/drivers/gpu/drm/panthor/panthor_drv.c
@@ -86,15 +86,15 @@ panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride,
int ret = 0;
void *out_alloc;
+ if (!in->count)
+ return NULL;
+
/* User stride must be at least the minimum object size, otherwise it might
* lack useful information.
*/
if (in->stride < min_stride)
return ERR_PTR(-EINVAL);
- if (!in->count)
- return NULL;
-
out_alloc = kvmalloc_array(in->count, obj_size, GFP_KERNEL);
if (!out_alloc)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index 79ffcbc41d78..9a0ff48f7061 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -459,6 +459,16 @@ struct panthor_queue {
atomic64_t seqno;
/**
+ * @last_fence: Fence of the last submitted job.
+ *
+ * We return this fence when we get an empty command stream.
+ * This way, we are guaranteed that all earlier jobs have completed
+ * when drm_sched_job::s_fence::finished without having to feed
+ * the CS ring buffer with a dummy job that only signals the fence.
+ */
+ struct dma_fence *last_fence;
+
+ /**
* @in_flight_jobs: List containing all in-flight jobs.
*
* Used to keep track and signal panthor_job::done_fence when the
@@ -829,6 +839,9 @@ static void group_free_queue(struct panthor_group *group, struct panthor_queue *
panthor_kernel_bo_destroy(queue->ringbuf);
panthor_kernel_bo_destroy(queue->iface.mem);
+ /* Release the last_fence we were holding, if any. */
+ dma_fence_put(queue->fence_ctx.last_fence);
+
kfree(queue);
}
@@ -2784,9 +2797,6 @@ static void group_sync_upd_work(struct work_struct *work)
spin_lock(&queue->fence_ctx.lock);
list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) {
- if (!job->call_info.size)
- continue;
-
if (syncobj->seqno < job->done_fence->seqno)
break;
@@ -2865,11 +2875,14 @@ queue_run_job(struct drm_sched_job *sched_job)
static_assert(sizeof(call_instrs) % 64 == 0,
"call_instrs is not aligned on a cacheline");
- /* Stream size is zero, nothing to do => return a NULL fence and let
- * drm_sched signal the parent.
+ /* Stream size is zero, nothing to do except making sure all previously
+ * submitted jobs are done before we signal the
+ * drm_sched_job::s_fence::finished fence.
*/
- if (!job->call_info.size)
- return NULL;
+ if (!job->call_info.size) {
+ job->done_fence = dma_fence_get(queue->fence_ctx.last_fence);
+ return dma_fence_get(job->done_fence);
+ }
ret = pm_runtime_resume_and_get(ptdev->base.dev);
if (drm_WARN_ON(&ptdev->base, ret))
@@ -2928,6 +2941,10 @@ queue_run_job(struct drm_sched_job *sched_job)
}
}
+ /* Update the last fence. */
+ dma_fence_put(queue->fence_ctx.last_fence);
+ queue->fence_ctx.last_fence = dma_fence_get(job->done_fence);
+
done_fence = dma_fence_get(job->done_fence);
out_unlock:
@@ -3378,10 +3395,15 @@ panthor_job_create(struct panthor_file *pfile,
goto err_put_job;
}
- job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL);
- if (!job->done_fence) {
- ret = -ENOMEM;
- goto err_put_job;
+ /* Empty command streams don't need a fence, they'll pick the one from
+ * the previously submitted job.
+ */
+ if (job->call_info.size) {
+ job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL);
+ if (!job->done_fence) {
+ ret = -ENOMEM;
+ goto err_put_job;
+ }
}
ret = drm_sched_job_init(&job->base,
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index 2ef201a072f1..e66a230331ee 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -642,7 +642,7 @@ static void radeon_gem_va_update_vm(struct radeon_device *rdev,
if (r)
goto error_unlock;
- if (bo_va->it.start)
+ if (bo_va->it.start && bo_va->bo)
r = radeon_vm_bo_update(rdev, bo_va, bo_va->bo->tbo.resource);
error_unlock:
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 6396dece0db1..2427be8bc97f 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -346,6 +346,7 @@ static void ttm_bo_release(struct kref *kref)
if (!dma_resv_test_signaled(bo->base.resv,
DMA_RESV_USAGE_BOOKKEEP) ||
(want_init_on_free() && (bo->ttm != NULL)) ||
+ bo->type == ttm_bo_type_sg ||
!dma_resv_trylock(bo->base.resv)) {
/* The BO is not idle, resurrect it for delayed destroy */
ttm_bo_flush_all_fences(bo);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
index 2651fe0ef518..1f15990d3934 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
@@ -48,8 +48,6 @@
#define RETRIES 3
-#define VMW_HYPERVISOR_MAGIC 0x564D5868
-
#define VMW_PORT_CMD_MSG 30
#define VMW_PORT_CMD_HB_MSG 0
#define VMW_PORT_CMD_OPEN_CHANNEL (MSG_TYPE_OPEN << 16 | VMW_PORT_CMD_MSG)
@@ -104,20 +102,18 @@ static const char* const mksstat_kern_name_desc[MKSSTAT_KERN_COUNT][2] =
*/
static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol)
{
- unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
+ u32 ecx, edx, esi, edi;
- VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL,
- (protocol | GUESTMSG_FLAG_COOKIE), si, di,
- 0,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall6(VMW_PORT_CMD_OPEN_CHANNEL,
+ (protocol | GUESTMSG_FLAG_COOKIE), 0,
+ &ecx, &edx, &esi, &edi);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
return -EINVAL;
channel->channel_id = HIGH_WORD(edx);
- channel->cookie_high = si;
- channel->cookie_low = di;
+ channel->cookie_high = esi;
+ channel->cookie_low = edi;
return 0;
}
@@ -133,17 +129,13 @@ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol)
*/
static int vmw_close_channel(struct rpc_channel *channel)
{
- unsigned long eax, ebx, ecx, edx, si, di;
-
- /* Set up additional parameters */
- si = channel->cookie_high;
- di = channel->cookie_low;
+ u32 ecx;
- VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL,
- 0, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall5(VMW_PORT_CMD_CLOSE_CHANNEL,
+ 0, channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ecx);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
return -EINVAL;
@@ -163,24 +155,18 @@ static int vmw_close_channel(struct rpc_channel *channel)
static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
const char *msg, bool hb)
{
- unsigned long si, di, eax, ebx, ecx, edx;
+ u32 ebx, ecx;
unsigned long msg_len = strlen(msg);
/* HB port can't access encrypted memory. */
if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) {
- unsigned long bp = channel->cookie_high;
- u32 channel_id = (channel->channel_id << 16);
-
- si = (uintptr_t) msg;
- di = channel->cookie_low;
-
- VMW_PORT_HB_OUT(
+ vmware_hypercall_hb_out(
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
- msg_len, si, di,
- VMWARE_HYPERVISOR_HB | channel_id |
- VMWARE_HYPERVISOR_OUT,
- VMW_HYPERVISOR_MAGIC, bp,
- eax, ebx, ecx, edx, si, di);
+ msg_len,
+ channel->channel_id << 16,
+ (uintptr_t) msg, channel->cookie_low,
+ channel->cookie_high,
+ &ebx);
return ebx;
}
@@ -194,14 +180,13 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
memcpy(&word, msg, bytes);
msg_len -= bytes;
msg += bytes;
- si = channel->cookie_high;
- di = channel->cookie_low;
-
- VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16),
- word, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+
+ vmware_hypercall5(VMW_PORT_CMD_MSG |
+ (MSG_TYPE_SENDPAYLOAD << 16),
+ word, channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ecx);
}
return ecx;
@@ -220,22 +205,17 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
unsigned long reply_len, bool hb)
{
- unsigned long si, di, eax, ebx, ecx, edx;
+ u32 ebx, ecx, edx;
/* HB port can't access encrypted memory */
if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) {
- unsigned long bp = channel->cookie_low;
- u32 channel_id = (channel->channel_id << 16);
-
- si = channel->cookie_high;
- di = (uintptr_t) reply;
-
- VMW_PORT_HB_IN(
+ vmware_hypercall_hb_in(
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
- reply_len, si, di,
- VMWARE_HYPERVISOR_HB | channel_id,
- VMW_HYPERVISOR_MAGIC, bp,
- eax, ebx, ecx, edx, si, di);
+ reply_len,
+ channel->channel_id << 16,
+ channel->cookie_high,
+ (uintptr_t) reply, channel->cookie_low,
+ &ebx);
return ebx;
}
@@ -245,14 +225,13 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
while (reply_len) {
unsigned int bytes = min_t(unsigned long, reply_len, 4);
- si = channel->cookie_high;
- di = channel->cookie_low;
-
- VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_RECVPAYLOAD << 16),
- MESSAGE_STATUS_SUCCESS, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall7(VMW_PORT_CMD_MSG |
+ (MSG_TYPE_RECVPAYLOAD << 16),
+ MESSAGE_STATUS_SUCCESS,
+ channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ebx, &ecx, &edx);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
break;
@@ -276,22 +255,18 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
*/
static int vmw_send_msg(struct rpc_channel *channel, const char *msg)
{
- unsigned long eax, ebx, ecx, edx, si, di;
+ u32 ebx, ecx;
size_t msg_len = strlen(msg);
int retries = 0;
while (retries < RETRIES) {
retries++;
- /* Set up additional parameters */
- si = channel->cookie_high;
- di = channel->cookie_low;
-
- VMW_PORT(VMW_PORT_CMD_SENDSIZE,
- msg_len, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall5(VMW_PORT_CMD_SENDSIZE,
+ msg_len, channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ecx);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
/* Expected success. Give up. */
@@ -329,7 +304,7 @@ STACK_FRAME_NON_STANDARD(vmw_send_msg);
static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
size_t *msg_len)
{
- unsigned long eax, ebx, ecx, edx, si, di;
+ u32 ebx, ecx, edx;
char *reply;
size_t reply_len;
int retries = 0;
@@ -341,15 +316,11 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
while (retries < RETRIES) {
retries++;
- /* Set up additional parameters */
- si = channel->cookie_high;
- di = channel->cookie_low;
-
- VMW_PORT(VMW_PORT_CMD_RECVSIZE,
- 0, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall7(VMW_PORT_CMD_RECVSIZE,
+ 0, channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ebx, &ecx, &edx);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
DRM_ERROR("Failed to get reply size for host message.\n");
@@ -384,16 +355,12 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
reply[reply_len] = '\0';
-
- /* Ack buffer */
- si = channel->cookie_high;
- di = channel->cookie_low;
-
- VMW_PORT(VMW_PORT_CMD_RECVSTATUS,
- MESSAGE_STATUS_SUCCESS, si, di,
- channel->channel_id << 16,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall5(VMW_PORT_CMD_RECVSTATUS,
+ MESSAGE_STATUS_SUCCESS,
+ channel->channel_id << 16,
+ channel->cookie_high,
+ channel->cookie_low,
+ &ecx);
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
kfree(reply);
@@ -652,13 +619,7 @@ static inline void reset_ppn_array(PPN64 *arr, size_t size)
*/
static inline void hypervisor_ppn_reset_all(void)
{
- unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
-
- VMW_PORT(VMW_PORT_CMD_MKSGS_RESET,
- 0, si, di,
- 0,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall1(VMW_PORT_CMD_MKSGS_RESET, 0);
}
/**
@@ -669,13 +630,7 @@ static inline void hypervisor_ppn_reset_all(void)
*/
static inline void hypervisor_ppn_add(PPN64 pfn)
{
- unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
-
- VMW_PORT(VMW_PORT_CMD_MKSGS_ADD_PPN,
- (unsigned long)pfn, si, di,
- 0,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall1(VMW_PORT_CMD_MKSGS_ADD_PPN, (unsigned long)pfn);
}
/**
@@ -686,13 +641,7 @@ static inline void hypervisor_ppn_add(PPN64 pfn)
*/
static inline void hypervisor_ppn_remove(PPN64 pfn)
{
- unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
-
- VMW_PORT(VMW_PORT_CMD_MKSGS_REMOVE_PPN,
- (unsigned long)pfn, si, di,
- 0,
- VMW_HYPERVISOR_MAGIC,
- eax, ebx, ecx, edx, si, di);
+ vmware_hypercall1(VMW_PORT_CMD_MKSGS_REMOVE_PPN, (unsigned long)pfn);
}
#if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h
index 4f40167ad61f..3c78e9338b54 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h
@@ -34,6 +34,8 @@
#define VMWARE_HYPERVISOR_HB BIT(0)
#define VMWARE_HYPERVISOR_OUT BIT(1)
+#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
+
#define X86_IO_MAGIC 0x86
#define X86_IO_W7_SIZE_SHIFT 0
@@ -45,86 +47,158 @@
#define X86_IO_W7_IMM_SHIFT 5
#define X86_IO_W7_IMM_MASK (0xff << X86_IO_W7_IMM_SHIFT)
-static inline void vmw_port(unsigned long cmd, unsigned long in_ebx,
- unsigned long in_si, unsigned long in_di,
- unsigned long flags, unsigned long magic,
- unsigned long *eax, unsigned long *ebx,
- unsigned long *ecx, unsigned long *edx,
- unsigned long *si, unsigned long *di)
+static inline
+unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
{
- register u64 x0 asm("x0") = magic;
- register u64 x1 asm("x1") = in_ebx;
+ register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
+ register u64 x1 asm("x1") = in1;
register u64 x2 asm("x2") = cmd;
- register u64 x3 asm("x3") = flags | VMWARE_HYPERVISOR_PORT;
- register u64 x4 asm("x4") = in_si;
- register u64 x5 asm("x5") = in_di;
+ register u64 x3 asm("x3") = VMWARE_HYPERVISOR_PORT;
+ register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
+ X86_IO_W7_WITH |
+ X86_IO_W7_DIR |
+ (2 << X86_IO_W7_SIZE_SHIFT);
+ asm_inline volatile (
+ "mrs xzr, mdccsr_el0; "
+ : "+r" (x0)
+ : "r" (x1), "r" (x2), "r" (x3), "r" (x7)
+ : "memory");
+
+ return x0;
+}
+
+static inline
+unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, u32 *out2)
+{
+ register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
+ register u64 x1 asm("x1") = in1;
+ register u64 x2 asm("x2") = cmd;
+ register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT;
+ register u64 x4 asm("x4") = in4;
+ register u64 x5 asm("x5") = in5;
register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
X86_IO_W7_WITH |
X86_IO_W7_DIR |
(2 << X86_IO_W7_SIZE_SHIFT);
- asm volatile("mrs xzr, mdccsr_el0 \n\t"
- : "+r"(x0), "+r"(x1), "+r"(x2),
- "+r"(x3), "+r"(x4), "+r"(x5)
- : "r"(x7)
- :);
- *eax = x0;
- *ebx = x1;
- *ecx = x2;
- *edx = x3;
- *si = x4;
- *di = x5;
+ asm_inline volatile (
+ "mrs xzr, mdccsr_el0; "
+ : "+r" (x0), "+r" (x2)
+ : "r" (x1), "r" (x3), "r" (x4), "r" (x5), "r" (x7)
+ : "memory");
+
+ *out2 = x2;
+ return x0;
}
-static inline void vmw_port_hb(unsigned long cmd, unsigned long in_ecx,
- unsigned long in_si, unsigned long in_di,
- unsigned long flags, unsigned long magic,
- unsigned long bp, u32 w7dir,
- unsigned long *eax, unsigned long *ebx,
- unsigned long *ecx, unsigned long *edx,
- unsigned long *si, unsigned long *di)
+static inline
+unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1,
+ unsigned long in3, u32 *out2,
+ u32 *out3, u32 *out4, u32 *out5)
{
- register u64 x0 asm("x0") = magic;
+ register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
+ register u64 x1 asm("x1") = in1;
+ register u64 x2 asm("x2") = cmd;
+ register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT;
+ register u64 x4 asm("x4");
+ register u64 x5 asm("x5");
+ register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
+ X86_IO_W7_WITH |
+ X86_IO_W7_DIR |
+ (2 << X86_IO_W7_SIZE_SHIFT);
+
+ asm_inline volatile (
+ "mrs xzr, mdccsr_el0; "
+ : "+r" (x0), "+r" (x2), "+r" (x3), "=r" (x4), "=r" (x5)
+ : "r" (x1), "r" (x7)
+ : "memory");
+
+ *out2 = x2;
+ *out3 = x3;
+ *out4 = x4;
+ *out5 = x5;
+ return x0;
+}
+
+static inline
+unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, u32 *out1,
+ u32 *out2, u32 *out3)
+{
+ register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
+ register u64 x1 asm("x1") = in1;
+ register u64 x2 asm("x2") = cmd;
+ register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT;
+ register u64 x4 asm("x4") = in4;
+ register u64 x5 asm("x5") = in5;
+ register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
+ X86_IO_W7_WITH |
+ X86_IO_W7_DIR |
+ (2 << X86_IO_W7_SIZE_SHIFT);
+
+ asm_inline volatile (
+ "mrs xzr, mdccsr_el0; "
+ : "+r" (x0), "+r" (x1), "+r" (x2), "+r" (x3)
+ : "r" (x4), "r" (x5), "r" (x7)
+ : "memory");
+
+ *out1 = x1;
+ *out2 = x2;
+ *out3 = x3;
+ return x0;
+}
+
+static inline
+unsigned long vmware_hypercall_hb(unsigned long cmd, unsigned long in2,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, unsigned long in6,
+ u32 *out1, int dir)
+{
+ register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
register u64 x1 asm("x1") = cmd;
- register u64 x2 asm("x2") = in_ecx;
- register u64 x3 asm("x3") = flags | VMWARE_HYPERVISOR_PORT_HB;
- register u64 x4 asm("x4") = in_si;
- register u64 x5 asm("x5") = in_di;
- register u64 x6 asm("x6") = bp;
+ register u64 x2 asm("x2") = in2;
+ register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT_HB;
+ register u64 x4 asm("x4") = in4;
+ register u64 x5 asm("x5") = in5;
+ register u64 x6 asm("x6") = in6;
register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
X86_IO_W7_STR |
X86_IO_W7_WITH |
- w7dir;
-
- asm volatile("mrs xzr, mdccsr_el0 \n\t"
- : "+r"(x0), "+r"(x1), "+r"(x2),
- "+r"(x3), "+r"(x4), "+r"(x5)
- : "r"(x6), "r"(x7)
- :);
- *eax = x0;
- *ebx = x1;
- *ecx = x2;
- *edx = x3;
- *si = x4;
- *di = x5;
-}
+ dir;
-#define VMW_PORT(cmd, in_ebx, in_si, in_di, flags, magic, eax, ebx, ecx, edx, \
- si, di) \
- vmw_port(cmd, in_ebx, in_si, in_di, flags, magic, &eax, &ebx, &ecx, \
- &edx, &si, &di)
+ asm_inline volatile (
+ "mrs xzr, mdccsr_el0; "
+ : "+r" (x0), "+r" (x1)
+ : "r" (x2), "r" (x3), "r" (x4), "r" (x5),
+ "r" (x6), "r" (x7)
+ : "memory");
-#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, flags, magic, bp, eax, ebx, \
- ecx, edx, si, di) \
- vmw_port_hb(cmd, in_ecx, in_si, in_di, flags, magic, bp, \
- 0, &eax, &ebx, &ecx, &edx, &si, &di)
+ *out1 = x1;
+ return x0;
+}
-#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, flags, magic, bp, eax, ebx, \
- ecx, edx, si, di) \
- vmw_port_hb(cmd, in_ecx, in_si, in_di, flags, magic, bp, \
- X86_IO_W7_DIR, &eax, &ebx, &ecx, &edx, &si, &di)
+static inline
+unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, unsigned long in6,
+ u32 *out1)
+{
+ return vmware_hypercall_hb(cmd, in2, in3, in4, in5, in6, out1, 0);
+}
+static inline
+unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2,
+ unsigned long in3, unsigned long in4,
+ unsigned long in5, unsigned long in6,
+ u32 *out1)
+{
+ return vmware_hypercall_hb(cmd, in2, in3, in4, in5, in6, out1,
+ X86_IO_W7_DIR);
+}
#endif
#endif /* _VMWGFX_MSG_ARM64_H */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h
index 23899d743a90..13304d34cc6e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h
@@ -37,191 +37,6 @@
#include <asm/vmware.h>
-/**
- * Hypervisor-specific bi-directional communication channel. Should never
- * execute on bare metal hardware. The caller must make sure to check for
- * supported hypervisor before using these macros.
- *
- * The last two parameters are both input and output and must be initialized.
- *
- * @cmd: [IN] Message Cmd
- * @in_ebx: [IN] Message Len, through EBX
- * @in_si: [IN] Input argument through SI, set to 0 if not used
- * @in_di: [IN] Input argument through DI, set ot 0 if not used
- * @flags: [IN] hypercall flags + [channel id]
- * @magic: [IN] hypervisor magic value
- * @eax: [OUT] value of EAX register
- * @ebx: [OUT] e.g. status from an HB message status command
- * @ecx: [OUT] e.g. status from a non-HB message status command
- * @edx: [OUT] e.g. channel id
- * @si: [OUT]
- * @di: [OUT]
- */
-#define VMW_PORT(cmd, in_ebx, in_si, in_di, \
- flags, magic, \
- eax, ebx, ecx, edx, si, di) \
-({ \
- asm volatile (VMWARE_HYPERCALL : \
- "=a"(eax), \
- "=b"(ebx), \
- "=c"(ecx), \
- "=d"(edx), \
- "=S"(si), \
- "=D"(di) : \
- "a"(magic), \
- "b"(in_ebx), \
- "c"(cmd), \
- "d"(flags), \
- "S"(in_si), \
- "D"(in_di) : \
- "memory"); \
-})
-
-
-/**
- * Hypervisor-specific bi-directional communication channel. Should never
- * execute on bare metal hardware. The caller must make sure to check for
- * supported hypervisor before using these macros.
- *
- * The last 3 parameters are both input and output and must be initialized.
- *
- * @cmd: [IN] Message Cmd
- * @in_ecx: [IN] Message Len, through ECX
- * @in_si: [IN] Input argument through SI, set to 0 if not used
- * @in_di: [IN] Input argument through DI, set to 0 if not used
- * @flags: [IN] hypercall flags + [channel id]
- * @magic: [IN] hypervisor magic value
- * @bp: [IN]
- * @eax: [OUT] value of EAX register
- * @ebx: [OUT] e.g. status from an HB message status command
- * @ecx: [OUT] e.g. status from a non-HB message status command
- * @edx: [OUT] e.g. channel id
- * @si: [OUT]
- * @di: [OUT]
- */
-#ifdef __x86_64__
-
-#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \
- flags, magic, bp, \
- eax, ebx, ecx, edx, si, di) \
-({ \
- asm volatile ( \
- UNWIND_HINT_SAVE \
- "push %%rbp;" \
- UNWIND_HINT_UNDEFINED \
- "mov %12, %%rbp;" \
- VMWARE_HYPERCALL_HB_OUT \
- "pop %%rbp;" \
- UNWIND_HINT_RESTORE : \
- "=a"(eax), \
- "=b"(ebx), \
- "=c"(ecx), \
- "=d"(edx), \
- "=S"(si), \
- "=D"(di) : \
- "a"(magic), \
- "b"(cmd), \
- "c"(in_ecx), \
- "d"(flags), \
- "S"(in_si), \
- "D"(in_di), \
- "r"(bp) : \
- "memory", "cc"); \
-})
-
-
-#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \
- flags, magic, bp, \
- eax, ebx, ecx, edx, si, di) \
-({ \
- asm volatile ( \
- UNWIND_HINT_SAVE \
- "push %%rbp;" \
- UNWIND_HINT_UNDEFINED \
- "mov %12, %%rbp;" \
- VMWARE_HYPERCALL_HB_IN \
- "pop %%rbp;" \
- UNWIND_HINT_RESTORE : \
- "=a"(eax), \
- "=b"(ebx), \
- "=c"(ecx), \
- "=d"(edx), \
- "=S"(si), \
- "=D"(di) : \
- "a"(magic), \
- "b"(cmd), \
- "c"(in_ecx), \
- "d"(flags), \
- "S"(in_si), \
- "D"(in_di), \
- "r"(bp) : \
- "memory", "cc"); \
-})
-
-#elif defined(__i386__)
-
-/*
- * In the 32-bit version of this macro, we store bp in a memory location
- * because we've ran out of registers.
- * Now we can't reference that memory location while we've modified
- * %esp or %ebp, so we first push it on the stack, just before we push
- * %ebp, and then when we need it we read it from the stack where we
- * just pushed it.
- */
-#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \
- flags, magic, bp, \
- eax, ebx, ecx, edx, si, di) \
-({ \
- asm volatile ("push %12;" \
- "push %%ebp;" \
- "mov 0x04(%%esp), %%ebp;" \
- VMWARE_HYPERCALL_HB_OUT \
- "pop %%ebp;" \
- "add $0x04, %%esp;" : \
- "=a"(eax), \
- "=b"(ebx), \
- "=c"(ecx), \
- "=d"(edx), \
- "=S"(si), \
- "=D"(di) : \
- "a"(magic), \
- "b"(cmd), \
- "c"(in_ecx), \
- "d"(flags), \
- "S"(in_si), \
- "D"(in_di), \
- "m"(bp) : \
- "memory", "cc"); \
-})
-
-
-#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \
- flags, magic, bp, \
- eax, ebx, ecx, edx, si, di) \
-({ \
- asm volatile ("push %12;" \
- "push %%ebp;" \
- "mov 0x04(%%esp), %%ebp;" \
- VMWARE_HYPERCALL_HB_IN \
- "pop %%ebp;" \
- "add $0x04, %%esp;" : \
- "=a"(eax), \
- "=b"(ebx), \
- "=c"(ecx), \
- "=d"(edx), \
- "=S"(si), \
- "=D"(di) : \
- "a"(magic), \
- "b"(cmd), \
- "c"(in_ecx), \
- "d"(flags), \
- "S"(in_si), \
- "D"(in_di), \
- "m"(bp) : \
- "memory", "cc"); \
-})
-#endif /* defined(__i386__) */
-
#endif /* defined(__i386__) || defined(__x86_64__) */
#endif /* _VMWGFX_MSG_X86_H */
diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
index d46f87a039f2..b3d3c065dd9d 100644
--- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
+++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
@@ -159,12 +159,16 @@ void intel_hdcp_gsc_fini(struct xe_device *xe)
{
struct intel_hdcp_gsc_message *hdcp_message =
xe->display.hdcp.hdcp_message;
+ struct i915_hdcp_arbiter *arb = xe->display.hdcp.arbiter;
- if (!hdcp_message)
- return;
+ if (hdcp_message) {
+ xe_bo_unpin_map_no_vm(hdcp_message->hdcp_bo);
+ kfree(hdcp_message);
+ xe->display.hdcp.hdcp_message = NULL;
+ }
- xe_bo_unpin_map_no_vm(hdcp_message->hdcp_bo);
- kfree(hdcp_message);
+ kfree(arb);
+ xe->display.hdcp.arbiter = NULL;
}
static int xe_gsc_send_sync(struct xe_device *xe,
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index bc1f794e3e61..b6f3a43d637f 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -317,7 +317,7 @@ static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo,
struct xe_device *xe = xe_bo_device(bo);
struct xe_ttm_tt *tt;
unsigned long extra_pages;
- enum ttm_caching caching;
+ enum ttm_caching caching = ttm_cached;
int err;
tt = kzalloc(sizeof(*tt), GFP_KERNEL);
@@ -331,26 +331,35 @@ static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo,
extra_pages = DIV_ROUND_UP(xe_device_ccs_bytes(xe, bo->size),
PAGE_SIZE);
- switch (bo->cpu_caching) {
- case DRM_XE_GEM_CPU_CACHING_WC:
- caching = ttm_write_combined;
- break;
- default:
- caching = ttm_cached;
- break;
- }
-
- WARN_ON((bo->flags & XE_BO_FLAG_USER) && !bo->cpu_caching);
-
/*
- * Display scanout is always non-coherent with the CPU cache.
- *
- * For Xe_LPG and beyond, PPGTT PTE lookups are also non-coherent and
- * require a CPU:WC mapping.
+ * DGFX system memory is always WB / ttm_cached, since
+ * other caching modes are only supported on x86. DGFX
+ * GPU system memory accesses are always coherent with the
+ * CPU.
*/
- if ((!bo->cpu_caching && bo->flags & XE_BO_FLAG_SCANOUT) ||
- (xe->info.graphics_verx100 >= 1270 && bo->flags & XE_BO_FLAG_PAGETABLE))
- caching = ttm_write_combined;
+ if (!IS_DGFX(xe)) {
+ switch (bo->cpu_caching) {
+ case DRM_XE_GEM_CPU_CACHING_WC:
+ caching = ttm_write_combined;
+ break;
+ default:
+ caching = ttm_cached;
+ break;
+ }
+
+ WARN_ON((bo->flags & XE_BO_FLAG_USER) && !bo->cpu_caching);
+
+ /*
+ * Display scanout is always non-coherent with the CPU cache.
+ *
+ * For Xe_LPG and beyond, PPGTT PTE lookups are also
+ * non-coherent and require a CPU:WC mapping.
+ */
+ if ((!bo->cpu_caching && bo->flags & XE_BO_FLAG_SCANOUT) ||
+ (xe->info.graphics_verx100 >= 1270 &&
+ bo->flags & XE_BO_FLAG_PAGETABLE))
+ caching = ttm_write_combined;
+ }
err = ttm_tt_init(&tt->ttm, &bo->ttm, page_flags, caching, extra_pages);
if (err) {
diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h
index 86422e113d39..10450f1fbbde 100644
--- a/drivers/gpu/drm/xe/xe_bo_types.h
+++ b/drivers/gpu/drm/xe/xe_bo_types.h
@@ -66,7 +66,8 @@ struct xe_bo {
/**
* @cpu_caching: CPU caching mode. Currently only used for userspace
- * objects.
+ * objects. Exceptions are system memory on DGFX, which is always
+ * WB.
*/
u16 cpu_caching;
diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c
index 577bd7043740..0443e07880a0 100644
--- a/drivers/gpu/drm/xe/xe_gt_mcr.c
+++ b/drivers/gpu/drm/xe/xe_gt_mcr.c
@@ -342,7 +342,7 @@ static void init_steering_oaddrm(struct xe_gt *gt)
else
gt->steering[OADDRM].group_target = 1;
- gt->steering[DSS].instance_target = 0; /* unused */
+ gt->steering[OADDRM].instance_target = 0; /* unused */
}
static void init_steering_sqidi_psmi(struct xe_gt *gt)
@@ -357,8 +357,8 @@ static void init_steering_sqidi_psmi(struct xe_gt *gt)
static void init_steering_inst0(struct xe_gt *gt)
{
- gt->steering[DSS].group_target = 0; /* unused */
- gt->steering[DSS].instance_target = 0; /* unused */
+ gt->steering[INSTANCE0].group_target = 0; /* unused */
+ gt->steering[INSTANCE0].instance_target = 0; /* unused */
}
static const struct {
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 65e5a3f4c340..198f5c2189cb 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -1334,7 +1334,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
GFP_KERNEL, true, 0);
if (IS_ERR(sa_bo)) {
err = PTR_ERR(sa_bo);
- goto err;
+ goto err_bb;
}
ppgtt_ofs = NUM_KERNEL_PDE +
@@ -1385,7 +1385,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
update_idx);
if (IS_ERR(job)) {
err = PTR_ERR(job);
- goto err_bb;
+ goto err_sa;
}
/* Wait on BO move */
@@ -1434,12 +1434,12 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
err_job:
xe_sched_job_put(job);
+err_sa:
+ drm_suballoc_free(sa_bo, NULL);
err_bb:
if (!q)
mutex_unlock(&m->job_mutex);
xe_bb_free(bb, NULL);
-err:
- drm_suballoc_free(sa_bo, NULL);
return ERR_PTR(err);
}
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index e14ae18a973b..b60fe2e58ad6 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -105,18 +105,6 @@ config SENSORS_AD7418
This driver can also be built as a module. If so, the module
will be called ad7418.
-config SENSORS_ADM1021
- tristate "Analog Devices ADM1021 and compatibles"
- depends on I2C
- depends on SENSORS_LM90=n
- help
- If you say yes here you get support for Analog Devices ADM1021
- and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
- Genesys Logic GL523SM, National Semiconductor LM84 and TI THMC10.
-
- This driver can also be built as a module. If so, the module
- will be called adm1021.
-
config SENSORS_ADM1025
tristate "Analog Devices ADM1025 and compatibles"
depends on I2C
@@ -506,6 +494,17 @@ config SENSORS_CORSAIR_PSU
This driver can also be built as a module. If so, the module
will be called corsair-psu.
+config SENSORS_CROS_EC
+ tristate "ChromeOS Embedded Controller sensors"
+ depends on MFD_CROS_EC_DEV
+ default MFD_CROS_EC_DEV
+ help
+ If you say yes here you get support for ChromeOS Embedded Controller
+ sensors.
+
+ This driver can also be built as a module. If so, the module
+ will be called cros_ec_hwmon.
+
config SENSORS_DRIVETEMP
tristate "Hard disk drives with temperature sensors"
depends on SCSI && ATA
@@ -1241,18 +1240,6 @@ config SENSORS_MAX6639
This driver can also be built as a module. If so, the module
will be called max6639.
-config SENSORS_MAX6642
- tristate "Maxim MAX6642 sensor chip"
- depends on I2C
- depends on SENSORS_LM90=n
- help
- If you say yes here you get support for MAX6642 sensor chip.
- MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor
- with Overtemperature Alarm from Maxim.
-
- This driver can also be built as a module. If so, the module
- will be called max6642.
-
config SENSORS_MAX6650
tristate "Maxim MAX6650 sensor chip"
depends on I2C
@@ -2127,6 +2114,7 @@ config SENSORS_ADS7871
config SENSORS_AMC6821
tristate "Texas Instruments AMC6821"
depends on I2C
+ select REGMAP_I2C
help
If you say yes here you get support for the Texas Instruments
AMC6821 hardware monitoring chips.
@@ -2181,6 +2169,37 @@ config SENSORS_INA3221
This driver can also be built as a module. If so, the module
will be called ina3221.
+config SENSORS_SPD5118
+ tristate "SPD5118 Compliant Temperature Sensors"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you say yes here you get support for SPD5118 (JEDEC JESD300)
+ compliant temperature sensors. Such sensors are found on DDR5 memory
+ modules.
+
+ This driver can also be built as a module. If so, the module
+ will be called spd5118.
+
+config SENSORS_SPD5118_DETECT
+ bool "Enable detect function"
+ depends on SENSORS_SPD5118
+ default (!DMI || !X86)
+ help
+ If enabled, the driver auto-detects if a chip in the SPD address
+ range is compliant to the SPD51888 standard and auto-instantiates
+ if that is the case. If disabled, SPD5118 compliant devices have
+ to be instantiated by other means. On X86 systems with DMI support
+ this will typically be done from DMI DDR detection code in the
+ I2C SMBus subsystem. Devicetree based systems will instantiate
+ attached devices if the DIMMs are listed in the devicetree file.
+
+ Disabling the detect function will speed up boot time and reduce
+ the risk of mis-detecting SPD5118 compliant devices. However, it
+ may result in missed DIMMs under some circumstances.
+
+ If unsure, say Y.
+
config SENSORS_TC74
tristate "Microchip TC74"
depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index e3f25475d1f0..b1c7056c37db 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -31,7 +31,6 @@ obj-$(CONFIG_SENSORS_AD7414) += ad7414.o
obj-$(CONFIG_SENSORS_AD7418) += ad7418.o
obj-$(CONFIG_SENSORS_ADC128D818) += adc128d818.o
obj-$(CONFIG_SENSORS_ADCXX) += adcxx.o
-obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o
obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o
@@ -64,6 +63,7 @@ obj-$(CONFIG_SENSORS_CHIPCAP2) += chipcap2.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
obj-$(CONFIG_SENSORS_CORSAIR_CPRO) += corsair-cpro.o
obj-$(CONFIG_SENSORS_CORSAIR_PSU) += corsair-psu.o
+obj-$(CONFIG_SENSORS_CROS_EC) += cros_ec_hwmon.o
obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o
obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o
@@ -154,7 +154,6 @@ obj-$(CONFIG_SENSORS_MAX31760) += max31760.o
obj-$(CONFIG_SENSORS_MAX6620) += max6620.o
obj-$(CONFIG_SENSORS_MAX6621) += max6621.o
obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
-obj-$(CONFIG_SENSORS_MAX6642) += max6642.o
obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_MAX6697) += max6697.o
obj-$(CONFIG_SENSORS_MAX31790) += max31790.o
@@ -207,6 +206,7 @@ obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o
+obj-$(CONFIG_SENSORS_SPD5118) += spd5118.o
obj-$(CONFIG_SENSORS_STTS751) += stts751.o
obj-$(CONFIG_SENSORS_SURFACE_FAN)+= surface_fan.o
obj-$(CONFIG_SENSORS_SY7636A) += sy7636a-hwmon.o
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c
index 4829f83ff52e..7a132accdf8a 100644
--- a/drivers/hwmon/ad7418.c
+++ b/drivers/hwmon/ad7418.c
@@ -230,8 +230,6 @@ static void ad7418_init_client(struct i2c_client *client)
}
}
-static const struct i2c_device_id ad7418_id[];
-
static int ad7418_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -252,10 +250,7 @@ static int ad7418_probe(struct i2c_client *client)
mutex_init(&data->lock);
data->client = client;
- if (dev->of_node)
- data->type = (uintptr_t)of_device_get_match_data(dev);
- else
- data->type = i2c_match_id(ad7418_id, client)->driver_data;
+ data->type = (uintptr_t)i2c_get_match_data(client);
switch (data->type) {
case ad7416:
diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c
index 8ac6e735ec5c..5e805d4ee76a 100644
--- a/drivers/hwmon/adc128d818.c
+++ b/drivers/hwmon/adc128d818.c
@@ -175,7 +175,7 @@ static ssize_t adc128_in_store(struct device *dev,
mutex_lock(&data->update_lock);
/* 10 mV LSB on limit registers */
- regval = clamp_val(DIV_ROUND_CLOSEST(val, 10), 0, 255);
+ regval = DIV_ROUND_CLOSEST(clamp_val(val, 0, 2550), 10);
data->in[index][nr] = regval << 4;
reg = index == 1 ? ADC128_REG_IN_MIN(nr) : ADC128_REG_IN_MAX(nr);
i2c_smbus_write_byte_data(data->client, reg, regval);
@@ -213,7 +213,7 @@ static ssize_t adc128_temp_store(struct device *dev,
return err;
mutex_lock(&data->update_lock);
- regval = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+ regval = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000);
data->temp[index] = regval << 1;
i2c_smbus_write_byte_data(data->client,
index == 1 ? ADC128_REG_TEMP_MAX
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
deleted file mode 100644
index 7c15398ebb37..000000000000
--- a/drivers/hwmon/adm1021.c
+++ /dev/null
@@ -1,505 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * adm1021.c - Part of lm_sensors, Linux kernel modules for hardware
- * monitoring
- * Copyright (c) 1998, 1999 Frodo Looijaard <[email protected]> and
- * Philip Edelbrock <[email protected]>
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-
-
-/* Addresses to scan */
-static const unsigned short normal_i2c[] = {
- 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
-
-enum chips {
- adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066 };
-
-/* adm1021 constants specified below */
-
-/* The adm1021 registers */
-/* Read-only */
-/* For nr in 0-1 */
-#define ADM1021_REG_TEMP(nr) (nr)
-#define ADM1021_REG_STATUS 0x02
-/* 0x41 = AD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi */
-#define ADM1021_REG_MAN_ID 0xFE
-/* ADM1021 = 0x0X, ADM1023 = 0x3X */
-#define ADM1021_REG_DEV_ID 0xFF
-/* These use different addresses for reading/writing */
-#define ADM1021_REG_CONFIG_R 0x03
-#define ADM1021_REG_CONFIG_W 0x09
-#define ADM1021_REG_CONV_RATE_R 0x04
-#define ADM1021_REG_CONV_RATE_W 0x0A
-/* These are for the ADM1023's additional precision on the remote temp sensor */
-#define ADM1023_REG_REM_TEMP_PREC 0x10
-#define ADM1023_REG_REM_OFFSET 0x11
-#define ADM1023_REG_REM_OFFSET_PREC 0x12
-#define ADM1023_REG_REM_TOS_PREC 0x13
-#define ADM1023_REG_REM_THYST_PREC 0x14
-/* limits */
-/* For nr in 0-1 */
-#define ADM1021_REG_TOS_R(nr) (0x05 + 2 * (nr))
-#define ADM1021_REG_TOS_W(nr) (0x0B + 2 * (nr))
-#define ADM1021_REG_THYST_R(nr) (0x06 + 2 * (nr))
-#define ADM1021_REG_THYST_W(nr) (0x0C + 2 * (nr))
-/* write-only */
-#define ADM1021_REG_ONESHOT 0x0F
-
-/* Initial values */
-
-/*
- * Note: Even though I left the low and high limits named os and hyst,
- * they don't quite work like a thermostat the way the LM75 does. I.e.,
- * a lower temp than THYST actually triggers an alarm instead of
- * clearing it. Weird, ey? --Phil
- */
-
-/* Each client has this additional data */
-struct adm1021_data {
- struct i2c_client *client;
- enum chips type;
-
- const struct attribute_group *groups[3];
-
- struct mutex update_lock;
- bool valid; /* true if following fields are valid */
- char low_power; /* !=0 if device in low power mode */
- unsigned long last_updated; /* In jiffies */
-
- int temp_max[2]; /* Register values */
- int temp_min[2];
- int temp[2];
- u8 alarms;
- /* Special values for ADM1023 only */
- u8 remote_temp_offset;
- u8 remote_temp_offset_prec;
-};
-
-/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
-static bool read_only;
-
-static struct adm1021_data *adm1021_update_device(struct device *dev)
-{
- struct adm1021_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
- || !data->valid) {
- int i;
-
- dev_dbg(dev, "Starting adm1021 update\n");
-
- for (i = 0; i < 2; i++) {
- data->temp[i] = 1000 *
- (s8) i2c_smbus_read_byte_data(
- client, ADM1021_REG_TEMP(i));
- data->temp_max[i] = 1000 *
- (s8) i2c_smbus_read_byte_data(
- client, ADM1021_REG_TOS_R(i));
- if (data->type != lm84) {
- data->temp_min[i] = 1000 *
- (s8) i2c_smbus_read_byte_data(client,
- ADM1021_REG_THYST_R(i));
- }
- }
- data->alarms = i2c_smbus_read_byte_data(client,
- ADM1021_REG_STATUS) & 0x7c;
- if (data->type == adm1023) {
- /*
- * The ADM1023 provides 3 extra bits of precision for
- * the remote sensor in extra registers.
- */
- data->temp[1] += 125 * (i2c_smbus_read_byte_data(
- client, ADM1023_REG_REM_TEMP_PREC) >> 5);
- data->temp_max[1] += 125 * (i2c_smbus_read_byte_data(
- client, ADM1023_REG_REM_TOS_PREC) >> 5);
- data->temp_min[1] += 125 * (i2c_smbus_read_byte_data(
- client, ADM1023_REG_REM_THYST_PREC) >> 5);
- data->remote_temp_offset =
- i2c_smbus_read_byte_data(client,
- ADM1023_REG_REM_OFFSET);
- data->remote_temp_offset_prec =
- i2c_smbus_read_byte_data(client,
- ADM1023_REG_REM_OFFSET_PREC);
- }
- data->last_updated = jiffies;
- data->valid = true;
- }
-
- mutex_unlock(&data->update_lock);
-
- return data;
-}
-
-static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- int index = to_sensor_dev_attr(devattr)->index;
- struct adm1021_data *data = adm1021_update_device(dev);
-
- return sprintf(buf, "%d\n", data->temp[index]);
-}
-
-static ssize_t temp_max_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- int index = to_sensor_dev_attr(devattr)->index;
- struct adm1021_data *data = adm1021_update_device(dev);
-
- return sprintf(buf, "%d\n", data->temp_max[index]);
-}
-
-static ssize_t temp_min_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- int index = to_sensor_dev_attr(devattr)->index;
- struct adm1021_data *data = adm1021_update_device(dev);
-
- return sprintf(buf, "%d\n", data->temp_min[index]);
-}
-
-static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- int index = to_sensor_dev_attr(attr)->index;
- struct adm1021_data *data = adm1021_update_device(dev);
- return sprintf(buf, "%u\n", (data->alarms >> index) & 1);
-}
-
-static ssize_t alarms_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct adm1021_data *data = adm1021_update_device(dev);
- return sprintf(buf, "%u\n", data->alarms);
-}
-
-static ssize_t temp_max_store(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- int index = to_sensor_dev_attr(devattr)->index;
- struct adm1021_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- long temp;
- int reg_val, err;
-
- err = kstrtol(buf, 10, &temp);
- if (err)
- return err;
- temp /= 1000;
-
- mutex_lock(&data->update_lock);
- reg_val = clamp_val(temp, -128, 127);
- data->temp_max[index] = reg_val * 1000;
- if (!read_only)
- i2c_smbus_write_byte_data(client, ADM1021_REG_TOS_W(index),
- reg_val);
- mutex_unlock(&data->update_lock);
-
- return count;
-}
-
-static ssize_t temp_min_store(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- int index = to_sensor_dev_attr(devattr)->index;
- struct adm1021_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- long temp;
- int reg_val, err;
-
- err = kstrtol(buf, 10, &temp);
- if (err)
- return err;
- temp /= 1000;
-
- mutex_lock(&data->update_lock);
- reg_val = clamp_val(temp, -128, 127);
- data->temp_min[index] = reg_val * 1000;
- if (!read_only)
- i2c_smbus_write_byte_data(client, ADM1021_REG_THYST_W(index),
- reg_val);
- mutex_unlock(&data->update_lock);
-
- return count;
-}
-
-static ssize_t low_power_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct adm1021_data *data = adm1021_update_device(dev);
- return sprintf(buf, "%d\n", data->low_power);
-}
-
-static ssize_t low_power_store(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- struct adm1021_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- char low_power;
- unsigned long val;
- int err;
-
- err = kstrtoul(buf, 10, &val);
- if (err)
- return err;
- low_power = val != 0;
-
- mutex_lock(&data->update_lock);
- if (low_power != data->low_power) {
- int config = i2c_smbus_read_byte_data(
- client, ADM1021_REG_CONFIG_R);
- data->low_power = low_power;
- i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W,
- (config & 0xBF) | (low_power << 6));
- }
- mutex_unlock(&data->update_lock);
-
- return count;
-}
-
-
-static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
-static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
-static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0);
-static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
-static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
-static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1);
-static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
-static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 5);
-static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 4);
-static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, alarm, 3);
-static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 2);
-
-static DEVICE_ATTR_RO(alarms);
-static DEVICE_ATTR_RW(low_power);
-
-static struct attribute *adm1021_attributes[] = {
- &sensor_dev_attr_temp1_max.dev_attr.attr,
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_temp2_max.dev_attr.attr,
- &sensor_dev_attr_temp2_input.dev_attr.attr,
- &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_fault.dev_attr.attr,
- &dev_attr_alarms.attr,
- &dev_attr_low_power.attr,
- NULL
-};
-
-static const struct attribute_group adm1021_group = {
- .attrs = adm1021_attributes,
-};
-
-static struct attribute *adm1021_min_attributes[] = {
- &sensor_dev_attr_temp1_min.dev_attr.attr,
- &sensor_dev_attr_temp2_min.dev_attr.attr,
- &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group adm1021_min_group = {
- .attrs = adm1021_min_attributes,
-};
-
-/* Return 0 if detection is successful, -ENODEV otherwise */
-static int adm1021_detect(struct i2c_client *client,
- struct i2c_board_info *info)
-{
- struct i2c_adapter *adapter = client->adapter;
- const char *type_name;
- int reg, conv_rate, status, config, man_id, dev_id;
-
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
- pr_debug("detect failed, smbus byte data not supported!\n");
- return -ENODEV;
- }
-
- status = i2c_smbus_read_byte_data(client, ADM1021_REG_STATUS);
- conv_rate = i2c_smbus_read_byte_data(client,
- ADM1021_REG_CONV_RATE_R);
- config = i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R);
-
- /* Check unused bits */
- if ((status & 0x03) || (config & 0x3F) || (conv_rate & 0xF8)) {
- pr_debug("detect failed, chip not detected!\n");
- return -ENODEV;
- }
-
- /* Determine the chip type. */
- man_id = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID);
- dev_id = i2c_smbus_read_byte_data(client, ADM1021_REG_DEV_ID);
-
- if (man_id < 0 || dev_id < 0)
- return -ENODEV;
-
- if (man_id == 0x4d && dev_id == 0x01) {
- /*
- * dev_id 0x01 matches MAX6680, MAX6695, MAX6696, and possibly
- * others. Read register which is unsupported on MAX1617 but
- * exists on all those chips and compare with the dev_id
- * register. If it matches, it may be a MAX1617A.
- */
- reg = i2c_smbus_read_byte_data(client,
- ADM1023_REG_REM_TEMP_PREC);
- if (reg != dev_id)
- return -ENODEV;
- type_name = "max1617a";
- } else if (man_id == 0x41) {
- if ((dev_id & 0xF0) == 0x30)
- type_name = "adm1023";
- else if ((dev_id & 0xF0) == 0x00)
- type_name = "adm1021";
- else
- return -ENODEV;
- } else if (man_id == 0x49)
- type_name = "thmc10";
- else if (man_id == 0x23)
- type_name = "gl523sm";
- else if (man_id == 0x54)
- type_name = "mc1066";
- else {
- int lte, rte, lhi, rhi, llo, rlo;
-
- /* extra checks for LM84 and MAX1617 to avoid misdetections */
-
- llo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(0));
- rlo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(1));
-
- /* fail if any of the additional register reads failed */
- if (llo < 0 || rlo < 0)
- return -ENODEV;
-
- lte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(0));
- rte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(1));
- lhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(0));
- rhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(1));
-
- /*
- * Fail for negative temperatures and negative high limits.
- * This check also catches read errors on the tested registers.
- */
- if ((s8)lte < 0 || (s8)rte < 0 || (s8)lhi < 0 || (s8)rhi < 0)
- return -ENODEV;
-
- /* fail if all registers hold the same value */
- if (lte == rte && lte == lhi && lte == rhi && lte == llo
- && lte == rlo)
- return -ENODEV;
-
- /*
- * LM84 Mfr ID is in a different place,
- * and it has more unused bits. Registers at 0xfe and 0xff
- * are undefined and return the most recently read value,
- * here the value of the configuration register.
- */
- if (conv_rate == 0x00
- && man_id == config && dev_id == config
- && (config & 0x7F) == 0x00
- && (status & 0xAB) == 0x00) {
- type_name = "lm84";
- } else {
- if ((config & 0x3f) || (status & 0x03))
- return -ENODEV;
- /* fail if low limits are larger than high limits */
- if ((s8)llo > lhi || (s8)rlo > rhi)
- return -ENODEV;
- type_name = "max1617";
- }
- }
-
- pr_debug("Detected chip %s at adapter %d, address 0x%02x.\n",
- type_name, i2c_adapter_id(adapter), client->addr);
- strscpy(info->type, type_name, I2C_NAME_SIZE);
-
- return 0;
-}
-
-static void adm1021_init_client(struct i2c_client *client)
-{
- /* Enable ADC and disable suspend mode */
- i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W,
- i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF);
- /* Set Conversion rate to 1/sec (this can be tinkered with) */
- i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
-}
-
-static const struct i2c_device_id adm1021_id[];
-
-static int adm1021_probe(struct i2c_client *client)
-{
- struct device *dev = &client->dev;
- struct adm1021_data *data;
- struct device *hwmon_dev;
-
- data = devm_kzalloc(dev, sizeof(struct adm1021_data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- data->client = client;
- data->type = i2c_match_id(adm1021_id, client)->driver_data;
- mutex_init(&data->update_lock);
-
- /* Initialize the ADM1021 chip */
- if (data->type != lm84 && !read_only)
- adm1021_init_client(client);
-
- data->groups[0] = &adm1021_group;
- if (data->type != lm84)
- data->groups[1] = &adm1021_min_group;
-
- hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
- data, data->groups);
-
- return PTR_ERR_OR_ZERO(hwmon_dev);
-}
-
-static const struct i2c_device_id adm1021_id[] = {
- { "adm1021", adm1021 },
- { "adm1023", adm1023 },
- { "max1617", max1617 },
- { "max1617a", max1617a },
- { "thmc10", thmc10 },
- { "lm84", lm84 },
- { "gl523sm", gl523sm },
- { "mc1066", mc1066 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adm1021_id);
-
-static struct i2c_driver adm1021_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "adm1021",
- },
- .probe = adm1021_probe,
- .id_table = adm1021_id,
- .detect = adm1021_detect,
- .address_list = normal_i2c,
-};
-
-module_i2c_driver(adm1021_driver);
-
-MODULE_AUTHOR("Frodo Looijaard <[email protected]> and "
- "Philip Edelbrock <[email protected]>");
-MODULE_DESCRIPTION("adm1021 driver");
-MODULE_LICENSE("GPL");
-
-module_param(read_only, bool, 0);
-MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 88c7e0d62d08..343118532cdb 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -1021,8 +1021,6 @@ static void adm1031_init_client(struct i2c_client *client)
data->update_interval = update_intervals[i];
}
-static const struct i2c_device_id adm1031_id[];
-
static int adm1031_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -1035,7 +1033,7 @@ static int adm1031_probe(struct i2c_client *client)
i2c_set_clientdata(client, data);
data->client = client;
- data->chip_type = i2c_match_id(adm1031_id, client)->driver_data;
+ data->chip_type = (uintptr_t)i2c_get_match_data(client);
mutex_init(&data->update_lock);
if (data->chip_type == adm1030)
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index 809e830f52a6..436637264056 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -99,8 +99,6 @@ static const struct regmap_config ads2830_regmap_config = {
.val_bits = 8,
};
-static const struct i2c_device_id ads7828_device_ids[];
-
static int ads7828_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -138,10 +136,7 @@ static int ads7828_probe(struct i2c_client *client)
}
}
- if (client->dev.of_node)
- chip = (uintptr_t)of_device_get_match_data(&client->dev);
- else
- chip = i2c_match_id(ads7828_device_ids, client)->driver_data;
+ chip = (uintptr_t)i2c_get_match_data(client);
/* Bound Vref with min/max values */
vref_mv = clamp_val(vref_mv, ADS7828_EXT_VREF_MV_MIN,
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index 4224ffb30483..bc186c61a2c0 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -1676,7 +1676,6 @@ static int adt7475_probe(struct i2c_client *client)
struct device *hwmon_dev;
int i, ret = 0, revision, group_num = 0;
u8 config3;
- const struct i2c_device_id *id = i2c_match_id(adt7475_id, client);
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (data == NULL)
@@ -1686,10 +1685,7 @@ static int adt7475_probe(struct i2c_client *client)
data->client = client;
i2c_set_clientdata(client, data);
- if (client->dev.of_node)
- chip = (uintptr_t)of_device_get_match_data(&client->dev);
- else
- chip = id->driver_data;
+ chip = (uintptr_t)i2c_get_match_data(client);
/* Initialize device-specific values */
switch (chip) {
@@ -1717,7 +1713,7 @@ static int adt7475_probe(struct i2c_client *client)
if (!(config3 & CONFIG3_SMBALERT))
data->has_pwm2 = 1;
/* Meaning of this bit is inverted for the ADT7473-1 */
- if (id->driver_data == adt7473 && revision >= 1)
+ if (chip == adt7473 && revision >= 1)
data->has_pwm2 = !data->has_pwm2;
data->config4 = adt7475_read(REG_CONFIG4);
@@ -1730,12 +1726,12 @@ static int adt7475_probe(struct i2c_client *client)
* because 2 different pins (TACH4 and +2.5 Vin) can be used for
* this function
*/
- if (id->driver_data == adt7490) {
+ if (chip == adt7490) {
if ((data->config4 & CONFIG4_PINFUNC) == 0x1 &&
!(config3 & CONFIG3_THERM))
data->has_fan4 = 1;
}
- if (id->driver_data == adt7476 || id->driver_data == adt7490) {
+ if (chip == adt7476 || chip == adt7490) {
if (!(config3 & CONFIG3_THERM) ||
(data->config4 & CONFIG4_PINFUNC) == 0x1)
data->has_voltage |= (1 << 0); /* in0 */
@@ -1745,7 +1741,7 @@ static int adt7475_probe(struct i2c_client *client)
* On the ADT7476, the +12V input pin may instead be used as VID5,
* and VID pins may alternatively be used as GPIO
*/
- if (id->driver_data == adt7476) {
+ if (chip == adt7476) {
u8 vid = adt7475_read(REG_VID);
if (!(vid & VID_VIDSEL))
data->has_voltage |= (1 << 4); /* in4 */
@@ -1829,7 +1825,7 @@ static int adt7475_probe(struct i2c_client *client)
}
dev_info(&client->dev, "%s device, revision %d\n",
- names[id->driver_data], revision);
+ names[chip], revision);
if ((data->has_voltage & 0x11) || data->has_fan4 || data->has_pwm2)
dev_info(&client->dev, "Optional features:%s%s%s%s%s\n",
(data->has_voltage & (1 << 0)) ? " in0" : "",
@@ -1900,7 +1896,7 @@ static void adt7475_read_pwm(struct i2c_client *client, int index)
data->pwm[CONTROL][index] &= ~0xE0;
data->pwm[CONTROL][index] |= (7 << 5);
- i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
+ i2c_smbus_write_byte_data(client, PWM_REG(index),
data->pwm[INPUT][index]);
i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
diff --git a/drivers/hwmon/aht10.c b/drivers/hwmon/aht10.c
index f136bf3ff40a..312ef3e98754 100644
--- a/drivers/hwmon/aht10.c
+++ b/drivers/hwmon/aht10.c
@@ -331,8 +331,7 @@ static const struct hwmon_chip_info aht10_chip_info = {
static int aht10_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_match_id(aht10_id, client);
- enum aht10_variant variant = id->driver_data;
+ enum aht10_variant variant = (uintptr_t)i2c_get_match_data(client);
struct device *device = &client->dev;
struct device *hwmon_dev;
struct aht10_data *data;
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
index 9b02b304c2f5..ec94392fcb65 100644
--- a/drivers/hwmon/amc6821.c
+++ b/drivers/hwmon/amc6821.c
@@ -6,18 +6,24 @@
*
* Based on max6650.c:
* Copyright (C) 2007 Hans J. Koch <[email protected]>
+ *
+ * Conversion to regmap and with_info API:
+ * Copyright (C) 2024 Guenter Roeck <[email protected]>
*/
-#include <linux/kernel.h> /* Needed for KERN_INFO */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/i2c.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/bits.h>
+#include <linux/err.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
/*
* Addresses to scan.
@@ -36,519 +42,594 @@ module_param(pwminv, int, 0444);
static int init = 1; /*Power-on initialization.*/
module_param(init, int, 0444);
-enum chips { amc6821 };
-
-#define AMC6821_REG_DEV_ID 0x3D
-#define AMC6821_REG_COMP_ID 0x3E
-#define AMC6821_REG_CONF1 0x00
-#define AMC6821_REG_CONF2 0x01
-#define AMC6821_REG_CONF3 0x3F
-#define AMC6821_REG_CONF4 0x04
-#define AMC6821_REG_STAT1 0x02
-#define AMC6821_REG_STAT2 0x03
-#define AMC6821_REG_TDATA_LOW 0x08
-#define AMC6821_REG_TDATA_HI 0x09
-#define AMC6821_REG_LTEMP_HI 0x0A
-#define AMC6821_REG_RTEMP_HI 0x0B
-#define AMC6821_REG_LTEMP_LIMIT_MIN 0x15
-#define AMC6821_REG_LTEMP_LIMIT_MAX 0x14
-#define AMC6821_REG_RTEMP_LIMIT_MIN 0x19
-#define AMC6821_REG_RTEMP_LIMIT_MAX 0x18
-#define AMC6821_REG_LTEMP_CRIT 0x1B
-#define AMC6821_REG_RTEMP_CRIT 0x1D
-#define AMC6821_REG_PSV_TEMP 0x1C
-#define AMC6821_REG_DCY 0x22
-#define AMC6821_REG_LTEMP_FAN_CTRL 0x24
-#define AMC6821_REG_RTEMP_FAN_CTRL 0x25
-#define AMC6821_REG_DCY_LOW_TEMP 0x21
-
-#define AMC6821_REG_TACH_LLIMITL 0x10
-#define AMC6821_REG_TACH_LLIMITH 0x11
-#define AMC6821_REG_TACH_HLIMITL 0x12
-#define AMC6821_REG_TACH_HLIMITH 0x13
-
-#define AMC6821_CONF1_START 0x01
-#define AMC6821_CONF1_FAN_INT_EN 0x02
-#define AMC6821_CONF1_FANIE 0x04
-#define AMC6821_CONF1_PWMINV 0x08
-#define AMC6821_CONF1_FAN_FAULT_EN 0x10
-#define AMC6821_CONF1_FDRC0 0x20
-#define AMC6821_CONF1_FDRC1 0x40
-#define AMC6821_CONF1_THERMOVIE 0x80
-
-#define AMC6821_CONF2_PWM_EN 0x01
-#define AMC6821_CONF2_TACH_MODE 0x02
-#define AMC6821_CONF2_TACH_EN 0x04
-#define AMC6821_CONF2_RTFIE 0x08
-#define AMC6821_CONF2_LTOIE 0x10
-#define AMC6821_CONF2_RTOIE 0x20
-#define AMC6821_CONF2_PSVIE 0x40
-#define AMC6821_CONF2_RST 0x80
-
-#define AMC6821_CONF3_THERM_FAN_EN 0x80
-#define AMC6821_CONF3_REV_MASK 0x0F
-
-#define AMC6821_CONF4_OVREN 0x10
-#define AMC6821_CONF4_TACH_FAST 0x20
-#define AMC6821_CONF4_PSPR 0x40
-#define AMC6821_CONF4_MODE 0x80
-
-#define AMC6821_STAT1_RPM_ALARM 0x01
-#define AMC6821_STAT1_FANS 0x02
-#define AMC6821_STAT1_RTH 0x04
-#define AMC6821_STAT1_RTL 0x08
-#define AMC6821_STAT1_R_THERM 0x10
-#define AMC6821_STAT1_RTF 0x20
-#define AMC6821_STAT1_LTH 0x40
-#define AMC6821_STAT1_LTL 0x80
-
-#define AMC6821_STAT2_RTC 0x08
-#define AMC6821_STAT2_LTC 0x10
-#define AMC6821_STAT2_LPSV 0x20
-#define AMC6821_STAT2_L_THERM 0x40
-#define AMC6821_STAT2_THERM_IN 0x80
-
-enum {IDX_TEMP1_INPUT = 0, IDX_TEMP1_MIN, IDX_TEMP1_MAX,
- IDX_TEMP1_CRIT, IDX_TEMP2_INPUT, IDX_TEMP2_MIN,
- IDX_TEMP2_MAX, IDX_TEMP2_CRIT,
- TEMP_IDX_LEN, };
-
-static const u8 temp_reg[] = {AMC6821_REG_LTEMP_HI,
- AMC6821_REG_LTEMP_LIMIT_MIN,
- AMC6821_REG_LTEMP_LIMIT_MAX,
- AMC6821_REG_LTEMP_CRIT,
- AMC6821_REG_RTEMP_HI,
- AMC6821_REG_RTEMP_LIMIT_MIN,
- AMC6821_REG_RTEMP_LIMIT_MAX,
- AMC6821_REG_RTEMP_CRIT, };
-
-enum {IDX_FAN1_INPUT = 0, IDX_FAN1_MIN, IDX_FAN1_MAX,
- FAN1_IDX_LEN, };
-
-static const u8 fan_reg_low[] = {AMC6821_REG_TDATA_LOW,
- AMC6821_REG_TACH_LLIMITL,
- AMC6821_REG_TACH_HLIMITL, };
-
-
-static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI,
- AMC6821_REG_TACH_LLIMITH,
- AMC6821_REG_TACH_HLIMITH, };
+#define AMC6821_REG_DEV_ID 0x3D
+#define AMC6821_REG_COMP_ID 0x3E
+#define AMC6821_REG_CONF1 0x00
+#define AMC6821_REG_CONF2 0x01
+#define AMC6821_REG_CONF3 0x3F
+#define AMC6821_REG_CONF4 0x04
+#define AMC6821_REG_STAT1 0x02
+#define AMC6821_REG_STAT2 0x03
+#define AMC6821_REG_TEMP_LO 0x06
+#define AMC6821_REG_TDATA_LOW 0x08
+#define AMC6821_REG_TDATA_HI 0x09
+#define AMC6821_REG_LTEMP_HI 0x0A
+#define AMC6821_REG_RTEMP_HI 0x0B
+#define AMC6821_REG_LTEMP_LIMIT_MIN 0x15
+#define AMC6821_REG_LTEMP_LIMIT_MAX 0x14
+#define AMC6821_REG_RTEMP_LIMIT_MIN 0x19
+#define AMC6821_REG_RTEMP_LIMIT_MAX 0x18
+#define AMC6821_REG_LTEMP_CRIT 0x1B
+#define AMC6821_REG_RTEMP_CRIT 0x1D
+#define AMC6821_REG_PSV_TEMP 0x1C
+#define AMC6821_REG_DCY 0x22
+#define AMC6821_REG_LTEMP_FAN_CTRL 0x24
+#define AMC6821_REG_RTEMP_FAN_CTRL 0x25
+#define AMC6821_REG_DCY_LOW_TEMP 0x21
+
+#define AMC6821_REG_TACH_LLIMITL 0x10
+#define AMC6821_REG_TACH_HLIMITL 0x12
+#define AMC6821_REG_TACH_SETTINGL 0x1e
+
+#define AMC6821_CONF1_START BIT(0)
+#define AMC6821_CONF1_FAN_INT_EN BIT(1)
+#define AMC6821_CONF1_FANIE BIT(2)
+#define AMC6821_CONF1_PWMINV BIT(3)
+#define AMC6821_CONF1_FAN_FAULT_EN BIT(4)
+#define AMC6821_CONF1_FDRC0 BIT(5)
+#define AMC6821_CONF1_FDRC1 BIT(6)
+#define AMC6821_CONF1_THERMOVIE BIT(7)
+
+#define AMC6821_CONF2_PWM_EN BIT(0)
+#define AMC6821_CONF2_TACH_MODE BIT(1)
+#define AMC6821_CONF2_TACH_EN BIT(2)
+#define AMC6821_CONF2_RTFIE BIT(3)
+#define AMC6821_CONF2_LTOIE BIT(4)
+#define AMC6821_CONF2_RTOIE BIT(5)
+#define AMC6821_CONF2_PSVIE BIT(6)
+#define AMC6821_CONF2_RST BIT(7)
+
+#define AMC6821_CONF3_THERM_FAN_EN BIT(7)
+#define AMC6821_CONF3_REV_MASK GENMASK(3, 0)
+
+#define AMC6821_CONF4_OVREN BIT(4)
+#define AMC6821_CONF4_TACH_FAST BIT(5)
+#define AMC6821_CONF4_PSPR BIT(6)
+#define AMC6821_CONF4_MODE BIT(7)
+
+#define AMC6821_STAT1_RPM_ALARM BIT(0)
+#define AMC6821_STAT1_FANS BIT(1)
+#define AMC6821_STAT1_RTH BIT(2)
+#define AMC6821_STAT1_RTL BIT(3)
+#define AMC6821_STAT1_R_THERM BIT(4)
+#define AMC6821_STAT1_RTF BIT(5)
+#define AMC6821_STAT1_LTH BIT(6)
+#define AMC6821_STAT1_LTL BIT(7)
+
+#define AMC6821_STAT2_RTC BIT(3)
+#define AMC6821_STAT2_LTC BIT(4)
+#define AMC6821_STAT2_LPSV BIT(5)
+#define AMC6821_STAT2_L_THERM BIT(6)
+#define AMC6821_STAT2_THERM_IN BIT(7)
+
+#define AMC6821_TEMP_SLOPE_MASK GENMASK(2, 0)
+#define AMC6821_TEMP_LIMIT_MASK GENMASK(7, 3)
/*
* Client data (each client gets its own)
*/
struct amc6821_data {
- struct i2c_client *client;
+ struct regmap *regmap;
struct mutex update_lock;
- bool valid; /* false until following fields are valid */
- unsigned long last_updated; /* in jiffies */
+};
- /* register values */
- int temp[TEMP_IDX_LEN];
+/*
+ * Return 0 on success or negative error code.
+ *
+ * temps returns set of three temperatures, in °C:
+ * temps[0]: Passive cooling temperature, applies to both channels
+ * temps[1]: Low temperature, start slope calculations
+ * temps[2]: High temperature
+ *
+ * Channel 0: local, channel 1: remote.
+ */
+static int amc6821_get_auto_point_temps(struct regmap *regmap, int channel, u8 *temps)
+{
+ u32 pwm, regval;
+ int err;
- u16 fan[FAN1_IDX_LEN];
- u8 fan1_div;
+ err = regmap_read(regmap, AMC6821_REG_DCY_LOW_TEMP, &pwm);
+ if (err)
+ return err;
- u8 pwm1;
- u8 temp1_auto_point_temp[3];
- u8 temp2_auto_point_temp[3];
- u8 pwm1_auto_point_pwm[3];
- u8 pwm1_enable;
- u8 pwm1_auto_channels_temp;
+ err = regmap_read(regmap, AMC6821_REG_PSV_TEMP, &regval);
+ if (err)
+ return err;
+ temps[0] = regval;
- u8 stat1;
- u8 stat2;
-};
+ err = regmap_read(regmap,
+ channel ? AMC6821_REG_RTEMP_FAN_CTRL : AMC6821_REG_LTEMP_FAN_CTRL,
+ &regval);
+ if (err)
+ return err;
+ temps[1] = FIELD_GET(AMC6821_TEMP_LIMIT_MASK, regval) * 4;
+
+ /* slope is 32 >> <slope bits> in °C */
+ regval = 32 >> FIELD_GET(AMC6821_TEMP_SLOPE_MASK, regval);
+ if (regval)
+ temps[2] = temps[1] + DIV_ROUND_CLOSEST(255 - pwm, regval);
+ else
+ temps[2] = 255;
+
+ return 0;
+}
-static struct amc6821_data *amc6821_update_device(struct device *dev)
+static int amc6821_temp_read_values(struct regmap *regmap, u32 attr, int channel, long *val)
{
- struct amc6821_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- int timeout = HZ;
- u8 reg;
- int i;
+ int reg, err;
+ u32 regval;
- mutex_lock(&data->update_lock);
+ switch (attr) {
+ case hwmon_temp_input:
+ reg = channel ? AMC6821_REG_RTEMP_HI : AMC6821_REG_LTEMP_HI;
+ break;
+ case hwmon_temp_min:
+ reg = channel ? AMC6821_REG_RTEMP_LIMIT_MIN : AMC6821_REG_LTEMP_LIMIT_MIN;
+ break;
+ case hwmon_temp_max:
+ reg = channel ? AMC6821_REG_RTEMP_LIMIT_MAX : AMC6821_REG_LTEMP_LIMIT_MAX;
+ break;
+ case hwmon_temp_crit:
+ reg = channel ? AMC6821_REG_RTEMP_CRIT : AMC6821_REG_LTEMP_CRIT;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ err = regmap_read(regmap, reg, &regval);
+ if (err)
+ return err;
+ *val = sign_extend32(regval, 7) * 1000;
+ return 0;
+}
- if (time_after(jiffies, data->last_updated + timeout) ||
- !data->valid) {
-
- for (i = 0; i < TEMP_IDX_LEN; i++)
- data->temp[i] = (int8_t)i2c_smbus_read_byte_data(
- client, temp_reg[i]);
-
- data->stat1 = i2c_smbus_read_byte_data(client,
- AMC6821_REG_STAT1);
- data->stat2 = i2c_smbus_read_byte_data(client,
- AMC6821_REG_STAT2);
-
- data->pwm1 = i2c_smbus_read_byte_data(client,
- AMC6821_REG_DCY);
- for (i = 0; i < FAN1_IDX_LEN; i++) {
- data->fan[i] = i2c_smbus_read_byte_data(
- client,
- fan_reg_low[i]);
- data->fan[i] += i2c_smbus_read_byte_data(
- client,
- fan_reg_hi[i]) << 8;
- }
- data->fan1_div = i2c_smbus_read_byte_data(client,
- AMC6821_REG_CONF4);
- data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2;
-
- data->pwm1_auto_point_pwm[0] = 0;
- data->pwm1_auto_point_pwm[2] = 255;
- data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client,
- AMC6821_REG_DCY_LOW_TEMP);
-
- data->temp1_auto_point_temp[0] =
- i2c_smbus_read_byte_data(client,
- AMC6821_REG_PSV_TEMP);
- data->temp2_auto_point_temp[0] =
- data->temp1_auto_point_temp[0];
- reg = i2c_smbus_read_byte_data(client,
- AMC6821_REG_LTEMP_FAN_CTRL);
- data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1;
- reg &= 0x07;
- reg = 0x20 >> reg;
- if (reg > 0)
- data->temp1_auto_point_temp[2] =
- data->temp1_auto_point_temp[1] +
- (data->pwm1_auto_point_pwm[2] -
- data->pwm1_auto_point_pwm[1]) / reg;
- else
- data->temp1_auto_point_temp[2] = 255;
-
- reg = i2c_smbus_read_byte_data(client,
- AMC6821_REG_RTEMP_FAN_CTRL);
- data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1;
- reg &= 0x07;
- reg = 0x20 >> reg;
- if (reg > 0)
- data->temp2_auto_point_temp[2] =
- data->temp2_auto_point_temp[1] +
- (data->pwm1_auto_point_pwm[2] -
- data->pwm1_auto_point_pwm[1]) / reg;
- else
- data->temp2_auto_point_temp[2] = 255;
-
- reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
- reg = (reg >> 5) & 0x3;
- switch (reg) {
- case 0: /*open loop: software sets pwm1*/
- data->pwm1_auto_channels_temp = 0;
- data->pwm1_enable = 1;
+static int amc6821_read_alarms(struct regmap *regmap, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ int reg, mask, err;
+ u32 regval;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_min_alarm:
+ reg = AMC6821_REG_STAT1;
+ mask = channel ? AMC6821_STAT1_RTL : AMC6821_STAT1_LTL;
break;
- case 2: /*closed loop: remote T (temp2)*/
- data->pwm1_auto_channels_temp = 2;
- data->pwm1_enable = 2;
+ case hwmon_temp_max_alarm:
+ reg = AMC6821_REG_STAT1;
+ mask = channel ? AMC6821_STAT1_RTH : AMC6821_STAT1_LTH;
break;
- case 3: /*closed loop: local and remote T (temp2)*/
- data->pwm1_auto_channels_temp = 3;
- data->pwm1_enable = 3;
+ case hwmon_temp_crit_alarm:
+ reg = AMC6821_REG_STAT2;
+ mask = channel ? AMC6821_STAT2_RTC : AMC6821_STAT2_LTC;
break;
- case 1: /*
- * semi-open loop: software sets rpm, chip controls
- * pwm1, currently not implemented
- */
- data->pwm1_auto_channels_temp = 0;
- data->pwm1_enable = 0;
+ case hwmon_temp_fault:
+ reg = AMC6821_REG_STAT1;
+ mask = AMC6821_STAT1_RTF;
break;
+ default:
+ return -EOPNOTSUPP;
}
-
- data->last_updated = jiffies;
- data->valid = true;
+ break;
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_fault:
+ reg = AMC6821_REG_STAT1;
+ mask = AMC6821_STAT1_FANS;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ break;
+ default:
+ return -EOPNOTSUPP;
}
- mutex_unlock(&data->update_lock);
- return data;
+ err = regmap_read(regmap, reg, &regval);
+ if (err)
+ return err;
+ *val = !!(regval & mask);
+ return 0;
}
-static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
+static int amc6821_temp_read(struct device *dev, u32 attr, int channel, long *val)
{
- struct amc6821_data *data = amc6821_update_device(dev);
- int ix = to_sensor_dev_attr(devattr)->index;
+ struct amc6821_data *data = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", data->temp[ix] * 1000);
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_min:
+ case hwmon_temp_max:
+ case hwmon_temp_crit:
+ return amc6821_temp_read_values(data->regmap, attr, channel, val);
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_crit_alarm:
+ case hwmon_temp_fault:
+ return amc6821_read_alarms(data->regmap, hwmon_temp, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
}
-static ssize_t temp_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static int amc6821_temp_write(struct device *dev, u32 attr, int channel, long val)
{
struct amc6821_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- int ix = to_sensor_dev_attr(attr)->index;
- long val;
+ int reg;
- int ret = kstrtol(buf, 10, &val);
- if (ret)
- return ret;
- val = clamp_val(val / 1000, -128, 127);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000);
- mutex_lock(&data->update_lock);
- data->temp[ix] = val;
- if (i2c_smbus_write_byte_data(client, temp_reg[ix], data->temp[ix])) {
- dev_err(&client->dev, "Register write error, aborting.\n");
- count = -EIO;
+ switch (attr) {
+ case hwmon_temp_min:
+ reg = channel ? AMC6821_REG_RTEMP_LIMIT_MIN : AMC6821_REG_LTEMP_LIMIT_MIN;
+ break;
+ case hwmon_temp_max:
+ reg = channel ? AMC6821_REG_RTEMP_LIMIT_MAX : AMC6821_REG_LTEMP_LIMIT_MAX;
+ break;
+ case hwmon_temp_crit:
+ reg = channel ? AMC6821_REG_RTEMP_CRIT : AMC6821_REG_LTEMP_CRIT;
+ break;
+ default:
+ return -EOPNOTSUPP;
}
- mutex_unlock(&data->update_lock);
- return count;
+ return regmap_write(data->regmap, reg, val);
}
-static ssize_t temp_alarm_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
+static int amc6821_pwm_read(struct device *dev, u32 attr, long *val)
{
- struct amc6821_data *data = amc6821_update_device(dev);
- int ix = to_sensor_dev_attr(devattr)->index;
- u8 flag;
+ struct amc6821_data *data = dev_get_drvdata(dev);
+ struct regmap *regmap = data->regmap;
+ u32 regval;
+ int err;
- switch (ix) {
- case IDX_TEMP1_MIN:
- flag = data->stat1 & AMC6821_STAT1_LTL;
- break;
- case IDX_TEMP1_MAX:
- flag = data->stat1 & AMC6821_STAT1_LTH;
+ switch (attr) {
+ case hwmon_pwm_enable:
+ err = regmap_read(regmap, AMC6821_REG_CONF1, &regval);
+ if (err)
+ return err;
+ switch (regval & (AMC6821_CONF1_FDRC0 | AMC6821_CONF1_FDRC1)) {
+ case 0:
+ *val = 1; /* manual */
+ break;
+ case AMC6821_CONF1_FDRC0:
+ *val = 4; /* target rpm (fan1_target) controlled */
+ break;
+ case AMC6821_CONF1_FDRC1:
+ *val = 2; /* remote temp controlled */
+ break;
+ default:
+ *val = 3; /* max(local, remote) temp controlled */
+ break;
+ }
+ return 0;
+ case hwmon_pwm_mode:
+ err = regmap_read(regmap, AMC6821_REG_CONF2, &regval);
+ if (err)
+ return err;
+ *val = !!(regval & AMC6821_CONF2_TACH_MODE);
+ return 0;
+ case hwmon_pwm_auto_channels_temp:
+ err = regmap_read(regmap, AMC6821_REG_CONF1, &regval);
+ if (err)
+ return err;
+ switch (regval & (AMC6821_CONF1_FDRC0 | AMC6821_CONF1_FDRC1)) {
+ case 0:
+ case AMC6821_CONF1_FDRC0:
+ *val = 0; /* manual or target rpm controlled */
+ break;
+ case AMC6821_CONF1_FDRC1:
+ *val = 2; /* remote temp controlled */
+ break;
+ default:
+ *val = 3; /* max(local, remote) temp controlled */
+ break;
+ }
+ return 0;
+ case hwmon_pwm_input:
+ err = regmap_read(regmap, AMC6821_REG_DCY, &regval);
+ if (err)
+ return err;
+ *val = regval;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int amc6821_pwm_write(struct device *dev, u32 attr, long val)
+{
+ struct amc6821_data *data = dev_get_drvdata(dev);
+ struct regmap *regmap = data->regmap;
+ u32 mode;
+
+ switch (attr) {
+ case hwmon_pwm_enable:
+ switch (val) {
+ case 1:
+ mode = 0;
+ break;
+ case 2:
+ mode = AMC6821_CONF1_FDRC1;
+ break;
+ case 3:
+ mode = AMC6821_CONF1_FDRC0 | AMC6821_CONF1_FDRC1;
+ break;
+ case 4:
+ mode = AMC6821_CONF1_FDRC0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return regmap_update_bits(regmap, AMC6821_REG_CONF1,
+ AMC6821_CONF1_FDRC0 | AMC6821_CONF1_FDRC1,
+ mode);
+ case hwmon_pwm_mode:
+ if (val < 0 || val > 1)
+ return -EINVAL;
+ return regmap_update_bits(regmap, AMC6821_REG_CONF2,
+ AMC6821_CONF2_TACH_MODE,
+ val ? AMC6821_CONF2_TACH_MODE : 0);
break;
- case IDX_TEMP1_CRIT:
- flag = data->stat2 & AMC6821_STAT2_LTC;
+ case hwmon_pwm_input:
+ if (val < 0 || val > 255)
+ return -EINVAL;
+ return regmap_write(regmap, AMC6821_REG_DCY, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int amc6821_fan_read_rpm(struct regmap *regmap, u32 attr, long *val)
+{
+ int reg, err;
+ u8 regs[2];
+ u32 regval;
+
+ switch (attr) {
+ case hwmon_fan_input:
+ reg = AMC6821_REG_TDATA_LOW;
break;
- case IDX_TEMP2_MIN:
- flag = data->stat1 & AMC6821_STAT1_RTL;
+ case hwmon_fan_min:
+ reg = AMC6821_REG_TACH_LLIMITL;
break;
- case IDX_TEMP2_MAX:
- flag = data->stat1 & AMC6821_STAT1_RTH;
+ case hwmon_fan_max:
+ reg = AMC6821_REG_TACH_HLIMITL;
break;
- case IDX_TEMP2_CRIT:
- flag = data->stat2 & AMC6821_STAT2_RTC;
+ case hwmon_fan_target:
+ reg = AMC6821_REG_TACH_SETTINGL;
break;
default:
- dev_dbg(dev, "Unknown attr->index (%d).\n", ix);
- return -EINVAL;
+ return -EOPNOTSUPP;
}
- if (flag)
- return sprintf(buf, "1");
- else
- return sprintf(buf, "0");
-}
-static ssize_t temp2_fault_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct amc6821_data *data = amc6821_update_device(dev);
- if (data->stat1 & AMC6821_STAT1_RTF)
- return sprintf(buf, "1");
- else
- return sprintf(buf, "0");
-}
+ err = regmap_bulk_read(regmap, reg, regs, 2);
+ if (err)
+ return err;
-static ssize_t pwm1_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct amc6821_data *data = amc6821_update_device(dev);
- return sprintf(buf, "%d\n", data->pwm1);
+ regval = (regs[1] << 8) | regs[0];
+ *val = regval ? 6000000 / regval : 0;
+
+ return 0;
}
-static ssize_t pwm1_store(struct device *dev,
- struct device_attribute *devattr, const char *buf,
- size_t count)
+static int amc6821_fan_read(struct device *dev, u32 attr, long *val)
{
struct amc6821_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- long val;
- int ret = kstrtol(buf, 10, &val);
- if (ret)
- return ret;
-
- mutex_lock(&data->update_lock);
- data->pwm1 = clamp_val(val , 0, 255);
- i2c_smbus_write_byte_data(client, AMC6821_REG_DCY, data->pwm1);
- mutex_unlock(&data->update_lock);
- return count;
-}
+ struct regmap *regmap = data->regmap;
+ u32 regval;
+ int err;
-static ssize_t pwm1_enable_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct amc6821_data *data = amc6821_update_device(dev);
- return sprintf(buf, "%d\n", data->pwm1_enable);
+ switch (attr) {
+ case hwmon_fan_input:
+ case hwmon_fan_min:
+ case hwmon_fan_max:
+ case hwmon_fan_target:
+ return amc6821_fan_read_rpm(regmap, attr, val);
+ case hwmon_fan_fault:
+ return amc6821_read_alarms(regmap, hwmon_fan, attr, 0, val);
+ case hwmon_fan_pulses:
+ err = regmap_read(regmap, AMC6821_REG_CONF4, &regval);
+ if (err)
+ return err;
+ *val = (regval & AMC6821_CONF4_PSPR) ? 4 : 2;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
}
-static ssize_t pwm1_enable_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static int amc6821_fan_write(struct device *dev, u32 attr, long val)
{
struct amc6821_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- long val;
- int config = kstrtol(buf, 10, &val);
- if (config)
- return config;
-
- mutex_lock(&data->update_lock);
- config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
- if (config < 0) {
- dev_err(&client->dev,
- "Error reading configuration register, aborting.\n");
- count = config;
- goto unlock;
+ struct regmap *regmap = data->regmap;
+ u8 regs[2];
+ int reg;
+
+ if (attr == hwmon_fan_pulses) {
+ if (val != 2 && val != 4)
+ return -EINVAL;
+ return regmap_update_bits(regmap, AMC6821_REG_CONF4,
+ AMC6821_CONF4_PSPR,
+ val == 4 ? AMC6821_CONF4_PSPR : 0);
}
- switch (val) {
- case 1:
- config &= ~AMC6821_CONF1_FDRC0;
- config &= ~AMC6821_CONF1_FDRC1;
+ if (val < 0)
+ return -EINVAL;
+
+ switch (attr) {
+ case hwmon_fan_min:
+ if (!val) /* no unlimited minimum speed */
+ return -EINVAL;
+ reg = AMC6821_REG_TACH_LLIMITL;
break;
- case 2:
- config &= ~AMC6821_CONF1_FDRC0;
- config |= AMC6821_CONF1_FDRC1;
+ case hwmon_fan_max:
+ reg = AMC6821_REG_TACH_HLIMITL;
break;
- case 3:
- config |= AMC6821_CONF1_FDRC0;
- config |= AMC6821_CONF1_FDRC1;
+ case hwmon_fan_target:
+ if (!val) /* no unlimited target speed */
+ return -EINVAL;
+ reg = AMC6821_REG_TACH_SETTINGL;
break;
default:
- count = -EINVAL;
- goto unlock;
+ return -EOPNOTSUPP;
}
- if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) {
- dev_err(&client->dev,
- "Configuration register write error, aborting.\n");
- count = -EIO;
- }
-unlock:
- mutex_unlock(&data->update_lock);
- return count;
-}
-static ssize_t pwm1_auto_channels_temp_show(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct amc6821_data *data = amc6821_update_device(dev);
- return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp);
+ val = val ? 6000000 / clamp_val(val, 1, 6000000) : 0;
+ val = clamp_val(val, 0, 0xffff);
+
+ regs[0] = val & 0xff;
+ regs[1] = val >> 8;
+
+ return regmap_bulk_write(data->regmap, reg, regs, 2);
}
static ssize_t temp_auto_point_temp_show(struct device *dev,
struct device_attribute *devattr,
char *buf)
{
+ struct amc6821_data *data = dev_get_drvdata(dev);
int ix = to_sensor_dev_attr_2(devattr)->index;
int nr = to_sensor_dev_attr_2(devattr)->nr;
- struct amc6821_data *data = amc6821_update_device(dev);
- switch (nr) {
- case 1:
- return sprintf(buf, "%d\n",
- data->temp1_auto_point_temp[ix] * 1000);
- case 2:
- return sprintf(buf, "%d\n",
- data->temp2_auto_point_temp[ix] * 1000);
- default:
- dev_dbg(dev, "Unknown attr->nr (%d).\n", nr);
- return -EINVAL;
- }
+ u8 temps[3];
+ int err;
+
+ mutex_lock(&data->update_lock);
+ err = amc6821_get_auto_point_temps(data->regmap, nr, temps);
+ mutex_unlock(&data->update_lock);
+ if (err)
+ return err;
+
+ return sysfs_emit(buf, "%d\n", temps[ix] * 1000);
}
static ssize_t pwm1_auto_point_pwm_show(struct device *dev,
struct device_attribute *devattr,
char *buf)
{
+ struct amc6821_data *data = dev_get_drvdata(dev);
int ix = to_sensor_dev_attr(devattr)->index;
- struct amc6821_data *data = amc6821_update_device(dev);
- return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]);
+ u32 val;
+ int err;
+
+ switch (ix) {
+ case 0:
+ val = 0;
+ break;
+ case 1:
+ err = regmap_read(data->regmap, AMC6821_REG_DCY_LOW_TEMP, &val);
+ if (err)
+ return err;
+ break;
+ default:
+ val = 255;
+ break;
+ }
+ return sysfs_emit(buf, "%d\n", val);
}
-static inline ssize_t set_slope_register(struct i2c_client *client,
- u8 reg,
- u8 dpwm,
- u8 *ptemp)
+/*
+ * Set TEMP[0-4] (low temperature) and SLP[0-2] (slope) of local or remote
+ * TEMP-FAN control register.
+ *
+ * Return 0 on success or negative error code.
+ *
+ * Channel 0: local, channel 1: remote
+ */
+static inline int set_slope_register(struct regmap *regmap, int channel, u8 *temps)
{
- int dt;
- u8 tmp;
+ u8 regval = FIELD_PREP(AMC6821_TEMP_LIMIT_MASK, temps[1] / 4);
+ u8 tmp, dpwm;
+ int err, dt;
+ u32 pwm;
+
+ err = regmap_read(regmap, AMC6821_REG_DCY_LOW_TEMP, &pwm);
+ if (err)
+ return err;
- dt = ptemp[2]-ptemp[1];
+ dpwm = 255 - pwm;
+
+ dt = temps[2] - temps[1];
for (tmp = 4; tmp > 0; tmp--) {
- if (dt * (0x20 >> tmp) >= dpwm)
+ if (dt * (32 >> tmp) >= dpwm)
break;
}
- tmp |= (ptemp[1] & 0x7C) << 1;
- if (i2c_smbus_write_byte_data(client,
- reg, tmp)) {
- dev_err(&client->dev, "Register write error, aborting.\n");
- return -EIO;
- }
- return 0;
+ regval |= FIELD_PREP(AMC6821_TEMP_SLOPE_MASK, tmp);
+
+ return regmap_write(regmap,
+ channel ? AMC6821_REG_RTEMP_FAN_CTRL : AMC6821_REG_LTEMP_FAN_CTRL,
+ regval);
}
static ssize_t temp_auto_point_temp_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct amc6821_data *data = amc6821_update_device(dev);
- struct i2c_client *client = data->client;
+ struct amc6821_data *data = dev_get_drvdata(dev);
int ix = to_sensor_dev_attr_2(attr)->index;
int nr = to_sensor_dev_attr_2(attr)->nr;
- u8 *ptemp;
- u8 reg;
- int dpwm;
+ struct regmap *regmap = data->regmap;
+ u8 temps[3], otemps[3];
long val;
- int ret = kstrtol(buf, 10, &val);
+ int ret;
+
+ ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
- switch (nr) {
- case 1:
- ptemp = data->temp1_auto_point_temp;
- reg = AMC6821_REG_LTEMP_FAN_CTRL;
- break;
- case 2:
- ptemp = data->temp2_auto_point_temp;
- reg = AMC6821_REG_RTEMP_FAN_CTRL;
- break;
- default:
- dev_dbg(dev, "Unknown attr->nr (%d).\n", nr);
- return -EINVAL;
- }
-
mutex_lock(&data->update_lock);
- data->valid = false;
+
+ ret = amc6821_get_auto_point_temps(data->regmap, nr, temps);
+ if (ret)
+ goto unlock;
switch (ix) {
case 0:
- ptemp[0] = clamp_val(val / 1000, 0,
- data->temp1_auto_point_temp[1]);
- ptemp[0] = clamp_val(ptemp[0], 0,
- data->temp2_auto_point_temp[1]);
- ptemp[0] = clamp_val(ptemp[0], 0, 63);
- if (i2c_smbus_write_byte_data(
- client,
- AMC6821_REG_PSV_TEMP,
- ptemp[0])) {
- dev_err(&client->dev,
- "Register write error, aborting.\n");
- count = -EIO;
- }
- goto EXIT;
+ /*
+ * Passive cooling temperature. Range limit against low limit
+ * of both channels.
+ */
+ ret = amc6821_get_auto_point_temps(data->regmap, 1 - nr, otemps);
+ if (ret)
+ goto unlock;
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, 63000), 1000);
+ val = clamp_val(val, 0, min(temps[1], otemps[1]));
+ ret = regmap_write(regmap, AMC6821_REG_PSV_TEMP, val);
+ break;
case 1:
- ptemp[1] = clamp_val(val / 1000, (ptemp[0] & 0x7C) + 4, 124);
- ptemp[1] &= 0x7C;
- ptemp[2] = clamp_val(ptemp[2], ptemp[1] + 1, 255);
+ /*
+ * Low limit; must be between passive and high limit,
+ * and not exceed 124. Step size is 4 degrees C.
+ */
+ val = clamp_val(val, DIV_ROUND_UP(temps[0], 4) * 4000, 124000);
+ temps[1] = DIV_ROUND_CLOSEST(val, 4000) * 4;
+ val = temps[1] / 4;
+ /* Auto-adjust high limit if necessary */
+ temps[2] = clamp_val(temps[2], temps[1] + 1, 255);
+ ret = set_slope_register(regmap, nr, temps);
break;
case 2:
- ptemp[2] = clamp_val(val / 1000, ptemp[1]+1, 255);
+ /* high limit, must be higher than low limit */
+ val = clamp_val(val, (temps[1] + 1) * 1000, 255000);
+ temps[2] = DIV_ROUND_CLOSEST(val, 1000);
+ ret = set_slope_register(regmap, nr, temps);
break;
default:
- dev_dbg(dev, "Unknown attr->index (%d).\n", ix);
- count = -EINVAL;
- goto EXIT;
+ ret = -EINVAL;
+ break;
}
- dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1];
- if (set_slope_register(client, reg, dpwm, ptemp))
- count = -EIO;
-
-EXIT:
+unlock:
mutex_unlock(&data->update_lock);
- return count;
+ return ret ? : count;
}
static ssize_t pwm1_auto_point_pwm_store(struct device *dev,
@@ -556,204 +637,52 @@ static ssize_t pwm1_auto_point_pwm_store(struct device *dev,
const char *buf, size_t count)
{
struct amc6821_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- int dpwm;
- long val;
- int ret = kstrtol(buf, 10, &val);
- if (ret)
- return ret;
-
- mutex_lock(&data->update_lock);
- data->pwm1_auto_point_pwm[1] = clamp_val(val, 0, 254);
- if (i2c_smbus_write_byte_data(client, AMC6821_REG_DCY_LOW_TEMP,
- data->pwm1_auto_point_pwm[1])) {
- dev_err(&client->dev, "Register write error, aborting.\n");
- count = -EIO;
- goto EXIT;
- }
- dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1];
- if (set_slope_register(client, AMC6821_REG_LTEMP_FAN_CTRL, dpwm,
- data->temp1_auto_point_temp)) {
- count = -EIO;
- goto EXIT;
- }
- if (set_slope_register(client, AMC6821_REG_RTEMP_FAN_CTRL, dpwm,
- data->temp2_auto_point_temp)) {
- count = -EIO;
- goto EXIT;
- }
-
-EXIT:
- data->valid = false;
- mutex_unlock(&data->update_lock);
- return count;
-}
-
-static ssize_t fan_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct amc6821_data *data = amc6821_update_device(dev);
- int ix = to_sensor_dev_attr(devattr)->index;
- if (0 == data->fan[ix])
- return sprintf(buf, "0");
- return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix]));
-}
+ struct regmap *regmap = data->regmap;
+ int i, ret;
+ u8 val;
-static ssize_t fan1_fault_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct amc6821_data *data = amc6821_update_device(dev);
- if (data->stat1 & AMC6821_STAT1_FANS)
- return sprintf(buf, "1");
- else
- return sprintf(buf, "0");
-}
-
-static ssize_t fan_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct amc6821_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- long val;
- int ix = to_sensor_dev_attr(attr)->index;
- int ret = kstrtol(buf, 10, &val);
+ ret = kstrtou8(buf, 10, &val);
if (ret)
return ret;
- val = 1 > val ? 0xFFFF : 6000000/val;
mutex_lock(&data->update_lock);
- data->fan[ix] = (u16) clamp_val(val, 1, 0xFFFF);
- if (i2c_smbus_write_byte_data(client, fan_reg_low[ix],
- data->fan[ix] & 0xFF)) {
- dev_err(&client->dev, "Register write error, aborting.\n");
- count = -EIO;
- goto EXIT;
- }
- if (i2c_smbus_write_byte_data(client,
- fan_reg_hi[ix], data->fan[ix] >> 8)) {
- dev_err(&client->dev, "Register write error, aborting.\n");
- count = -EIO;
- }
-EXIT:
- mutex_unlock(&data->update_lock);
- return count;
-}
-
-static ssize_t fan1_div_show(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct amc6821_data *data = amc6821_update_device(dev);
- return sprintf(buf, "%d\n", data->fan1_div);
-}
+ ret = regmap_write(regmap, AMC6821_REG_DCY_LOW_TEMP, val);
+ if (ret)
+ goto unlock;
-static ssize_t fan1_div_store(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t count)
-{
- struct amc6821_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- long val;
- int config = kstrtol(buf, 10, &val);
- if (config)
- return config;
+ for (i = 0; i < 2; i++) {
+ u8 temps[3];
- mutex_lock(&data->update_lock);
- config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
- if (config < 0) {
- dev_err(&client->dev,
- "Error reading configuration register, aborting.\n");
- count = config;
- goto EXIT;
- }
- switch (val) {
- case 2:
- config &= ~AMC6821_CONF4_PSPR;
- data->fan1_div = 2;
- break;
- case 4:
- config |= AMC6821_CONF4_PSPR;
- data->fan1_div = 4;
- break;
- default:
- count = -EINVAL;
- goto EXIT;
- }
- if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, config)) {
- dev_err(&client->dev,
- "Configuration register write error, aborting.\n");
- count = -EIO;
+ ret = amc6821_get_auto_point_temps(regmap, i, temps);
+ if (ret)
+ break;
+ ret = set_slope_register(regmap, i, temps);
+ if (ret)
+ break;
}
-EXIT:
+unlock:
mutex_unlock(&data->update_lock);
- return count;
+ return ret ? : count;
}
-static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, IDX_TEMP1_INPUT);
-static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, IDX_TEMP1_MIN);
-static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, IDX_TEMP1_MAX);
-static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, IDX_TEMP1_CRIT);
-static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, temp_alarm, IDX_TEMP1_MIN);
-static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, temp_alarm, IDX_TEMP1_MAX);
-static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, temp_alarm, IDX_TEMP1_CRIT);
-static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, IDX_TEMP2_INPUT);
-static SENSOR_DEVICE_ATTR_RW(temp2_min, temp, IDX_TEMP2_MIN);
-static SENSOR_DEVICE_ATTR_RW(temp2_max, temp, IDX_TEMP2_MAX);
-static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp, IDX_TEMP2_CRIT);
-static SENSOR_DEVICE_ATTR_RO(temp2_fault, temp2_fault, 0);
-static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, temp_alarm, IDX_TEMP2_MIN);
-static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, temp_alarm, IDX_TEMP2_MAX);
-static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, temp_alarm, IDX_TEMP2_CRIT);
-static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, IDX_FAN1_INPUT);
-static SENSOR_DEVICE_ATTR_RW(fan1_min, fan, IDX_FAN1_MIN);
-static SENSOR_DEVICE_ATTR_RW(fan1_max, fan, IDX_FAN1_MAX);
-static SENSOR_DEVICE_ATTR_RO(fan1_fault, fan1_fault, 0);
-static SENSOR_DEVICE_ATTR_RW(fan1_div, fan1_div, 0);
-
-static SENSOR_DEVICE_ATTR_RW(pwm1, pwm1, 0);
-static SENSOR_DEVICE_ATTR_RW(pwm1_enable, pwm1_enable, 0);
static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm, pwm1_auto_point_pwm, 0);
static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_pwm, pwm1_auto_point_pwm, 1);
static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point3_pwm, pwm1_auto_point_pwm, 2);
-static SENSOR_DEVICE_ATTR_RO(pwm1_auto_channels_temp, pwm1_auto_channels_temp,
- 0);
static SENSOR_DEVICE_ATTR_2_RO(temp1_auto_point1_temp, temp_auto_point_temp,
- 1, 0);
+ 0, 0);
static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_point2_temp, temp_auto_point_temp,
- 1, 1);
+ 0, 1);
static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_point3_temp, temp_auto_point_temp,
- 1, 2);
+ 0, 2);
static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_point1_temp, temp_auto_point_temp,
- 2, 0);
+ 1, 0);
static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_point2_temp, temp_auto_point_temp,
- 2, 1);
+ 1, 1);
static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_point3_temp, temp_auto_point_temp,
- 2, 2);
+ 1, 2);
static struct attribute *amc6821_attrs[] = {
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_temp1_min.dev_attr.attr,
- &sensor_dev_attr_temp1_max.dev_attr.attr,
- &sensor_dev_attr_temp1_crit.dev_attr.attr,
- &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
- &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
- &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_input.dev_attr.attr,
- &sensor_dev_attr_temp2_min.dev_attr.attr,
- &sensor_dev_attr_temp2_max.dev_attr.attr,
- &sensor_dev_attr_temp2_crit.dev_attr.attr,
- &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_fault.dev_attr.attr,
- &sensor_dev_attr_fan1_input.dev_attr.attr,
- &sensor_dev_attr_fan1_min.dev_attr.attr,
- &sensor_dev_attr_fan1_max.dev_attr.attr,
- &sensor_dev_attr_fan1_fault.dev_attr.attr,
- &sensor_dev_attr_fan1_div.dev_attr.attr,
- &sensor_dev_attr_pwm1.dev_attr.attr,
- &sensor_dev_attr_pwm1_enable.dev_attr.attr,
- &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
&sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
@@ -765,13 +694,118 @@ static struct attribute *amc6821_attrs[] = {
&sensor_dev_attr_temp2_auto_point3_temp.dev_attr.attr,
NULL
};
-
ATTRIBUTE_GROUPS(amc6821);
+static int amc6821_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ switch (type) {
+ case hwmon_temp:
+ return amc6821_temp_read(dev, attr, channel, val);
+ case hwmon_fan:
+ return amc6821_fan_read(dev, attr, val);
+ case hwmon_pwm:
+ return amc6821_pwm_read(dev, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int amc6821_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ switch (type) {
+ case hwmon_temp:
+ return amc6821_temp_write(dev, attr, channel, val);
+ case hwmon_fan:
+ return amc6821_fan_write(dev, attr, val);
+ case hwmon_pwm:
+ return amc6821_pwm_write(dev, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t amc6821_is_visible(const void *data,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_crit_alarm:
+ case hwmon_temp_fault:
+ return 0444;
+ case hwmon_temp_min:
+ case hwmon_temp_max:
+ case hwmon_temp_crit:
+ return 0644;
+ default:
+ return 0;
+ }
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_input:
+ case hwmon_fan_fault:
+ return 0444;
+ case hwmon_fan_pulses:
+ case hwmon_fan_min:
+ case hwmon_fan_max:
+ case hwmon_fan_target:
+ return 0644;
+ default:
+ return 0;
+ }
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_mode:
+ case hwmon_pwm_enable:
+ case hwmon_pwm_input:
+ return 0644;
+ case hwmon_pwm_auto_channels_temp:
+ return 0444;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+static const struct hwmon_channel_info * const amc6821_info[] = {
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
+ HWMON_T_CRIT | HWMON_T_MIN_ALARM |
+ HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM,
+ HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
+ HWMON_T_CRIT | HWMON_T_MIN_ALARM |
+ HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM |
+ HWMON_T_FAULT),
+ HWMON_CHANNEL_INFO(fan,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX |
+ HWMON_F_TARGET | HWMON_F_PULSES | HWMON_F_FAULT),
+ HWMON_CHANNEL_INFO(pwm,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE | HWMON_PWM_MODE |
+ HWMON_PWM_AUTO_CHANNELS_TEMP),
+ NULL
+};
+
+static const struct hwmon_ops amc6821_hwmon_ops = {
+ .is_visible = amc6821_is_visible,
+ .read = amc6821_read,
+ .write = amc6821_write,
+};
+
+static const struct hwmon_chip_info amc6821_chip_info = {
+ .ops = &amc6821_hwmon_ops,
+ .info = amc6821_info,
+};
+
/* Return 0 if detection is successful, -ENODEV otherwise */
-static int amc6821_detect(
- struct i2c_client *client,
- struct i2c_board_info *info)
+static int amc6821_detect(struct i2c_client *client, struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
int address = client->addr;
@@ -814,121 +848,90 @@ static int amc6821_detect(
return 0;
}
-static int amc6821_init_client(struct i2c_client *client)
+static int amc6821_init_client(struct amc6821_data *data)
{
- int config;
- int err = -EIO;
+ struct regmap *regmap = data->regmap;
+ int err;
if (init) {
- config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
-
- if (config < 0) {
- dev_err(&client->dev,
- "Error reading configuration register, aborting.\n");
- return err;
- }
-
- config |= AMC6821_CONF4_MODE;
-
- if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4,
- config)) {
- dev_err(&client->dev,
- "Configuration register write error, aborting.\n");
- return err;
- }
-
- config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF3);
-
- if (config < 0) {
- dev_err(&client->dev,
- "Error reading configuration register, aborting.\n");
- return err;
- }
-
- dev_info(&client->dev, "Revision %d\n", config & 0x0f);
-
- config &= ~AMC6821_CONF3_THERM_FAN_EN;
-
- if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF3,
- config)) {
- dev_err(&client->dev,
- "Configuration register write error, aborting.\n");
- return err;
- }
-
- config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF2);
-
- if (config < 0) {
- dev_err(&client->dev,
- "Error reading configuration register, aborting.\n");
+ err = regmap_set_bits(regmap, AMC6821_REG_CONF4, AMC6821_CONF4_MODE);
+ if (err)
return err;
- }
-
- config &= ~AMC6821_CONF2_RTFIE;
- config &= ~AMC6821_CONF2_LTOIE;
- config &= ~AMC6821_CONF2_RTOIE;
- if (i2c_smbus_write_byte_data(client,
- AMC6821_REG_CONF2, config)) {
- dev_err(&client->dev,
- "Configuration register write error, aborting.\n");
+ err = regmap_clear_bits(regmap, AMC6821_REG_CONF3, AMC6821_CONF3_THERM_FAN_EN);
+ if (err)
return err;
- }
-
- config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
-
- if (config < 0) {
- dev_err(&client->dev,
- "Error reading configuration register, aborting.\n");
+ err = regmap_clear_bits(regmap, AMC6821_REG_CONF2,
+ AMC6821_CONF2_RTFIE |
+ AMC6821_CONF2_LTOIE |
+ AMC6821_CONF2_RTOIE);
+ if (err)
return err;
- }
- config &= ~AMC6821_CONF1_THERMOVIE;
- config &= ~AMC6821_CONF1_FANIE;
- config |= AMC6821_CONF1_START;
- if (pwminv)
- config |= AMC6821_CONF1_PWMINV;
- else
- config &= ~AMC6821_CONF1_PWMINV;
-
- if (i2c_smbus_write_byte_data(
- client, AMC6821_REG_CONF1, config)) {
- dev_err(&client->dev,
- "Configuration register write error, aborting.\n");
+ err = regmap_update_bits(regmap, AMC6821_REG_CONF1,
+ AMC6821_CONF1_THERMOVIE | AMC6821_CONF1_FANIE |
+ AMC6821_CONF1_START | AMC6821_CONF1_PWMINV,
+ AMC6821_CONF1_START |
+ (pwminv ? AMC6821_CONF1_PWMINV : 0));
+ if (err)
return err;
- }
}
return 0;
}
+static bool amc6821_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case AMC6821_REG_STAT1:
+ case AMC6821_REG_STAT2:
+ case AMC6821_REG_TEMP_LO:
+ case AMC6821_REG_TDATA_LOW:
+ case AMC6821_REG_LTEMP_HI:
+ case AMC6821_REG_RTEMP_HI:
+ case AMC6821_REG_TDATA_HI:
+ return true;
+ default:
+ return false;
+ }
+}
+
+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,
+};
+
static int amc6821_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct amc6821_data *data;
struct device *hwmon_dev;
+ struct regmap *regmap;
int err;
data = devm_kzalloc(dev, sizeof(struct amc6821_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- data->client = client;
- mutex_init(&data->update_lock);
+ regmap = devm_regmap_init_i2c(client, &amc6821_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to initialize regmap\n");
+ data->regmap = regmap;
- /*
- * Initialize the amc6821 chip
- */
- err = amc6821_init_client(client);
+ err = amc6821_init_client(data);
if (err)
return err;
- hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
- data,
- amc6821_groups);
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
+ data, &amc6821_chip_info,
+ amc6821_groups);
return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id amc6821_id[] = {
- { "amc6821", amc6821 },
+ { "amc6821", 0 },
{ }
};
@@ -937,7 +940,6 @@ MODULE_DEVICE_TABLE(i2c, amc6821_id);
static const struct of_device_id __maybe_unused amc6821_of_match[] = {
{
.compatible = "ti,amc6821",
- .data = (void *)amc6821,
},
{ }
};
diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c
index 36f9e38000d5..6bb8d7b1d219 100644
--- a/drivers/hwmon/asus-ec-sensors.c
+++ b/drivers/hwmon/asus-ec-sensors.c
@@ -322,6 +322,14 @@ static const struct ec_board_info board_info_pro_art_x570_creator_wifi = {
.family = family_amd_500_series,
};
+static const struct ec_board_info board_info_pro_art_x670E_creator_wifi = {
+ .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE |
+ SENSOR_TEMP_MB | SENSOR_TEMP_VRM |
+ SENSOR_TEMP_T_SENSOR,
+ .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
+ .family = family_amd_600_series,
+};
+
static const struct ec_board_info board_info_pro_art_b550_creator = {
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
SENSOR_TEMP_T_SENSOR |
@@ -486,6 +494,8 @@ static const struct dmi_system_id dmi_table[] = {
&board_info_prime_x570_pro),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt X570-CREATOR WIFI",
&board_info_pro_art_x570_creator_wifi),
+ DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt X670E-CREATOR WIFI",
+ &board_info_pro_art_x670E_creator_wifi),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt B550-CREATOR",
&board_info_pro_art_b550_creator),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("Pro WS X570-ACE",
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index d778a2aaefec..3751c1e3eddd 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -1389,4 +1389,5 @@ static void __exit atk0110_exit(void)
module_init(atk0110_init);
module_exit(atk0110_exit);
+MODULE_DESCRIPTION("ASUS ATK0110 driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c
index 3e63666a61bd..e1a7f7aa7f80 100644
--- a/drivers/hwmon/corsair-cpro.c
+++ b/drivers/hwmon/corsair-cpro.c
@@ -10,11 +10,13 @@
#include <linux/bitops.h>
#include <linux/completion.h>
+#include <linux/debugfs.h>
#include <linux/hid.h>
#include <linux/hwmon.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
@@ -28,6 +30,8 @@
#define LABEL_LENGTH 11
#define REQ_TIMEOUT 300
+#define CTL_GET_FW_VER 0x02 /* returns the firmware version in bytes 1-3 */
+#define CTL_GET_BL_VER 0x06 /* returns the bootloader version in bytes 1-2 */
#define CTL_GET_TMP_CNCT 0x10 /*
* returns in bytes 1-4 for each temp sensor:
* 0 not connected
@@ -78,6 +82,7 @@
struct ccp_device {
struct hid_device *hdev;
struct device *hwmon_dev;
+ struct dentry *debugfs;
/* For reinitializing the completion below */
spinlock_t wait_input_report_lock;
struct completion wait_input_report;
@@ -88,6 +93,8 @@ struct ccp_device {
DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS);
DECLARE_BITMAP(fan_cnct, NUM_FANS);
char fan_label[6][LABEL_LENGTH];
+ u8 firmware_ver[3];
+ u8 bootloader_ver[2];
};
/* converts response error in buffer to errno */
@@ -496,6 +503,83 @@ static int get_temp_cnct(struct ccp_device *ccp)
return 0;
}
+/* read firmware version */
+static int get_fw_version(struct ccp_device *ccp)
+{
+ int ret;
+
+ ret = send_usb_cmd(ccp, CTL_GET_FW_VER, 0, 0, 0);
+ if (ret) {
+ hid_notice(ccp->hdev, "Failed to read firmware version.\n");
+ return ret;
+ }
+ ccp->firmware_ver[0] = ccp->buffer[1];
+ ccp->firmware_ver[1] = ccp->buffer[2];
+ ccp->firmware_ver[2] = ccp->buffer[3];
+
+ return 0;
+}
+
+/* read bootloader version */
+static int get_bl_version(struct ccp_device *ccp)
+{
+ int ret;
+
+ ret = send_usb_cmd(ccp, CTL_GET_BL_VER, 0, 0, 0);
+ if (ret) {
+ hid_notice(ccp->hdev, "Failed to read bootloader version.\n");
+ return ret;
+ }
+ ccp->bootloader_ver[0] = ccp->buffer[1];
+ ccp->bootloader_ver[1] = ccp->buffer[2];
+
+ return 0;
+}
+
+static int firmware_show(struct seq_file *seqf, void *unused)
+{
+ struct ccp_device *ccp = seqf->private;
+
+ seq_printf(seqf, "%d.%d.%d\n",
+ ccp->firmware_ver[0],
+ ccp->firmware_ver[1],
+ ccp->firmware_ver[2]);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(firmware);
+
+static int bootloader_show(struct seq_file *seqf, void *unused)
+{
+ struct ccp_device *ccp = seqf->private;
+
+ seq_printf(seqf, "%d.%d\n",
+ ccp->bootloader_ver[0],
+ ccp->bootloader_ver[1]);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(bootloader);
+
+static void ccp_debugfs_init(struct ccp_device *ccp)
+{
+ char name[32];
+ int ret;
+
+ scnprintf(name, sizeof(name), "corsaircpro-%s", dev_name(&ccp->hdev->dev));
+ ccp->debugfs = debugfs_create_dir(name, NULL);
+
+ ret = get_fw_version(ccp);
+ if (!ret)
+ debugfs_create_file("firmware_version", 0444,
+ ccp->debugfs, ccp, &firmware_fops);
+
+ ret = get_bl_version(ccp);
+ if (!ret)
+ debugfs_create_file("bootloader_version", 0444,
+ ccp->debugfs, ccp, &bootloader_fops);
+}
+
static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
struct ccp_device *ccp;
@@ -542,6 +626,9 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
ret = get_fan_cnct(ccp);
if (ret)
goto out_hw_close;
+
+ ccp_debugfs_init(ccp);
+
ccp->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsaircpro",
ccp, &ccp_chip_info, NULL);
if (IS_ERR(ccp->hwmon_dev)) {
@@ -562,6 +649,7 @@ static void ccp_remove(struct hid_device *hdev)
{
struct ccp_device *ccp = hid_get_drvdata(hdev);
+ debugfs_remove_recursive(ccp->debugfs);
hwmon_device_unregister(ccp->hwmon_dev);
hid_hw_close(hdev);
hid_hw_stop(hdev);
@@ -582,6 +670,7 @@ static struct hid_driver ccp_driver = {
};
MODULE_DEVICE_TABLE(hid, ccp_devices);
+MODULE_DESCRIPTION("Corsair Commander Pro controller driver");
MODULE_LICENSE("GPL");
static int __init ccp_init(void)
diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
index 2c7c92272fe3..f8f22b8a67cd 100644
--- a/drivers/hwmon/corsair-psu.c
+++ b/drivers/hwmon/corsair-psu.c
@@ -875,15 +875,16 @@ static const struct hid_device_id corsairpsu_idtable[] = {
{ HID_USB_DEVICE(0x1b1c, 0x1c04) }, /* Corsair HX650i */
{ HID_USB_DEVICE(0x1b1c, 0x1c05) }, /* Corsair HX750i */
{ HID_USB_DEVICE(0x1b1c, 0x1c06) }, /* Corsair HX850i */
- { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Series 2022 */
- { HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i */
+ { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Legacy */
+ { HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i Legacy */
{ HID_USB_DEVICE(0x1b1c, 0x1c09) }, /* Corsair RM550i */
{ HID_USB_DEVICE(0x1b1c, 0x1c0a) }, /* Corsair RM650i */
{ HID_USB_DEVICE(0x1b1c, 0x1c0b) }, /* Corsair RM750i */
{ HID_USB_DEVICE(0x1b1c, 0x1c0c) }, /* Corsair RM850i */
{ HID_USB_DEVICE(0x1b1c, 0x1c0d) }, /* Corsair RM1000i */
{ HID_USB_DEVICE(0x1b1c, 0x1c1e) }, /* Corsair HX1000i Series 2023 */
- { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Series 2022 and 2023 */
+ { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Legacy and Series 2023 */
+ { HID_USB_DEVICE(0x1b1c, 0x1c23) }, /* Corsair HX1200i Series 2023 */
{ },
};
MODULE_DEVICE_TABLE(hid, corsairpsu_idtable);
diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c
new file mode 100644
index 000000000000..5514cf780b8b
--- /dev/null
+++ b/drivers/hwmon/cros_ec_hwmon.c
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * ChromeOS EC driver for hwmon
+ *
+ * Copyright (C) 2024 Thomas Weißschuh <[email protected]>
+ */
+
+#include <linux/device.h>
+#include <linux/hwmon.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/cros_ec_commands.h>
+#include <linux/platform_data/cros_ec_proto.h>
+#include <linux/types.h>
+#include <linux/units.h>
+
+#define DRV_NAME "cros-ec-hwmon"
+
+struct cros_ec_hwmon_priv {
+ struct cros_ec_device *cros_ec;
+ const char *temp_sensor_names[EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES];
+ u8 usable_fans;
+};
+
+static int cros_ec_hwmon_read_fan_speed(struct cros_ec_device *cros_ec, u8 index, u16 *speed)
+{
+ int ret;
+ __le16 __speed;
+
+ ret = cros_ec_cmd_readmem(cros_ec, EC_MEMMAP_FAN + index * 2, 2, &__speed);
+ if (ret < 0)
+ return ret;
+
+ *speed = le16_to_cpu(__speed);
+ return 0;
+}
+
+static int cros_ec_hwmon_read_temp(struct cros_ec_device *cros_ec, u8 index, u8 *temp)
+{
+ unsigned int offset;
+ int ret;
+
+ if (index < EC_TEMP_SENSOR_ENTRIES)
+ offset = EC_MEMMAP_TEMP_SENSOR + index;
+ else
+ offset = EC_MEMMAP_TEMP_SENSOR_B + index - EC_TEMP_SENSOR_ENTRIES;
+
+ ret = cros_ec_cmd_readmem(cros_ec, offset, 1, temp);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static bool cros_ec_hwmon_is_error_fan(u16 speed)
+{
+ return speed == EC_FAN_SPEED_NOT_PRESENT || speed == EC_FAN_SPEED_STALLED;
+}
+
+static bool cros_ec_hwmon_is_error_temp(u8 temp)
+{
+ return temp == EC_TEMP_SENSOR_NOT_PRESENT ||
+ temp == EC_TEMP_SENSOR_ERROR ||
+ temp == EC_TEMP_SENSOR_NOT_POWERED ||
+ temp == EC_TEMP_SENSOR_NOT_CALIBRATED;
+}
+
+static long cros_ec_hwmon_temp_to_millicelsius(u8 temp)
+{
+ return kelvin_to_millicelsius((((long)temp) + EC_TEMP_SENSOR_OFFSET));
+}
+
+static int cros_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct cros_ec_hwmon_priv *priv = dev_get_drvdata(dev);
+ int ret = -EOPNOTSUPP;
+ u16 speed;
+ u8 temp;
+
+ if (type == hwmon_fan) {
+ if (attr == hwmon_fan_input) {
+ ret = cros_ec_hwmon_read_fan_speed(priv->cros_ec, channel, &speed);
+ if (ret == 0) {
+ if (cros_ec_hwmon_is_error_fan(speed))
+ ret = -ENODATA;
+ else
+ *val = speed;
+ }
+ } else if (attr == hwmon_fan_fault) {
+ ret = cros_ec_hwmon_read_fan_speed(priv->cros_ec, channel, &speed);
+ if (ret == 0)
+ *val = cros_ec_hwmon_is_error_fan(speed);
+ }
+ } else if (type == hwmon_temp) {
+ if (attr == hwmon_temp_input) {
+ ret = cros_ec_hwmon_read_temp(priv->cros_ec, channel, &temp);
+ if (ret == 0) {
+ if (cros_ec_hwmon_is_error_temp(temp))
+ ret = -ENODATA;
+ else
+ *val = cros_ec_hwmon_temp_to_millicelsius(temp);
+ }
+ } else if (attr == hwmon_temp_fault) {
+ ret = cros_ec_hwmon_read_temp(priv->cros_ec, channel, &temp);
+ if (ret == 0)
+ *val = cros_ec_hwmon_is_error_temp(temp);
+ }
+ }
+
+ return ret;
+}
+
+static int cros_ec_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, const char **str)
+{
+ struct cros_ec_hwmon_priv *priv = dev_get_drvdata(dev);
+
+ if (type == hwmon_temp && attr == hwmon_temp_label) {
+ *str = priv->temp_sensor_names[channel];
+ return 0;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ const struct cros_ec_hwmon_priv *priv = data;
+
+ if (type == hwmon_fan) {
+ if (priv->usable_fans & BIT(channel))
+ return 0444;
+ } else if (type == hwmon_temp) {
+ if (priv->temp_sensor_names[channel])
+ return 0444;
+ }
+
+ return 0;
+}
+
+static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(fan,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT),
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL),
+ NULL
+};
+
+static const struct hwmon_ops cros_ec_hwmon_ops = {
+ .read = cros_ec_hwmon_read,
+ .read_string = cros_ec_hwmon_read_string,
+ .is_visible = cros_ec_hwmon_is_visible,
+};
+
+static const struct hwmon_chip_info cros_ec_hwmon_chip_info = {
+ .ops = &cros_ec_hwmon_ops,
+ .info = cros_ec_hwmon_info,
+};
+
+static void cros_ec_hwmon_probe_temp_sensors(struct device *dev, struct cros_ec_hwmon_priv *priv,
+ u8 thermal_version)
+{
+ struct ec_params_temp_sensor_get_info req = {};
+ struct ec_response_temp_sensor_get_info resp;
+ size_t candidates, i, sensor_name_size;
+ int ret;
+ u8 temp;
+
+ if (thermal_version < 2)
+ candidates = EC_TEMP_SENSOR_ENTRIES;
+ else
+ candidates = ARRAY_SIZE(priv->temp_sensor_names);
+
+ for (i = 0; i < candidates; i++) {
+ if (cros_ec_hwmon_read_temp(priv->cros_ec, i, &temp) < 0)
+ continue;
+
+ if (temp == EC_TEMP_SENSOR_NOT_PRESENT)
+ continue;
+
+ req.id = i;
+ ret = cros_ec_cmd(priv->cros_ec, 0, EC_CMD_TEMP_SENSOR_GET_INFO,
+ &req, sizeof(req), &resp, sizeof(resp));
+ if (ret < 0)
+ continue;
+
+ sensor_name_size = strnlen(resp.sensor_name, sizeof(resp.sensor_name));
+ priv->temp_sensor_names[i] = devm_kasprintf(dev, GFP_KERNEL, "%.*s",
+ (int)sensor_name_size,
+ resp.sensor_name);
+ }
+}
+
+static void cros_ec_hwmon_probe_fans(struct cros_ec_hwmon_priv *priv)
+{
+ u16 speed;
+ size_t i;
+ int ret;
+
+ for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++) {
+ ret = cros_ec_hwmon_read_fan_speed(priv->cros_ec, i, &speed);
+ if (ret == 0 && speed != EC_FAN_SPEED_NOT_PRESENT)
+ priv->usable_fans |= BIT(i);
+ }
+}
+
+static int cros_ec_hwmon_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
+ struct cros_ec_device *cros_ec = ec_dev->ec_dev;
+ struct cros_ec_hwmon_priv *priv;
+ struct device *hwmon_dev;
+ u8 thermal_version;
+ int ret;
+
+ ret = cros_ec_cmd_readmem(cros_ec, EC_MEMMAP_THERMAL_VERSION, 1, &thermal_version);
+ if (ret < 0)
+ return ret;
+
+ /* Covers both fan and temp sensors */
+ if (thermal_version == 0)
+ return -ENODEV;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->cros_ec = cros_ec;
+
+ cros_ec_hwmon_probe_temp_sensors(dev, priv, thermal_version);
+ cros_ec_hwmon_probe_fans(priv);
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, "cros_ec", priv,
+ &cros_ec_hwmon_chip_info, NULL);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct platform_device_id cros_ec_hwmon_id[] = {
+ { DRV_NAME, 0 },
+ {}
+};
+
+static struct platform_driver cros_ec_hwmon_driver = {
+ .driver.name = DRV_NAME,
+ .probe = cros_ec_hwmon_probe,
+ .id_table = cros_ec_hwmon_id,
+};
+module_platform_driver(cros_ec_hwmon_driver);
+
+MODULE_DEVICE_TABLE(platform, cros_ec_hwmon_id);
+MODULE_DESCRIPTION("ChromeOS EC Hardware Monitoring Driver");
+MODULE_AUTHOR("Thomas Weißschuh <[email protected]");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index 942526bd4775..0362a13f6525 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -1264,6 +1264,13 @@ static const struct dmi_system_id i8k_dmi_table[] __initconst = {
},
},
{
+ .ident = "Dell OptiPlex 7060",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "OptiPlex 7060"),
+ },
+ },
+ {
.ident = "Dell Precision",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index 3dcef221041d..1a9b28dc91e6 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -2461,8 +2461,6 @@ static int dme1737_i2c_detect(struct i2c_client *client,
return 0;
}
-static const struct i2c_device_id dme1737_id[];
-
static int dme1737_i2c_probe(struct i2c_client *client)
{
struct dme1737_data *data;
@@ -2474,7 +2472,7 @@ static int dme1737_i2c_probe(struct i2c_client *client)
return -ENOMEM;
i2c_set_clientdata(client, data);
- data->type = i2c_match_id(dme1737_id, client)->driver_data;
+ data->type = (uintptr_t)i2c_get_match_data(client);
data->client = client;
data->name = client->name;
mutex_init(&data->update_lock);
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index bffbc8040171..42ec34cb8a5f 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -342,8 +342,6 @@ static const struct attribute_group ds1621_group = {
};
__ATTRIBUTE_GROUPS(ds1621);
-static const struct i2c_device_id ds1621_id[];
-
static int ds1621_probe(struct i2c_client *client)
{
struct ds1621_data *data;
@@ -356,7 +354,7 @@ static int ds1621_probe(struct i2c_client *client)
mutex_init(&data->update_lock);
- data->kind = i2c_match_id(ds1621_id, client)->driver_data;
+ data->kind = (uintptr_t)i2c_get_match_data(client);
data->client = client;
/* Initialize the DS1621 chip */
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index 8c572bb64f5d..7e867f132420 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -111,31 +111,6 @@ struct f75375_data {
s8 temp_max_hyst[2];
};
-static int f75375_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int f75375_probe(struct i2c_client *client);
-static void f75375_remove(struct i2c_client *client);
-
-static const struct i2c_device_id f75375_id[] = {
- { "f75373", f75373 },
- { "f75375", f75375 },
- { "f75387", f75387 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, f75375_id);
-
-static struct i2c_driver f75375_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "f75375",
- },
- .probe = f75375_probe,
- .remove = f75375_remove,
- .id_table = f75375_id,
- .detect = f75375_detect,
- .address_list = normal_i2c,
-};
-
static inline int f75375_read8(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
@@ -830,7 +805,7 @@ static int f75375_probe(struct i2c_client *client)
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
- data->kind = i2c_match_id(f75375_id, client)->driver_data;
+ data->kind = (uintptr_t)i2c_get_match_data(client);
err = sysfs_create_group(&client->dev.kobj, &f75375_group);
if (err)
@@ -901,6 +876,25 @@ static int f75375_detect(struct i2c_client *client,
return 0;
}
+static const struct i2c_device_id f75375_id[] = {
+ { "f75373", f75373 },
+ { "f75375", f75375 },
+ { "f75387", f75387 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, f75375_id);
+
+static struct i2c_driver f75375_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "f75375",
+ },
+ .probe = f75375_probe,
+ .remove = f75375_remove,
+ .id_table = f75375_id,
+ .detect = f75375_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(f75375_driver);
MODULE_AUTHOR("Riku Voipio");
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index b30512a705a7..1811f84d835e 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -1087,7 +1087,7 @@ static int fschmd_probe(struct i2c_client *client)
"Heracles", "Heimdall", "Hades", "Syleus" };
static const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
int i, err;
- enum chips kind = i2c_match_id(fschmd_id, client)->driver_data;
+ enum chips kind = (uintptr_t)i2c_get_match_data(client);
data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL);
if (!data)
diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index af1228708e25..4fa3aa1271da 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -44,6 +44,7 @@
#define DRVNAME "g762"
static const struct i2c_device_id g762_id[] = {
+ { "g761" },
{ "g762" },
{ "g763" },
{ }
@@ -69,6 +70,7 @@ enum g762_regs {
#define G762_REG_FAN_CMD1_PWM_POLARITY 0x02 /* PWM polarity */
#define G762_REG_FAN_CMD1_PULSE_PER_REV 0x01 /* pulse per fan revolution */
+#define G761_REG_FAN_CMD2_FAN_CLOCK 0x20 /* choose internal clock*/
#define G762_REG_FAN_CMD2_GEAR_MODE_1 0x08 /* fan gear mode */
#define G762_REG_FAN_CMD2_GEAR_MODE_0 0x04
#define G762_REG_FAN_CMD2_FAN_STARTV_1 0x02 /* fan startup voltage */
@@ -115,6 +117,7 @@ enum g762_regs {
struct g762_data {
struct i2c_client *client;
+ bool internal_clock;
struct clk *clk;
/* update mutex */
@@ -566,6 +569,7 @@ static int do_set_fan_startv(struct device *dev, unsigned long val)
#ifdef CONFIG_OF
static const struct of_device_id g762_dt_match[] = {
+ { .compatible = "gmt,g761" },
{ .compatible = "gmt,g762" },
{ .compatible = "gmt,g763" },
{ },
@@ -597,6 +601,21 @@ static int g762_of_clock_enable(struct i2c_client *client)
if (!client->dev.of_node)
return 0;
+ data = i2c_get_clientdata(client);
+
+ /*
+ * Skip CLK detection and handling if we use internal clock.
+ * This is only valid for g761.
+ */
+ data->internal_clock = of_device_is_compatible(client->dev.of_node,
+ "gmt,g761") &&
+ !of_property_present(client->dev.of_node,
+ "clocks");
+ if (data->internal_clock) {
+ do_set_clk_freq(&client->dev, 32768);
+ return 0;
+ }
+
clk = of_clk_get(client->dev.of_node, 0);
if (IS_ERR(clk)) {
dev_err(&client->dev, "failed to get clock\n");
@@ -616,7 +635,6 @@ static int g762_of_clock_enable(struct i2c_client *client)
goto clk_unprep;
}
- data = i2c_get_clientdata(client);
data->clk = clk;
ret = devm_add_action(&client->dev, g762_of_clock_disable, data);
@@ -1025,16 +1043,26 @@ ATTRIBUTE_GROUPS(g762);
static inline int g762_fan_init(struct device *dev)
{
struct g762_data *data = g762_update_client(dev);
+ int ret;
if (IS_ERR(data))
return PTR_ERR(data);
+ /* internal_clock can only be set with compatible g761 */
+ if (data->internal_clock)
+ data->fan_cmd2 |= G761_REG_FAN_CMD2_FAN_CLOCK;
+
data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_FAIL;
data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_OOC;
data->valid = false;
- return i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
- data->fan_cmd1);
+ ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
+ data->fan_cmd1);
+ if (ret)
+ return ret;
+
+ return i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD2,
+ data->fan_cmd2);
}
static int g762_probe(struct i2c_client *client)
@@ -1056,15 +1084,16 @@ static int g762_probe(struct i2c_client *client)
data->client = client;
mutex_init(&data->update_lock);
- /* Enable fan failure detection and fan out of control protection */
- ret = g762_fan_init(dev);
+ /* Get configuration via DT ... */
+ ret = g762_of_clock_enable(client);
if (ret)
return ret;
- /* Get configuration via DT ... */
- ret = g762_of_clock_enable(client);
+ /* Enable fan failure detection and fan out of control protection */
+ ret = g762_fan_init(dev);
if (ret)
return ret;
+
ret = g762_of_prop_import(client);
if (ret)
return ret;
diff --git a/drivers/hwmon/gsc-hwmon.c b/drivers/hwmon/gsc-hwmon.c
index 1501ceb551e7..cb2f01dc4326 100644
--- a/drivers/hwmon/gsc-hwmon.c
+++ b/drivers/hwmon/gsc-hwmon.c
@@ -39,7 +39,7 @@ struct gsc_hwmon_data {
struct hwmon_chip_info chip;
};
-static struct regmap_bus gsc_hwmon_regmap_bus = {
+static const struct regmap_bus gsc_hwmon_regmap_bus = {
.reg_read = gsc_read,
.reg_write = gsc_write,
};
@@ -249,7 +249,6 @@ gsc_hwmon_get_devtree_pdata(struct device *dev)
{
struct gsc_hwmon_platform_data *pdata;
struct gsc_hwmon_channel *ch;
- struct fwnode_handle *child;
struct device_node *fan;
int nchannels;
@@ -276,25 +275,21 @@ gsc_hwmon_get_devtree_pdata(struct device *dev)
ch = pdata->channels;
/* allocate structures for channels and count instances of each type */
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
if (fwnode_property_read_string(child, "label", &ch->name)) {
dev_err(dev, "channel without label\n");
- fwnode_handle_put(child);
return ERR_PTR(-EINVAL);
}
if (fwnode_property_read_u32(child, "reg", &ch->reg)) {
dev_err(dev, "channel without reg\n");
- fwnode_handle_put(child);
return ERR_PTR(-EINVAL);
}
if (fwnode_property_read_u32(child, "gw,mode", &ch->mode)) {
dev_err(dev, "channel without mode\n");
- fwnode_handle_put(child);
return ERR_PTR(-EINVAL);
}
if (ch->mode > mode_max) {
dev_err(dev, "invalid channel mode\n");
- fwnode_handle_put(child);
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 3b259c425ab7..a362080d41fa 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/gfp.h>
#include <linux/hwmon.h>
+#include <linux/i2c.h>
#include <linux/idr.h>
#include <linux/kstrtox.h>
#include <linux/list.h>
@@ -136,7 +137,7 @@ static void hwmon_dev_release(struct device *dev)
kfree(hwdev);
}
-static struct class hwmon_class = {
+static const struct class hwmon_class = {
.name = "hwmon",
.dev_groups = hwmon_dev_attr_groups,
.dev_release = hwmon_dev_release,
@@ -309,6 +310,114 @@ static int hwmon_attr_base(enum hwmon_sensor_types type)
return 1;
}
+#if IS_REACHABLE(CONFIG_I2C)
+
+/*
+ * PEC support
+ *
+ * The 'pec' attribute is attached to I2C client devices. It is only provided
+ * if the i2c controller supports PEC.
+ *
+ * The mutex ensures that PEC configuration between i2c device and the hardware
+ * is consistent. Use a single mutex because attribute writes are supposed to be
+ * rare, and maintaining a separate mutex for each hardware monitoring device
+ * would add substantial complexity to the driver for little if any gain.
+ *
+ * The hardware monitoring device is identified as child of the i2c client
+ * device. This assumes that only a single hardware monitoring device is
+ * attached to an i2c client device.
+ */
+
+static DEFINE_MUTEX(hwmon_pec_mutex);
+
+static int hwmon_match_device(struct device *dev, void *data)
+{
+ return dev->class == &hwmon_class;
+}
+
+static ssize_t pec_show(struct device *dev, struct device_attribute *dummy,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ return sysfs_emit(buf, "%d\n", !!(client->flags & I2C_CLIENT_PEC));
+}
+
+static ssize_t pec_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct hwmon_device *hwdev;
+ struct device *hdev;
+ bool val;
+ int err;
+
+ err = kstrtobool(buf, &val);
+ if (err < 0)
+ return err;
+
+ hdev = device_find_child(dev, NULL, hwmon_match_device);
+ if (!hdev)
+ return -ENODEV;
+
+ mutex_lock(&hwmon_pec_mutex);
+
+ /*
+ * If there is no write function, we assume that chip specific
+ * handling is not required.
+ */
+ hwdev = to_hwmon_device(hdev);
+ if (hwdev->chip->ops->write) {
+ err = hwdev->chip->ops->write(hdev, hwmon_chip, hwmon_chip_pec, 0, val);
+ if (err && err != -EOPNOTSUPP)
+ goto unlock;
+ }
+
+ if (!val)
+ client->flags &= ~I2C_CLIENT_PEC;
+ else
+ client->flags |= I2C_CLIENT_PEC;
+
+ err = count;
+unlock:
+ mutex_unlock(&hwmon_pec_mutex);
+ put_device(hdev);
+
+ return err;
+}
+
+static DEVICE_ATTR_RW(pec);
+
+static void hwmon_remove_pec(void *dev)
+{
+ device_remove_file(dev, &dev_attr_pec);
+}
+
+static int hwmon_pec_register(struct device *hdev)
+{
+ struct i2c_client *client = i2c_verify_client(hdev->parent);
+ int err;
+
+ if (!client)
+ return -EINVAL;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_PEC))
+ return 0;
+
+ err = device_create_file(&client->dev, &dev_attr_pec);
+ if (err)
+ return err;
+
+ return devm_add_action_or_reset(hdev, hwmon_remove_pec, &client->dev);
+}
+
+#else /* CONFIG_I2C */
+static int hwmon_pec_register(struct device *hdev)
+{
+ return -EINVAL;
+}
+#endif /* CONFIG_I2C */
+
/* sysfs attribute management */
static ssize_t hwmon_attr_show(struct device *dev,
@@ -397,10 +506,6 @@ static struct attribute *hwmon_genattr(const void *drvdata,
const char *name;
bool is_string = is_string_attr(type, attr);
- /* The attribute is invisible if there is no template string */
- if (!template)
- return ERR_PTR(-ENOENT);
-
mode = ops->is_visible(drvdata, type, attr, index);
if (!mode)
return ERR_PTR(-ENOENT);
@@ -712,8 +817,8 @@ static int hwmon_genattrs(const void *drvdata,
attr = __ffs(attr_mask);
attr_mask &= ~BIT(attr);
- if (attr >= template_size)
- return -EINVAL;
+ if (attr >= template_size || !templates[attr])
+ continue; /* attribute is invisible */
a = hwmon_genattr(drvdata, info->type, attr, i,
templates[attr], ops);
if (IS_ERR(a)) {
@@ -849,16 +954,26 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
INIT_LIST_HEAD(&hwdev->tzdata);
if (hdev->of_node && chip && chip->ops->read &&
- chip->info[0]->type == hwmon_chip &&
- (chip->info[0]->config[0] & HWMON_C_REGISTER_TZ)) {
- err = hwmon_thermal_register_sensors(hdev);
- if (err) {
- device_unregister(hdev);
- /*
- * Don't worry about hwdev; hwmon_dev_release(), called
- * from device_unregister(), will free it.
- */
- goto ida_remove;
+ chip->info[0]->type == hwmon_chip) {
+ u32 config = chip->info[0]->config[0];
+
+ if (config & HWMON_C_REGISTER_TZ) {
+ err = hwmon_thermal_register_sensors(hdev);
+ if (err) {
+ device_unregister(hdev);
+ /*
+ * Don't worry about hwdev; hwmon_dev_release(),
+ * called from device_unregister(), will free it.
+ */
+ goto ida_remove;
+ }
+ }
+ if (config & HWMON_C_PEC) {
+ err = hwmon_pec_register(hdev);
+ if (err) {
+ device_unregister(hdev);
+ goto ida_remove;
+ }
}
}
diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c
index 4c8a80847891..fab32e1e15f2 100644
--- a/drivers/hwmon/iio_hwmon.c
+++ b/drivers/hwmon/iio_hwmon.c
@@ -49,16 +49,17 @@ static ssize_t iio_hwmon_read_val(struct device *dev,
struct iio_channel *chan = &state->channels[sattr->index];
enum iio_chan_type type;
- ret = iio_read_channel_processed(chan, &result);
- if (ret < 0)
- return ret;
-
ret = iio_get_channel_type(chan, &type);
if (ret < 0)
return ret;
if (type == IIO_POWER)
- result *= 1000; /* mili-Watts to micro-Watts conversion */
+ /* mili-Watts to micro-Watts conversion */
+ ret = iio_read_channel_processed_scale(chan, &result, 1000);
+ else
+ ret = iio_read_channel_processed(chan, &result);
+ if (ret < 0)
+ return ret;
return sprintf(buf, "%d\n", result);
}
diff --git a/drivers/hwmon/ina238.c b/drivers/hwmon/ina238.c
index 855626f1bc01..2d9f12f68d50 100644
--- a/drivers/hwmon/ina238.c
+++ b/drivers/hwmon/ina238.c
@@ -96,7 +96,7 @@
#define INA238_BUS_VOLTAGE_LSB 3125 /* 3.125 mV/lsb */
#define INA238_DIE_TEMP_LSB 125 /* 125 mC/lsb */
-static struct regmap_config ina238_regmap_config = {
+static const struct regmap_config ina238_regmap_config = {
.max_register = INA238_REGISTERS,
.reg_bits = 8,
.val_bits = 16,
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index d8415d1f21fc..9ab4205622e2 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -73,6 +73,11 @@
#define INA226_READ_AVG(reg) (((reg) & INA226_AVG_RD_MASK) >> 9)
#define INA226_SHIFT_AVG(val) ((val) << 9)
+#define INA226_ALERT_POLARITY_MASK 0x0002
+#define INA226_SHIFT_ALERT_POLARITY(val) ((val) << 1)
+#define INA226_ALERT_POL_LOW 0
+#define INA226_ALERT_POL_HIGH 1
+
/* bit number of alert functions in Mask/Enable Register */
#define INA226_SHUNT_OVER_VOLTAGE_BIT 15
#define INA226_SHUNT_UNDER_VOLTAGE_BIT 14
@@ -178,6 +183,14 @@ static u16 ina226_interval_to_reg(int interval)
return INA226_SHIFT_AVG(avg_bits);
}
+static int ina2xx_set_alert_polarity(struct ina2xx_data *data,
+ unsigned long val)
+{
+ return regmap_update_bits(data->regmap, INA226_MASK_ENABLE,
+ INA226_ALERT_POLARITY_MASK,
+ INA226_SHIFT_ALERT_POLARITY(val));
+}
+
/*
* Calibration register is set to the best value, which eliminates
* truncation errors on calculating current register in hardware.
@@ -612,8 +625,6 @@ static const struct attribute_group ina226_group = {
.attrs = ina226_attrs,
};
-static const struct i2c_device_id ina2xx_id[];
-
static int ina2xx_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -623,10 +634,7 @@ static int ina2xx_probe(struct i2c_client *client)
int ret, group = 0;
enum ina2xx_ids chip;
- if (client->dev.of_node)
- chip = (uintptr_t)of_device_get_match_data(&client->dev);
- else
- chip = i2c_match_id(ina2xx_id, client)->driver_data;
+ chip = (uintptr_t)i2c_get_match_data(client);
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
@@ -659,6 +667,25 @@ static int ina2xx_probe(struct i2c_client *client)
if (ret)
return dev_err_probe(dev, ret, "failed to enable vs regulator\n");
+ if (chip == ina226) {
+ if (of_property_read_bool(dev->of_node, "ti,alert-polarity-active-high")) {
+ ret = ina2xx_set_alert_polarity(data,
+ INA226_ALERT_POL_HIGH);
+ if (ret < 0) {
+ return dev_err_probe(dev, ret,
+ "failed to set alert polarity active high\n");
+ }
+ } else {
+ /* Set default value i.e active low */
+ ret = ina2xx_set_alert_polarity(data,
+ INA226_ALERT_POL_LOW);
+ if (ret < 0) {
+ return dev_err_probe(dev, ret,
+ "failed to set alert polarity active low\n");
+ }
+ }
+ }
+
ret = ina2xx_init(data);
if (ret < 0) {
dev_err(dev, "error configuring the device: %d\n", ret);
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c
index 7092f8f025b8..a260cff750a5 100644
--- a/drivers/hwmon/jc42.c
+++ b/drivers/hwmon/jc42.c
@@ -79,20 +79,9 @@ static const unsigned short normal_i2c[] = {
#define AT30TS00_DEVID 0x8201
#define AT30TS00_DEVID_MASK 0xffff
-#define AT30TSE004_DEVID 0x2200
-#define AT30TSE004_DEVID_MASK 0xffff
-
-/* Giantec */
-#define GT30TS00_DEVID 0x2200
-#define GT30TS00_DEVID_MASK 0xff00
-
#define GT34TS02_DEVID 0x3300
#define GT34TS02_DEVID_MASK 0xff00
-/* IDT */
-#define TSE2004_DEVID 0x2200
-#define TSE2004_DEVID_MASK 0xff00
-
#define TS3000_DEVID 0x2900 /* Also matches TSE2002 */
#define TS3000_DEVID_MASK 0xff00
@@ -116,9 +105,6 @@ static const unsigned short normal_i2c[] = {
#define MCP98243_DEVID 0x2100
#define MCP98243_DEVID_MASK 0xfffc
-#define MCP98244_DEVID 0x2200
-#define MCP98244_DEVID_MASK 0xfffc
-
#define MCP9843_DEVID 0x0000 /* Also matches mcp9805 */
#define MCP9843_DEVID_MASK 0xfffe
@@ -136,12 +122,6 @@ static const unsigned short normal_i2c[] = {
#define CAT34TS02C_DEVID 0x0a00
#define CAT34TS02C_DEVID_MASK 0xfff0
-#define CAT34TS04_DEVID 0x2200
-#define CAT34TS04_DEVID_MASK 0xfff0
-
-#define N34TS04_DEVID 0x2230
-#define N34TS04_DEVID_MASK 0xfff0
-
/* ST Microelectronics */
#define STTS424_DEVID 0x0101
#define STTS424_DEVID_MASK 0xffff
@@ -152,15 +132,12 @@ static const unsigned short normal_i2c[] = {
#define STTS2002_DEVID 0x0300
#define STTS2002_DEVID_MASK 0xffff
-#define STTS2004_DEVID 0x2201
-#define STTS2004_DEVID_MASK 0xffff
-
#define STTS3000_DEVID 0x0200
#define STTS3000_DEVID_MASK 0xffff
-/* Seiko Instruments */
-#define S34TS04A_DEVID 0x2221
-#define S34TS04A_DEVID_MASK 0xffff
+/* TSE2004 compliant sensors */
+#define TSE2004_DEVID 0x2200
+#define TSE2004_DEVID_MASK 0xff00
static u16 jc42_hysteresis[] = { 0, 1500, 3000, 6000 };
@@ -173,8 +150,8 @@ struct jc42_chips {
static struct jc42_chips jc42_chips[] = {
{ ADT_MANID, ADT7408_DEVID, ADT7408_DEVID_MASK },
{ ATMEL_MANID, AT30TS00_DEVID, AT30TS00_DEVID_MASK },
- { ATMEL_MANID2, AT30TSE004_DEVID, AT30TSE004_DEVID_MASK },
- { GT_MANID, GT30TS00_DEVID, GT30TS00_DEVID_MASK },
+ { ATMEL_MANID2, TSE2004_DEVID, TSE2004_DEVID_MASK },
+ { GT_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },
{ GT_MANID2, GT34TS02_DEVID, GT34TS02_DEVID_MASK },
{ IDT_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },
{ IDT_MANID, TS3000_DEVID, TS3000_DEVID_MASK },
@@ -184,19 +161,19 @@ static struct jc42_chips jc42_chips[] = {
{ MCP_MANID, MCP9808_DEVID, MCP9808_DEVID_MASK },
{ MCP_MANID, MCP98242_DEVID, MCP98242_DEVID_MASK },
{ MCP_MANID, MCP98243_DEVID, MCP98243_DEVID_MASK },
- { MCP_MANID, MCP98244_DEVID, MCP98244_DEVID_MASK },
+ { MCP_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },
{ MCP_MANID, MCP9843_DEVID, MCP9843_DEVID_MASK },
{ NXP_MANID, SE97_DEVID, SE97_DEVID_MASK },
{ ONS_MANID, CAT6095_DEVID, CAT6095_DEVID_MASK },
{ ONS_MANID, CAT34TS02C_DEVID, CAT34TS02C_DEVID_MASK },
- { ONS_MANID, CAT34TS04_DEVID, CAT34TS04_DEVID_MASK },
- { ONS_MANID, N34TS04_DEVID, N34TS04_DEVID_MASK },
+ { ONS_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },
+ { ONS_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },
{ NXP_MANID, SE98_DEVID, SE98_DEVID_MASK },
- { SI_MANID, S34TS04A_DEVID, S34TS04A_DEVID_MASK },
+ { SI_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },
{ STM_MANID, STTS424_DEVID, STTS424_DEVID_MASK },
{ STM_MANID, STTS424E_DEVID, STTS424E_DEVID_MASK },
{ STM_MANID, STTS2002_DEVID, STTS2002_DEVID_MASK },
- { STM_MANID, STTS2004_DEVID, STTS2004_DEVID_MASK },
+ { STM_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },
{ STM_MANID, STTS3000_DEVID, STTS3000_DEVID_MASK },
};
@@ -436,7 +413,11 @@ static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info)
if (cap < 0 || config < 0 || manid < 0 || devid < 0)
return -ENODEV;
- if ((cap & 0xff00) || (config & 0xf800))
+ if ((cap & 0xff00) || (config & 0xf820))
+ return -ENODEV;
+
+ if ((devid & TSE2004_DEVID_MASK) == TSE2004_DEVID &&
+ (cap & 0x00e7) != 0x00e7)
return -ENODEV;
for (i = 0; i < ARRAY_SIZE(jc42_chips); i++) {
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index 8092312c0a87..543526bac042 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -101,7 +101,6 @@ struct k10temp_data {
#define TCCD_BIT(x) ((x) + 2)
#define HAVE_TEMP(d, channel) ((d)->show_temp & BIT(channel))
-#define HAVE_TDIE(d) HAVE_TEMP(d, TDIE_BIT)
struct tctl_offset {
u8 model;
@@ -153,8 +152,16 @@ static void read_tempreg_nb_f15(struct pci_dev *pdev, u32 *regval)
static void read_tempreg_nb_zen(struct pci_dev *pdev, u32 *regval)
{
- amd_smn_read(amd_pci_dev_to_node_id(pdev),
- ZEN_REPORTED_TEMP_CTRL_BASE, regval);
+ if (amd_smn_read(amd_pci_dev_to_node_id(pdev),
+ ZEN_REPORTED_TEMP_CTRL_BASE, regval))
+ *regval = 0;
+}
+
+static int read_ccd_temp_reg(struct k10temp_data *data, int ccd, u32 *regval)
+{
+ u16 node_id = amd_pci_dev_to_node_id(data->pdev);
+
+ return amd_smn_read(node_id, ZEN_CCD_TEMP(data->ccd_offset, ccd), regval);
}
static long get_raw_temp(struct k10temp_data *data)
@@ -205,6 +212,7 @@ static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
long *val)
{
struct k10temp_data *data = dev_get_drvdata(dev);
+ int ret = -EOPNOTSUPP;
u32 regval;
switch (attr) {
@@ -221,13 +229,15 @@ static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
*val = 0;
break;
case 2 ... 13: /* Tccd{1-12} */
- amd_smn_read(amd_pci_dev_to_node_id(data->pdev),
- ZEN_CCD_TEMP(data->ccd_offset, channel - 2),
- &regval);
+ ret = read_ccd_temp_reg(data, channel - 2, &regval);
+
+ if (ret)
+ return ret;
+
*val = (regval & ZEN_CCD_TEMP_MASK) * 125 - 49000;
break;
default:
- return -EOPNOTSUPP;
+ return ret;
}
break;
case hwmon_temp_max:
@@ -243,7 +253,7 @@ static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
- ((regval >> 24) & 0xf)) * 500 + 52000;
break;
default:
- return -EOPNOTSUPP;
+ return ret;
}
return 0;
}
@@ -259,11 +269,11 @@ static int k10temp_read(struct device *dev, enum hwmon_sensor_types type,
}
}
-static umode_t k10temp_is_visible(const void *_data,
+static umode_t k10temp_is_visible(const void *drvdata,
enum hwmon_sensor_types type,
u32 attr, int channel)
{
- const struct k10temp_data *data = _data;
+ const struct k10temp_data *data = drvdata;
struct pci_dev *pdev = data->pdev;
u32 reg;
@@ -374,15 +384,25 @@ static const struct hwmon_chip_info k10temp_chip_info = {
.info = k10temp_info,
};
-static void k10temp_get_ccd_support(struct pci_dev *pdev,
- struct k10temp_data *data, int limit)
+static void k10temp_get_ccd_support(struct k10temp_data *data, int limit)
{
u32 regval;
int i;
for (i = 0; i < limit; i++) {
- amd_smn_read(amd_pci_dev_to_node_id(pdev),
- ZEN_CCD_TEMP(data->ccd_offset, i), &regval);
+ /*
+ * Ignore inaccessible CCDs.
+ *
+ * Some systems will return a register value of 0, and the TEMP_VALID
+ * bit check below will naturally fail.
+ *
+ * Other systems will return a PCI_ERROR_RESPONSE (0xFFFFFFFF) for
+ * the register value. And this will incorrectly pass the TEMP_VALID
+ * bit check.
+ */
+ if (read_ccd_temp_reg(data, i, &regval))
+ continue;
+
if (regval & ZEN_CCD_TEMP_VALID)
data->show_temp |= BIT(TCCD_BIT(i));
}
@@ -434,18 +454,18 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
case 0x11: /* Zen APU */
case 0x18: /* Zen+ APU */
data->ccd_offset = 0x154;
- k10temp_get_ccd_support(pdev, data, 4);
+ k10temp_get_ccd_support(data, 4);
break;
case 0x31: /* Zen2 Threadripper */
case 0x60: /* Renoir */
case 0x68: /* Lucienne */
case 0x71: /* Zen2 */
data->ccd_offset = 0x154;
- k10temp_get_ccd_support(pdev, data, 8);
+ k10temp_get_ccd_support(data, 8);
break;
case 0xa0 ... 0xaf:
data->ccd_offset = 0x300;
- k10temp_get_ccd_support(pdev, data, 8);
+ k10temp_get_ccd_support(data, 8);
break;
}
} else if (boot_cpu_data.x86 == 0x19) {
@@ -459,21 +479,21 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
case 0x21: /* Zen3 Ryzen Desktop */
case 0x50 ... 0x5f: /* Green Sardine */
data->ccd_offset = 0x154;
- k10temp_get_ccd_support(pdev, data, 8);
+ k10temp_get_ccd_support(data, 8);
break;
case 0x40 ... 0x4f: /* Yellow Carp */
data->ccd_offset = 0x300;
- k10temp_get_ccd_support(pdev, data, 8);
+ k10temp_get_ccd_support(data, 8);
break;
case 0x60 ... 0x6f:
case 0x70 ... 0x7f:
data->ccd_offset = 0x308;
- k10temp_get_ccd_support(pdev, data, 8);
+ k10temp_get_ccd_support(data, 8);
break;
case 0x10 ... 0x1f:
case 0xa0 ... 0xaf:
data->ccd_offset = 0x300;
- k10temp_get_ccd_support(pdev, data, 12);
+ k10temp_get_ccd_support(data, 12);
break;
}
} else if (boot_cpu_data.x86 == 0x1a) {
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 0878a044dd8e..035176a98ce9 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -1104,10 +1104,7 @@ static int lm63_probe(struct i2c_client *client)
mutex_init(&data->update_lock);
/* Set the device type */
- if (client->dev.of_node)
- data->kind = (uintptr_t)of_device_get_match_data(&client->dev);
- else
- data->kind = i2c_match_id(lm63_id, client)->driver_data;
+ data->kind = (uintptr_t)i2c_get_match_data(client);
if (data->kind == lm64)
data->temp2_offset = 16000;
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 481e4e1f8f4f..0d5a250cb672 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -169,11 +169,7 @@ static int lm70_probe(struct spi_device *spi)
struct lm70 *p_lm70;
int chip;
- if (dev_fwnode(&spi->dev))
- chip = (int)(uintptr_t)device_get_match_data(&spi->dev);
- else
- chip = spi_get_device_id(spi)->driver_data;
-
+ chip = (kernel_ulong_t)spi_get_device_match_data(spi);
/* signaling is SPI_MODE_0 */
if ((spi->mode & SPI_MODE_X_MASK) != SPI_MODE_0)
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index e00750718536..2c2205aec7d4 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -625,20 +625,12 @@ static void lm75_remove(void *data)
i2c_smbus_write_byte_data(client, LM75_REG_CONF, lm75->orig_conf);
}
-static const struct i2c_device_id lm75_ids[];
-
static int lm75_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct device *hwmon_dev;
struct lm75_data *data;
int status, err;
- enum lm75_type kind;
-
- if (client->dev.of_node)
- kind = (uintptr_t)of_device_get_match_data(&client->dev);
- else
- kind = i2c_match_id(lm75_ids, client)->driver_data;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
@@ -649,7 +641,7 @@ static int lm75_probe(struct i2c_client *client)
return -ENOMEM;
data->client = client;
- data->kind = kind;
+ data->kind = (uintptr_t)i2c_get_match_data(client);
data->vs = devm_regulator_get(dev, "vs");
if (IS_ERR(data->vs))
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index b739c354311b..8b53bb312069 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -627,8 +627,6 @@ static int lm78_i2c_detect(struct i2c_client *client,
return -ENODEV;
}
-static const struct i2c_device_id lm78_i2c_id[];
-
static int lm78_i2c_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -640,7 +638,7 @@ static int lm78_i2c_probe(struct i2c_client *client)
return -ENOMEM;
data->client = client;
- data->type = i2c_match_id(lm78_i2c_id, client)->driver_data;
+ data->type = (uintptr_t)i2c_get_match_data(client);
/* Initialize the LM78 chip */
lm78_init_device(data);
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index b333c9bde4e6..f800fe2ef18b 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -417,13 +417,6 @@ static int lm83_detect(struct i2c_client *client,
return 0;
}
-static const struct i2c_device_id lm83_id[] = {
- { "lm83", lm83 },
- { "lm82", lm82 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, lm83_id);
-
static int lm83_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -438,7 +431,7 @@ static int lm83_probe(struct i2c_client *client)
if (IS_ERR(data->regmap))
return PTR_ERR(data->regmap);
- data->type = i2c_match_id(lm83_id, client)->driver_data;
+ data->type = (uintptr_t)i2c_get_match_data(client);
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
data, &lm83_chip_info, NULL);
@@ -449,6 +442,13 @@ static int lm83_probe(struct i2c_client *client)
* Driver data (common to all clients)
*/
+static const struct i2c_device_id lm83_id[] = {
+ { "lm83", lm83 },
+ { "lm82", lm82 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lm83_id);
+
static struct i2c_driver lm83_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 68c210002357..1c244ed75122 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -1544,8 +1544,6 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
return 0;
}
-static const struct i2c_device_id lm85_id[];
-
static int lm85_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -1558,10 +1556,7 @@ static int lm85_probe(struct i2c_client *client)
return -ENOMEM;
data->client = client;
- if (client->dev.of_node)
- data->type = (uintptr_t)of_device_get_match_data(&client->dev);
- else
- data->type = i2c_match_id(lm85_id, client)->driver_data;
+ data->type = (uintptr_t)i2c_get_match_data(client);
mutex_init(&data->update_lock);
/* Fill in the chip specific driver values */
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index e0d7454a301c..ca5c52b38c0f 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -1270,42 +1270,6 @@ static int lm90_update_device(struct device *dev)
return 0;
}
-/* pec used for devices with PEC support */
-static ssize_t pec_show(struct device *dev, struct device_attribute *dummy,
- char *buf)
-{
- struct i2c_client *client = to_i2c_client(dev);
-
- return sprintf(buf, "%d\n", !!(client->flags & I2C_CLIENT_PEC));
-}
-
-static ssize_t pec_store(struct device *dev, struct device_attribute *dummy,
- const char *buf, size_t count)
-{
- struct i2c_client *client = to_i2c_client(dev);
- long val;
- int err;
-
- err = kstrtol(buf, 10, &val);
- if (err < 0)
- return err;
-
- switch (val) {
- case 0:
- client->flags &= ~I2C_CLIENT_PEC;
- break;
- case 1:
- client->flags |= I2C_CLIENT_PEC;
- break;
- default:
- return -EINVAL;
- }
-
- return count;
-}
-
-static DEVICE_ATTR_RW(pec);
-
static int lm90_temp_get_resolution(struct lm90_data *data, int index)
{
switch (index) {
@@ -2659,11 +2623,6 @@ static irqreturn_t lm90_irq_thread(int irq, void *dev_id)
return IRQ_NONE;
}
-static void lm90_remove_pec(void *dev)
-{
- device_remove_file(dev, &dev_attr_pec);
-}
-
static int lm90_probe_channel_from_dt(struct i2c_client *client,
struct device_node *child,
struct lm90_data *data)
@@ -2764,10 +2723,7 @@ static int lm90_probe(struct i2c_client *client)
INIT_WORK(&data->report_work, lm90_report_alarms);
/* Set the device type */
- if (client->dev.of_node)
- data->kind = (uintptr_t)of_device_get_match_data(&client->dev);
- else
- data->kind = i2c_match_id(lm90_id, client)->driver_data;
+ data->kind = (uintptr_t)i2c_get_match_data(client);
/*
* Different devices have different alarm bits triggering the
@@ -2802,6 +2758,8 @@ static int lm90_probe(struct i2c_client *client)
data->chip_config[0] |= HWMON_C_UPDATE_INTERVAL;
if (data->flags & LM90_HAVE_FAULTQUEUE)
data->chip_config[0] |= HWMON_C_TEMP_SAMPLES;
+ if (data->flags & (LM90_HAVE_PEC | LM90_HAVE_PARTIAL_PEC))
+ data->chip_config[0] |= HWMON_C_PEC;
data->info[1] = &data->temp_info;
info = &data->temp_info;
@@ -2878,19 +2836,6 @@ static int lm90_probe(struct i2c_client *client)
return err;
}
- /*
- * The 'pec' attribute is attached to the i2c device and thus created
- * separately.
- */
- if (data->flags & (LM90_HAVE_PEC | LM90_HAVE_PARTIAL_PEC)) {
- err = device_create_file(dev, &dev_attr_pec);
- if (err)
- return err;
- err = devm_add_action_or_reset(dev, lm90_remove_pec, dev);
- if (err)
- return err;
- }
-
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
data, &data->chip,
NULL);
diff --git a/drivers/hwmon/lm95234.c b/drivers/hwmon/lm95234.c
index 67b9d7636ee4..9a7afdb49895 100644
--- a/drivers/hwmon/lm95234.c
+++ b/drivers/hwmon/lm95234.c
@@ -301,7 +301,8 @@ static ssize_t tcrit2_store(struct device *dev, struct device_attribute *attr,
if (ret < 0)
return ret;
- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, index ? 255 : 127);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, (index ? 255 : 127) * 1000),
+ 1000);
mutex_lock(&data->update_lock);
data->tcrit2[index] = val;
@@ -350,7 +351,7 @@ static ssize_t tcrit1_store(struct device *dev, struct device_attribute *attr,
if (ret < 0)
return ret;
- 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->tcrit1[index] = val;
@@ -391,7 +392,7 @@ static ssize_t tcrit1_hyst_store(struct device *dev,
if (ret < 0)
return ret;
- val = DIV_ROUND_CLOSEST(val, 1000);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, -255000, 255000), 1000);
val = clamp_val((int)data->tcrit1[index] - val, 0, 31);
mutex_lock(&data->update_lock);
@@ -431,7 +432,7 @@ static ssize_t offset_store(struct device *dev, struct device_attribute *attr,
return ret;
/* Accuracy is 1/2 degrees C */
- val = clamp_val(DIV_ROUND_CLOSEST(val, 500), -128, 127);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, -64000, 63500), 500);
mutex_lock(&data->update_lock);
data->toffset[index] = val;
@@ -677,10 +678,9 @@ static int lm95234_init_client(struct i2c_client *client)
return 0;
}
-static const struct i2c_device_id lm95234_id[];
-
static int lm95234_probe(struct i2c_client *client)
{
+ enum chips type = (uintptr_t)i2c_get_match_data(client);
struct device *dev = &client->dev;
struct lm95234_data *data;
struct device *hwmon_dev;
@@ -699,7 +699,7 @@ static int lm95234_probe(struct i2c_client *client)
return err;
data->groups[0] = &lm95234_common_group;
- if (i2c_match_id(lm95234_id, client)->driver_data == lm95234)
+ if (type == lm95234)
data->groups[1] = &lm95234_group;
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
diff --git a/drivers/hwmon/ltc2991.c b/drivers/hwmon/ltc2991.c
index 06750bb93c23..573cd8f5721b 100644
--- a/drivers/hwmon/ltc2991.c
+++ b/drivers/hwmon/ltc2991.c
@@ -225,8 +225,8 @@ static umode_t ltc2991_is_visible(const void *data,
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
- if (st->temp_en[channel] ||
- channel == LTC2991_T_INT_CH_NR)
+ if (channel == LTC2991_T_INT_CH_NR ||
+ st->temp_en[channel])
return 0444;
break;
}
@@ -284,7 +284,6 @@ static const struct regmap_config ltc2991_regmap_config = {
static int ltc2991_init(struct ltc2991_state *st, struct device *dev)
{
- struct fwnode_handle *child;
int ret;
u32 val, addr;
u8 v5_v8_reg_data = 0, v1_v4_reg_data = 0;
@@ -294,17 +293,13 @@ static int ltc2991_init(struct ltc2991_state *st, struct device *dev)
return dev_err_probe(dev, ret,
"failed to enable regulator\n");
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
ret = fwnode_property_read_u32(child, "reg", &addr);
- if (ret < 0) {
- fwnode_handle_put(child);
+ if (ret < 0)
return ret;
- }
- if (addr > 3) {
- fwnode_handle_put(child);
+ if (addr > 3)
return -EINVAL;
- }
ret = fwnode_property_read_u32(child,
"shunt-resistor-micro-ohms",
diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c
index aa38c45adc09..7ce9a89f93a0 100644
--- a/drivers/hwmon/max16065.c
+++ b/drivers/hwmon/max16065.c
@@ -493,8 +493,6 @@ static const struct attribute_group max16065_max_group = {
.is_visible = max16065_secondary_is_visible,
};
-static const struct i2c_device_id max16065_id[];
-
static int max16065_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
@@ -505,7 +503,7 @@ static int max16065_probe(struct i2c_client *client)
bool have_secondary; /* true if chip has secondary limits */
bool secondary_is_max = false; /* secondary limits reflect max */
int groups = 0;
- const struct i2c_device_id *id = i2c_match_id(max16065_id, client);
+ enum chips chip = (uintptr_t)i2c_get_match_data(client);
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_READ_WORD_DATA))
@@ -518,9 +516,9 @@ static int max16065_probe(struct i2c_client *client)
data->client = client;
mutex_init(&data->update_lock);
- data->num_adc = max16065_num_adc[id->driver_data];
- data->have_current = max16065_have_current[id->driver_data];
- have_secondary = max16065_have_secondary[id->driver_data];
+ data->num_adc = max16065_num_adc[chip];
+ data->have_current = max16065_have_current[chip];
+ have_secondary = max16065_have_secondary[chip];
if (have_secondary) {
val = i2c_smbus_read_byte_data(client, MAX16065_SW_ENABLE);
diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c
index c4a02edefbee..9fc583ebb11b 100644
--- a/drivers/hwmon/max1668.c
+++ b/drivers/hwmon/max1668.c
@@ -391,8 +391,6 @@ static int max1668_detect(struct i2c_client *client,
return 0;
}
-static const struct i2c_device_id max1668_id[];
-
static int max1668_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
@@ -408,7 +406,7 @@ static int max1668_probe(struct i2c_client *client)
return -ENOMEM;
data->client = client;
- data->type = i2c_match_id(max1668_id, client)->driver_data;
+ data->type = (uintptr_t)i2c_get_match_data(client);
mutex_init(&data->update_lock);
/* sysfs hooks */
diff --git a/drivers/hwmon/max31827.c b/drivers/hwmon/max31827.c
index f8a13b30f100..48e8f8ba4d05 100644
--- a/drivers/hwmon/max31827.c
+++ b/drivers/hwmon/max31827.c
@@ -24,6 +24,7 @@
#define MAX31827_CONFIGURATION_1SHOT_MASK BIT(0)
#define MAX31827_CONFIGURATION_CNV_RATE_MASK GENMASK(3, 1)
+#define MAX31827_CONFIGURATION_PEC_EN_MASK BIT(4)
#define MAX31827_CONFIGURATION_TIMEOUT_MASK BIT(5)
#define MAX31827_CONFIGURATION_RESOLUTION_MASK GENMASK(7, 6)
#define MAX31827_CONFIGURATION_ALRM_POL_MASK BIT(8)
@@ -46,6 +47,11 @@
#define MAX31827_M_DGR_TO_16_BIT(x) (((x) << 4) / 1000)
#define MAX31827_DEVICE_ENABLE(x) ((x) ? 0xA : 0x0)
+/*
+ * The enum passed in the .data pointer of struct of_device_id must
+ * start with a value != 0 since that is a requirement for using
+ * device_get_match_data().
+ */
enum chips { max31827 = 1, max31828, max31829 };
enum max31827_cnv {
@@ -382,7 +388,8 @@ static int max31827_write(struct device *dev, enum hwmon_sensor_types type,
}
case hwmon_chip:
- if (attr == hwmon_chip_update_interval) {
+ switch (attr) {
+ case hwmon_chip_update_interval:
if (!st->enable)
return -EINVAL;
@@ -410,14 +417,18 @@ static int max31827_write(struct device *dev, enum hwmon_sensor_types type,
return ret;
st->update_interval = val;
- }
- break;
+ return 0;
+ case hwmon_chip_pec:
+ return regmap_update_bits(st->regmap, MAX31827_CONFIGURATION_REG,
+ MAX31827_CONFIGURATION_PEC_EN_MASK,
+ val ? MAX31827_CONFIGURATION_PEC_EN_MASK : 0);
+ default:
+ return -EOPNOTSUPP;
+ }
default:
return -EOPNOTSUPP;
}
-
- return 0;
}
static ssize_t temp1_resolution_show(struct device *dev,
@@ -583,7 +594,7 @@ static const struct hwmon_channel_info *max31827_info[] = {
HWMON_T_MIN_HYST | HWMON_T_MIN_ALARM |
HWMON_T_MAX | HWMON_T_MAX_HYST |
HWMON_T_MAX_ALARM),
- HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL),
+ HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL | HWMON_C_PEC),
NULL,
};
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index cbb595fe47aa..f54720d3d2ce 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -21,6 +21,7 @@
#include <linux/mutex.h>
#include <linux/platform_data/max6639.h>
#include <linux/regmap.h>
+#include <linux/util_macros.h>
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END };
@@ -55,13 +56,17 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END };
#define MAX6639_GCONFIG_PWM_FREQ_HI 0x08
#define MAX6639_FAN_CONFIG1_PWM 0x80
-
+#define MAX6639_FAN_CONFIG3_FREQ_MASK 0x03
#define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED 0x40
#define MAX6639_NUM_CHANNELS 2
static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 };
+/* Supported PWM frequency */
+static const unsigned int freq_table[] = { 20, 33, 50, 100, 5000, 8333, 12500,
+ 25000 };
+
#define FAN_FROM_REG(val, rpm_range) ((val) == 0 || (val) == 255 ? \
0 : (rpm_ranges[rpm_range] * 30) / (val))
#define TEMP_LIMIT_TO_REG(val) clamp_val((val) / 1000, 0, 255)
@@ -71,21 +76,19 @@ static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 };
*/
struct max6639_data {
struct regmap *regmap;
+ struct mutex update_lock;
/* Register values initialized only once */
- u8 ppr; /* Pulses per rotation 0..3 for 1..4 ppr */
- u8 rpm_range; /* Index in above rpm_ranges table */
+ u8 ppr[MAX6639_NUM_CHANNELS]; /* Pulses per rotation 0..3 for 1..4 ppr */
+ u8 rpm_range[MAX6639_NUM_CHANNELS]; /* Index in above rpm_ranges table */
/* Optional regulator for FAN supply */
struct regulator *reg;
};
-static ssize_t temp_input_show(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static int max6639_temp_read_input(struct device *dev, int channel, long *temp)
{
- long temp;
struct max6639_data *data = dev_get_drvdata(dev);
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
unsigned int val;
int res;
@@ -93,251 +96,444 @@ static ssize_t temp_input_show(struct device *dev,
* Lock isn't needed as MAX6639_REG_TEMP wpnt change for at least 250ms after reading
* MAX6639_REG_TEMP_EXT
*/
- res = regmap_read(data->regmap, MAX6639_REG_TEMP_EXT(attr->index), &val);
+ res = regmap_read(data->regmap, MAX6639_REG_TEMP_EXT(channel), &val);
if (res < 0)
return res;
- temp = val >> 5;
- res = regmap_read(data->regmap, MAX6639_REG_TEMP(attr->index), &val);
+ *temp = val >> 5;
+ res = regmap_read(data->regmap, MAX6639_REG_TEMP(channel), &val);
if (res < 0)
return res;
- temp |= val << 3;
- temp *= 125;
+ *temp |= val << 3;
+ *temp *= 125;
- return sprintf(buf, "%ld\n", temp);
+ return 0;
}
-static ssize_t temp_fault_show(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static int max6639_temp_read_fault(struct device *dev, int channel, long *fault)
{
struct max6639_data *data = dev_get_drvdata(dev);
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
unsigned int val;
int res;
- res = regmap_read(data->regmap, MAX6639_REG_TEMP_EXT(attr->index), &val);
+ res = regmap_read(data->regmap, MAX6639_REG_TEMP_EXT(channel), &val);
if (res < 0)
return res;
- return sprintf(buf, "%d\n", val & 1);
+ *fault = val & 1;
+
+ return 0;
}
-static ssize_t temp_max_show(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static int max6639_temp_read_max(struct device *dev, int channel, long *max)
{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
unsigned int val;
int res;
- res = regmap_read(data->regmap, MAX6639_REG_THERM_LIMIT(attr->index), &val);
+ res = regmap_read(data->regmap, MAX6639_REG_THERM_LIMIT(channel), &val);
if (res < 0)
return res;
- return sprintf(buf, "%d\n", (val * 1000));
+ *max = (long)val * 1000;
+
+ return 0;
}
-static ssize_t temp_max_store(struct device *dev,
- struct device_attribute *dev_attr,
- const char *buf, size_t count)
+static int max6639_temp_read_crit(struct device *dev, int channel, long *crit)
{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
- unsigned long val;
+ unsigned int val;
int res;
- res = kstrtoul(buf, 10, &val);
- if (res)
+ res = regmap_read(data->regmap, MAX6639_REG_ALERT_LIMIT(channel), &val);
+ if (res < 0)
return res;
- regmap_write(data->regmap, MAX6639_REG_THERM_LIMIT(attr->index),
- TEMP_LIMIT_TO_REG(val));
- return count;
+ *crit = (long)val * 1000;
+
+ return 0;
}
-static ssize_t temp_crit_show(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static int max6639_temp_read_emergency(struct device *dev, int channel, long *emerg)
{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
unsigned int val;
int res;
- res = regmap_read(data->regmap, MAX6639_REG_ALERT_LIMIT(attr->index), &val);
+ res = regmap_read(data->regmap, MAX6639_REG_OT_LIMIT(channel), &val);
if (res < 0)
return res;
- return sprintf(buf, "%d\n", (val * 1000));
+ *emerg = (long)val * 1000;
+
+ return 0;
}
-static ssize_t temp_crit_store(struct device *dev,
- struct device_attribute *dev_attr,
- const char *buf, size_t count)
+static int max6639_get_status(struct device *dev, unsigned int *status)
{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
- unsigned long val;
+ unsigned int val;
int res;
- res = kstrtoul(buf, 10, &val);
- if (res)
+ res = regmap_read(data->regmap, MAX6639_REG_STATUS, &val);
+ if (res < 0)
return res;
- regmap_write(data->regmap, MAX6639_REG_ALERT_LIMIT(attr->index),
- TEMP_LIMIT_TO_REG(val));
- return count;
+ *status = val;
+
+ return 0;
}
-static ssize_t temp_emergency_show(struct device *dev,
- struct device_attribute *dev_attr,
- char *buf)
+static int max6639_temp_set_max(struct max6639_data *data, int channel, long val)
{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
- struct max6639_data *data = dev_get_drvdata(dev);
- unsigned int val;
int res;
- res = regmap_read(data->regmap, MAX6639_REG_OT_LIMIT(attr->index), &val);
- if (res < 0)
- return res;
-
- return sprintf(buf, "%d\n", (val * 1000));
+ res = regmap_write(data->regmap, MAX6639_REG_THERM_LIMIT(channel),
+ TEMP_LIMIT_TO_REG(val));
+ return res;
}
-static ssize_t temp_emergency_store(struct device *dev,
- struct device_attribute *dev_attr,
- const char *buf, size_t count)
+static int max6639_temp_set_crit(struct max6639_data *data, int channel, long val)
{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
- struct max6639_data *data = dev_get_drvdata(dev);
- unsigned long val;
int res;
- res = kstrtoul(buf, 10, &val);
- if (res)
- return res;
+ res = regmap_write(data->regmap, MAX6639_REG_ALERT_LIMIT(channel), TEMP_LIMIT_TO_REG(val));
- regmap_write(data->regmap, MAX6639_REG_OT_LIMIT(attr->index), TEMP_LIMIT_TO_REG(val));
+ return res;
+}
- return count;
+static int max6639_temp_set_emergency(struct max6639_data *data, int channel, long val)
+{
+ int res;
+
+ res = regmap_write(data->regmap, MAX6639_REG_OT_LIMIT(channel), TEMP_LIMIT_TO_REG(val));
+
+ return res;
}
-static ssize_t pwm_show(struct device *dev, struct device_attribute *dev_attr,
- char *buf)
+static int max6639_read_fan(struct device *dev, u32 attr, int channel,
+ long *fan_val)
{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
unsigned int val;
int res;
- res = regmap_read(data->regmap, MAX6639_REG_TARGTDUTY(attr->index), &val);
- if (res < 0)
- return res;
+ switch (attr) {
+ case hwmon_fan_input:
+ res = regmap_read(data->regmap, MAX6639_REG_FAN_CNT(channel), &val);
+ if (res < 0)
+ return res;
+ *fan_val = FAN_FROM_REG(val, data->rpm_range[channel]);
+ return 0;
+ case hwmon_fan_fault:
+ res = max6639_get_status(dev, &val);
+ if (res < 0)
+ return res;
+ *fan_val = !!(val & BIT(1 - channel));
+ return 0;
+ case hwmon_fan_pulses:
+ *fan_val = data->ppr[channel];
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
- return sprintf(buf, "%d\n", val * 255 / 120);
+static int max6639_set_ppr(struct max6639_data *data, int channel, u8 ppr)
+{
+ /* Decrement the PPR value and shift left by 6 to match the register format */
+ return regmap_write(data->regmap, MAX6639_REG_FAN_PPR(channel), ppr-- << 6);
}
-static ssize_t pwm_store(struct device *dev,
- struct device_attribute *dev_attr, const char *buf,
- size_t count)
+static int max6639_write_fan(struct device *dev, u32 attr, int channel,
+ long val)
{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct max6639_data *data = dev_get_drvdata(dev);
- unsigned long val;
- int res;
+ int err;
- res = kstrtoul(buf, 10, &val);
- if (res)
- return res;
+ switch (attr) {
+ case hwmon_fan_pulses:
+ if (val <= 0 || val > 4)
+ return -EINVAL;
- val = clamp_val(val, 0, 255);
+ mutex_lock(&data->update_lock);
+ /* Set Fan pulse per revolution */
+ err = max6639_set_ppr(data, channel, val);
+ if (err < 0) {
+ mutex_unlock(&data->update_lock);
+ return err;
+ }
+ data->ppr[channel] = val;
- regmap_write(data->regmap, MAX6639_REG_TARGTDUTY(attr->index), val * 120 / 255);
+ mutex_unlock(&data->update_lock);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
- return count;
+static umode_t max6639_fan_is_visible(const void *_data, u32 attr, int channel)
+{
+ switch (attr) {
+ case hwmon_fan_input:
+ case hwmon_fan_fault:
+ return 0444;
+ case hwmon_fan_pulses:
+ return 0644;
+ default:
+ return 0;
+ }
}
-static ssize_t fan_input_show(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static int max6639_read_pwm(struct device *dev, u32 attr, int channel,
+ long *pwm_val)
{
struct max6639_data *data = dev_get_drvdata(dev);
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
unsigned int val;
int res;
+ u8 i;
+
+ switch (attr) {
+ case hwmon_pwm_input:
+ res = regmap_read(data->regmap, MAX6639_REG_TARGTDUTY(channel), &val);
+ if (res < 0)
+ return res;
+ *pwm_val = val * 255 / 120;
+ return 0;
+ case hwmon_pwm_freq:
+ mutex_lock(&data->update_lock);
+ res = regmap_read(data->regmap, MAX6639_REG_FAN_CONFIG3(channel), &val);
+ if (res < 0) {
+ mutex_unlock(&data->update_lock);
+ return res;
+ }
+ i = val & MAX6639_FAN_CONFIG3_FREQ_MASK;
- res = regmap_read(data->regmap, MAX6639_REG_FAN_CNT(attr->index), &val);
- if (res < 0)
- return res;
+ res = regmap_read(data->regmap, MAX6639_REG_GCONFIG, &val);
+ if (res < 0) {
+ mutex_unlock(&data->update_lock);
+ return res;
+ }
+
+ if (val & MAX6639_GCONFIG_PWM_FREQ_HI)
+ i |= 0x4;
+ i &= 0x7;
+ *pwm_val = freq_table[i];
- return sprintf(buf, "%d\n", FAN_FROM_REG(val, data->rpm_range));
+ mutex_unlock(&data->update_lock);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
}
-static ssize_t alarm_show(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static int max6639_write_pwm(struct device *dev, u32 attr, int channel,
+ long val)
{
struct max6639_data *data = dev_get_drvdata(dev);
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
- unsigned int val;
+ int err;
+ u8 i;
+
+ switch (attr) {
+ case hwmon_pwm_input:
+ if (val < 0 || val > 255)
+ return -EINVAL;
+ err = regmap_write(data->regmap, MAX6639_REG_TARGTDUTY(channel),
+ val * 120 / 255);
+ return err;
+ case hwmon_pwm_freq:
+ val = clamp_val(val, 0, 25000);
+
+ i = find_closest(val, freq_table, ARRAY_SIZE(freq_table));
+
+ mutex_lock(&data->update_lock);
+ err = regmap_update_bits(data->regmap, MAX6639_REG_FAN_CONFIG3(channel),
+ MAX6639_FAN_CONFIG3_FREQ_MASK, i);
+ if (err < 0) {
+ mutex_unlock(&data->update_lock);
+ return err;
+ }
+
+ if (i >> 2)
+ err = regmap_set_bits(data->regmap, MAX6639_REG_GCONFIG,
+ MAX6639_GCONFIG_PWM_FREQ_HI);
+ else
+ err = regmap_clear_bits(data->regmap, MAX6639_REG_GCONFIG,
+ MAX6639_GCONFIG_PWM_FREQ_HI);
+
+ mutex_unlock(&data->update_lock);
+ return err;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t max6639_pwm_is_visible(const void *_data, u32 attr, int channel)
+{
+ switch (attr) {
+ case hwmon_pwm_input:
+ case hwmon_pwm_freq:
+ return 0644;
+ default:
+ return 0;
+ }
+}
+
+static int max6639_read_temp(struct device *dev, u32 attr, int channel,
+ long *val)
+{
+ unsigned int status;
int res;
- res = regmap_read(data->regmap, MAX6639_REG_STATUS, &val);
- if (res < 0)
+ switch (attr) {
+ case hwmon_temp_input:
+ res = max6639_temp_read_input(dev, channel, val);
return res;
+ case hwmon_temp_fault:
+ res = max6639_temp_read_fault(dev, channel, val);
+ return res;
+ case hwmon_temp_max:
+ res = max6639_temp_read_max(dev, channel, val);
+ return res;
+ case hwmon_temp_crit:
+ res = max6639_temp_read_crit(dev, channel, val);
+ return res;
+ case hwmon_temp_emergency:
+ res = max6639_temp_read_emergency(dev, channel, val);
+ return res;
+ case hwmon_temp_max_alarm:
+ res = max6639_get_status(dev, &status);
+ if (res < 0)
+ return res;
+ *val = !!(status & BIT(3 - channel));
+ return 0;
+ case hwmon_temp_crit_alarm:
+ res = max6639_get_status(dev, &status);
+ if (res < 0)
+ return res;
+ *val = !!(status & BIT(7 - channel));
+ return 0;
+ case hwmon_temp_emergency_alarm:
+ res = max6639_get_status(dev, &status);
+ if (res < 0)
+ return res;
+ *val = !!(status & BIT(5 - channel));
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
- return sprintf(buf, "%d\n", !!(val & (1 << attr->index)));
+static int max6639_write_temp(struct device *dev, u32 attr, int channel,
+ long val)
+{
+ struct max6639_data *data = dev_get_drvdata(dev);
+
+ switch (attr) {
+ case hwmon_temp_max:
+ return max6639_temp_set_max(data, channel, val);
+ case hwmon_temp_crit:
+ return max6639_temp_set_crit(data, channel, val);
+ case hwmon_temp_emergency:
+ return max6639_temp_set_emergency(data, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
}
-static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
-static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1);
-static SENSOR_DEVICE_ATTR_RO(temp1_fault, temp_fault, 0);
-static SENSOR_DEVICE_ATTR_RO(temp2_fault, temp_fault, 1);
-static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
-static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
-static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp_crit, 0);
-static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp_crit, 1);
-static SENSOR_DEVICE_ATTR_RW(temp1_emergency, temp_emergency, 0);
-static SENSOR_DEVICE_ATTR_RW(temp2_emergency, temp_emergency, 1);
-static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
-static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
-static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0);
-static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1);
-static SENSOR_DEVICE_ATTR_RO(fan1_fault, alarm, 1);
-static SENSOR_DEVICE_ATTR_RO(fan2_fault, alarm, 0);
-static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 3);
-static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 2);
-static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 7);
-static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 6);
-static SENSOR_DEVICE_ATTR_RO(temp1_emergency_alarm, alarm, 5);
-static SENSOR_DEVICE_ATTR_RO(temp2_emergency_alarm, alarm, 4);
-
-
-static struct attribute *max6639_attrs[] = {
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_temp2_input.dev_attr.attr,
- &sensor_dev_attr_temp1_fault.dev_attr.attr,
- &sensor_dev_attr_temp2_fault.dev_attr.attr,
- &sensor_dev_attr_temp1_max.dev_attr.attr,
- &sensor_dev_attr_temp2_max.dev_attr.attr,
- &sensor_dev_attr_temp1_crit.dev_attr.attr,
- &sensor_dev_attr_temp2_crit.dev_attr.attr,
- &sensor_dev_attr_temp1_emergency.dev_attr.attr,
- &sensor_dev_attr_temp2_emergency.dev_attr.attr,
- &sensor_dev_attr_pwm1.dev_attr.attr,
- &sensor_dev_attr_pwm2.dev_attr.attr,
- &sensor_dev_attr_fan1_input.dev_attr.attr,
- &sensor_dev_attr_fan2_input.dev_attr.attr,
- &sensor_dev_attr_fan1_fault.dev_attr.attr,
- &sensor_dev_attr_fan2_fault.dev_attr.attr,
- &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
- &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
- &sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_emergency_alarm.dev_attr.attr,
+static umode_t max6639_temp_is_visible(const void *_data, u32 attr, int channel)
+{
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_fault:
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_crit_alarm:
+ case hwmon_temp_emergency_alarm:
+ return 0444;
+ case hwmon_temp_max:
+ case hwmon_temp_crit:
+ case hwmon_temp_emergency:
+ return 0644;
+ default:
+ return 0;
+ }
+}
+
+static int max6639_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ switch (type) {
+ case hwmon_fan:
+ return max6639_read_fan(dev, attr, channel, val);
+ case hwmon_pwm:
+ return max6639_read_pwm(dev, attr, channel, val);
+ case hwmon_temp:
+ return max6639_read_temp(dev, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int max6639_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ switch (type) {
+ case hwmon_fan:
+ return max6639_write_fan(dev, attr, channel, val);
+ case hwmon_pwm:
+ return max6639_write_pwm(dev, attr, channel, val);
+ case hwmon_temp:
+ return max6639_write_temp(dev, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t max6639_is_visible(const void *data,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ switch (type) {
+ case hwmon_fan:
+ return max6639_fan_is_visible(data, attr, channel);
+ case hwmon_pwm:
+ return max6639_pwm_is_visible(data, attr, channel);
+ case hwmon_temp:
+ return max6639_temp_is_visible(data, attr, channel);
+ default:
+ return 0;
+ }
+}
+
+static const struct hwmon_channel_info * const max6639_info[] = {
+ HWMON_CHANNEL_INFO(fan,
+ HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_PULSES,
+ HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_PULSES),
+ HWMON_CHANNEL_INFO(pwm,
+ HWMON_PWM_INPUT | HWMON_PWM_FREQ,
+ HWMON_PWM_INPUT | HWMON_PWM_FREQ),
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_MAX | HWMON_T_MAX_ALARM |
+ HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_EMERGENCY |
+ HWMON_T_EMERGENCY_ALARM,
+ HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_MAX | HWMON_T_MAX_ALARM |
+ HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_EMERGENCY |
+ HWMON_T_EMERGENCY_ALARM),
NULL
};
-ATTRIBUTE_GROUPS(max6639);
+
+static const struct hwmon_ops max6639_hwmon_ops = {
+ .is_visible = max6639_is_visible,
+ .read = max6639_read,
+ .write = max6639_write,
+};
+
+static const struct hwmon_chip_info max6639_chip_info = {
+ .ops = &max6639_hwmon_ops,
+ .info = max6639_info,
+};
/*
* returns respective index in rpm_ranges table
@@ -355,11 +551,6 @@ static int rpm_range_to_reg(int range)
return 1; /* default: 4000 RPM */
}
-static int max6639_set_ppr(struct max6639_data *data, u8 channel, u8 ppr)
-{
- return regmap_write(data->regmap, MAX6639_REG_FAN_PPR(channel), ppr << 6);
-}
-
static int max6639_init_client(struct i2c_client *client,
struct max6639_data *data)
{
@@ -380,30 +571,34 @@ static int max6639_init_client(struct i2c_client *client,
ppr = max6639_info->ppr;
else
ppr = 2;
- ppr -= 1;
+
+ data->ppr[0] = ppr;
+ data->ppr[1] = ppr;
if (max6639_info)
rpm_range = rpm_range_to_reg(max6639_info->rpm_range);
- data->rpm_range = rpm_range;
+ data->rpm_range[0] = rpm_range;
+ data->rpm_range[1] = rpm_range;
for (i = 0; i < MAX6639_NUM_CHANNELS; i++) {
-
/* Set Fan pulse per revolution */
- err = max6639_set_ppr(data, i, ppr);
+ err = max6639_set_ppr(data, i, data->ppr[i]);
if (err)
return err;
/* Fans config PWM, RPM */
err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG1(i),
- MAX6639_FAN_CONFIG1_PWM | rpm_range);
+ MAX6639_FAN_CONFIG1_PWM | data->rpm_range[i]);
if (err)
return err;
/* Fans PWM polarity high by default */
- if (max6639_info && 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);
+ 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);
+ }
if (err)
return err;
@@ -529,14 +724,17 @@ static int max6639_probe(struct i2c_client *client)
}
}
+ mutex_init(&data->update_lock);
+
/* Initialize the max6639 chip */
err = max6639_init_client(client, data);
if (err < 0)
return err;
- hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
- data,
- max6639_groups);
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
+ data, &max6639_chip_info,
+ NULL);
+
return PTR_ERR_OR_ZERO(hwmon_dev);
}
diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c
deleted file mode 100644
index 9302ab233910..000000000000
--- a/drivers/hwmon/max6642.c
+++ /dev/null
@@ -1,314 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Driver for +/-1 degree C, SMBus-Compatible Remote/Local Temperature Sensor
- * with Overtemperature Alarm
- *
- * Copyright (C) 2011 AppearTV AS
- *
- * Derived from:
- *
- * Based on the max1619 driver.
- * Copyright (C) 2003-2004 Oleksij Rempel <[email protected]>
- * Jean Delvare <[email protected]>
- *
- * The MAX6642 is a sensor chip made by Maxim.
- * It reports up to two temperatures (its own plus up to
- * one external one). Complete datasheet can be
- * obtained from Maxim's website at:
- * http://datasheets.maxim-ic.com/en/ds/MAX6642.pdf
- */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/sysfs.h>
-
-static const unsigned short normal_i2c[] = {
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-
-/*
- * The MAX6642 registers
- */
-
-#define MAX6642_REG_R_MAN_ID 0xFE
-#define MAX6642_REG_R_CONFIG 0x03
-#define MAX6642_REG_W_CONFIG 0x09
-#define MAX6642_REG_R_STATUS 0x02
-#define MAX6642_REG_R_LOCAL_TEMP 0x00
-#define MAX6642_REG_R_LOCAL_TEMPL 0x11
-#define MAX6642_REG_R_LOCAL_HIGH 0x05
-#define MAX6642_REG_W_LOCAL_HIGH 0x0B
-#define MAX6642_REG_R_REMOTE_TEMP 0x01
-#define MAX6642_REG_R_REMOTE_TEMPL 0x10
-#define MAX6642_REG_R_REMOTE_HIGH 0x07
-#define MAX6642_REG_W_REMOTE_HIGH 0x0D
-
-/*
- * Conversions
- */
-
-static int temp_from_reg10(int val)
-{
- return val * 250;
-}
-
-static int temp_from_reg(int val)
-{
- return val * 1000;
-}
-
-static int temp_to_reg(int val)
-{
- return val / 1000;
-}
-
-/*
- * Client data (each client gets its own)
- */
-
-struct max6642_data {
- struct i2c_client *client;
- struct mutex update_lock;
- bool valid; /* zero until following fields are valid */
- unsigned long last_updated; /* in jiffies */
-
- /* registers values */
- u16 temp_input[2]; /* local/remote */
- u16 temp_high[2]; /* local/remote */
- u8 alarms;
-};
-
-/*
- * Real code
- */
-
-static void max6642_init_client(struct max6642_data *data,
- struct i2c_client *client)
-{
- u8 config;
-
- /*
- * Start the conversions.
- */
- config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG);
- if (config & 0x40)
- i2c_smbus_write_byte_data(client, MAX6642_REG_W_CONFIG,
- config & 0xBF); /* run */
-
- data->temp_high[0] = i2c_smbus_read_byte_data(client,
- MAX6642_REG_R_LOCAL_HIGH);
- data->temp_high[1] = i2c_smbus_read_byte_data(client,
- MAX6642_REG_R_REMOTE_HIGH);
-}
-
-/* Return 0 if detection is successful, -ENODEV otherwise */
-static int max6642_detect(struct i2c_client *client,
- struct i2c_board_info *info)
-{
- struct i2c_adapter *adapter = client->adapter;
- u8 reg_config, reg_status, man_id;
-
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -ENODEV;
-
- /* identification */
- man_id = i2c_smbus_read_byte_data(client, MAX6642_REG_R_MAN_ID);
- if (man_id != 0x4D)
- return -ENODEV;
-
- /* sanity check */
- if (i2c_smbus_read_byte_data(client, 0x04) != 0x4D
- || i2c_smbus_read_byte_data(client, 0x06) != 0x4D
- || i2c_smbus_read_byte_data(client, 0xff) != 0x4D)
- return -ENODEV;
-
- /*
- * We read the config and status register, the 4 lower bits in the
- * config register should be zero and bit 5, 3, 1 and 0 should be
- * zero in the status register.
- */
- reg_config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG);
- if ((reg_config & 0x0f) != 0x00)
- return -ENODEV;
-
- /* in between, another round of sanity checks */
- if (i2c_smbus_read_byte_data(client, 0x04) != reg_config
- || i2c_smbus_read_byte_data(client, 0x06) != reg_config
- || i2c_smbus_read_byte_data(client, 0xff) != reg_config)
- return -ENODEV;
-
- reg_status = i2c_smbus_read_byte_data(client, MAX6642_REG_R_STATUS);
- if ((reg_status & 0x2b) != 0x00)
- return -ENODEV;
-
- strscpy(info->type, "max6642", I2C_NAME_SIZE);
-
- return 0;
-}
-
-static struct max6642_data *max6642_update_device(struct device *dev)
-{
- struct max6642_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- u16 val, tmp;
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
- dev_dbg(dev, "Updating max6642 data.\n");
- val = i2c_smbus_read_byte_data(client,
- MAX6642_REG_R_LOCAL_TEMPL);
- tmp = (val >> 6) & 3;
- val = i2c_smbus_read_byte_data(client,
- MAX6642_REG_R_LOCAL_TEMP);
- val = (val << 2) | tmp;
- data->temp_input[0] = val;
- val = i2c_smbus_read_byte_data(client,
- MAX6642_REG_R_REMOTE_TEMPL);
- tmp = (val >> 6) & 3;
- val = i2c_smbus_read_byte_data(client,
- MAX6642_REG_R_REMOTE_TEMP);
- val = (val << 2) | tmp;
- data->temp_input[1] = val;
- data->alarms = i2c_smbus_read_byte_data(client,
- MAX6642_REG_R_STATUS);
-
- data->last_updated = jiffies;
- data->valid = true;
- }
-
- mutex_unlock(&data->update_lock);
-
- return data;
-}
-
-/*
- * Sysfs stuff
- */
-
-static ssize_t temp_max10_show(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
- struct max6642_data *data = max6642_update_device(dev);
-
- return sprintf(buf, "%d\n",
- temp_from_reg10(data->temp_input[attr->index]));
-}
-
-static ssize_t temp_max_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
- struct max6642_data *data = max6642_update_device(dev);
-
- return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr]));
-}
-
-static ssize_t temp_max_store(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t count)
-{
- struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
- struct max6642_data *data = dev_get_drvdata(dev);
- unsigned long val;
- int err;
-
- err = kstrtoul(buf, 10, &val);
- if (err < 0)
- return err;
-
- mutex_lock(&data->update_lock);
- data->temp_high[attr2->nr] = clamp_val(temp_to_reg(val), 0, 255);
- i2c_smbus_write_byte_data(data->client, attr2->index,
- data->temp_high[attr2->nr]);
- mutex_unlock(&data->update_lock);
- return count;
-}
-
-static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- int bitnr = to_sensor_dev_attr(attr)->index;
- struct max6642_data *data = max6642_update_device(dev);
- return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
-}
-
-static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_max10, 0);
-static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_max10, 1);
-static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp_max, 0,
- MAX6642_REG_W_LOCAL_HIGH);
-static SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp_max, 1,
- MAX6642_REG_W_REMOTE_HIGH);
-static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 2);
-static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
-static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 4);
-
-static struct attribute *max6642_attrs[] = {
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_temp2_input.dev_attr.attr,
- &sensor_dev_attr_temp1_max.dev_attr.attr,
- &sensor_dev_attr_temp2_max.dev_attr.attr,
-
- &sensor_dev_attr_temp2_fault.dev_attr.attr,
- &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
- NULL
-};
-ATTRIBUTE_GROUPS(max6642);
-
-static int max6642_probe(struct i2c_client *client)
-{
- struct device *dev = &client->dev;
- struct max6642_data *data;
- struct device *hwmon_dev;
-
- data = devm_kzalloc(dev, sizeof(struct max6642_data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- data->client = client;
- mutex_init(&data->update_lock);
-
- /* Initialize the MAX6642 chip */
- max6642_init_client(data, client);
-
- hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
- client->name, data,
- max6642_groups);
- return PTR_ERR_OR_ZERO(hwmon_dev);
-}
-
-/*
- * Driver data (common to all clients)
- */
-
-static const struct i2c_device_id max6642_id[] = {
- { "max6642" },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, max6642_id);
-
-static struct i2c_driver max6642_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "max6642",
- },
- .probe = max6642_probe,
- .id_table = max6642_id,
- .detect = max6642_detect,
- .address_list = normal_i2c,
-};
-
-module_i2c_driver(max6642_driver);
-
-MODULE_AUTHOR("Per Dalen <[email protected]>");
-MODULE_DESCRIPTION("MAX6642 sensor driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c
index d161ba0e7813..20981f9443dd 100644
--- a/drivers/hwmon/max6697.c
+++ b/drivers/hwmon/max6697.c
@@ -311,6 +311,7 @@ static ssize_t temp_store(struct device *dev,
return ret;
mutex_lock(&data->update_lock);
+ temp = clamp_val(temp, -1000000, 1000000); /* prevent underflow */
temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset;
temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127);
data->temp[nr][index] = temp;
@@ -428,14 +429,14 @@ static SENSOR_DEVICE_ATTR_RO(temp6_max_alarm, alarm, 20);
static SENSOR_DEVICE_ATTR_RO(temp7_max_alarm, alarm, 21);
static SENSOR_DEVICE_ATTR_RO(temp8_max_alarm, alarm, 23);
-static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 14);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 15);
static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 8);
static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 9);
static SENSOR_DEVICE_ATTR_RO(temp4_crit_alarm, alarm, 10);
static SENSOR_DEVICE_ATTR_RO(temp5_crit_alarm, alarm, 11);
static SENSOR_DEVICE_ATTR_RO(temp6_crit_alarm, alarm, 12);
static SENSOR_DEVICE_ATTR_RO(temp7_crit_alarm, alarm, 13);
-static SENSOR_DEVICE_ATTR_RO(temp8_crit_alarm, alarm, 15);
+static SENSOR_DEVICE_ATTR_RO(temp8_crit_alarm, alarm, 14);
static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 1);
static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 2);
@@ -684,8 +685,6 @@ done:
return 0;
}
-static const struct i2c_device_id max6697_id[];
-
static int max6697_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
@@ -701,10 +700,7 @@ static int max6697_probe(struct i2c_client *client)
if (!data)
return -ENOMEM;
- if (client->dev.of_node)
- data->type = (uintptr_t)of_device_get_match_data(&client->dev);
- else
- data->type = i2c_match_id(max6697_id, client)->driver_data;
+ data->type = (uintptr_t)i2c_get_match_data(client);
data->chip = &max6697_chip_data[data->type];
data->client = client;
mutex_init(&data->update_lock);
diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c
index 9814eaf24564..bcddf6804d3a 100644
--- a/drivers/hwmon/mcp3021.c
+++ b/drivers/hwmon/mcp3021.c
@@ -116,13 +116,12 @@ static const struct hwmon_chip_info mcp3021_chip_info = {
.info = mcp3021_info,
};
-static const struct i2c_device_id mcp3021_id[];
-
static int mcp3021_probe(struct i2c_client *client)
{
struct mcp3021_data *data = NULL;
struct device_node *np = client->dev.of_node;
struct device *hwmon_dev;
+ enum chips type;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
@@ -149,7 +148,8 @@ static int mcp3021_probe(struct i2c_client *client)
data->vdd = MCP3021_VDD_REF_DEFAULT;
}
- switch (i2c_match_id(mcp3021_id, client)->driver_data) {
+ type = (uintptr_t)i2c_get_match_data(client);
+ switch (type) {
case mcp3021:
data->sar_shift = MCP3021_SAR_SHIFT;
data->sar_mask = MCP3021_SAR_MASK;
diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c
index 50a8b9c3f94d..7848198f8996 100644
--- a/drivers/hwmon/mr75203.c
+++ b/drivers/hwmon/mr75203.c
@@ -925,4 +925,5 @@ static struct platform_driver moortec_pvt_driver = {
};
module_platform_driver(moortec_pvt_driver);
+MODULE_DESCRIPTION("Moortec Semiconductor MR75203 PVT Controller driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/nct6683.c b/drivers/hwmon/nct6683.c
index 0d016fedb9c2..f71615e06a8f 100644
--- a/drivers/hwmon/nct6683.c
+++ b/drivers/hwmon/nct6683.c
@@ -1236,6 +1236,8 @@ static int nct6683_probe(struct platform_device *pdev)
default:
if (!force)
return -ENODEV;
+ dev_warn(dev, "Enabling support for unknown customer ID 0x%04x\n", data->customer_id);
+ break;
}
nct6683_init_device(data);
diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c
index 9fbab8f02334..934fed3dd586 100644
--- a/drivers/hwmon/nct6775-core.c
+++ b/drivers/hwmon/nct6775-core.c
@@ -2262,7 +2262,7 @@ store_temp_offset(struct device *dev, struct device_attribute *attr,
if (err < 0)
return err;
- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000);
mutex_lock(&data->update_lock);
data->temp_offset[nr] = val;
diff --git a/drivers/hwmon/nct6775.h b/drivers/hwmon/nct6775.h
index d31e7a030216..296eff99d003 100644
--- a/drivers/hwmon/nct6775.h
+++ b/drivers/hwmon/nct6775.h
@@ -4,7 +4,7 @@
#include <linux/types.h>
-enum kinds { nct6106 = 1, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792,
+enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792,
nct6793, nct6795, nct6796, nct6797, nct6798, nct6799 };
enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
index 7aa586eb74be..df6fa72a6b59 100644
--- a/drivers/hwmon/nzxt-smart2.c
+++ b/drivers/hwmon/nzxt-smart2.c
@@ -799,6 +799,7 @@ static const struct hid_device_id nzxt_smart2_hid_id_table[] = {
{ HID_USB_DEVICE(0x1e71, 0x2010) }, /* NZXT RGB & Fan Controller */
{ HID_USB_DEVICE(0x1e71, 0x2011) }, /* NZXT RGB & Fan Controller (6 RGB) */
{ HID_USB_DEVICE(0x1e71, 0x2019) }, /* NZXT RGB & Fan Controller (6 RGB) */
+ { HID_USB_DEVICE(0x1e71, 0x2020) }, /* NZXT RGB & Fan Controller (6 RGB) */
{},
};
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 08e82c457356..a4f02cad92fd 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -337,6 +337,15 @@ config SENSORS_MP2888
This driver can also be built as a module. If so, the module will
be called mp2888.
+config SENSORS_MP2891
+ tristate "MPS MP2891"
+ help
+ If you say yes here you get hardware monitoring support for MPS
+ MP2891 Dual Loop Digital Multi-Phase Controller.
+
+ This driver can also be built as a module. If so, the module will
+ be called mp2891.
+
config SENSORS_MP2975
tristate "MPS MP2975"
help
@@ -346,6 +355,15 @@ config SENSORS_MP2975
This driver can also be built as a module. If so, the module will
be called mp2975.
+config SENSORS_MP2993
+ tristate "MPS MP2993"
+ help
+ If you say yes here you get hardware monitoring support for MPS
+ MP2993 Dual Loop Digital Multi-Phase Controller.
+
+ This driver can also be built as a module. If so, the module will
+ be called mp2993.
+
config SENSORS_MP2975_REGULATOR
depends on SENSORS_MP2975 && REGULATOR
bool "Regulator support for MPS MP2975"
@@ -362,6 +380,15 @@ config SENSORS_MP5023
This driver can also be built as a module. If so, the module will
be called mp5023.
+config SENSORS_MP5920
+ tristate "MPS MP5920"
+ help
+ If you say yes here you get hardware monitoring support for Monolithic
+ MP5920.
+
+ This driver can also be built as a module. If so, the module will
+ be called mp5920.
+
config SENSORS_MP5990
tristate "MPS MP5990"
help
@@ -371,6 +398,15 @@ config SENSORS_MP5990
This driver can also be built as a module. If so, the module will
be called mp5990.
+config SENSORS_MP9941
+ tristate "MPS MP9941"
+ help
+ If you say yes here you get hardware monitoring support for MPS
+ MP9941.
+
+ This driver can also be built as a module. If so, the module will
+ be called mp9941.
+
config SENSORS_MPQ7932_REGULATOR
bool "Regulator support for MPQ7932"
depends on SENSORS_MPQ7932 && REGULATOR
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index 2279b3327bbf..d00bcc758b97 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -36,9 +36,13 @@ obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
obj-$(CONFIG_SENSORS_MP2856) += mp2856.o
obj-$(CONFIG_SENSORS_MP2888) += mp2888.o
+obj-$(CONFIG_SENSORS_MP2891) += mp2891.o
obj-$(CONFIG_SENSORS_MP2975) += mp2975.o
+obj-$(CONFIG_SENSORS_MP2993) += mp2993.o
obj-$(CONFIG_SENSORS_MP5023) += mp5023.o
+obj-$(CONFIG_SENSORS_MP5920) += mp5920.o
obj-$(CONFIG_SENSORS_MP5990) += mp5990.o
+obj-$(CONFIG_SENSORS_MP9941) += mp9941.o
obj-$(CONFIG_SENSORS_MPQ7932) += mpq7932.o
obj-$(CONFIG_SENSORS_MPQ8785) += mpq8785.o
obj-$(CONFIG_SENSORS_PLI1209BC) += pli1209bc.o
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
index cfffa4cdc0df..c36c124d1a2d 100644
--- a/drivers/hwmon/pmbus/lm25066.c
+++ b/drivers/hwmon/pmbus/lm25066.c
@@ -17,7 +17,7 @@
#include <linux/of.h>
#include "pmbus.h"
-enum chips { lm25056 = 1, lm25066, lm5064, lm5066, lm5066i };
+enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i };
#define LM25066_READ_VAUX 0xd0
#define LM25066_MFR_READ_IIN 0xd1
diff --git a/drivers/hwmon/pmbus/ltc4286.c b/drivers/hwmon/pmbus/ltc4286.c
index 9e7ceeb7e789..aabd0bcdfeee 100644
--- a/drivers/hwmon/pmbus/ltc4286.c
+++ b/drivers/hwmon/pmbus/ltc4286.c
@@ -58,8 +58,8 @@ static struct pmbus_driver_info ltc4286_info = {
};
static const struct i2c_device_id ltc4286_id[] = {
- { "ltc4286", 0 },
- { "ltc4287", 1 },
+ { "ltc4286", },
+ { "ltc4287", },
{}
};
MODULE_DEVICE_TABLE(i2c, ltc4286_id);
diff --git a/drivers/hwmon/pmbus/mp2856.c b/drivers/hwmon/pmbus/mp2856.c
index 6969350f5d7d..41bb86667091 100644
--- a/drivers/hwmon/pmbus/mp2856.c
+++ b/drivers/hwmon/pmbus/mp2856.c
@@ -46,7 +46,7 @@
#define MP2856_PAGE_NUM 2
-enum chips { mp2856 = 1, mp2857 };
+enum chips { mp2856, mp2857 };
static const int mp2856_max_phases[][MP2856_PAGE_NUM] = {
[mp2856] = { MP2856_MAX_PHASE_RAIL1, MP2856_MAX_PHASE_RAIL2 },
@@ -66,7 +66,6 @@ struct mp2856_data {
int vout_format[MP2856_PAGE_NUM];
int curr_sense_gain[MP2856_PAGE_NUM];
int max_phases[MP2856_PAGE_NUM];
- enum chips chip_id;
};
#define to_mp2856_data(x) container_of(x, struct mp2856_data, info)
@@ -397,6 +396,7 @@ static int mp2856_probe(struct i2c_client *client)
{
struct pmbus_driver_info *info;
struct mp2856_data *data;
+ enum chips chip_id;
int ret;
data = devm_kzalloc(&client->dev, sizeof(struct mp2856_data),
@@ -404,9 +404,9 @@ static int mp2856_probe(struct i2c_client *client)
if (!data)
return -ENOMEM;
- data->chip_id = (enum chips)(uintptr_t)i2c_get_match_data(client);
+ chip_id = (kernel_ulong_t)i2c_get_match_data(client);
- memcpy(data->max_phases, mp2856_max_phases[data->chip_id],
+ memcpy(data->max_phases, mp2856_max_phases[chip_id],
sizeof(data->max_phases));
memcpy(&data->info, &mp2856_info, sizeof(*info));
diff --git a/drivers/hwmon/pmbus/mp2891.c b/drivers/hwmon/pmbus/mp2891.c
new file mode 100644
index 000000000000..bb28b15a9103
--- /dev/null
+++ b/drivers/hwmon/pmbus/mp2891.c
@@ -0,0 +1,600 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers(MP2891)
+ */
+
+#include <linux/bitfield.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include "pmbus.h"
+
+/*
+ * Vender specific registers, the register MFR_SVI3_IOUT_PRT(0x65),
+ * MFR_VOUT_LOOP_CTRL(0xBD), READ_PIN_EST(0x94)and READ_IIN_EST(0x95)
+ * redefine the standard PMBUS register. The MFR_SVI3_IOUT_PRT(0x65)
+ * is used to identify the iout scale and the MFR_VOUT_LOOP_CTRL(0xBD)
+ * is used to identify the vout scale. The READ_PIN_EST(0x94) is used
+ * to read input power per rail. The MP2891 does not have standard
+ * READ_IIN register(0x89), the iin telemetry can be obtained through
+ * the vendor redefined register READ_IIN_EST(0x95).
+ */
+#define MFR_VOUT_LOOP_CTRL 0xBD
+#define READ_PIN_EST 0x94
+#define READ_IIN_EST 0x95
+#define MFR_SVI3_IOUT_PRT 0x65
+
+#define MP2891_TEMP_LIMIT_OFFSET 40
+#define MP2891_PIN_LIMIT_UINT 2
+#define MP2891_IOUT_LIMIT_UINT 8
+#define MP2891_IOUT_SCALE_DIV 32
+#define MP2891_VOUT_SCALE_DIV 100
+#define MP2891_OVUV_DELTA_SCALE 50
+#define MP2891_OV_LIMIT_SCALE 20
+#define MP2891_UV_LIMIT_SCALE 5
+
+#define MP2891_PAGE_NUM 2
+
+#define MP2891_RAIL1_FUNC (PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | \
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP | \
+ PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | \
+ PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_VOUT | \
+ PMBUS_HAVE_STATUS_IOUT | \
+ PMBUS_HAVE_STATUS_INPUT | \
+ PMBUS_HAVE_STATUS_TEMP)
+
+#define MP2891_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | \
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_POUT | \
+ PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | \
+ PMBUS_HAVE_STATUS_VOUT | \
+ PMBUS_HAVE_STATUS_IOUT | \
+ PMBUS_HAVE_STATUS_INPUT | \
+ PMBUS_HAVE_STATUS_TEMP)
+
+struct mp2891_data {
+ struct pmbus_driver_info info;
+ int vout_scale[MP2891_PAGE_NUM];
+ int iout_scale[MP2891_PAGE_NUM];
+};
+
+#define to_mp2891_data(x) container_of(x, struct mp2891_data, info)
+
+/* Converts a LINEAR11 value to DIRECT format */
+static u16 mp2891_reg2data_linear11(u16 word)
+{
+ s16 exponent;
+ s32 mantissa;
+ s64 val;
+
+ exponent = ((s16)word) >> 11;
+ mantissa = ((s16)((word & 0x7ff) << 5)) >> 5;
+ val = mantissa;
+
+ if (exponent >= 0)
+ val <<= exponent;
+ else
+ val >>= -exponent;
+
+ return val;
+}
+
+static int
+mp2891_identify_vout_scale(struct i2c_client *client, struct pmbus_driver_info *info,
+ int page)
+{
+ struct mp2891_data *data = to_mp2891_data(info);
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_word_data(client, MFR_VOUT_LOOP_CTRL);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * The output voltage is equal to the READ_VOUT(0x8B) register value multiplied
+ * by vout_scale.
+ * Obtain vout scale from the register MFR_VOUT_LOOP_CTRL, bits 15-14,bit 13.
+ * If MFR_VOUT_LOOP_CTRL[13] = 1, the vout scale is below:
+ * 2.5mV/LSB
+ * If MFR_VOUT_LOOP_CTRL[13] = 0, the vout scale is decided by
+ * MFR_VOUT_LOOP_CTRL[15:14]:
+ * 00b - 6.25mV/LSB, 01b - 5mV/LSB, 10b - 2mV/LSB, 11b - 1mV
+ */
+ if (ret & GENMASK(13, 13)) {
+ data->vout_scale[page] = 250;
+ } else {
+ ret = FIELD_GET(GENMASK(15, 14), ret);
+ if (ret == 0)
+ data->vout_scale[page] = 625;
+ else if (ret == 1)
+ data->vout_scale[page] = 500;
+ else if (ret == 2)
+ data->vout_scale[page] = 200;
+ else
+ data->vout_scale[page] = 100;
+ }
+
+ return 0;
+}
+
+static int
+mp2891_identify_iout_scale(struct i2c_client *client, struct pmbus_driver_info *info,
+ int page)
+{
+ struct mp2891_data *data = to_mp2891_data(info);
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_word_data(client, MFR_SVI3_IOUT_PRT);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * The output current is equal to the READ_IOUT(0x8C) register value
+ * multiplied by iout_scale.
+ * Obtain iout_scale from the register MFR_SVI3_IOUT_PRT[2:0].
+ * The value is selected as below:
+ * 000b - 1A/LSB, 001b - (1/32)A/LSB, 010b - (1/16)A/LSB,
+ * 011b - (1/8)A/LSB, 100b - (1/4)A/LSB, 101b - (1/2)A/LSB
+ * 110b - 1A/LSB, 111b - 2A/LSB
+ */
+ switch (ret & GENMASK(2, 0)) {
+ case 0:
+ case 6:
+ data->iout_scale[page] = 32;
+ break;
+ case 1:
+ data->iout_scale[page] = 1;
+ break;
+ case 2:
+ data->iout_scale[page] = 2;
+ break;
+ case 3:
+ data->iout_scale[page] = 4;
+ break;
+ case 4:
+ data->iout_scale[page] = 8;
+ break;
+ case 5:
+ data->iout_scale[page] = 16;
+ break;
+ default:
+ data->iout_scale[page] = 64;
+ break;
+ }
+
+ return 0;
+}
+
+static int mp2891_identify(struct i2c_client *client, struct pmbus_driver_info *info)
+{
+ int ret;
+
+ /* Identify vout scale for rail 1. */
+ ret = mp2891_identify_vout_scale(client, info, 0);
+ if (ret < 0)
+ return ret;
+
+ /* Identify vout scale for rail 2. */
+ ret = mp2891_identify_vout_scale(client, info, 1);
+ if (ret < 0)
+ return ret;
+
+ /* Identify iout scale for rail 1. */
+ ret = mp2891_identify_iout_scale(client, info, 0);
+ if (ret < 0)
+ return ret;
+
+ /* Identify iout scale for rail 2. */
+ return mp2891_identify_iout_scale(client, info, 1);
+}
+
+static int mp2891_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VOUT_MODE:
+ /*
+ * The MP2891 does not follow standard PMBus protocol completely, the
+ * PMBUS_VOUT_MODE(0x20) in MP2891 is reserved and 0x00 is always
+ * returned when the register is read. But the calculation of vout in
+ * this driver is based on direct format. As a result, the format of
+ * vout is enforced to direct.
+ */
+ ret = PB_VOUT_MODE_DIRECT;
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+
+ return ret;
+}
+
+static int mp2891_read_word_data(struct i2c_client *client, int page,
+ int phase, int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct mp2891_data *data = to_mp2891_data(info);
+ int ret;
+
+ switch (reg) {
+ case PMBUS_READ_VIN:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = ret & GENMASK(9, 0);
+ break;
+ case PMBUS_READ_IIN:
+ /*
+ * The MP2891 does not have standard PMBUS_READ_IIN register(0x89),
+ * the iin telemetry can be obtained through the vender redefined
+ * register READ_IIN_EST(0x95). The MP2891 PMBUS_READ_IIN register
+ * is linear11 format, But the pout scale is set to 1A/Lsb(using
+ * r/m/b scale). As a result, the iin read from MP2891 should be
+ * calculated to A, then return the result to pmbus core.
+ */
+ ret = pmbus_read_word_data(client, page, phase, READ_IIN_EST);
+ if (ret < 0)
+ return ret;
+
+ ret = mp2891_reg2data_linear11(ret);
+ break;
+ case PMBUS_READ_PIN:
+ /*
+ * The MP2891 has standard PMBUS_READ_PIN register(0x97), but this
+ * is not used to read the input power per rail. The input power
+ * per rail is read through the vender redefined register
+ * READ_PIN_EST(0x94). The MP2891 PMBUS_READ_PIN register is linear11
+ * format, But the pout scale is set to 1W/Lsb(using r/m/b scale).
+ * As a result, the pin read from MP2891 should be calculated to W,
+ * then return the result to pmbus core.
+ */
+ ret = pmbus_read_word_data(client, page, phase, READ_PIN_EST);
+ if (ret < 0)
+ return ret;
+
+ ret = mp2891_reg2data_linear11(ret);
+ break;
+ case PMBUS_READ_POUT:
+ /*
+ * The MP2891 PMBUS_READ_POUT register is linear11 format, and the
+ * exponent is not a constant value. But the pout scale is set to
+ * 1W/Lsb(using r/m/b scale). As a result, the pout read from MP2891
+ * should be calculated to W, then return the result to pmbus core.
+ */
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = mp2891_reg2data_linear11(ret);
+ break;
+ case PMBUS_READ_VOUT:
+ case PMBUS_VOUT_UV_WARN_LIMIT:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = DIV_ROUND_CLOSEST(ret * data->vout_scale[page], MP2891_VOUT_SCALE_DIV);
+ break;
+ case PMBUS_READ_IOUT:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = DIV_ROUND_CLOSEST((ret & GENMASK(10, 0)) * data->iout_scale[page],
+ MP2891_IOUT_SCALE_DIV);
+ break;
+ case PMBUS_OT_FAULT_LIMIT:
+ case PMBUS_OT_WARN_LIMIT:
+ /*
+ * The scale of MP2891 PMBUS_OT_FAULT_LIMIT and PMBUS_OT_WARN_LIMIT
+ * is 1°C/LSB and they have 40°C offset.
+ */
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = (ret & GENMASK(7, 0)) - MP2891_TEMP_LIMIT_OFFSET;
+ break;
+ case PMBUS_VIN_OV_FAULT_LIMIT:
+ /*
+ * The MP2891 PMBUS_VIN_OV_FAULT_LIMIT scale is 125mV/Lsb.
+ * but the vin scale is set to 31.25mV/Lsb(using r/m/b scale).
+ * As a result, the limit value should be multiplied by 4.
+ */
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = (ret & GENMASK(7, 0)) * 4;
+ break;
+ case PMBUS_VOUT_UV_FAULT_LIMIT:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ if (FIELD_GET(GENMASK(11, 8), ret))
+ ret = FIELD_GET(GENMASK(7, 0), ret) * MP2891_UV_LIMIT_SCALE -
+ (FIELD_GET(GENMASK(11, 8), ret) + 1) * MP2891_OVUV_DELTA_SCALE;
+ else
+ ret = FIELD_GET(GENMASK(7, 0), ret) * MP2891_UV_LIMIT_SCALE;
+
+ ret = ret < 0 ? 0 : ret;
+ break;
+ case PMBUS_VOUT_OV_FAULT_LIMIT:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ if (FIELD_GET(GENMASK(11, 8), ret))
+ ret = FIELD_GET(GENMASK(7, 0), ret) * MP2891_OV_LIMIT_SCALE +
+ (FIELD_GET(GENMASK(11, 8), ret) + 1) * MP2891_OVUV_DELTA_SCALE;
+ else
+ ret = FIELD_GET(GENMASK(7, 0), ret) * MP2891_OV_LIMIT_SCALE;
+ break;
+ case PMBUS_IOUT_OC_WARN_LIMIT:
+ case PMBUS_IOUT_OC_FAULT_LIMIT:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = DIV_ROUND_CLOSEST((ret & GENMASK(7, 0)) * data->iout_scale[page] *
+ MP2891_IOUT_LIMIT_UINT, MP2891_IOUT_SCALE_DIV);
+ break;
+ case PMBUS_IIN_OC_WARN_LIMIT:
+ /*
+ * The scale of PMBUS_IIN_OC_WARN_LIMIT is 0.5A/Lsb, but the iin scale
+ * is set to 1A/Lsb(using r/m/b scale), so the word data should be
+ * divided by 2.
+ */
+ ret = pmbus_read_word_data(client, 0, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = DIV_ROUND_CLOSEST((ret & GENMASK(9, 0)), 2);
+ break;
+ case PMBUS_PIN_OP_WARN_LIMIT:
+ /*
+ * The scale of PMBUS_PIN_OP_WARN_LIMIT is 2W/Lsb, but the pin scale
+ * is set to 1W/Lsb(using r/m/b scale), so the word data should be
+ * multiplied by 2.
+ */
+ ret = pmbus_read_word_data(client, 0, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = (ret & GENMASK(9, 0)) * MP2891_PIN_LIMIT_UINT;
+ break;
+ case PMBUS_READ_TEMPERATURE_1:
+ case PMBUS_VIN_UV_FAULT_LIMIT:
+ case PMBUS_VIN_UV_WARN_LIMIT:
+ ret = -ENODATA;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int mp2891_write_word_data(struct i2c_client *client, int page, int reg,
+ u16 word)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct mp2891_data *data = to_mp2891_data(info);
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VOUT_UV_WARN_LIMIT:
+ ret = pmbus_write_word_data(client, page, reg,
+ DIV_ROUND_CLOSEST(word * MP2891_VOUT_SCALE_DIV,
+ data->vout_scale[page]));
+ break;
+ case PMBUS_VOUT_UV_FAULT_LIMIT:
+ /*
+ * The PMBUS_VOUT_UV_FAULT_LIMIT[7:0] is the limit value, and bit8-bit15
+ * should not be changed.
+ */
+ ret = pmbus_read_word_data(client, page, 0xff, reg);
+ if (ret < 0)
+ return ret;
+
+ if (FIELD_GET(GENMASK(11, 8), ret))
+ ret = pmbus_write_word_data(client, page, reg,
+ (ret & ~GENMASK(7, 0)) |
+ FIELD_PREP(GENMASK(7, 0),
+ DIV_ROUND_CLOSEST(word +
+ (FIELD_GET(GENMASK(11, 8), ret) + 1) *
+ MP2891_OVUV_DELTA_SCALE,
+ MP2891_UV_LIMIT_SCALE)));
+ else
+ ret = pmbus_write_word_data(client, page, reg,
+ (ret & ~GENMASK(7, 0)) |
+ FIELD_PREP(GENMASK(7, 0),
+ DIV_ROUND_CLOSEST(word,
+ MP2891_UV_LIMIT_SCALE)));
+ break;
+ case PMBUS_VOUT_OV_FAULT_LIMIT:
+ /*
+ * The PMBUS_VOUT_OV_FAULT_LIMIT[7:0] is the limit value, and bit8-bit15
+ * should not be changed.
+ */
+ ret = pmbus_read_word_data(client, page, 0xff, reg);
+ if (ret < 0)
+ return ret;
+
+ if (FIELD_GET(GENMASK(11, 8), ret))
+ ret = pmbus_write_word_data(client, page, reg,
+ (ret & ~GENMASK(7, 0)) |
+ FIELD_PREP(GENMASK(7, 0),
+ DIV_ROUND_CLOSEST(word -
+ (FIELD_GET(GENMASK(11, 8), ret) + 1) *
+ MP2891_OVUV_DELTA_SCALE,
+ MP2891_OV_LIMIT_SCALE)));
+ else
+ ret = pmbus_write_word_data(client, page, reg,
+ (ret & ~GENMASK(7, 0)) |
+ FIELD_PREP(GENMASK(7, 0),
+ DIV_ROUND_CLOSEST(word,
+ MP2891_OV_LIMIT_SCALE)));
+ break;
+ case PMBUS_VIN_OV_FAULT_LIMIT:
+ /*
+ * The PMBUS_VIN_OV_FAULT_LIMIT[7:0] is the limit value, and bit8-bit15
+ * should not be changed. The scale of PMBUS_VIN_OV_FAULT_LIMIT is 125mV/Lsb,
+ * but the vin scale is set to 31.25mV/Lsb(using r/m/b scale), so the word data
+ * should be divided by 4.
+ */
+ ret = pmbus_read_word_data(client, page, 0xff, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = pmbus_write_word_data(client, page, reg,
+ (ret & ~GENMASK(7, 0)) |
+ FIELD_PREP(GENMASK(7, 0),
+ DIV_ROUND_CLOSEST(word, 4)));
+ break;
+ case PMBUS_OT_FAULT_LIMIT:
+ case PMBUS_OT_WARN_LIMIT:
+ /*
+ * The scale of MP2891 PMBUS_OT_FAULT_LIMIT and PMBUS_OT_WARN_LIMIT
+ * have 40°C offset. The bit0-bit7 is the limit value, and bit8-bit15
+ * should not be changed.
+ */
+ ret = pmbus_read_word_data(client, page, 0xff, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = pmbus_write_word_data(client, page, reg,
+ (ret & ~GENMASK(7, 0)) |
+ FIELD_PREP(GENMASK(7, 0), word + MP2891_TEMP_LIMIT_OFFSET));
+ break;
+ case PMBUS_IOUT_OC_WARN_LIMIT:
+ case PMBUS_IOUT_OC_FAULT_LIMIT:
+ ret = pmbus_write_word_data(client, page, reg,
+ DIV_ROUND_CLOSEST(word * MP2891_IOUT_SCALE_DIV,
+ MP2891_IOUT_LIMIT_UINT *
+ data->iout_scale[page]));
+ break;
+ case PMBUS_IIN_OC_WARN_LIMIT:
+ /*
+ * The scale of PMBUS_IIN_OC_WARN_LIMIT is 0.5A/Lsb, but the iin scale
+ * is set to 1A/Lsb(using r/m/b scale), so the word data should be
+ * multiplied by 2.
+ */
+ ret = pmbus_write_word_data(client, page, reg, word * 2);
+ break;
+ case PMBUS_PIN_OP_WARN_LIMIT:
+ /*
+ * The scale of PMBUS_PIN_OP_WARN_LIMIT is 2W/Lsb, but the pin scale
+ * is set to 1W/Lsb(using r/m/b scale), so the word data should be
+ * divided by 2.
+ */
+ ret = pmbus_write_word_data(client, page, reg,
+ DIV_ROUND_CLOSEST(word, MP2891_PIN_LIMIT_UINT));
+ break;
+ case PMBUS_VIN_UV_FAULT_LIMIT:
+ case PMBUS_VIN_UV_WARN_LIMIT:
+ ret = -ENODATA;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static const struct pmbus_driver_info mp2891_info = {
+ .pages = MP2891_PAGE_NUM,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_CURRENT_IN] = direct,
+ .format[PSC_CURRENT_OUT] = direct,
+ .format[PSC_TEMPERATURE] = direct,
+ .format[PSC_POWER] = direct,
+ .format[PSC_VOLTAGE_OUT] = direct,
+
+ /* set vin scale 31.25mV/Lsb */
+ .m[PSC_VOLTAGE_IN] = 32,
+ .R[PSC_VOLTAGE_IN] = 0,
+ .b[PSC_VOLTAGE_IN] = 0,
+
+ /* set temp scale 1000m°C/Lsb */
+ .m[PSC_TEMPERATURE] = 1,
+ .R[PSC_TEMPERATURE] = 0,
+ .b[PSC_TEMPERATURE] = 0,
+
+ .m[PSC_CURRENT_IN] = 1,
+ .R[PSC_CURRENT_IN] = 0,
+ .b[PSC_CURRENT_IN] = 0,
+
+ .m[PSC_CURRENT_OUT] = 1,
+ .R[PSC_CURRENT_OUT] = 0,
+ .b[PSC_CURRENT_OUT] = 0,
+
+ .m[PSC_POWER] = 1,
+ .R[PSC_POWER] = 0,
+ .b[PSC_POWER] = 0,
+
+ .m[PSC_VOLTAGE_OUT] = 1,
+ .R[PSC_VOLTAGE_OUT] = 3,
+ .b[PSC_VOLTAGE_OUT] = 0,
+
+ .func[0] = MP2891_RAIL1_FUNC,
+ .func[1] = MP2891_RAIL2_FUNC,
+ .read_word_data = mp2891_read_word_data,
+ .write_word_data = mp2891_write_word_data,
+ .read_byte_data = mp2891_read_byte_data,
+ .identify = mp2891_identify,
+};
+
+static int mp2891_probe(struct i2c_client *client)
+{
+ struct mp2891_data *data;
+
+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ memcpy(&data->info, &mp2891_info, sizeof(mp2891_info));
+
+ return pmbus_do_probe(client, &data->info);
+}
+
+static const struct i2c_device_id mp2891_id[] = {
+ {"mp2891", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, mp2891_id);
+
+static const struct of_device_id __maybe_unused mp2891_of_match[] = {
+ {.compatible = "mps,mp2891"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, mp2891_of_match);
+
+static struct i2c_driver mp2891_driver = {
+ .driver = {
+ .name = "mp2891",
+ .of_match_table = mp2891_of_match,
+ },
+ .probe = mp2891_probe,
+ .id_table = mp2891_id,
+};
+
+module_i2c_driver(mp2891_driver);
+
+MODULE_AUTHOR("Noah Wang <[email protected]>");
+MODULE_DESCRIPTION("PMBus driver for MPS MP2891");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(PMBUS);
diff --git a/drivers/hwmon/pmbus/mp2993.c b/drivers/hwmon/pmbus/mp2993.c
new file mode 100644
index 000000000000..944593e13231
--- /dev/null
+++ b/drivers/hwmon/pmbus/mp2993.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers(MP2993)
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include "pmbus.h"
+
+#define MP2993_VOUT_OVUV_UINT 125
+#define MP2993_VOUT_OVUV_DIV 64
+#define MP2993_VIN_LIMIT_UINT 1
+#define MP2993_VIN_LIMIT_DIV 8
+#define MP2993_READ_VIN_UINT 1
+#define MP2993_READ_VIN_DIV 32
+
+#define MP2993_PAGE_NUM 2
+
+#define MP2993_RAIL1_FUNC (PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | \
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_POUT | \
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_PIN | \
+ PMBUS_HAVE_IIN | \
+ PMBUS_HAVE_STATUS_VOUT | \
+ PMBUS_HAVE_STATUS_IOUT | \
+ PMBUS_HAVE_STATUS_TEMP | \
+ PMBUS_HAVE_STATUS_INPUT)
+
+#define MP2993_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | \
+ PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP | \
+ PMBUS_HAVE_STATUS_VOUT | \
+ PMBUS_HAVE_STATUS_IOUT | \
+ PMBUS_HAVE_STATUS_TEMP | \
+ PMBUS_HAVE_STATUS_INPUT)
+
+/* Converts a linear11 data exponent to a specified value */
+static u16 mp2993_linear11_exponent_transfer(u16 word, u16 expect_exponent)
+{
+ s16 exponent, mantissa, target_exponent;
+
+ exponent = ((s16)word) >> 11;
+ mantissa = ((s16)((word & 0x7ff) << 5)) >> 5;
+ target_exponent = (s16)((expect_exponent & 0x1f) << 11) >> 11;
+
+ if (exponent > target_exponent)
+ mantissa = mantissa << (exponent - target_exponent);
+ else
+ mantissa = mantissa >> (target_exponent - exponent);
+
+ return (mantissa & 0x7ff) | ((expect_exponent << 11) & 0xf800);
+}
+
+static int
+mp2993_set_vout_format(struct i2c_client *client, int page, int format)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
+ if (ret < 0)
+ return ret;
+
+ return i2c_smbus_write_byte_data(client, PMBUS_VOUT_MODE, format);
+}
+
+static int mp2993_identify(struct i2c_client *client, struct pmbus_driver_info *info)
+{
+ int ret;
+
+ /* Set vout to direct format for rail1. */
+ ret = mp2993_set_vout_format(client, 0, PB_VOUT_MODE_DIRECT);
+ if (ret < 0)
+ return ret;
+
+ /* Set vout to direct format for rail2. */
+ return mp2993_set_vout_format(client, 1, PB_VOUT_MODE_DIRECT);
+}
+
+static int mp2993_read_word_data(struct i2c_client *client, int page, int phase,
+ int reg)
+{
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VOUT_OV_FAULT_LIMIT:
+ case PMBUS_VOUT_UV_FAULT_LIMIT:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = DIV_ROUND_CLOSEST(ret * MP2993_VOUT_OVUV_UINT, MP2993_VOUT_OVUV_DIV);
+ break;
+ case PMBUS_OT_FAULT_LIMIT:
+ case PMBUS_OT_WARN_LIMIT:
+ /*
+ * The MP2993 ot fault limit value and ot warn limit value
+ * per rail are always the same, so only PMBUS_OT_FAULT_LIMIT
+ * and PMBUS_OT_WARN_LIMIT register in page 0 are defined to
+ * indicates the limit value.
+ */
+ ret = pmbus_read_word_data(client, 0, phase, reg);
+ break;
+ case PMBUS_READ_VIN:
+ /* The MP2993 vin scale is (1/32V)/Lsb */
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = DIV_ROUND_CLOSEST((ret & GENMASK(9, 0)) * MP2993_READ_VIN_UINT,
+ MP2993_READ_VIN_DIV);
+ break;
+ case PMBUS_VIN_OV_FAULT_LIMIT:
+ case PMBUS_VIN_OV_WARN_LIMIT:
+ case PMBUS_VIN_UV_WARN_LIMIT:
+ case PMBUS_VIN_UV_FAULT_LIMIT:
+ /* The MP2993 vin limit scale is (1/8V)/Lsb */
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = DIV_ROUND_CLOSEST((ret & GENMASK(7, 0)) * MP2993_VIN_LIMIT_UINT,
+ MP2993_VIN_LIMIT_DIV);
+ break;
+ case PMBUS_READ_IOUT:
+ case PMBUS_READ_IIN:
+ case PMBUS_IIN_OC_WARN_LIMIT:
+ case PMBUS_IOUT_OC_FAULT_LIMIT:
+ case PMBUS_IOUT_OC_WARN_LIMIT:
+ case PMBUS_READ_VOUT:
+ case PMBUS_READ_PIN:
+ case PMBUS_READ_POUT:
+ case PMBUS_READ_TEMPERATURE_1:
+ ret = -ENODATA;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int mp2993_write_word_data(struct i2c_client *client, int page, int reg,
+ u16 word)
+{
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VOUT_OV_FAULT_LIMIT:
+ case PMBUS_VOUT_UV_FAULT_LIMIT:
+ ret = DIV_ROUND_CLOSEST(word * MP2993_VOUT_OVUV_DIV, MP2993_VOUT_OVUV_UINT);
+ ret = pmbus_write_word_data(client, 0, reg, ret);
+ break;
+ case PMBUS_OT_FAULT_LIMIT:
+ case PMBUS_OT_WARN_LIMIT:
+ /*
+ * The MP2993 ot fault limit value and ot warn limit value
+ * per rail are always the same, so only PMBUS_OT_FAULT_LIMIT
+ * and PMBUS_OT_WARN_LIMIT register in page 0 are defined to
+ * config the ot limit value.
+ */
+ ret = pmbus_write_word_data(client, 0, reg, word);
+ break;
+ case PMBUS_VIN_OV_FAULT_LIMIT:
+ case PMBUS_VIN_OV_WARN_LIMIT:
+ case PMBUS_VIN_UV_WARN_LIMIT:
+ case PMBUS_VIN_UV_FAULT_LIMIT:
+ /* The MP2993 vin limit scale is (1/8V)/Lsb */
+ ret = pmbus_write_word_data(client, 0, reg,
+ DIV_ROUND_CLOSEST(word * MP2993_VIN_LIMIT_DIV,
+ MP2993_VIN_LIMIT_UINT));
+ break;
+ case PMBUS_IIN_OC_WARN_LIMIT:
+ /*
+ * The PMBUS_IIN_OC_WARN_LIMIT of MP2993 is linear11 format,
+ * and the exponent is a constant value(5'b00000), so the
+ * exponent of word parameter should be converted to 5'b00000.
+ */
+ ret = pmbus_write_word_data(client, page, reg,
+ mp2993_linear11_exponent_transfer(word, 0x00));
+ break;
+ //
+ case PMBUS_IOUT_OC_FAULT_LIMIT:
+ case PMBUS_IOUT_OC_WARN_LIMIT:
+ /*
+ * The PMBUS_IOUT_OC_FAULT_LIMIT and PMBUS_IOUT_OC_WARN_LIMIT
+ * of MP2993 can be regarded as linear11 format, and the
+ * exponent is a 5'b00001 or 5'b00000. To ensure a larger
+ * range of limit value, so the exponent of word parameter
+ * should be converted to 5'b00001.
+ */
+ ret = pmbus_write_word_data(client, page, reg,
+ mp2993_linear11_exponent_transfer(word, 0x01));
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static struct pmbus_driver_info mp2993_info = {
+ .pages = MP2993_PAGE_NUM,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_CURRENT_IN] = linear,
+ .format[PSC_CURRENT_OUT] = linear,
+ .format[PSC_TEMPERATURE] = direct,
+ .format[PSC_POWER] = linear,
+ .format[PSC_VOLTAGE_OUT] = direct,
+
+ .m[PSC_VOLTAGE_OUT] = 1,
+ .R[PSC_VOLTAGE_OUT] = 3,
+ .b[PSC_VOLTAGE_OUT] = 0,
+
+ .m[PSC_VOLTAGE_IN] = 1,
+ .R[PSC_VOLTAGE_IN] = 0,
+ .b[PSC_VOLTAGE_IN] = 0,
+
+ .m[PSC_TEMPERATURE] = 1,
+ .R[PSC_TEMPERATURE] = 0,
+ .b[PSC_TEMPERATURE] = 0,
+
+ .func[0] = MP2993_RAIL1_FUNC,
+ .func[1] = MP2993_RAIL2_FUNC,
+ .read_word_data = mp2993_read_word_data,
+ .write_word_data = mp2993_write_word_data,
+ .identify = mp2993_identify,
+};
+
+static int mp2993_probe(struct i2c_client *client)
+{
+ return pmbus_do_probe(client, &mp2993_info);
+}
+
+static const struct i2c_device_id mp2993_id[] = {
+ {"mp2993", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, mp2993_id);
+
+static const struct of_device_id __maybe_unused mp2993_of_match[] = {
+ {.compatible = "mps,mp2993"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, mp2993_of_match);
+
+static struct i2c_driver mp2993_driver = {
+ .driver = {
+ .name = "mp2993",
+ .of_match_table = mp2993_of_match,
+ },
+ .probe = mp2993_probe,
+ .id_table = mp2993_id,
+};
+
+module_i2c_driver(mp2993_driver);
+
+MODULE_AUTHOR("Noah Wang <[email protected]>");
+MODULE_DESCRIPTION("PMBus driver for MPS MP2993");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(PMBUS);
diff --git a/drivers/hwmon/pmbus/mp5920.c b/drivers/hwmon/pmbus/mp5920.c
new file mode 100644
index 000000000000..f6d7527ade7d
--- /dev/null
+++ b/drivers/hwmon/pmbus/mp5920.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hardware monitoring driver for MP5920 and compatible chips.
+ */
+
+#include <linux/i2c.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include "pmbus.h"
+
+static struct pmbus_driver_info mp5920_info = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .format[PSC_CURRENT_OUT] = direct,
+ .format[PSC_POWER] = direct,
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_VOLTAGE_IN] = 2266,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = -1,
+ .m[PSC_VOLTAGE_OUT] = 2266,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = -1,
+ .m[PSC_CURRENT_OUT] = 546,
+ .b[PSC_CURRENT_OUT] = 0,
+ .R[PSC_CURRENT_OUT] = -2,
+ .m[PSC_POWER] = 5840,
+ .b[PSC_POWER] = 0,
+ .R[PSC_POWER] = -3,
+ .m[PSC_TEMPERATURE] = 1067,
+ .b[PSC_TEMPERATURE] = 20500,
+ .R[PSC_TEMPERATURE] = -2,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_POUT |
+ PMBUS_HAVE_TEMP,
+};
+
+static int mp5920_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ int ret;
+ u8 buf[I2C_SMBUS_BLOCK_MAX];
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_WORD_DATA))
+ return -ENODEV;
+
+ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to read PMBUS_MFR_MODEL\n");
+
+ if (ret != 6 || strncmp(buf, "MP5920", 6)) {
+ return dev_err_probe(dev, -ENODEV, "Model '%.*s' not supported\n",
+ min_t(int, ret, sizeof(buf)), buf);
+ }
+
+ return pmbus_do_probe(client, &mp5920_info);
+}
+
+static const struct of_device_id mp5920_of_match[] = {
+ { .compatible = "mps,mp5920" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, mp5920_of_match);
+
+static const struct i2c_device_id mp5920_id[] = {
+ { "mp5920" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, mp5920_id);
+
+static struct i2c_driver mp5920_driver = {
+ .driver = {
+ .name = "mp5920",
+ .of_match_table = mp5920_of_match,
+ },
+ .probe = mp5920_probe,
+ .id_table = mp5920_id,
+};
+
+module_i2c_driver(mp5920_driver);
+
+MODULE_AUTHOR("Tony Ao <[email protected]>");
+MODULE_AUTHOR("Alex Vdovydchenko <[email protected]>");
+MODULE_DESCRIPTION("PMBus driver for MP5920 HSC");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(PMBUS);
diff --git a/drivers/hwmon/pmbus/mp9941.c b/drivers/hwmon/pmbus/mp9941.c
new file mode 100644
index 000000000000..543955cfce67
--- /dev/null
+++ b/drivers/hwmon/pmbus/mp9941.c
@@ -0,0 +1,319 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers(MP9941)
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include "pmbus.h"
+
+/*
+ * Vender specific registers. The MFR_ICC_MAX(0x02) is used to
+ * config the iin scale. The MFR_RESO_SET(0xC7) is used to
+ * config the vout format. The MFR_VR_MULTI_CONFIG_R1(0x0D) is
+ * used to identify the vout vid step.
+ */
+#define MFR_ICC_MAX 0x02
+#define MFR_RESO_SET 0xC7
+#define MFR_VR_MULTI_CONFIG_R1 0x0D
+
+#define MP9941_VIN_LIMIT_UINT 1
+#define MP9941_VIN_LIMIT_DIV 8
+#define MP9941_READ_VIN_UINT 1
+#define MP9941_READ_VIN_DIV 32
+
+#define MP9941_PAGE_NUM 1
+
+#define MP9941_RAIL1_FUNC (PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | \
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_POUT | \
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_PIN | \
+ PMBUS_HAVE_IIN | \
+ PMBUS_HAVE_STATUS_VOUT | \
+ PMBUS_HAVE_STATUS_IOUT | \
+ PMBUS_HAVE_STATUS_TEMP | \
+ PMBUS_HAVE_STATUS_INPUT)
+
+struct mp9941_data {
+ struct pmbus_driver_info info;
+ int vid_resolution;
+};
+
+#define to_mp9941_data(x) container_of(x, struct mp9941_data, info)
+
+static int mp9941_set_vout_format(struct i2c_client *client)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_word_data(client, MFR_RESO_SET);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * page = 0, MFR_RESO_SET[7:6] defines the vout format
+ * 2'b11 set the vout format as direct
+ */
+ ret = (ret & ~GENMASK(7, 6)) | FIELD_PREP(GENMASK(7, 6), 3);
+
+ return i2c_smbus_write_word_data(client, MFR_RESO_SET, ret);
+}
+
+static int
+mp9941_identify_vid_resolution(struct i2c_client *client, struct pmbus_driver_info *info)
+{
+ struct mp9941_data *data = to_mp9941_data(info);
+ int ret;
+
+ /*
+ * page = 2, MFR_VR_MULTI_CONFIG_R1[4:4] defines rail1 vid step value
+ * 1'b0 represents the vid step value is 10mV
+ * 1'b1 represents the vid step value is 5mV
+ */
+ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_word_data(client, MFR_VR_MULTI_CONFIG_R1);
+ if (ret < 0)
+ return ret;
+
+ if (FIELD_GET(GENMASK(4, 4), ret))
+ data->vid_resolution = 5;
+ else
+ data->vid_resolution = 10;
+
+ return 0;
+}
+
+static int mp9941_identify_iin_scale(struct i2c_client *client)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_word_data(client, MFR_RESO_SET);
+ if (ret < 0)
+ return ret;
+
+ ret = (ret & ~GENMASK(3, 2)) | FIELD_PREP(GENMASK(3, 2), 0);
+
+ ret = i2c_smbus_write_word_data(client, MFR_RESO_SET, ret);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * page = 2, MFR_ICC_MAX[15:13] defines the iin scale
+ * 3'b000 set the iout scale as 0.5A/Lsb
+ */
+ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_word_data(client, MFR_ICC_MAX);
+ if (ret < 0)
+ return ret;
+
+ ret = (ret & ~GENMASK(15, 13)) | FIELD_PREP(GENMASK(15, 13), 0);
+
+ return i2c_smbus_write_word_data(client, MFR_ICC_MAX, ret);
+}
+
+static int mp9941_identify(struct i2c_client *client, struct pmbus_driver_info *info)
+{
+ int ret;
+
+ ret = mp9941_identify_iin_scale(client);
+ if (ret < 0)
+ return ret;
+
+ ret = mp9941_identify_vid_resolution(client, info);
+ if (ret < 0)
+ return ret;
+
+ return mp9941_set_vout_format(client);
+}
+
+static int mp9941_read_word_data(struct i2c_client *client, int page, int phase,
+ int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct mp9941_data *data = to_mp9941_data(info);
+ int ret;
+
+ switch (reg) {
+ case PMBUS_READ_VIN:
+ /* The MP9941 vin scale is (1/32V)/Lsb */
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = DIV_ROUND_CLOSEST((ret & GENMASK(9, 0)) * MP9941_READ_VIN_UINT,
+ MP9941_READ_VIN_DIV);
+ break;
+ case PMBUS_READ_IIN:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = ret & GENMASK(10, 0);
+ break;
+ case PMBUS_VIN_OV_FAULT_LIMIT:
+ /* The MP9941 vin ov limit scale is (1/8V)/Lsb */
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = DIV_ROUND_CLOSEST((ret & GENMASK(7, 0)) * MP9941_VIN_LIMIT_UINT,
+ MP9941_VIN_LIMIT_DIV);
+ break;
+ case PMBUS_IIN_OC_WARN_LIMIT:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = ret & GENMASK(7, 0);
+ break;
+ case PMBUS_VOUT_UV_FAULT_LIMIT:
+ case PMBUS_MFR_VOUT_MIN:
+ case PMBUS_MFR_VOUT_MAX:
+ /*
+ * The vout scale is set to 1mV/Lsb(using r/m/b scale).
+ * But the vout uv limit and vout max/min scale is 1VID/Lsb,
+ * so the vout uv limit and vout max/min value should be
+ * multiplied by vid resolution.
+ */
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret < 0)
+ return ret;
+
+ ret = ret * data->vid_resolution;
+ break;
+ case PMBUS_READ_IOUT:
+ case PMBUS_READ_POUT:
+ case PMBUS_READ_TEMPERATURE_1:
+ case PMBUS_READ_VOUT:
+ case PMBUS_READ_PIN:
+ case PMBUS_OT_FAULT_LIMIT:
+ case PMBUS_OT_WARN_LIMIT:
+ ret = -ENODATA;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int mp9941_write_word_data(struct i2c_client *client, int page, int reg,
+ u16 word)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct mp9941_data *data = to_mp9941_data(info);
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VIN_OV_FAULT_LIMIT:
+ /* The MP9941 vin ov limit scale is (1/8V)/Lsb */
+ ret = pmbus_write_word_data(client, page, reg,
+ DIV_ROUND_CLOSEST(word * MP9941_VIN_LIMIT_DIV,
+ MP9941_VIN_LIMIT_UINT));
+ break;
+ case PMBUS_VOUT_UV_FAULT_LIMIT:
+ case PMBUS_MFR_VOUT_MIN:
+ case PMBUS_MFR_VOUT_MAX:
+ ret = pmbus_write_word_data(client, page, reg,
+ DIV_ROUND_CLOSEST(word, data->vid_resolution));
+ break;
+ case PMBUS_IIN_OC_WARN_LIMIT:
+ case PMBUS_OT_FAULT_LIMIT:
+ case PMBUS_OT_WARN_LIMIT:
+ ret = -ENODATA;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static const struct pmbus_driver_info mp9941_info = {
+ .pages = MP9941_PAGE_NUM,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_CURRENT_IN] = direct,
+ .format[PSC_CURRENT_OUT] = linear,
+ .format[PSC_POWER] = linear,
+ .format[PSC_TEMPERATURE] = direct,
+ .format[PSC_VOLTAGE_OUT] = direct,
+
+ .m[PSC_TEMPERATURE] = 1,
+ .R[PSC_TEMPERATURE] = 0,
+ .b[PSC_TEMPERATURE] = 0,
+
+ .m[PSC_VOLTAGE_IN] = 1,
+ .R[PSC_VOLTAGE_IN] = 0,
+ .b[PSC_VOLTAGE_IN] = 0,
+
+ .m[PSC_CURRENT_IN] = 2,
+ .R[PSC_CURRENT_IN] = 0,
+ .b[PSC_CURRENT_IN] = 0,
+
+ .m[PSC_VOLTAGE_OUT] = 1,
+ .R[PSC_VOLTAGE_OUT] = 3,
+ .b[PSC_VOLTAGE_OUT] = 0,
+
+ .func[0] = MP9941_RAIL1_FUNC,
+ .read_word_data = mp9941_read_word_data,
+ .write_word_data = mp9941_write_word_data,
+ .identify = mp9941_identify,
+};
+
+static int mp9941_probe(struct i2c_client *client)
+{
+ struct mp9941_data *data;
+
+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ memcpy(&data->info, &mp9941_info, sizeof(mp9941_info));
+
+ return pmbus_do_probe(client, &data->info);
+}
+
+static const struct i2c_device_id mp9941_id[] = {
+ {"mp9941", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, mp9941_id);
+
+static const struct of_device_id __maybe_unused mp9941_of_match[] = {
+ {.compatible = "mps,mp9941"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, mp9941_of_match);
+
+static struct i2c_driver mp9941_driver = {
+ .driver = {
+ .name = "mp9941",
+ .of_match_table = mp9941_of_match,
+ },
+ .probe = mp9941_probe,
+ .id_table = mp9941_id,
+};
+
+module_i2c_driver(mp9941_driver);
+
+MODULE_AUTHOR("Noah Wang <[email protected]>");
+MODULE_DESCRIPTION("PMBus driver for MPS MP9941");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(PMBUS);
diff --git a/drivers/hwmon/powr1220.c b/drivers/hwmon/powr1220.c
index 2388d0565e7e..5f9ca6543530 100644
--- a/drivers/hwmon/powr1220.c
+++ b/drivers/hwmon/powr1220.c
@@ -279,12 +279,11 @@ static const struct hwmon_chip_info powr1220_chip_info = {
.info = powr1220_info,
};
-static const struct i2c_device_id powr1220_ids[];
-
static int powr1220_probe(struct i2c_client *client)
{
struct powr1220_data *data;
struct device *hwmon_dev;
+ enum powr1xxx_chips chip;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
@@ -293,7 +292,8 @@ static int powr1220_probe(struct i2c_client *client)
if (!data)
return -ENOMEM;
- switch (i2c_match_id(powr1220_ids, client)->driver_data) {
+ chip = (uintptr_t)i2c_get_match_data(client);
+ switch (chip) {
case powr1014:
data->max_channels = 10;
break;
diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c
index c0d02fbcdb76..650b0bcc2359 100644
--- a/drivers/hwmon/sht3x.c
+++ b/drivers/hwmon/sht3x.c
@@ -882,15 +882,6 @@ static const struct hwmon_chip_info sht3x_chip_info = {
.info = sht3x_channel_info,
};
-/* device ID table */
-static const struct i2c_device_id sht3x_ids[] = {
- {"sht3x", sht3x},
- {"sts3x", sts3x},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, sht3x_ids);
-
static int sht3x_probe(struct i2c_client *client)
{
int ret;
@@ -920,7 +911,7 @@ static int sht3x_probe(struct i2c_client *client)
data->mode = 0;
data->last_update = jiffies - msecs_to_jiffies(3000);
data->client = client;
- data->chip_id = i2c_match_id(sht3x_ids, client)->driver_data;
+ data->chip_id = (uintptr_t)i2c_get_match_data(client);
crc8_populate_msb(sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL);
sht3x_select_command(data);
@@ -963,6 +954,15 @@ static int sht3x_probe(struct i2c_client *client)
return PTR_ERR_OR_ZERO(hwmon_dev);
}
+/* device ID table */
+static const struct i2c_device_id sht3x_ids[] = {
+ {"sht3x", sht3x},
+ {"sts3x", sts3x},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, sht3x_ids);
+
static struct i2c_driver sht3x_i2c_driver = {
.driver.name = "sht3x",
.probe = sht3x_probe,
diff --git a/drivers/hwmon/shtc1.c b/drivers/hwmon/shtc1.c
index 439dd3dba5fc..2ac906e8e173 100644
--- a/drivers/hwmon/shtc1.c
+++ b/drivers/hwmon/shtc1.c
@@ -186,8 +186,6 @@ static void shtc1_select_command(struct shtc1_data *data)
}
}
-static const struct i2c_device_id shtc1_id[];
-
static int shtc1_probe(struct i2c_client *client)
{
int ret;
@@ -195,7 +193,7 @@ static int shtc1_probe(struct i2c_client *client)
char id_reg_buf[2];
struct shtc1_data *data;
struct device *hwmon_dev;
- enum shtcx_chips chip = i2c_match_id(shtc1_id, client)->driver_data;
+ enum shtcx_chips chip = (uintptr_t)i2c_get_match_data(client);
struct i2c_adapter *adap = client->adapter;
struct device *dev = &client->dev;
struct device_node *np = dev->of_node;
diff --git a/drivers/hwmon/spd5118.c b/drivers/hwmon/spd5118.c
new file mode 100644
index 000000000000..fcbce5a01e55
--- /dev/null
+++ b/drivers/hwmon/spd5118.c
@@ -0,0 +1,703 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for Jedec 5118 compliant temperature sensors
+ *
+ * Derived from https://github.com/Steve-Tech/SPD5118-DKMS
+ * Originally from T/2 driver at https://t2sde.org/packages/linux
+ * Copyright (c) 2023 René Rebe, ExactCODE GmbH; Germany.
+ *
+ * Copyright (c) 2024 Guenter Roeck
+ *
+ * Inspired by ee1004.c and jc42.c.
+ *
+ * SPD5118 compliant temperature sensors are typically used on DDR5
+ * memory modules.
+ */
+
+#include <linux/bitops.h>
+#include <linux/bits.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/nvmem-provider.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/units.h>
+
+/* Addresses to scan */
+static const unsigned short normal_i2c[] = {
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, I2C_CLIENT_END };
+
+/* SPD5118 registers. */
+#define SPD5118_REG_TYPE 0x00 /* MR0:MR1 */
+#define SPD5118_REG_REVISION 0x02 /* MR2 */
+#define SPD5118_REG_VENDOR 0x03 /* MR3:MR4 */
+#define SPD5118_REG_CAPABILITY 0x05 /* MR5 */
+#define SPD5118_REG_I2C_LEGACY_MODE 0x0B /* MR11 */
+#define SPD5118_REG_TEMP_CLR 0x13 /* MR19 */
+#define SPD5118_REG_ERROR_CLR 0x14 /* MR20 */
+#define SPD5118_REG_TEMP_CONFIG 0x1A /* MR26 */
+#define SPD5118_REG_TEMP_MAX 0x1c /* MR28:MR29 */
+#define SPD5118_REG_TEMP_MIN 0x1e /* MR30:MR31 */
+#define SPD5118_REG_TEMP_CRIT 0x20 /* MR32:MR33 */
+#define SPD5118_REG_TEMP_LCRIT 0x22 /* MR34:MR35 */
+#define SPD5118_REG_TEMP 0x31 /* MR49:MR50 */
+#define SPD5118_REG_TEMP_STATUS 0x33 /* MR51 */
+
+#define SPD5118_TEMP_STATUS_HIGH BIT(0)
+#define SPD5118_TEMP_STATUS_LOW BIT(1)
+#define SPD5118_TEMP_STATUS_CRIT BIT(2)
+#define SPD5118_TEMP_STATUS_LCRIT BIT(3)
+
+#define SPD5118_CAP_TS_SUPPORT BIT(1) /* temperature sensor support */
+
+#define SPD5118_TS_DISABLE BIT(0) /* temperature sensor disable */
+
+#define SPD5118_LEGACY_MODE_ADDR BIT(3)
+#define SPD5118_LEGACY_PAGE_MASK GENMASK(2, 0)
+#define SPD5118_LEGACY_MODE_MASK (SPD5118_LEGACY_MODE_ADDR | SPD5118_LEGACY_PAGE_MASK)
+
+#define SPD5118_NUM_PAGES 8
+#define SPD5118_PAGE_SIZE 128
+#define SPD5118_PAGE_SHIFT 7
+#define SPD5118_PAGE_MASK GENMASK(6, 0)
+#define SPD5118_EEPROM_BASE 0x80
+#define SPD5118_EEPROM_SIZE (SPD5118_PAGE_SIZE * SPD5118_NUM_PAGES)
+
+/* Temperature unit in millicelsius */
+#define SPD5118_TEMP_UNIT (MILLIDEGREE_PER_DEGREE / 4)
+/* Representable temperature range in millicelsius */
+#define SPD5118_TEMP_RANGE_MIN -256000
+#define SPD5118_TEMP_RANGE_MAX 255750
+
+struct spd5118_data {
+ struct regmap *regmap;
+ struct mutex nvmem_lock;
+};
+
+/* hwmon */
+
+static int spd5118_temp_from_reg(u16 reg)
+{
+ int temp = sign_extend32(reg >> 2, 10);
+
+ return temp * SPD5118_TEMP_UNIT;
+}
+
+static u16 spd5118_temp_to_reg(long temp)
+{
+ temp = clamp_val(temp, SPD5118_TEMP_RANGE_MIN, SPD5118_TEMP_RANGE_MAX);
+ return (DIV_ROUND_CLOSEST(temp, SPD5118_TEMP_UNIT) & 0x7ff) << 2;
+}
+
+static int spd5118_read_temp(struct regmap *regmap, u32 attr, long *val)
+{
+ int reg, err;
+ u8 regval[2];
+ u16 temp;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ reg = SPD5118_REG_TEMP;
+ break;
+ case hwmon_temp_max:
+ reg = SPD5118_REG_TEMP_MAX;
+ break;
+ case hwmon_temp_min:
+ reg = SPD5118_REG_TEMP_MIN;
+ break;
+ case hwmon_temp_crit:
+ reg = SPD5118_REG_TEMP_CRIT;
+ break;
+ case hwmon_temp_lcrit:
+ reg = SPD5118_REG_TEMP_LCRIT;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ err = regmap_bulk_read(regmap, reg, regval, 2);
+ if (err)
+ return err;
+
+ temp = (regval[1] << 8) | regval[0];
+
+ *val = spd5118_temp_from_reg(temp);
+ return 0;
+}
+
+static int spd5118_read_alarm(struct regmap *regmap, u32 attr, long *val)
+{
+ unsigned int mask, regval;
+ int err;
+
+ switch (attr) {
+ case hwmon_temp_max_alarm:
+ mask = SPD5118_TEMP_STATUS_HIGH;
+ break;
+ case hwmon_temp_min_alarm:
+ mask = SPD5118_TEMP_STATUS_LOW;
+ break;
+ case hwmon_temp_crit_alarm:
+ mask = SPD5118_TEMP_STATUS_CRIT;
+ break;
+ case hwmon_temp_lcrit_alarm:
+ mask = SPD5118_TEMP_STATUS_LCRIT;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ err = regmap_read(regmap, SPD5118_REG_TEMP_STATUS, &regval);
+ if (err < 0)
+ return err;
+ *val = !!(regval & mask);
+ if (*val)
+ return regmap_write(regmap, SPD5118_REG_TEMP_CLR, mask);
+ return 0;
+}
+
+static int spd5118_read_enable(struct regmap *regmap, long *val)
+{
+ u32 regval;
+ int err;
+
+ err = regmap_read(regmap, SPD5118_REG_TEMP_CONFIG, &regval);
+ if (err < 0)
+ return err;
+ *val = !(regval & SPD5118_TS_DISABLE);
+ return 0;
+}
+
+static int spd5118_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct regmap *regmap = dev_get_drvdata(dev);
+
+ if (type != hwmon_temp)
+ return -EOPNOTSUPP;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_max:
+ case hwmon_temp_min:
+ case hwmon_temp_crit:
+ case hwmon_temp_lcrit:
+ return spd5118_read_temp(regmap, attr, val);
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_crit_alarm:
+ case hwmon_temp_lcrit_alarm:
+ return spd5118_read_alarm(regmap, attr, val);
+ case hwmon_temp_enable:
+ return spd5118_read_enable(regmap, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int spd5118_write_temp(struct regmap *regmap, u32 attr, long val)
+{
+ u8 regval[2];
+ u16 temp;
+ int reg;
+
+ switch (attr) {
+ case hwmon_temp_max:
+ reg = SPD5118_REG_TEMP_MAX;
+ break;
+ case hwmon_temp_min:
+ reg = SPD5118_REG_TEMP_MIN;
+ break;
+ case hwmon_temp_crit:
+ reg = SPD5118_REG_TEMP_CRIT;
+ break;
+ case hwmon_temp_lcrit:
+ reg = SPD5118_REG_TEMP_LCRIT;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ temp = spd5118_temp_to_reg(val);
+ regval[0] = temp & 0xff;
+ regval[1] = temp >> 8;
+
+ return regmap_bulk_write(regmap, reg, regval, 2);
+}
+
+static int spd5118_write_enable(struct regmap *regmap, long val)
+{
+ if (val && val != 1)
+ return -EINVAL;
+
+ return regmap_update_bits(regmap, SPD5118_REG_TEMP_CONFIG,
+ SPD5118_TS_DISABLE,
+ val ? 0 : SPD5118_TS_DISABLE);
+}
+
+static int spd5118_temp_write(struct regmap *regmap, u32 attr, long val)
+{
+ switch (attr) {
+ case hwmon_temp_max:
+ case hwmon_temp_min:
+ case hwmon_temp_crit:
+ case hwmon_temp_lcrit:
+ return spd5118_write_temp(regmap, attr, val);
+ case hwmon_temp_enable:
+ return spd5118_write_enable(regmap, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int spd5118_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ struct regmap *regmap = dev_get_drvdata(dev);
+
+ switch (type) {
+ case hwmon_temp:
+ return spd5118_temp_write(regmap, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t spd5118_is_visible(const void *_data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ if (type != hwmon_temp)
+ return 0;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ return 0444;
+ case hwmon_temp_min:
+ case hwmon_temp_max:
+ case hwmon_temp_lcrit:
+ case hwmon_temp_crit:
+ case hwmon_temp_enable:
+ return 0644;
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_crit_alarm:
+ case hwmon_temp_lcrit_alarm:
+ return 0444;
+ default:
+ return 0;
+ }
+}
+
+static inline bool spd5118_parity8(u8 w)
+{
+ w ^= w >> 4;
+ return (0x6996 >> (w & 0xf)) & 1;
+}
+
+/*
+ * Bank and vendor id are 8-bit fields with seven data bits and odd parity.
+ * Vendor IDs 0 and 0x7f are invalid.
+ * See Jedec standard JEP106BJ for details and a list of assigned vendor IDs.
+ */
+static bool spd5118_vendor_valid(u8 bank, u8 id)
+{
+ if (!spd5118_parity8(bank) || !spd5118_parity8(id))
+ return false;
+
+ id &= 0x7f;
+ return id && id != 0x7f;
+}
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int spd5118_detect(struct i2c_client *client, struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ int regval;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA))
+ return -ENODEV;
+
+ regval = i2c_smbus_read_word_swapped(client, SPD5118_REG_TYPE);
+ if (regval != 0x5118)
+ return -ENODEV;
+
+ regval = i2c_smbus_read_word_data(client, SPD5118_REG_VENDOR);
+ if (regval < 0 || !spd5118_vendor_valid(regval & 0xff, regval >> 8))
+ return -ENODEV;
+
+ regval = i2c_smbus_read_byte_data(client, SPD5118_REG_CAPABILITY);
+ if (regval < 0)
+ return -ENODEV;
+ if (!(regval & SPD5118_CAP_TS_SUPPORT) || (regval & 0xfc))
+ return -ENODEV;
+
+ regval = i2c_smbus_read_byte_data(client, SPD5118_REG_TEMP_CLR);
+ if (regval)
+ return -ENODEV;
+ regval = i2c_smbus_read_byte_data(client, SPD5118_REG_ERROR_CLR);
+ if (regval)
+ return -ENODEV;
+
+ regval = i2c_smbus_read_byte_data(client, SPD5118_REG_REVISION);
+ if (regval < 0 || (regval & 0xc1))
+ return -ENODEV;
+
+ regval = i2c_smbus_read_byte_data(client, SPD5118_REG_TEMP_CONFIG);
+ if (regval < 0)
+ return -ENODEV;
+ if (regval & ~SPD5118_TS_DISABLE)
+ return -ENODEV;
+
+ strscpy(info->type, "spd5118", I2C_NAME_SIZE);
+ return 0;
+}
+
+static const struct hwmon_channel_info *spd5118_info[] = {
+ HWMON_CHANNEL_INFO(chip,
+ HWMON_C_REGISTER_TZ),
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT |
+ HWMON_T_LCRIT | HWMON_T_LCRIT_ALARM |
+ HWMON_T_MIN | HWMON_T_MIN_ALARM |
+ HWMON_T_MAX | HWMON_T_MAX_ALARM |
+ HWMON_T_CRIT | HWMON_T_CRIT_ALARM |
+ HWMON_T_ENABLE),
+ NULL
+};
+
+static const struct hwmon_ops spd5118_hwmon_ops = {
+ .is_visible = spd5118_is_visible,
+ .read = spd5118_read,
+ .write = spd5118_write,
+};
+
+static const struct hwmon_chip_info spd5118_chip_info = {
+ .ops = &spd5118_hwmon_ops,
+ .info = spd5118_info,
+};
+
+/* nvmem */
+
+static ssize_t spd5118_nvmem_read_page(struct regmap *regmap, char *buf,
+ unsigned int offset, size_t count)
+{
+ int addr = (offset >> SPD5118_PAGE_SHIFT) * 0x100 + SPD5118_EEPROM_BASE;
+ int err;
+
+ offset &= SPD5118_PAGE_MASK;
+
+ /* Can't cross page boundaries */
+ if (offset + count > SPD5118_PAGE_SIZE)
+ count = SPD5118_PAGE_SIZE - offset;
+
+ err = regmap_bulk_read(regmap, addr + offset, buf, count);
+ if (err)
+ return err;
+
+ return count;
+}
+
+static int spd5118_nvmem_read(void *priv, unsigned int off, void *val, size_t count)
+{
+ struct spd5118_data *data = priv;
+ char *buf = val;
+ int ret;
+
+ if (unlikely(!count))
+ return count;
+
+ if (off + count > SPD5118_EEPROM_SIZE)
+ return -EINVAL;
+
+ mutex_lock(&data->nvmem_lock);
+
+ while (count) {
+ ret = spd5118_nvmem_read_page(data->regmap, buf, off, count);
+ if (ret < 0) {
+ mutex_unlock(&data->nvmem_lock);
+ return ret;
+ }
+ buf += ret;
+ off += ret;
+ count -= ret;
+ }
+ mutex_unlock(&data->nvmem_lock);
+ return 0;
+}
+
+static int spd5118_nvmem_init(struct device *dev, struct spd5118_data *data)
+{
+ struct nvmem_config nvmem_config = {
+ .type = NVMEM_TYPE_EEPROM,
+ .name = dev_name(dev),
+ .id = NVMEM_DEVID_NONE,
+ .dev = dev,
+ .base_dev = dev,
+ .read_only = true,
+ .root_only = false,
+ .owner = THIS_MODULE,
+ .compat = true,
+ .reg_read = spd5118_nvmem_read,
+ .priv = data,
+ .stride = 1,
+ .word_size = 1,
+ .size = SPD5118_EEPROM_SIZE,
+ };
+ struct nvmem_device *nvmem;
+
+ nvmem = devm_nvmem_register(dev, &nvmem_config);
+ return PTR_ERR_OR_ZERO(nvmem);
+}
+
+/* regmap */
+
+static bool spd5118_writeable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case SPD5118_REG_I2C_LEGACY_MODE:
+ case SPD5118_REG_TEMP_CLR:
+ case SPD5118_REG_TEMP_CONFIG:
+ case SPD5118_REG_TEMP_MAX:
+ case SPD5118_REG_TEMP_MAX + 1:
+ case SPD5118_REG_TEMP_MIN:
+ case SPD5118_REG_TEMP_MIN + 1:
+ case SPD5118_REG_TEMP_CRIT:
+ case SPD5118_REG_TEMP_CRIT + 1:
+ case SPD5118_REG_TEMP_LCRIT:
+ case SPD5118_REG_TEMP_LCRIT + 1:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool spd5118_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case SPD5118_REG_TEMP_CLR:
+ case SPD5118_REG_ERROR_CLR:
+ case SPD5118_REG_TEMP:
+ case SPD5118_REG_TEMP + 1:
+ case SPD5118_REG_TEMP_STATUS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_range_cfg spd5118_regmap_range_cfg[] = {
+ {
+ .selector_reg = SPD5118_REG_I2C_LEGACY_MODE,
+ .selector_mask = SPD5118_LEGACY_PAGE_MASK,
+ .selector_shift = 0,
+ .window_start = 0,
+ .window_len = 0x100,
+ .range_min = 0,
+ .range_max = 0x7ff,
+ },
+};
+
+static const struct regmap_config spd5118_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x7ff,
+ .writeable_reg = spd5118_writeable_reg,
+ .volatile_reg = spd5118_volatile_reg,
+ .cache_type = REGCACHE_MAPLE,
+
+ .ranges = spd5118_regmap_range_cfg,
+ .num_ranges = ARRAY_SIZE(spd5118_regmap_range_cfg),
+};
+
+static int spd5118_init(struct i2c_client *client)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ int err, regval, mode;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA))
+ return -ENODEV;
+
+ regval = i2c_smbus_read_word_swapped(client, SPD5118_REG_TYPE);
+ if (regval < 0 || (regval && regval != 0x5118))
+ return -ENODEV;
+
+ /*
+ * If the device type registers return 0, it is possible that the chip
+ * has a non-zero page selected and takes the specification literally,
+ * i.e. disables access to volatile registers besides the page register
+ * if the page is not 0. Try to identify such chips.
+ */
+ if (!regval) {
+ /* Vendor ID registers must also be 0 */
+ regval = i2c_smbus_read_word_data(client, SPD5118_REG_VENDOR);
+ if (regval)
+ return -ENODEV;
+
+ /* The selected page in MR11 must not be 0 */
+ mode = i2c_smbus_read_byte_data(client, SPD5118_REG_I2C_LEGACY_MODE);
+ if (mode < 0 || (mode & ~SPD5118_LEGACY_MODE_MASK) ||
+ !(mode & SPD5118_LEGACY_PAGE_MASK))
+ return -ENODEV;
+
+ err = i2c_smbus_write_byte_data(client, SPD5118_REG_I2C_LEGACY_MODE,
+ mode & SPD5118_LEGACY_MODE_ADDR);
+ if (err)
+ return -ENODEV;
+
+ /*
+ * If the device type registers are still bad after selecting
+ * page 0, this is not a SPD5118 device. Restore original
+ * legacy mode register value and abort.
+ */
+ regval = i2c_smbus_read_word_swapped(client, SPD5118_REG_TYPE);
+ if (regval != 0x5118) {
+ i2c_smbus_write_byte_data(client, SPD5118_REG_I2C_LEGACY_MODE, mode);
+ return -ENODEV;
+ }
+ }
+
+ /* We are reasonably sure that this is really a SPD5118 hub controller */
+ return 0;
+}
+
+static int spd5118_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ unsigned int regval, revision, vendor, bank;
+ struct spd5118_data *data;
+ struct device *hwmon_dev;
+ struct regmap *regmap;
+ int err;
+
+ err = spd5118_init(client);
+ if (err)
+ return err;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ regmap = devm_regmap_init_i2c(client, &spd5118_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap), "regmap init failed\n");
+
+ err = regmap_read(regmap, SPD5118_REG_CAPABILITY, &regval);
+ if (err)
+ return err;
+ if (!(regval & SPD5118_CAP_TS_SUPPORT))
+ return -ENODEV;
+
+ err = regmap_read(regmap, SPD5118_REG_REVISION, &revision);
+ if (err)
+ return err;
+
+ err = regmap_read(regmap, SPD5118_REG_VENDOR, &bank);
+ if (err)
+ return err;
+ err = regmap_read(regmap, SPD5118_REG_VENDOR + 1, &vendor);
+ if (err)
+ return err;
+ if (!spd5118_vendor_valid(bank, vendor))
+ return -ENODEV;
+
+ data->regmap = regmap;
+ mutex_init(&data->nvmem_lock);
+ dev_set_drvdata(dev, data);
+
+ err = spd5118_nvmem_init(dev, data);
+ /* Ignore if NVMEM support is disabled */
+ if (err && err != -EOPNOTSUPP) {
+ dev_err_probe(dev, err, "failed to register nvmem\n");
+ return err;
+ }
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, "spd5118",
+ regmap, &spd5118_chip_info,
+ NULL);
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
+
+ /*
+ * From JESD300-5B
+ * MR2 bits [5:4]: Major revision, 1..4
+ * MR2 bits [3:1]: Minor revision, 0..8? Probably a typo, assume 1..8
+ */
+ dev_info(dev, "DDR5 temperature sensor: vendor 0x%02x:0x%02x revision %d.%d\n",
+ bank & 0x7f, vendor, ((revision >> 4) & 0x03) + 1, ((revision >> 1) & 0x07) + 1);
+
+ return 0;
+}
+
+static int spd5118_suspend(struct device *dev)
+{
+ struct spd5118_data *data = dev_get_drvdata(dev);
+ struct regmap *regmap = data->regmap;
+ u32 regval;
+ int err;
+
+ /*
+ * Make sure the configuration register in the regmap cache is current
+ * before bypassing it.
+ */
+ err = regmap_read(regmap, SPD5118_REG_TEMP_CONFIG, &regval);
+ if (err < 0)
+ return err;
+
+ regcache_cache_bypass(regmap, true);
+ regmap_update_bits(regmap, SPD5118_REG_TEMP_CONFIG, SPD5118_TS_DISABLE,
+ SPD5118_TS_DISABLE);
+ regcache_cache_bypass(regmap, false);
+
+ regcache_cache_only(regmap, true);
+ regcache_mark_dirty(regmap);
+
+ return 0;
+}
+
+static int spd5118_resume(struct device *dev)
+{
+ struct spd5118_data *data = dev_get_drvdata(dev);
+ struct regmap *regmap = data->regmap;
+
+ regcache_cache_only(regmap, false);
+ return regcache_sync(regmap);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(spd5118_pm_ops, spd5118_suspend, spd5118_resume);
+
+static const struct i2c_device_id spd5118_id[] = {
+ { "spd5118", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, spd5118_id);
+
+static const struct of_device_id spd5118_of_ids[] = {
+ { .compatible = "jedec,spd5118", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, spd5118_of_ids);
+
+static struct i2c_driver spd5118_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "spd5118",
+ .of_match_table = spd5118_of_ids,
+ .pm = pm_sleep_ptr(&spd5118_pm_ops),
+ },
+ .probe = spd5118_probe,
+ .id_table = spd5118_id,
+ .detect = IS_ENABLED(CONFIG_SENSORS_SPD5118_DETECT) ? spd5118_detect : NULL,
+ .address_list = IS_ENABLED(CONFIG_SENSORS_SPD5118_DETECT) ? normal_i2c : NULL,
+};
+
+module_i2c_driver(spd5118_driver);
+
+MODULE_AUTHOR("René Rebe <[email protected]>");
+MODULE_AUTHOR("Guenter Roeck <[email protected]>");
+MODULE_DESCRIPTION("SPD 5118 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c
index 68ba26bc9014..0cbdb91698b1 100644
--- a/drivers/hwmon/thmc50.c
+++ b/drivers/hwmon/thmc50.c
@@ -377,8 +377,6 @@ static void thmc50_init_client(struct thmc50_data *data)
i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config);
}
-static const struct i2c_device_id thmc50_id[];
-
static int thmc50_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -391,7 +389,7 @@ static int thmc50_probe(struct i2c_client *client)
return -ENOMEM;
data->client = client;
- data->type = i2c_match_id(thmc50_id, client)->driver_data;
+ data->type = (uintptr_t)i2c_get_match_data(client);
mutex_init(&data->update_lock);
thmc50_init_client(data);
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
index df1b45a62e80..853dbe708ff5 100644
--- a/drivers/hwmon/tmp401.c
+++ b/drivers/hwmon/tmp401.c
@@ -693,7 +693,7 @@ static int tmp401_probe(struct i2c_client *client)
data->client = client;
mutex_init(&data->update_lock);
- data->kind = i2c_match_id(tmp401_id, client)->driver_data;
+ data->kind = (uintptr_t)i2c_get_match_data(client);
data->regmap = devm_regmap_init(dev, NULL, data, &tmp401_regmap_config);
if (IS_ERR(data->regmap))
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 10b66c9ce045..7a6f9532e594 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -446,11 +446,7 @@ static int tmp421_probe(struct i2c_client *client)
return -ENOMEM;
mutex_init(&data->update_lock);
- if (client->dev.of_node)
- data->channels = (unsigned long)
- of_device_get_match_data(&client->dev);
- else
- data->channels = i2c_match_id(tmp421_id, client)->driver_data;
+ data->channels = (unsigned long)i2c_get_match_data(client);
data->client = client;
for (i = 0; i < data->channels; i++) {
diff --git a/drivers/hwmon/tmp464.c b/drivers/hwmon/tmp464.c
index f58ca4c6acb6..3ee1137533d6 100644
--- a/drivers/hwmon/tmp464.c
+++ b/drivers/hwmon/tmp464.c
@@ -666,10 +666,7 @@ static int tmp464_probe(struct i2c_client *client)
mutex_init(&data->update_lock);
- if (dev->of_node)
- data->channels = (int)(unsigned long)of_device_get_match_data(&client->dev);
- else
- data->channels = i2c_match_id(tmp464_id, client)->driver_data;
+ data->channels = (int)(unsigned long)i2c_get_match_data(client);
data->regmap = devm_regmap_init_i2c(client, &tmp464_regmap_config);
if (IS_ERR(data->regmap))
diff --git a/drivers/hwmon/tmp513.c b/drivers/hwmon/tmp513.c
index ea6f4416c124..926d28cd3fab 100644
--- a/drivers/hwmon/tmp513.c
+++ b/drivers/hwmon/tmp513.c
@@ -159,7 +159,7 @@ static const u8 TMP51X_CURR_INPUT[2] = {
TMP51X_BUS_CURRENT_RESULT
};
-static struct regmap_config tmp51x_regmap_config = {
+static const struct regmap_config tmp51x_regmap_config = {
.reg_bits = 8,
.val_bits = 16,
.max_register = TMP51X_MAX_REGISTER_ADDR,
diff --git a/drivers/hwmon/tps23861.c b/drivers/hwmon/tps23861.c
index d33ecbac00d6..dfcfb09d9f3c 100644
--- a/drivers/hwmon/tps23861.c
+++ b/drivers/hwmon/tps23861.c
@@ -117,7 +117,7 @@ struct tps23861_data {
struct dentry *debugfs_dir;
};
-static struct regmap_config tps23861_regmap_config = {
+static const struct regmap_config tps23861_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x6f,
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index fe960c0a624f..7d7d70afde65 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -895,7 +895,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, 127);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, 127000), 1000);
mutex_lock(&data->update_lock);
data->target_temp[nr] = val;
@@ -920,7 +920,7 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
return err;
/* Limit the temp to 0C - 15C */
- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 15);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, 15000), 1000);
mutex_lock(&data->update_lock);
reg = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[nr]);
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index cba5ec432e6d..b7957c84d235 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1192,8 +1192,6 @@ static void w83781d_remove_files(struct device *dev)
sysfs_remove_group(&dev->kobj, &w83781d_group_other);
}
-static const struct i2c_device_id w83781d_ids[];
-
static int w83781d_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -1208,7 +1206,7 @@ static int w83781d_probe(struct i2c_client *client)
mutex_init(&data->lock);
mutex_init(&data->update_lock);
- data->type = i2c_match_id(w83781d_ids, client)->driver_data;
+ data->type = (uintptr_t)i2c_get_match_data(client);
data->client = client;
/* attach secondary i2c lm75-like clients */
diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c
index c446e00db658..5174db69db5e 100644
--- a/drivers/hwmon/w83795.c
+++ b/drivers/hwmon/w83795.c
@@ -2134,8 +2134,6 @@ static void w83795_apply_temp_config(struct w83795_data *data, u8 config,
}
}
-static const struct i2c_device_id w83795_id[];
-
static int w83795_probe(struct i2c_client *client)
{
int i;
@@ -2149,7 +2147,7 @@ static int w83795_probe(struct i2c_client *client)
return -ENOMEM;
i2c_set_clientdata(client, data);
- data->chip_type = i2c_match_id(w83795_id, client)->driver_data;
+ data->chip_type = (uintptr_t)i2c_get_match_data(client);
data->bank = i2c_smbus_read_byte_data(client, W83795_REG_BANKSEL);
mutex_init(&data->update_lock);
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 9388823bb0bb..44710267d669 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -135,7 +135,7 @@ config I2C_SLAVE_EEPROM
Documentation/i2c/slave-eeprom-backend.rst for further details.
config I2C_SLAVE_TESTUNIT
- tristate "I2C eeprom testunit driver"
+ tristate "I2C testunit driver"
help
This backend can be used to trigger test cases for I2C bus masters
which require a remote device with certain capabilities, e.g.
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index a12525b3186b..f448505d5468 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -15,7 +15,6 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/timer.h>
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/io.h>
@@ -32,7 +31,6 @@ struct i2c_pnx_mif {
int ret; /* Return value */
int mode; /* Interface mode */
struct completion complete; /* I/O completion */
- struct timer_list timer; /* Timeout */
u8 * buf; /* Data buffer */
int len; /* Length of data buffer */
int order; /* RX Bytes to order via TX */
@@ -117,24 +115,6 @@ static inline int wait_reset(struct i2c_pnx_algo_data *data)
return (timeout <= 0);
}
-static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
-{
- struct timer_list *timer = &alg_data->mif.timer;
- unsigned long expires = msecs_to_jiffies(alg_data->timeout);
-
- if (expires <= 1)
- expires = 2;
-
- del_timer_sync(timer);
-
- dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n",
- jiffies, expires);
-
- timer->expires = jiffies + expires;
-
- add_timer(timer);
-}
-
/**
* i2c_pnx_start - start a device
* @slave_addr: slave address
@@ -259,8 +239,6 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
I2C_REG_CTL(alg_data));
- del_timer_sync(&alg_data->mif.timer);
-
dev_dbg(&alg_data->adapter.dev,
"%s(): Waking up xfer routine.\n",
__func__);
@@ -276,8 +254,6 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
I2C_REG_CTL(alg_data));
- /* Stop timer. */
- del_timer_sync(&alg_data->mif.timer);
dev_dbg(&alg_data->adapter.dev,
"%s(): Waking up xfer routine after zero-xfer.\n",
__func__);
@@ -364,8 +340,6 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
mcntrl_drmie | mcntrl_daie);
iowrite32(ctl, I2C_REG_CTL(alg_data));
- /* Kill timer. */
- del_timer_sync(&alg_data->mif.timer);
complete(&alg_data->mif.complete);
}
}
@@ -400,8 +374,6 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
mcntrl_drmie);
iowrite32(ctl, I2C_REG_CTL(alg_data));
- /* Stop timer, to prevent timeout. */
- del_timer_sync(&alg_data->mif.timer);
complete(&alg_data->mif.complete);
} else if (stat & mstatus_nai) {
/* Slave did not acknowledge, generate a STOP */
@@ -419,8 +391,6 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
/* Our return value. */
alg_data->mif.ret = -EIO;
- /* Stop timer, to prevent timeout. */
- del_timer_sync(&alg_data->mif.timer);
complete(&alg_data->mif.complete);
} else {
/*
@@ -453,9 +423,8 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void i2c_pnx_timeout(struct timer_list *t)
+static void i2c_pnx_timeout(struct i2c_pnx_algo_data *alg_data)
{
- struct i2c_pnx_algo_data *alg_data = from_timer(alg_data, t, mif.timer);
u32 ctl;
dev_err(&alg_data->adapter.dev,
@@ -472,7 +441,6 @@ static void i2c_pnx_timeout(struct timer_list *t)
iowrite32(ctl, I2C_REG_CTL(alg_data));
wait_reset(alg_data);
alg_data->mif.ret = -EIO;
- complete(&alg_data->mif.complete);
}
static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
@@ -514,6 +482,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
struct i2c_msg *pmsg;
int rc = 0, completed = 0, i;
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+ unsigned long time_left;
u32 stat;
dev_dbg(&alg_data->adapter.dev,
@@ -548,7 +517,6 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n",
__func__, alg_data->mif.mode, alg_data->mif.len);
- i2c_pnx_arm_timer(alg_data);
/* initialize the completion var */
init_completion(&alg_data->mif.complete);
@@ -564,7 +532,10 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
break;
/* Wait for completion */
- wait_for_completion(&alg_data->mif.complete);
+ time_left = wait_for_completion_timeout(&alg_data->mif.complete,
+ alg_data->timeout);
+ if (time_left == 0)
+ i2c_pnx_timeout(alg_data);
if (!(rc = alg_data->mif.ret))
completed++;
@@ -653,7 +624,10 @@ static int i2c_pnx_probe(struct platform_device *pdev)
alg_data->adapter.algo_data = alg_data;
alg_data->adapter.nr = pdev->id;
- alg_data->timeout = I2C_PNX_TIMEOUT_DEFAULT;
+ alg_data->timeout = msecs_to_jiffies(I2C_PNX_TIMEOUT_DEFAULT);
+ if (alg_data->timeout <= 1)
+ alg_data->timeout = 2;
+
#ifdef CONFIG_OF
alg_data->adapter.dev.of_node = of_node_get(pdev->dev.of_node);
if (pdev->dev.of_node) {
@@ -673,8 +647,6 @@ static int i2c_pnx_probe(struct platform_device *pdev)
if (IS_ERR(alg_data->clk))
return PTR_ERR(alg_data->clk);
- timer_setup(&alg_data->mif.timer, i2c_pnx_timeout, 0);
-
snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
"%s", pdev->name);
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 828aa2ea0fe4..185a5d60f101 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -257,6 +257,14 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
}
}
+static void rcar_i2c_reset_slave(struct rcar_i2c_priv *priv)
+{
+ rcar_i2c_write(priv, ICSIER, 0);
+ rcar_i2c_write(priv, ICSSR, 0);
+ rcar_i2c_write(priv, ICSCR, SDBS);
+ rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
+}
+
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
{
int ret;
@@ -875,6 +883,10 @@ static int rcar_i2c_do_reset(struct rcar_i2c_priv *priv)
{
int ret;
+ /* Don't reset if a slave instance is currently running */
+ if (priv->slave)
+ return -EISCONN;
+
ret = reset_control_reset(priv->rstc);
if (ret)
return ret;
@@ -903,10 +915,10 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
/* Gen3+ needs a reset. That also allows RXDMA once */
if (priv->devtype >= I2C_RCAR_GEN3) {
- priv->flags &= ~ID_P_NO_RXDMA;
ret = rcar_i2c_do_reset(priv);
if (ret)
goto out;
+ priv->flags &= ~ID_P_NO_RXDMA;
}
rcar_i2c_init(priv);
@@ -1033,11 +1045,8 @@ static int rcar_unreg_slave(struct i2c_client *slave)
/* ensure no irq is running before clearing ptr */
disable_irq(priv->irq);
- rcar_i2c_write(priv, ICSIER, 0);
- rcar_i2c_write(priv, ICSSR, 0);
+ rcar_i2c_reset_slave(priv);
enable_irq(priv->irq);
- rcar_i2c_write(priv, ICSCR, SDBS);
- rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
priv->slave = NULL;
@@ -1152,7 +1161,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
goto out_pm_disable;
}
- rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
+ /* Bring hardware to known state */
+ rcar_i2c_init(priv);
+ rcar_i2c_reset_slave(priv);
if (priv->devtype < I2C_RCAR_GEN3) {
irqflags |= IRQF_NO_THREAD;
@@ -1168,6 +1179,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
if (of_property_read_bool(dev->of_node, "smbus"))
priv->flags |= ID_P_HOST_NOTIFY;
+ /* R-Car Gen3+ needs a reset before every transfer */
if (priv->devtype >= I2C_RCAR_GEN3) {
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(priv->rstc)) {
@@ -1178,6 +1190,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
ret = reset_control_status(priv->rstc);
if (ret < 0)
goto out_pm_put;
+
+ /* hard reset disturbs HostNotify local target, so disable it */
+ priv->flags &= ~ID_P_HOST_NOTIFY;
}
ret = platform_get_irq(pdev, 0);
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index db0d1ac82910..7e7b15440832 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1067,6 +1067,7 @@ EXPORT_SYMBOL(i2c_find_device_by_fwnode);
static const struct i2c_device_id dummy_id[] = {
{ "dummy", 0 },
+ { "smbus_host_notify", 0 },
{ },
};
diff --git a/drivers/i2c/i2c-slave-testunit.c b/drivers/i2c/i2c-slave-testunit.c
index ca43e98cae1b..23a11e4e9256 100644
--- a/drivers/i2c/i2c-slave-testunit.c
+++ b/drivers/i2c/i2c-slave-testunit.c
@@ -118,6 +118,13 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client,
queue_delayed_work(system_long_wq, &tu->worker,
msecs_to_jiffies(10 * tu->regs[TU_REG_DELAY]));
}
+
+ /*
+ * Reset reg_idx to avoid that work gets queued again in case of
+ * STOP after a following read message. But do not clear TU regs
+ * here because we still need them in the workqueue!
+ */
+ tu->reg_idx = 0;
break;
case I2C_SLAVE_WRITE_REQUESTED:
diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
index 97f338b123b1..f809f0ef2004 100644
--- a/drivers/i2c/i2c-smbus.c
+++ b/drivers/i2c/i2c-smbus.c
@@ -308,7 +308,7 @@ EXPORT_SYMBOL_GPL(i2c_free_slave_host_notify_device);
* target systems are the same.
* Restrictions to automatic SPD instantiation:
* - Only works if all filled slots have the same memory type
- * - Only works for DDR, DDR2, DDR3 and DDR4 for now
+ * - Only works for (LP)DDR memory types up to DDR5
* - Only works on systems with 1 to 8 memory slots
*/
#if IS_ENABLED(CONFIG_DMI)
@@ -382,6 +382,10 @@ void i2c_register_spd(struct i2c_adapter *adap)
case 0x1E: /* LPDDR4 */
name = "ee1004";
break;
+ case 0x22: /* DDR5 */
+ case 0x23: /* LPDDR5 */
+ name = "spd5118";
+ break;
default:
dev_info(&adap->dev,
"Memory type 0x%02x not supported yet, not instantiating SPD\n",
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 16de57846bd9..2e84776f4fbd 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -315,7 +315,7 @@ int iio_trigger_attach_poll_func(struct iio_trigger *trig,
* this is the case if the IIO device and the trigger device share the
* same parent device.
*/
- if (iio_validate_own_trigger(pf->indio_dev, trig))
+ if (!iio_validate_own_trigger(pf->indio_dev, trig))
trig->attached_own_device = true;
return ret;
diff --git a/drivers/iio/light/apds9306.c b/drivers/iio/light/apds9306.c
index d6627b3e6000..66a063ea3db4 100644
--- a/drivers/iio/light/apds9306.c
+++ b/drivers/iio/light/apds9306.c
@@ -583,8 +583,8 @@ static int apds9306_intg_time_set(struct apds9306_data *data, int val2)
return ret;
intg_old = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx);
- if (ret < 0)
- return ret;
+ if (intg_old < 0)
+ return intg_old;
if (intg_old == val2)
return 0;
diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
index ea9eff7c8099..fb1d986a6895 100644
--- a/drivers/input/mouse/vmmouse.c
+++ b/drivers/input/mouse/vmmouse.c
@@ -21,19 +21,16 @@
#include "psmouse.h"
#include "vmmouse.h"
-#define VMMOUSE_PROTO_MAGIC 0x564D5868U
-
/*
* Main commands supported by the vmmouse hypervisor port.
*/
-#define VMMOUSE_PROTO_CMD_GETVERSION 10
-#define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA 39
-#define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS 40
-#define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND 41
-#define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT 86
+#define VMWARE_CMD_ABSPOINTER_DATA 39
+#define VMWARE_CMD_ABSPOINTER_STATUS 40
+#define VMWARE_CMD_ABSPOINTER_COMMAND 41
+#define VMWARE_CMD_ABSPOINTER_RESTRICT 86
/*
- * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND
+ * Subcommands for VMWARE_CMD_ABSPOINTER_COMMAND
*/
#define VMMOUSE_CMD_ENABLE 0x45414552U
#define VMMOUSE_CMD_DISABLE 0x000000f5U
@@ -76,28 +73,6 @@ struct vmmouse_data {
char dev_name[128];
};
-/*
- * Hypervisor-specific bi-directional communication channel
- * implementing the vmmouse protocol. Should never execute on
- * bare metal hardware.
- */
-#define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \
-({ \
- unsigned long __dummy1, __dummy2; \
- __asm__ __volatile__ (VMWARE_HYPERCALL : \
- "=a"(out1), \
- "=b"(out2), \
- "=c"(out3), \
- "=d"(out4), \
- "=S"(__dummy1), \
- "=D"(__dummy2) : \
- "a"(VMMOUSE_PROTO_MAGIC), \
- "b"(in1), \
- "c"(VMMOUSE_PROTO_CMD_##cmd), \
- "d"(0) : \
- "memory"); \
-})
-
/**
* vmmouse_report_button - report button state on the correct input device
*
@@ -145,14 +120,12 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse)
struct input_dev *abs_dev = priv->abs_dev;
struct input_dev *pref_dev;
u32 status, x, y, z;
- u32 dummy1, dummy2, dummy3;
unsigned int queue_length;
unsigned int count = 255;
while (count--) {
/* See if we have motion data. */
- VMMOUSE_CMD(ABSPOINTER_STATUS, 0,
- status, dummy1, dummy2, dummy3);
+ status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0);
if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) {
psmouse_err(psmouse, "failed to fetch status data\n");
/*
@@ -172,7 +145,8 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse)
}
/* Now get it */
- VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z);
+ status = vmware_hypercall4(VMWARE_CMD_ABSPOINTER_DATA, 4,
+ &x, &y, &z);
/*
* And report what we've got. Prefer to report button
@@ -247,14 +221,10 @@ static psmouse_ret_t vmmouse_process_byte(struct psmouse *psmouse)
static void vmmouse_disable(struct psmouse *psmouse)
{
u32 status;
- u32 dummy1, dummy2, dummy3, dummy4;
-
- VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE,
- dummy1, dummy2, dummy3, dummy4);
- VMMOUSE_CMD(ABSPOINTER_STATUS, 0,
- status, dummy1, dummy2, dummy3);
+ vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE);
+ status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0);
if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR)
psmouse_warn(psmouse, "failed to disable vmmouse device\n");
}
@@ -271,26 +241,24 @@ static void vmmouse_disable(struct psmouse *psmouse)
static int vmmouse_enable(struct psmouse *psmouse)
{
u32 status, version;
- u32 dummy1, dummy2, dummy3, dummy4;
/*
* Try enabling the device. If successful, we should be able to
* read valid version ID back from it.
*/
- VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE,
- dummy1, dummy2, dummy3, dummy4);
+ vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE);
/*
* See if version ID can be retrieved.
*/
- VMMOUSE_CMD(ABSPOINTER_STATUS, 0, status, dummy1, dummy2, dummy3);
+ status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0);
if ((status & 0x0000ffff) == 0) {
psmouse_dbg(psmouse, "empty flags - assuming no device\n");
return -ENXIO;
}
- VMMOUSE_CMD(ABSPOINTER_DATA, 1 /* single item */,
- version, dummy1, dummy2, dummy3);
+ version = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_DATA,
+ 1 /* single item */);
if (version != VMMOUSE_VERSION_ID) {
psmouse_dbg(psmouse, "Unexpected version value: %u vs %u\n",
(unsigned) version, VMMOUSE_VERSION_ID);
@@ -301,11 +269,11 @@ static int vmmouse_enable(struct psmouse *psmouse)
/*
* Restrict ioport access, if possible.
*/
- VMMOUSE_CMD(ABSPOINTER_RESTRICT, VMMOUSE_RESTRICT_CPL0,
- dummy1, dummy2, dummy3, dummy4);
+ vmware_hypercall1(VMWARE_CMD_ABSPOINTER_RESTRICT,
+ VMMOUSE_RESTRICT_CPL0);
- VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_REQUEST_ABSOLUTE,
- dummy1, dummy2, dummy3, dummy4);
+ vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND,
+ VMMOUSE_CMD_REQUEST_ABSOLUTE);
return 0;
}
@@ -342,7 +310,7 @@ static bool vmmouse_check_hypervisor(void)
*/
int vmmouse_detect(struct psmouse *psmouse, bool set_properties)
{
- u32 response, version, dummy1, dummy2;
+ u32 response, version, type;
if (!vmmouse_check_hypervisor()) {
psmouse_dbg(psmouse,
@@ -351,9 +319,9 @@ int vmmouse_detect(struct psmouse *psmouse, bool set_properties)
}
/* Check if the device is present */
- response = ~VMMOUSE_PROTO_MAGIC;
- VMMOUSE_CMD(GETVERSION, 0, version, response, dummy1, dummy2);
- if (response != VMMOUSE_PROTO_MAGIC || version == 0xffffffffU)
+ response = ~VMWARE_HYPERVISOR_MAGIC;
+ version = vmware_hypercall3(VMWARE_CMD_GETVERSION, 0, &response, &type);
+ if (response != VMWARE_HYPERVISOR_MAGIC || version == 0xffffffffU)
return -ENXIO;
if (set_properties) {
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index afd6a1841715..c776f9142610 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -7,6 +7,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqchip/arm-gic.h>
+#include <linux/kernel.h>
#include "irq-gic-common.h"
@@ -45,7 +46,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
}
int gic_configure_irq(unsigned int irq, unsigned int type,
- void __iomem *base, void (*sync_access)(void))
+ void __iomem *base)
{
u32 confmask = 0x2 << ((irq % 16) * 2);
u32 confoff = (irq / 16) * 4;
@@ -84,14 +85,10 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
- if (sync_access)
- sync_access();
-
return ret;
}
-void gic_dist_config(void __iomem *base, int gic_irqs,
- void (*sync_access)(void))
+void gic_dist_config(void __iomem *base, int gic_irqs, u8 priority)
{
unsigned int i;
@@ -106,7 +103,8 @@ void gic_dist_config(void __iomem *base, int gic_irqs,
* Set priority on all global interrupts.
*/
for (i = 32; i < gic_irqs; i += 4)
- writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
+ writel_relaxed(REPEAT_BYTE_U32(priority),
+ base + GIC_DIST_PRI + i);
/*
* Deactivate and disable all SPIs. Leave the PPI and SGIs
@@ -118,12 +116,9 @@ void gic_dist_config(void __iomem *base, int gic_irqs,
writel_relaxed(GICD_INT_EN_CLR_X32,
base + GIC_DIST_ENABLE_CLEAR + i / 8);
}
-
- if (sync_access)
- sync_access();
}
-void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void))
+void gic_cpu_config(void __iomem *base, int nr, u8 priority)
{
int i;
@@ -142,9 +137,6 @@ void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void))
* Set priority on PPI and SGI interrupts
*/
for (i = 0; i < nr; i += 4)
- writel_relaxed(GICD_INT_DEF_PRI_X4,
+ writel_relaxed(REPEAT_BYTE_U32(priority),
base + GIC_DIST_PRI + i * 4 / 4);
-
- if (sync_access)
- sync_access();
}
diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
index f407cce9ecaa..e8eab72ef195 100644
--- a/drivers/irqchip/irq-gic-common.h
+++ b/drivers/irqchip/irq-gic-common.h
@@ -20,10 +20,9 @@ struct gic_quirk {
};
int gic_configure_irq(unsigned int irq, unsigned int type,
- void __iomem *base, void (*sync_access)(void));
-void gic_dist_config(void __iomem *base, int gic_irqs,
- void (*sync_access)(void));
-void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void));
+ void __iomem *base);
+void gic_dist_config(void __iomem *base, int gic_irqs, u8 priority);
+void gic_cpu_config(void __iomem *base, int nr, u8 priority);
void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void *data);
void gic_enable_of_quirks(const struct device_node *np,
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 3c755d5dad6e..42e63272154e 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -59,7 +59,7 @@ static u32 lpi_id_bits;
#define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K)
#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
-#define LPI_PROP_DEFAULT_PRIO GICD_INT_DEF_PRI
+static u8 __ro_after_init lpi_prop_prio;
/*
* Collection structure - just an ID, and a redistributor address to
@@ -1926,7 +1926,7 @@ static int its_vlpi_unmap(struct irq_data *d)
/* and restore the physical one */
irqd_clr_forwarded_to_vcpu(d);
its_send_mapti(its_dev, d->hwirq, event);
- lpi_update_config(d, 0xff, (LPI_PROP_DEFAULT_PRIO |
+ lpi_update_config(d, 0xff, (lpi_prop_prio |
LPI_PROP_ENABLED |
LPI_PROP_GROUP1));
@@ -2181,8 +2181,8 @@ static void its_lpi_free(unsigned long *bitmap, u32 base, u32 nr_ids)
static void gic_reset_prop_table(void *va)
{
- /* Priority 0xa0, Group-1, disabled */
- memset(va, LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1, LPI_PROPBASE_SZ);
+ /* Regular IRQ priority, Group-1, disabled */
+ memset(va, lpi_prop_prio | LPI_PROP_GROUP1, LPI_PROPBASE_SZ);
/* Make sure the GIC will observe the written configuration */
gic_flush_dcache_to_poc(va, LPI_PROPBASE_SZ);
@@ -5650,7 +5650,7 @@ int __init its_lpi_memreserve_init(void)
}
int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
- struct irq_domain *parent_domain)
+ struct irq_domain *parent_domain, u8 irq_prio)
{
struct device_node *of_node;
struct its_node *its;
@@ -5660,6 +5660,7 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
gic_rdists = rdists;
+ lpi_prop_prio = irq_prio;
its_parent = parent_domain;
of_node = to_of_node(handle);
if (of_node)
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 6fb276504bcc..6393f3d780e9 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
+#include <linux/kernel.h>
#include <linux/kstrtox.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -24,6 +25,7 @@
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic-common.h>
#include <linux/irqchip/arm-gic-v3.h>
+#include <linux/irqchip/arm-gic-v3-prio.h>
#include <linux/irqchip/irq-partition-percpu.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
@@ -36,7 +38,8 @@
#include "irq-gic-common.h"
-#define GICD_INT_NMI_PRI (GICD_INT_DEF_PRI & ~0x80)
+static u8 dist_prio_irq __ro_after_init = GICV3_PRIO_IRQ;
+static u8 dist_prio_nmi __ro_after_init = GICV3_PRIO_NMI;
#define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0)
#define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1)
@@ -44,6 +47,8 @@
#define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)
+static struct cpumask broken_rdists __read_mostly __maybe_unused;
+
struct redist_region {
void __iomem *redist_base;
phys_addr_t phys_base;
@@ -108,29 +113,96 @@ static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
*/
static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis);
-DEFINE_STATIC_KEY_FALSE(gic_nonsecure_priorities);
-EXPORT_SYMBOL(gic_nonsecure_priorities);
+static u32 gic_get_pribits(void)
+{
+ u32 pribits;
-/*
- * When the Non-secure world has access to group 0 interrupts (as a
- * consequence of SCR_EL3.FIQ == 0), reading the ICC_RPR_EL1 register will
- * return the Distributor's view of the interrupt priority.
- *
- * When GIC security is enabled (GICD_CTLR.DS == 0), the interrupt priority
- * written by software is moved to the Non-secure range by the Distributor.
- *
- * If both are true (which is when gic_nonsecure_priorities gets enabled),
- * we need to shift down the priority programmed by software to match it
- * against the value returned by ICC_RPR_EL1.
- */
-#define GICD_INT_RPR_PRI(priority) \
- ({ \
- u32 __priority = (priority); \
- if (static_branch_unlikely(&gic_nonsecure_priorities)) \
- __priority = 0x80 | (__priority >> 1); \
- \
- __priority; \
- })
+ pribits = gic_read_ctlr();
+ pribits &= ICC_CTLR_EL1_PRI_BITS_MASK;
+ pribits >>= ICC_CTLR_EL1_PRI_BITS_SHIFT;
+ pribits++;
+
+ return pribits;
+}
+
+static bool gic_has_group0(void)
+{
+ u32 val;
+ u32 old_pmr;
+
+ old_pmr = gic_read_pmr();
+
+ /*
+ * Let's find out if Group0 is under control of EL3 or not by
+ * setting the highest possible, non-zero priority in PMR.
+ *
+ * If SCR_EL3.FIQ is set, the priority gets shifted down in
+ * order for the CPU interface to set bit 7, and keep the
+ * actual priority in the non-secure range. In the process, it
+ * looses the least significant bit and the actual priority
+ * becomes 0x80. Reading it back returns 0, indicating that
+ * we're don't have access to Group0.
+ */
+ gic_write_pmr(BIT(8 - gic_get_pribits()));
+ val = gic_read_pmr();
+
+ gic_write_pmr(old_pmr);
+
+ return val != 0;
+}
+
+static inline bool gic_dist_security_disabled(void)
+{
+ return readl_relaxed(gic_data.dist_base + GICD_CTLR) & GICD_CTLR_DS;
+}
+
+static bool cpus_have_security_disabled __ro_after_init;
+static bool cpus_have_group0 __ro_after_init;
+
+static void __init gic_prio_init(void)
+{
+ cpus_have_security_disabled = gic_dist_security_disabled();
+ cpus_have_group0 = gic_has_group0();
+
+ /*
+ * How priority values are used by the GIC depends on two things:
+ * the security state of the GIC (controlled by the GICD_CTRL.DS bit)
+ * and if Group 0 interrupts can be delivered to Linux in the non-secure
+ * world as FIQs (controlled by the SCR_EL3.FIQ bit). These affect the
+ * way priorities are presented in ICC_PMR_EL1 and in the distributor:
+ *
+ * GICD_CTRL.DS | SCR_EL3.FIQ | ICC_PMR_EL1 | Distributor
+ * -------------------------------------------------------
+ * 1 | - | unchanged | unchanged
+ * -------------------------------------------------------
+ * 0 | 1 | non-secure | non-secure
+ * -------------------------------------------------------
+ * 0 | 0 | unchanged | non-secure
+ *
+ * In the non-secure view reads and writes are modified:
+ *
+ * - A value written is right-shifted by one and the MSB is set,
+ * forcing the priority into the non-secure range.
+ *
+ * - A value read is left-shifted by one.
+ *
+ * In the first two cases, where ICC_PMR_EL1 and the interrupt priority
+ * are both either modified or unchanged, we can use the same set of
+ * priorities.
+ *
+ * In the last case, where only the interrupt priorities are modified to
+ * be in the non-secure range, we program the non-secure values into
+ * the distributor to match the PMR values we want.
+ */
+ if (cpus_have_group0 & !cpus_have_security_disabled) {
+ dist_prio_irq = __gicv3_prio_to_ns(dist_prio_irq);
+ dist_prio_nmi = __gicv3_prio_to_ns(dist_prio_nmi);
+ }
+
+ pr_info("GICD_CTRL.DS=%d, SCR_EL3.FIQ=%d\n",
+ cpus_have_security_disabled,
+ !cpus_have_group0);
+}
/* rdist_nmi_refs[n] == number of cpus having the rdist interrupt n set as NMI */
static refcount_t *rdist_nmi_refs;
@@ -556,7 +628,7 @@ static int gic_irq_nmi_setup(struct irq_data *d)
desc->handle_irq = handle_fasteoi_nmi;
}
- gic_irq_set_prio(d, GICD_INT_NMI_PRI);
+ gic_irq_set_prio(d, dist_prio_nmi);
return 0;
}
@@ -591,7 +663,7 @@ static void gic_irq_nmi_teardown(struct irq_data *d)
desc->handle_irq = handle_fasteoi_irq;
}
- gic_irq_set_prio(d, GICD_INT_DEF_PRI);
+ gic_irq_set_prio(d, dist_prio_irq);
}
static bool gic_arm64_erratum_2941627_needed(struct irq_data *d)
@@ -670,7 +742,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
offset = convert_offset_index(d, GICD_ICFGR, &index);
- ret = gic_configure_irq(index, type, base + offset, NULL);
+ ret = gic_configure_irq(index, type, base + offset);
if (ret && (range == PPI_RANGE || range == EPPI_RANGE)) {
/* Misconfigured PPIs are usually not fatal */
pr_warn("GIC: PPI INTID%ld is secure or misconfigured\n", irq);
@@ -753,7 +825,7 @@ static bool gic_rpr_is_nmi_prio(void)
if (!gic_supports_nmi())
return false;
- return unlikely(gic_read_rpr() == GICD_INT_RPR_PRI(GICD_INT_NMI_PRI));
+ return unlikely(gic_read_rpr() == GICV3_PRIO_NMI);
}
static bool gic_irqnr_is_special(u32 irqnr)
@@ -866,44 +938,6 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
__gic_handle_irq_from_irqson(regs);
}
-static u32 gic_get_pribits(void)
-{
- u32 pribits;
-
- pribits = gic_read_ctlr();
- pribits &= ICC_CTLR_EL1_PRI_BITS_MASK;
- pribits >>= ICC_CTLR_EL1_PRI_BITS_SHIFT;
- pribits++;
-
- return pribits;
-}
-
-static bool gic_has_group0(void)
-{
- u32 val;
- u32 old_pmr;
-
- old_pmr = gic_read_pmr();
-
- /*
- * Let's find out if Group0 is under control of EL3 or not by
- * setting the highest possible, non-zero priority in PMR.
- *
- * If SCR_EL3.FIQ is set, the priority gets shifted down in
- * order for the CPU interface to set bit 7, and keep the
- * actual priority in the non-secure range. In the process, it
- * looses the least significant bit and the actual priority
- * becomes 0x80. Reading it back returns 0, indicating that
- * we're don't have access to Group0.
- */
- gic_write_pmr(BIT(8 - gic_get_pribits()));
- val = gic_read_pmr();
-
- gic_write_pmr(old_pmr);
-
- return val != 0;
-}
-
static void __init gic_dist_init(void)
{
unsigned int i;
@@ -937,10 +971,11 @@ static void __init gic_dist_init(void)
writel_relaxed(0, base + GICD_ICFGRnE + i / 4);
for (i = 0; i < GIC_ESPI_NR; i += 4)
- writel_relaxed(GICD_INT_DEF_PRI_X4, base + GICD_IPRIORITYRnE + i);
+ writel_relaxed(REPEAT_BYTE_U32(dist_prio_irq),
+ base + GICD_IPRIORITYRnE + i);
/* Now do the common stuff */
- gic_dist_config(base, GIC_LINE_NR, NULL);
+ gic_dist_config(base, GIC_LINE_NR, dist_prio_irq);
val = GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1;
if (gic_data.rdists.gicd_typer2 & GICD_TYPER2_nASSGIcap) {
@@ -1119,12 +1154,6 @@ static void gic_update_rdist_properties(void)
gic_data.rdists.has_vpend_valid_dirty ? "Valid+Dirty " : "");
}
-/* Check whether it's single security state view */
-static inline bool gic_dist_security_disabled(void)
-{
- return readl_relaxed(gic_data.dist_base + GICD_CTLR) & GICD_CTLR_DS;
-}
-
static void gic_cpu_sys_reg_init(void)
{
int i, cpu = smp_processor_id();
@@ -1152,18 +1181,14 @@ static void gic_cpu_sys_reg_init(void)
write_gicreg(DEFAULT_PMR_VALUE, ICC_PMR_EL1);
} else if (gic_supports_nmi()) {
/*
- * Mismatch configuration with boot CPU, the system is likely
- * to die as interrupt masking will not work properly on all
- * CPUs
+ * Check that all CPUs use the same priority space.
*
- * The boot CPU calls this function before enabling NMI support,
- * and as a result we'll never see this warning in the boot path
- * for that CPU.
+ * If there's a mismatch with the boot CPU, the system is
+ * likely to die as interrupt masking will not work properly on
+ * all CPUs.
*/
- if (static_branch_unlikely(&gic_nonsecure_priorities))
- WARN_ON(!group0 || gic_dist_security_disabled());
- else
- WARN_ON(group0 && !gic_dist_security_disabled());
+ WARN_ON(group0 != cpus_have_group0);
+ WARN_ON(gic_dist_security_disabled() != cpus_have_security_disabled);
}
/*
@@ -1282,7 +1307,8 @@ static void gic_cpu_init(void)
for (i = 0; i < gic_data.ppi_nr + SGI_NR; i += 32)
writel_relaxed(~0, rbase + GICR_IGROUPR0 + i / 8);
- gic_cpu_config(rbase, gic_data.ppi_nr + SGI_NR, gic_redist_wait_for_rwp);
+ gic_cpu_config(rbase, gic_data.ppi_nr + SGI_NR, dist_prio_irq);
+ gic_redist_wait_for_rwp();
/* initialise system registers */
gic_cpu_sys_reg_init();
@@ -1293,6 +1319,18 @@ static void gic_cpu_init(void)
#define MPIDR_TO_SGI_RS(mpidr) (MPIDR_RS(mpidr) << ICC_SGI1R_RS_SHIFT)
#define MPIDR_TO_SGI_CLUSTER_ID(mpidr) ((mpidr) & ~0xFUL)
+/*
+ * gic_starting_cpu() is called after the last point where cpuhp is allowed
+ * to fail. So pre check for problems earlier.
+ */
+static int gic_check_rdist(unsigned int cpu)
+{
+ if (cpumask_test_cpu(cpu, &broken_rdists))
+ return -EINVAL;
+
+ return 0;
+}
+
static int gic_starting_cpu(unsigned int cpu)
{
gic_cpu_init();
@@ -1384,6 +1422,10 @@ static void __init gic_smp_init(void)
};
int base_sgi;
+ cpuhp_setup_state_nocalls(CPUHP_BP_PREPARE_DYN,
+ "irqchip/arm/gicv3:checkrdist",
+ gic_check_rdist, NULL);
+
cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,
"irqchip/arm/gicv3:starting",
gic_starting_cpu, NULL);
@@ -1948,36 +1990,6 @@ static void gic_enable_nmi_support(void)
pr_info("Pseudo-NMIs enabled using %s ICC_PMR_EL1 synchronisation\n",
gic_has_relaxed_pmr_sync() ? "relaxed" : "forced");
- /*
- * How priority values are used by the GIC depends on two things:
- * the security state of the GIC (controlled by the GICD_CTRL.DS bit)
- * and if Group 0 interrupts can be delivered to Linux in the non-secure
- * world as FIQs (controlled by the SCR_EL3.FIQ bit). These affect the
- * ICC_PMR_EL1 register and the priority that software assigns to
- * interrupts:
- *
- * GICD_CTRL.DS | SCR_EL3.FIQ | ICC_PMR_EL1 | Group 1 priority
- * -----------------------------------------------------------
- * 1 | - | unchanged | unchanged
- * -----------------------------------------------------------
- * 0 | 1 | non-secure | non-secure
- * -----------------------------------------------------------
- * 0 | 0 | unchanged | non-secure
- *
- * where non-secure means that the value is right-shifted by one and the
- * MSB bit set, to make it fit in the non-secure priority range.
- *
- * In the first two cases, where ICC_PMR_EL1 and the interrupt priority
- * are both either modified or unchanged, we can use the same set of
- * priorities.
- *
- * In the last case, where only the interrupt priorities are modified to
- * be in the non-secure range, we use a different PMR value to mask IRQs
- * and the rest of the values that we use remain unchanged.
- */
- if (gic_has_group0() && !gic_dist_security_disabled())
- static_branch_enable(&gic_nonsecure_priorities);
-
static_branch_enable(&supports_pseudo_nmis);
if (static_branch_likely(&supports_deactivate_key))
@@ -2058,6 +2070,7 @@ static int __init gic_init_bases(phys_addr_t dist_phys_base,
gic_update_rdist_properties();
+ gic_prio_init();
gic_dist_init();
gic_cpu_init();
gic_enable_nmi_support();
@@ -2065,7 +2078,7 @@ static int __init gic_init_bases(phys_addr_t dist_phys_base,
gic_cpu_pm_init();
if (gic_dist_supports_lpis()) {
- its_init(handle, &gic_data.rdists, gic_data.domain);
+ its_init(handle, &gic_data.rdists, gic_data.domain, dist_prio_irq);
its_cpu_init();
its_lpi_memreserve_init();
} else {
@@ -2365,8 +2378,24 @@ gic_acpi_parse_madt_gicc(union acpi_subtable_headers *header,
u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2;
void __iomem *redist_base;
- if (!acpi_gicc_is_usable(gicc))
+ /* Neither enabled or online capable means it doesn't exist, skip it */
+ if (!(gicc->flags & (ACPI_MADT_ENABLED | ACPI_MADT_GICC_ONLINE_CAPABLE)))
+ return 0;
+
+ /*
+ * Capable but disabled CPUs can be brought online later. What about
+ * the redistributor? ACPI doesn't want to say!
+ * Virtual hotplug systems can use the MADT's "always-on" GICR entries.
+ * Otherwise, prevent such CPUs from being brought online.
+ */
+ if (!(gicc->flags & ACPI_MADT_ENABLED)) {
+ int cpu = get_cpu_for_acpi_id(gicc->uid);
+
+ pr_warn("CPU %u's redistributor is inaccessible: this CPU can't be brought online\n", cpu);
+ if (cpu >= 0)
+ cpumask_set_cpu(cpu, &broken_rdists);
return 0;
+ }
redist_base = ioremap(gicc->gicr_base_address, size);
if (!redist_base)
@@ -2413,21 +2442,15 @@ static int __init gic_acpi_match_gicc(union acpi_subtable_headers *header,
/*
* If GICC is enabled and has valid gicr base address, then it means
- * GICR base is presented via GICC
+ * GICR base is presented via GICC. The redistributor is only known to
+ * be accessible if the GICC is marked as enabled. If this bit is not
+ * set, we'd need to add the redistributor at runtime, which isn't
+ * supported.
*/
- if (acpi_gicc_is_usable(gicc) && gicc->gicr_base_address) {
+ if (gicc->flags & ACPI_MADT_ENABLED && gicc->gicr_base_address)
acpi_data.enabled_rdists++;
- return 0;
- }
- /*
- * It's perfectly valid firmware can pass disabled GICC entry, driver
- * should not treat as errors, skip the entry instead of probe fail.
- */
- if (!acpi_gicc_is_usable(gicc))
- return 0;
-
- return -ENODEV;
+ return 0;
}
static int __init gic_acpi_count_gicr_regions(void)
@@ -2483,7 +2506,8 @@ static int __init gic_acpi_parse_virt_madt_gicc(union acpi_subtable_headers *hea
int maint_irq_mode;
static int first_madt = true;
- if (!acpi_gicc_is_usable(gicc))
+ if (!(gicc->flags &
+ (ACPI_MADT_ENABLED | ACPI_MADT_GICC_ONLINE_CAPABLE)))
return 0;
maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ?
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 98aa383e39db..3be7bd8cd8cd 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -303,7 +303,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
type != IRQ_TYPE_EDGE_RISING)
return -EINVAL;
- ret = gic_configure_irq(gicirq, type, base + GIC_DIST_CONFIG, NULL);
+ ret = gic_configure_irq(gicirq, type, base + GIC_DIST_CONFIG);
if (ret && gicirq < 32) {
/* Misconfigured PPIs are usually not fatal */
pr_warn("GIC: PPI%ld is secure or misconfigured\n", gicirq - 16);
@@ -479,7 +479,7 @@ static void gic_dist_init(struct gic_chip_data *gic)
for (i = 32; i < gic_irqs; i += 4)
writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
- gic_dist_config(base, gic_irqs, NULL);
+ gic_dist_config(base, gic_irqs, GICD_INT_DEF_PRI);
writel_relaxed(GICD_ENABLE, base + GIC_DIST_CTRL);
}
@@ -516,7 +516,7 @@ static int gic_cpu_init(struct gic_chip_data *gic)
gic_cpu_map[i] &= ~cpu_mask;
}
- gic_cpu_config(dist_base, 32, NULL);
+ gic_cpu_config(dist_base, 32, GICD_INT_DEF_PRI);
writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK);
gic_cpu_if_up(gic);
@@ -608,7 +608,7 @@ void gic_dist_restore(struct gic_chip_data *gic)
dist_base + GIC_DIST_CONFIG + i * 4);
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
- writel_relaxed(GICD_INT_DEF_PRI_X4,
+ writel_relaxed(REPEAT_BYTE_U32(GICD_INT_DEF_PRI),
dist_base + GIC_DIST_PRI + i * 4);
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
@@ -697,7 +697,7 @@ void gic_cpu_restore(struct gic_chip_data *gic)
writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
- writel_relaxed(GICD_INT_DEF_PRI_X4,
+ writel_relaxed(REPEAT_BYTE_U32(GICD_INT_DEF_PRI),
dist_base + GIC_DIST_PRI + i * 4);
writel_relaxed(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK);
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
index 46161f6ff289..31c3f70a5d5e 100644
--- a/drivers/irqchip/irq-hip04.c
+++ b/drivers/irqchip/irq-hip04.c
@@ -130,7 +130,7 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type)
raw_spin_lock(&irq_controller_lock);
- ret = gic_configure_irq(irq, type, base + GIC_DIST_CONFIG, NULL);
+ ret = gic_configure_irq(irq, type, base + GIC_DIST_CONFIG);
if (ret && irq < 32) {
/* Misconfigured PPIs are usually not fatal */
pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
@@ -260,7 +260,7 @@ static void __init hip04_irq_dist_init(struct hip04_irq_data *intc)
for (i = 32; i < nr_irqs; i += 2)
writel_relaxed(cpumask, base + GIC_DIST_TARGET + ((i * 2) & ~3));
- gic_dist_config(base, nr_irqs, NULL);
+ gic_dist_config(base, nr_irqs, GICD_INT_DEF_PRI);
writel_relaxed(1, base + GIC_DIST_CTRL);
}
@@ -287,7 +287,7 @@ static void hip04_irq_cpu_init(struct hip04_irq_data *intc)
if (i != cpu)
hip04_cpu_map[i] &= ~cpu_mask;
- gic_cpu_config(dist_base, 32, NULL);
+ gic_cpu_config(dist_base, 32, GICD_INT_DEF_PRI);
writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
writel_relaxed(1, base + GIC_CPU_CTRL);
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 4d11fc664cb0..b5d6ef430b86 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -897,7 +897,6 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
sector_t sectors, struct block_device *cached_bdev,
const struct block_device_operations *ops)
{
- struct request_queue *q;
const size_t max_stripes = min_t(size_t, INT_MAX,
SIZE_MAX / sizeof(atomic_t));
struct queue_limits lim = {
@@ -909,6 +908,7 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
.io_min = block_size,
.logical_block_size = block_size,
.physical_block_size = block_size,
+ .features = BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA,
};
uint64_t n;
int idx;
@@ -974,13 +974,6 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
d->disk->minors = BCACHE_MINORS;
d->disk->fops = ops;
d->disk->private_data = d;
-
- q = d->disk->queue;
-
- blk_queue_flag_set(QUEUE_FLAG_NONROT, d->disk->queue);
-
- blk_queue_write_cache(q, true, true);
-
return 0;
out_bioset_exit:
@@ -1423,8 +1416,8 @@ static int cached_dev_init(struct cached_dev *dc, unsigned int block_size)
}
if (bdev_io_opt(dc->bdev))
- dc->partial_stripes_expensive =
- q->limits.raid_partial_stripes_expensive;
+ dc->partial_stripes_expensive = !!(q->limits.features &
+ BLK_FEAT_RAID_PARTIAL_STRIPES_EXPENSIVE);
ret = bcache_device_init(&dc->disk, block_size,
bdev_nr_sectors(dc->bdev) - dc->sb.data_offset,
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 16884b585053..2d8dd9283ff4 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -3403,7 +3403,6 @@ static void set_discard_limits(struct cache *cache, struct queue_limits *limits)
limits->max_hw_discard_sectors = origin_limits->max_hw_discard_sectors;
limits->discard_granularity = origin_limits->discard_granularity;
limits->discard_alignment = origin_limits->discard_alignment;
- limits->discard_misaligned = origin_limits->discard_misaligned;
}
static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits)
diff --git a/drivers/md/dm-clone-target.c b/drivers/md/dm-clone-target.c
index ad79b52ffc14..b4384a8b13e3 100644
--- a/drivers/md/dm-clone-target.c
+++ b/drivers/md/dm-clone-target.c
@@ -2059,7 +2059,6 @@ static void set_discard_limits(struct clone *clone, struct queue_limits *limits)
limits->max_hw_discard_sectors = dest_limits->max_hw_discard_sectors;
limits->discard_granularity = dest_limits->discard_granularity;
limits->discard_alignment = dest_limits->discard_alignment;
- limits->discard_misaligned = dest_limits->discard_misaligned;
limits->max_discard_segments = dest_limits->max_discard_segments;
}
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index 08700bfc3e23..14a44c0f8286 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -206,7 +206,6 @@ struct dm_table {
bool integrity_supported:1;
bool singleton:1;
- unsigned integrity_added:1;
/*
* Indicates the rw permissions for the new logical device. This
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 1b7a97cc3779..6c013ceb0e5f 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1176,8 +1176,8 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
struct blk_integrity *bi = blk_get_integrity(cc->dev->bdev->bd_disk);
struct mapped_device *md = dm_table_get_md(ti->table);
- /* From now we require underlying device with our integrity profile */
- if (!bi || strcasecmp(bi->profile->name, "DM-DIF-EXT-TAG")) {
+ /* We require an underlying device with non-PI metadata */
+ if (!bi || bi->csum_type != BLK_INTEGRITY_CSUM_NONE) {
ti->error = "Integrity profile not supported.";
return -EINVAL;
}
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 417fddebe367..2a89f8eb4713 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -350,25 +350,6 @@ static struct kmem_cache *journal_io_cache;
#define DEBUG_bytes(bytes, len, msg, ...) do { } while (0)
#endif
-static void dm_integrity_prepare(struct request *rq)
-{
-}
-
-static void dm_integrity_complete(struct request *rq, unsigned int nr_bytes)
-{
-}
-
-/*
- * DM Integrity profile, protection is performed layer above (dm-crypt)
- */
-static const struct blk_integrity_profile dm_integrity_profile = {
- .name = "DM-DIF-EXT-TAG",
- .generate_fn = NULL,
- .verify_fn = NULL,
- .prepare_fn = dm_integrity_prepare,
- .complete_fn = dm_integrity_complete,
-};
-
static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map);
static void integrity_bio_wait(struct work_struct *w);
static void dm_integrity_dtr(struct dm_target *ti);
@@ -3494,6 +3475,17 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *lim
limits->dma_alignment = limits->logical_block_size - 1;
limits->discard_granularity = ic->sectors_per_block << SECTOR_SHIFT;
}
+
+ if (!ic->internal_hash) {
+ struct blk_integrity *bi = &limits->integrity;
+
+ memset(bi, 0, sizeof(*bi));
+ bi->tuple_size = ic->tag_size;
+ bi->tag_size = bi->tuple_size;
+ bi->interval_exp =
+ ic->sb->log2_sectors_per_block + SECTOR_SHIFT;
+ }
+
limits->max_integrity_segments = USHRT_MAX;
}
@@ -3650,20 +3642,6 @@ try_smaller_buffer:
return 0;
}
-static void dm_integrity_set(struct dm_target *ti, struct dm_integrity_c *ic)
-{
- struct gendisk *disk = dm_disk(dm_table_get_md(ti->table));
- struct blk_integrity bi;
-
- memset(&bi, 0, sizeof(bi));
- bi.profile = &dm_integrity_profile;
- bi.tuple_size = ic->tag_size;
- bi.tag_size = bi.tuple_size;
- bi.interval_exp = ic->sb->log2_sectors_per_block + SECTOR_SHIFT;
-
- blk_integrity_register(disk, &bi);
-}
-
static void dm_integrity_free_page_list(struct page_list *pl)
{
unsigned int i;
@@ -4649,9 +4627,6 @@ try_smaller_buffer:
}
}
- if (!ic->internal_hash)
- dm_integrity_set(ti, ic);
-
ti->num_flush_bios = 1;
ti->flush_supported = true;
if (ic->discard)
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index abe88d1e6735..052c00c1eb15 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -3542,7 +3542,7 @@ static void raid_status(struct dm_target *ti, status_type_t type,
recovery = rs->md.recovery;
state = decipher_sync_action(mddev, recovery);
progress = rs_get_progress(rs, recovery, state, resync_max_sectors);
- resync_mismatches = (mddev->last_sync_action && !strcasecmp(mddev->last_sync_action, "check")) ?
+ resync_mismatches = mddev->last_sync_action == ACTION_CHECK ?
atomic64_read(&mddev->resync_mismatches) : 0;
/* HM FIXME: do we want another state char for raid0? It shows 'D'/'A'/'-' now */
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index b2d5246cff21..92d18dcdb3e9 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -425,6 +425,13 @@ static int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
q->limits.logical_block_size,
q->limits.alignment_offset,
(unsigned long long) start << SECTOR_SHIFT);
+
+ /*
+ * Only stack the integrity profile if the target doesn't have native
+ * integrity support.
+ */
+ if (!dm_target_has_integrity(ti->type))
+ queue_limits_stack_integrity_bdev(limits, bdev);
return 0;
}
@@ -572,6 +579,12 @@ int dm_split_args(int *argc, char ***argvp, char *input)
return 0;
}
+static void dm_set_stacking_limits(struct queue_limits *limits)
+{
+ blk_set_stacking_limits(limits);
+ limits->features |= BLK_FEAT_IO_STAT | BLK_FEAT_NOWAIT | BLK_FEAT_POLL;
+}
+
/*
* Impose necessary and sufficient conditions on a devices's table such
* that any incoming bio which respects its logical_block_size can be
@@ -610,7 +623,7 @@ static int validate_hardware_logical_block_alignment(struct dm_table *t,
for (i = 0; i < t->num_targets; i++) {
ti = dm_table_get_target(t, i);
- blk_set_stacking_limits(&ti_limits);
+ dm_set_stacking_limits(&ti_limits);
/* combine all target devices' limits */
if (ti->type->iterate_devices)
@@ -702,9 +715,6 @@ int dm_table_add_target(struct dm_table *t, const char *type,
t->immutable_target_type = ti->type;
}
- if (dm_target_has_integrity(ti->type))
- t->integrity_added = 1;
-
ti->table = t;
ti->begin = start;
ti->len = len;
@@ -1014,14 +1024,13 @@ bool dm_table_request_based(struct dm_table *t)
return __table_type_request_based(dm_table_get_type(t));
}
-static bool dm_table_supports_poll(struct dm_table *t);
-
static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *md)
{
enum dm_queue_mode type = dm_table_get_type(t);
unsigned int per_io_data_size = 0, front_pad, io_front_pad;
unsigned int min_pool_size = 0, pool_size;
struct dm_md_mempools *pools;
+ unsigned int bioset_flags = 0;
if (unlikely(type == DM_TYPE_NONE)) {
DMERR("no table type is set, can't allocate mempools");
@@ -1038,6 +1047,9 @@ static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *
goto init_bs;
}
+ if (md->queue->limits.features & BLK_FEAT_POLL)
+ bioset_flags |= BIOSET_PERCPU_CACHE;
+
for (unsigned int i = 0; i < t->num_targets; i++) {
struct dm_target *ti = dm_table_get_target(t, i);
@@ -1050,8 +1062,7 @@ static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *
io_front_pad = roundup(per_io_data_size,
__alignof__(struct dm_io)) + DM_IO_BIO_OFFSET;
- if (bioset_init(&pools->io_bs, pool_size, io_front_pad,
- dm_table_supports_poll(t) ? BIOSET_PERCPU_CACHE : 0))
+ if (bioset_init(&pools->io_bs, pool_size, io_front_pad, bioset_flags))
goto out_free_pools;
if (t->integrity_supported &&
bioset_integrity_create(&pools->io_bs, pool_size))
@@ -1119,99 +1130,6 @@ static int dm_table_build_index(struct dm_table *t)
return r;
}
-static bool integrity_profile_exists(struct gendisk *disk)
-{
- return !!blk_get_integrity(disk);
-}
-
-/*
- * Get a disk whose integrity profile reflects the table's profile.
- * Returns NULL if integrity support was inconsistent or unavailable.
- */
-static struct gendisk *dm_table_get_integrity_disk(struct dm_table *t)
-{
- struct list_head *devices = dm_table_get_devices(t);
- struct dm_dev_internal *dd = NULL;
- struct gendisk *prev_disk = NULL, *template_disk = NULL;
-
- for (unsigned int i = 0; i < t->num_targets; i++) {
- struct dm_target *ti = dm_table_get_target(t, i);
-
- if (!dm_target_passes_integrity(ti->type))
- goto no_integrity;
- }
-
- list_for_each_entry(dd, devices, list) {
- template_disk = dd->dm_dev->bdev->bd_disk;
- if (!integrity_profile_exists(template_disk))
- goto no_integrity;
- else if (prev_disk &&
- blk_integrity_compare(prev_disk, template_disk) < 0)
- goto no_integrity;
- prev_disk = template_disk;
- }
-
- return template_disk;
-
-no_integrity:
- if (prev_disk)
- DMWARN("%s: integrity not set: %s and %s profile mismatch",
- dm_device_name(t->md),
- prev_disk->disk_name,
- template_disk->disk_name);
- return NULL;
-}
-
-/*
- * Register the mapped device for blk_integrity support if the
- * underlying devices have an integrity profile. But all devices may
- * not have matching profiles (checking all devices isn't reliable
- * during table load because this table may use other DM device(s) which
- * must be resumed before they will have an initialized integity
- * profile). Consequently, stacked DM devices force a 2 stage integrity
- * profile validation: First pass during table load, final pass during
- * resume.
- */
-static int dm_table_register_integrity(struct dm_table *t)
-{
- struct mapped_device *md = t->md;
- struct gendisk *template_disk = NULL;
-
- /* If target handles integrity itself do not register it here. */
- if (t->integrity_added)
- return 0;
-
- template_disk = dm_table_get_integrity_disk(t);
- if (!template_disk)
- return 0;
-
- if (!integrity_profile_exists(dm_disk(md))) {
- t->integrity_supported = true;
- /*
- * Register integrity profile during table load; we can do
- * this because the final profile must match during resume.
- */
- blk_integrity_register(dm_disk(md),
- blk_get_integrity(template_disk));
- return 0;
- }
-
- /*
- * If DM device already has an initialized integrity
- * profile the new profile should not conflict.
- */
- if (blk_integrity_compare(dm_disk(md), template_disk) < 0) {
- DMERR("%s: conflict with existing integrity profile: %s profile mismatch",
- dm_device_name(t->md),
- template_disk->disk_name);
- return 1;
- }
-
- /* Preserve existing integrity profile */
- t->integrity_supported = true;
- return 0;
-}
-
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
struct dm_crypto_profile {
@@ -1423,12 +1341,6 @@ int dm_table_complete(struct dm_table *t)
return r;
}
- r = dm_table_register_integrity(t);
- if (r) {
- DMERR("could not register integrity profile.");
- return r;
- }
-
r = dm_table_construct_crypto_profile(t);
if (r) {
DMERR("could not construct crypto profile.");
@@ -1493,14 +1405,6 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
return &t->targets[(KEYS_PER_NODE * n) + k];
}
-static int device_not_poll_capable(struct dm_target *ti, struct dm_dev *dev,
- sector_t start, sector_t len, void *data)
-{
- struct request_queue *q = bdev_get_queue(dev->bdev);
-
- return !test_bit(QUEUE_FLAG_POLL, &q->queue_flags);
-}
-
/*
* type->iterate_devices() should be called when the sanity check needs to
* iterate and check all underlying data devices. iterate_devices() will
@@ -1548,19 +1452,6 @@ static int count_device(struct dm_target *ti, struct dm_dev *dev,
return 0;
}
-static bool dm_table_supports_poll(struct dm_table *t)
-{
- for (unsigned int i = 0; i < t->num_targets; i++) {
- struct dm_target *ti = dm_table_get_target(t, i);
-
- if (!ti->type->iterate_devices ||
- ti->type->iterate_devices(ti, device_not_poll_capable, NULL))
- return false;
- }
-
- return true;
-}
-
/*
* Check whether a table has no data devices attached using each
* target's iterate_devices method.
@@ -1686,12 +1577,20 @@ int dm_calculate_queue_limits(struct dm_table *t,
unsigned int zone_sectors = 0;
bool zoned = false;
- blk_set_stacking_limits(limits);
+ dm_set_stacking_limits(limits);
+
+ t->integrity_supported = true;
+ for (unsigned int i = 0; i < t->num_targets; i++) {
+ struct dm_target *ti = dm_table_get_target(t, i);
+
+ if (!dm_target_passes_integrity(ti->type))
+ t->integrity_supported = false;
+ }
for (unsigned int i = 0; i < t->num_targets; i++) {
struct dm_target *ti = dm_table_get_target(t, i);
- blk_set_stacking_limits(&ti_limits);
+ dm_set_stacking_limits(&ti_limits);
if (!ti->type->iterate_devices) {
/* Set I/O hints portion of queue limits */
@@ -1706,12 +1605,12 @@ int dm_calculate_queue_limits(struct dm_table *t,
ti->type->iterate_devices(ti, dm_set_device_limits,
&ti_limits);
- if (!zoned && ti_limits.zoned) {
+ if (!zoned && (ti_limits.features & BLK_FEAT_ZONED)) {
/*
* After stacking all limits, validate all devices
* in table support this zoned model and zone sectors.
*/
- zoned = ti_limits.zoned;
+ zoned = (ti_limits.features & BLK_FEAT_ZONED);
zone_sectors = ti_limits.chunk_sectors;
}
@@ -1738,6 +1637,18 @@ combine_limits:
dm_device_name(t->md),
(unsigned long long) ti->begin,
(unsigned long long) ti->len);
+
+ if (t->integrity_supported ||
+ dm_target_has_integrity(ti->type)) {
+ if (!queue_limits_stack_integrity(limits, &ti_limits)) {
+ DMWARN("%s: adding target device (start sect %llu len %llu) "
+ "disabled integrity support due to incompatibility",
+ dm_device_name(t->md),
+ (unsigned long long) ti->begin,
+ (unsigned long long) ti->len);
+ t->integrity_supported = false;
+ }
+ }
}
/*
@@ -1747,12 +1658,12 @@ combine_limits:
* zoned model on host-managed zoned block devices.
* BUT...
*/
- if (limits->zoned) {
+ if (limits->features & BLK_FEAT_ZONED) {
/*
* ...IF the above limits stacking determined a zoned model
* validate that all of the table's devices conform to it.
*/
- zoned = limits->zoned;
+ zoned = limits->features & BLK_FEAT_ZONED;
zone_sectors = limits->chunk_sectors;
}
if (validate_hardware_zoned(t, zoned, zone_sectors))
@@ -1762,63 +1673,15 @@ combine_limits:
}
/*
- * Verify that all devices have an integrity profile that matches the
- * DM device's registered integrity profile. If the profiles don't
- * match then unregister the DM device's integrity profile.
+ * Check if a target requires flush support even if none of the underlying
+ * devices need it (e.g. to persist target-specific metadata).
*/
-static void dm_table_verify_integrity(struct dm_table *t)
-{
- struct gendisk *template_disk = NULL;
-
- if (t->integrity_added)
- return;
-
- if (t->integrity_supported) {
- /*
- * Verify that the original integrity profile
- * matches all the devices in this table.
- */
- template_disk = dm_table_get_integrity_disk(t);
- if (template_disk &&
- blk_integrity_compare(dm_disk(t->md), template_disk) >= 0)
- return;
- }
-
- if (integrity_profile_exists(dm_disk(t->md))) {
- DMWARN("%s: unable to establish an integrity profile",
- dm_device_name(t->md));
- blk_integrity_unregister(dm_disk(t->md));
- }
-}
-
-static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev,
- sector_t start, sector_t len, void *data)
+static bool dm_table_supports_flush(struct dm_table *t)
{
- unsigned long flush = (unsigned long) data;
- struct request_queue *q = bdev_get_queue(dev->bdev);
-
- return (q->queue_flags & flush);
-}
-
-static bool dm_table_supports_flush(struct dm_table *t, unsigned long flush)
-{
- /*
- * Require at least one underlying device to support flushes.
- * t->devices includes internal dm devices such as mirror logs
- * so we need to use iterate_devices here, which targets
- * supporting flushes must provide.
- */
for (unsigned int i = 0; i < t->num_targets; i++) {
struct dm_target *ti = dm_table_get_target(t, i);
- if (!ti->num_flush_bios)
- continue;
-
- if (ti->flush_supported)
- return true;
-
- if (ti->type->iterate_devices &&
- ti->type->iterate_devices(ti, device_flush_capable, (void *) flush))
+ if (ti->num_flush_bios && ti->flush_supported)
return true;
}
@@ -1839,20 +1702,6 @@ static int device_dax_write_cache_enabled(struct dm_target *ti,
return false;
}
-static int device_is_rotational(struct dm_target *ti, struct dm_dev *dev,
- sector_t start, sector_t len, void *data)
-{
- return !bdev_nonrot(dev->bdev);
-}
-
-static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev,
- sector_t start, sector_t len, void *data)
-{
- struct request_queue *q = bdev_get_queue(dev->bdev);
-
- return !blk_queue_add_random(q);
-}
-
static int device_not_write_zeroes_capable(struct dm_target *ti, struct dm_dev *dev,
sector_t start, sector_t len, void *data)
{
@@ -1877,12 +1726,6 @@ static bool dm_table_supports_write_zeroes(struct dm_table *t)
return true;
}
-static int device_not_nowait_capable(struct dm_target *ti, struct dm_dev *dev,
- sector_t start, sector_t len, void *data)
-{
- return !bdev_nowait(dev->bdev);
-}
-
static bool dm_table_supports_nowait(struct dm_table *t)
{
for (unsigned int i = 0; i < t->num_targets; i++) {
@@ -1890,10 +1733,6 @@ static bool dm_table_supports_nowait(struct dm_table *t)
if (!dm_target_supports_nowait(ti->type))
return false;
-
- if (!ti->type->iterate_devices ||
- ti->type->iterate_devices(ti, device_not_nowait_capable, NULL))
- return false;
}
return true;
@@ -1950,29 +1789,25 @@ static bool dm_table_supports_secure_erase(struct dm_table *t)
return true;
}
-static int device_requires_stable_pages(struct dm_target *ti,
- struct dm_dev *dev, sector_t start,
- sector_t len, void *data)
-{
- return bdev_stable_writes(dev->bdev);
-}
-
int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
struct queue_limits *limits)
{
- bool wc = false, fua = false;
int r;
- if (dm_table_supports_nowait(t))
- blk_queue_flag_set(QUEUE_FLAG_NOWAIT, q);
- else
- blk_queue_flag_clear(QUEUE_FLAG_NOWAIT, q);
+ if (!dm_table_supports_nowait(t))
+ limits->features &= ~BLK_FEAT_NOWAIT;
+
+ /*
+ * The current polling impementation does not support request based
+ * stacking.
+ */
+ if (!__table_type_bio_based(t->type))
+ limits->features &= ~BLK_FEAT_POLL;
if (!dm_table_supports_discards(t)) {
limits->max_hw_discard_sectors = 0;
limits->discard_granularity = 0;
limits->discard_alignment = 0;
- limits->discard_misaligned = 0;
}
if (!dm_table_supports_write_zeroes(t))
@@ -1981,58 +1816,22 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
if (!dm_table_supports_secure_erase(t))
limits->max_secure_erase_sectors = 0;
- if (dm_table_supports_flush(t, (1UL << QUEUE_FLAG_WC))) {
- wc = true;
- if (dm_table_supports_flush(t, (1UL << QUEUE_FLAG_FUA)))
- fua = true;
- }
- blk_queue_write_cache(q, wc, fua);
+ if (dm_table_supports_flush(t))
+ limits->features |= BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA;
if (dm_table_supports_dax(t, device_not_dax_capable)) {
- blk_queue_flag_set(QUEUE_FLAG_DAX, q);
+ limits->features |= BLK_FEAT_DAX;
if (dm_table_supports_dax(t, device_not_dax_synchronous_capable))
set_dax_synchronous(t->md->dax_dev);
} else
- blk_queue_flag_clear(QUEUE_FLAG_DAX, q);
+ limits->features &= ~BLK_FEAT_DAX;
if (dm_table_any_dev_attr(t, device_dax_write_cache_enabled, NULL))
dax_write_cache(t->md->dax_dev, true);
- /* Ensure that all underlying devices are non-rotational. */
- if (dm_table_any_dev_attr(t, device_is_rotational, NULL))
- blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
- else
- blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
-
- dm_table_verify_integrity(t);
-
- /*
- * Some devices don't use blk_integrity but still want stable pages
- * because they do their own checksumming.
- * If any underlying device requires stable pages, a table must require
- * them as well. Only targets that support iterate_devices are considered:
- * don't want error, zero, etc to require stable pages.
- */
- if (dm_table_any_dev_attr(t, device_requires_stable_pages, NULL))
- blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, q);
- else
- blk_queue_flag_clear(QUEUE_FLAG_STABLE_WRITES, q);
-
- /*
- * Determine whether or not this queue's I/O timings contribute
- * to the entropy pool, Only request-based targets use this.
- * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not
- * have it set.
- */
- if (blk_queue_add_random(q) &&
- dm_table_any_dev_attr(t, device_is_not_random, NULL))
- blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
-
- /*
- * For a zoned target, setup the zones related queue attributes
- * and resources necessary for zone append emulation if necessary.
- */
- if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) && limits->zoned) {
+ /* For a zoned table, setup the zone related queue attributes. */
+ if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
+ (limits->features & BLK_FEAT_ZONED)) {
r = dm_set_zones_restrictions(t, q, limits);
if (r)
return r;
@@ -2042,22 +1841,18 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
if (r)
return r;
- dm_update_crypto_profile(q, t);
-
/*
- * Check for request-based device is left to
- * dm_mq_init_request_queue()->blk_mq_init_allocated_queue().
- *
- * For bio-based device, only set QUEUE_FLAG_POLL when all
- * underlying devices supporting polling.
+ * Now that the limits are set, check the zones mapped by the table
+ * and setup the resources for zone append emulation if necessary.
*/
- if (__table_type_bio_based(t->type)) {
- if (dm_table_supports_poll(t))
- blk_queue_flag_set(QUEUE_FLAG_POLL, q);
- else
- blk_queue_flag_clear(QUEUE_FLAG_POLL, q);
+ if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
+ (limits->features & BLK_FEAT_ZONED)) {
+ r = dm_revalidate_zones(t, q);
+ if (r)
+ return r;
}
+ dm_update_crypto_profile(q, t);
return 0;
}
diff --git a/drivers/md/dm-vdo/dm-vdo-target.c b/drivers/md/dm-vdo/dm-vdo-target.c
index b423bec6458b..9d51f72a9d66 100644
--- a/drivers/md/dm-vdo/dm-vdo-target.c
+++ b/drivers/md/dm-vdo/dm-vdo-target.c
@@ -945,7 +945,7 @@ static void vdo_io_hints(struct dm_target *ti, struct queue_limits *limits)
* The value is used by dm-thin to determine whether to pass down discards. The block layer
* splits large discards on this boundary when this is set.
*/
- limits->max_discard_sectors =
+ limits->max_hw_discard_sectors =
(vdo->device_config->max_discard_blocks * VDO_SECTORS_PER_BLOCK);
/*
diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c
index 5d66d916730e..c0d41c36e06e 100644
--- a/drivers/md/dm-zone.c
+++ b/drivers/md/dm-zone.c
@@ -13,8 +13,6 @@
#define DM_MSG_PREFIX "zone"
-#define DM_ZONE_INVALID_WP_OFST UINT_MAX
-
/*
* For internal zone reports bypassing the top BIO submission path.
*/
@@ -146,34 +144,27 @@ bool dm_is_zone_write(struct mapped_device *md, struct bio *bio)
}
/*
- * Count conventional zones of a mapped zoned device. If the device
- * only has conventional zones, do not expose it as zoned.
- */
-static int dm_check_zoned_cb(struct blk_zone *zone, unsigned int idx,
- void *data)
-{
- unsigned int *nr_conv_zones = data;
-
- if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
- (*nr_conv_zones)++;
-
- return 0;
-}
-
-/*
* Revalidate the zones of a mapped device to initialize resource necessary
* for zone append emulation. Note that we cannot simply use the block layer
* blk_revalidate_disk_zones() function here as the mapped device is suspended
* (this is called from __bind() context).
*/
-static int dm_revalidate_zones(struct mapped_device *md, struct dm_table *t)
+int dm_revalidate_zones(struct dm_table *t, struct request_queue *q)
{
+ struct mapped_device *md = t->md;
struct gendisk *disk = md->disk;
int ret;
+ if (!get_capacity(disk))
+ return 0;
+
/* Revalidate only if something changed. */
- if (!disk->nr_zones || disk->nr_zones != md->nr_zones)
+ if (!disk->nr_zones || disk->nr_zones != md->nr_zones) {
+ DMINFO("%s using %s zone append",
+ disk->disk_name,
+ queue_emulates_zone_append(q) ? "emulated" : "native");
md->nr_zones = 0;
+ }
if (md->nr_zones)
return 0;
@@ -220,13 +211,129 @@ static bool dm_table_supports_zone_append(struct dm_table *t)
return true;
}
+struct dm_device_zone_count {
+ sector_t start;
+ sector_t len;
+ unsigned int total_nr_seq_zones;
+ unsigned int target_nr_seq_zones;
+};
+
+/*
+ * Count the total number of and the number of mapped sequential zones of a
+ * target zoned device.
+ */
+static int dm_device_count_zones_cb(struct blk_zone *zone,
+ unsigned int idx, void *data)
+{
+ struct dm_device_zone_count *zc = data;
+
+ if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL) {
+ zc->total_nr_seq_zones++;
+ if (zone->start >= zc->start &&
+ zone->start < zc->start + zc->len)
+ zc->target_nr_seq_zones++;
+ }
+
+ return 0;
+}
+
+static int dm_device_count_zones(struct dm_dev *dev,
+ struct dm_device_zone_count *zc)
+{
+ int ret;
+
+ ret = blkdev_report_zones(dev->bdev, 0, BLK_ALL_ZONES,
+ dm_device_count_zones_cb, zc);
+ if (ret < 0)
+ return ret;
+ if (!ret)
+ return -EIO;
+ return 0;
+}
+
+struct dm_zone_resource_limits {
+ unsigned int mapped_nr_seq_zones;
+ struct queue_limits *lim;
+ bool reliable_limits;
+};
+
+static int device_get_zone_resource_limits(struct dm_target *ti,
+ struct dm_dev *dev, sector_t start,
+ sector_t len, void *data)
+{
+ struct dm_zone_resource_limits *zlim = data;
+ struct gendisk *disk = dev->bdev->bd_disk;
+ unsigned int max_open_zones, max_active_zones;
+ int ret;
+ struct dm_device_zone_count zc = {
+ .start = start,
+ .len = len,
+ };
+
+ /*
+ * If the target is not the whole device, the device zone resources may
+ * be shared between different targets. Check this by counting the
+ * number of mapped sequential zones: if this number is smaller than the
+ * total number of sequential zones of the target device, then resource
+ * sharing may happen and the zone limits will not be reliable.
+ */
+ ret = dm_device_count_zones(dev, &zc);
+ if (ret) {
+ DMERR("Count %s zones failed %d", disk->disk_name, ret);
+ return ret;
+ }
+
+ /*
+ * If the target does not map any sequential zones, then we do not need
+ * any zone resource limits.
+ */
+ if (!zc.target_nr_seq_zones)
+ return 0;
+
+ /*
+ * If the target does not map all sequential zones, the limits
+ * will not be reliable and we cannot use REQ_OP_ZONE_RESET_ALL.
+ */
+ if (zc.target_nr_seq_zones < zc.total_nr_seq_zones) {
+ zlim->reliable_limits = false;
+ ti->zone_reset_all_supported = false;
+ }
+
+ /*
+ * If the target maps less sequential zones than the limit values, then
+ * we do not have limits for this target.
+ */
+ max_active_zones = disk->queue->limits.max_active_zones;
+ if (max_active_zones >= zc.target_nr_seq_zones)
+ max_active_zones = 0;
+ zlim->lim->max_active_zones =
+ min_not_zero(max_active_zones, zlim->lim->max_active_zones);
+
+ max_open_zones = disk->queue->limits.max_open_zones;
+ if (max_open_zones >= zc.target_nr_seq_zones)
+ max_open_zones = 0;
+ zlim->lim->max_open_zones =
+ min_not_zero(max_open_zones, zlim->lim->max_open_zones);
+
+ /*
+ * Also count the total number of sequential zones for the mapped
+ * device so that when we are done inspecting all its targets, we are
+ * able to check if the mapped device actually has any sequential zones.
+ */
+ zlim->mapped_nr_seq_zones += zc.target_nr_seq_zones;
+
+ return 0;
+}
+
int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q,
struct queue_limits *lim)
{
struct mapped_device *md = t->md;
struct gendisk *disk = md->disk;
- unsigned int nr_conv_zones = 0;
- int ret;
+ struct dm_zone_resource_limits zlim = {
+ .reliable_limits = true,
+ .lim = lim,
+ };
/*
* Check if zone append is natively supported, and if not, set the
@@ -240,46 +347,63 @@ int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q,
lim->max_zone_append_sectors = 0;
}
- if (!get_capacity(md->disk))
- return 0;
-
/*
- * Count conventional zones to check that the mapped device will indeed
- * have sequential write required zones.
+ * Determine the max open and max active zone limits for the mapped
+ * device by inspecting the zone resource limits and the zones mapped
+ * by each target.
*/
- md->zone_revalidate_map = t;
- ret = dm_blk_report_zones(disk, 0, UINT_MAX,
- dm_check_zoned_cb, &nr_conv_zones);
- md->zone_revalidate_map = NULL;
- if (ret < 0) {
- DMERR("Check zoned failed %d", ret);
- return ret;
+ for (unsigned int i = 0; i < t->num_targets; i++) {
+ struct dm_target *ti = dm_table_get_target(t, i);
+
+ /*
+ * Assume that the target can accept REQ_OP_ZONE_RESET_ALL.
+ * device_get_zone_resource_limits() may adjust this if one of
+ * the device used by the target does not have all its
+ * sequential write required zones mapped.
+ */
+ ti->zone_reset_all_supported = true;
+
+ if (!ti->type->iterate_devices ||
+ ti->type->iterate_devices(ti,
+ device_get_zone_resource_limits, &zlim)) {
+ DMERR("Could not determine %s zone resource limits",
+ disk->disk_name);
+ return -ENODEV;
+ }
}
/*
- * If we only have conventional zones, expose the mapped device as
- * a regular device.
+ * If we only have conventional zones mapped, expose the mapped device
+ + as a regular device.
*/
- if (nr_conv_zones >= ret) {
+ if (!zlim.mapped_nr_seq_zones) {
lim->max_open_zones = 0;
lim->max_active_zones = 0;
- lim->zoned = false;
+ lim->max_zone_append_sectors = 0;
+ lim->zone_write_granularity = 0;
+ lim->chunk_sectors = 0;
+ lim->features &= ~BLK_FEAT_ZONED;
clear_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
+ md->nr_zones = 0;
disk->nr_zones = 0;
return 0;
}
- if (!md->disk->nr_zones) {
- DMINFO("%s using %s zone append",
- md->disk->disk_name,
- queue_emulates_zone_append(q) ? "emulated" : "native");
- }
-
- ret = dm_revalidate_zones(md, t);
- if (ret < 0)
- return ret;
+ /*
+ * Warn once (when the capacity is not yet set) if the mapped device is
+ * partially using zone resources of the target devices as that leads to
+ * unreliable limits, i.e. if another mapped device uses the same
+ * underlying devices, we cannot enforce zone limits to guarantee that
+ * writing will not lead to errors. Note that we really should return
+ * an error for such case but there is no easy way to find out if
+ * another mapped device uses the same underlying zoned devices.
+ */
+ if (!get_capacity(disk) && !zlim.reliable_limits)
+ DMWARN("%s zone resource limits may be unreliable",
+ disk->disk_name);
- if (!static_key_enabled(&zoned_enabled.key))
+ if (lim->features & BLK_FEAT_ZONED &&
+ !static_key_enabled(&zoned_enabled.key))
static_branch_enable(&zoned_enabled);
return 0;
}
@@ -306,3 +430,39 @@ void dm_zone_endio(struct dm_io *io, struct bio *clone)
return;
}
+
+static int dm_zone_need_reset_cb(struct blk_zone *zone, unsigned int idx,
+ void *data)
+{
+ /*
+ * For an all-zones reset, ignore conventional, empty, read-only
+ * and offline zones.
+ */
+ switch (zone->cond) {
+ case BLK_ZONE_COND_NOT_WP:
+ case BLK_ZONE_COND_EMPTY:
+ case BLK_ZONE_COND_READONLY:
+ case BLK_ZONE_COND_OFFLINE:
+ return 0;
+ default:
+ set_bit(idx, (unsigned long *)data);
+ return 0;
+ }
+}
+
+int dm_zone_get_reset_bitmap(struct mapped_device *md, struct dm_table *t,
+ sector_t sector, unsigned int nr_zones,
+ unsigned long *need_reset)
+{
+ int ret;
+
+ ret = dm_blk_do_report_zones(md, t, sector, nr_zones,
+ dm_zone_need_reset_cb, need_reset);
+ if (ret != nr_zones) {
+ DMERR("Get %s zone reset bitmap failed\n",
+ md->disk->disk_name);
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/drivers/md/dm-zoned-target.c b/drivers/md/dm-zoned-target.c
index 12236e6f46f3..cd0ee144973f 100644
--- a/drivers/md/dm-zoned-target.c
+++ b/drivers/md/dm-zoned-target.c
@@ -1009,7 +1009,7 @@ static void dmz_io_hints(struct dm_target *ti, struct queue_limits *limits)
limits->max_sectors = chunk_sectors;
/* We are exposing a drive-managed zoned block device */
- limits->zoned = false;
+ limits->features &= ~BLK_FEAT_ZONED;
}
/*
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 13037d6a6f62..4b1b69e576a5 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1188,7 +1188,7 @@ static sector_t __max_io_len(struct dm_target *ti, sector_t sector,
return len;
return min_t(sector_t, len,
min(max_sectors ? : queue_max_sectors(ti->table->md->queue),
- blk_chunk_sectors_left(target_offset, max_granularity)));
+ blk_boundary_sectors_left(target_offset, max_granularity)));
}
static inline sector_t max_io_len(struct dm_target *ti, sector_t sector)
@@ -1598,20 +1598,19 @@ static void __send_abnormal_io(struct clone_info *ci, struct dm_target *ti,
static bool is_abnormal_io(struct bio *bio)
{
- enum req_op op = bio_op(bio);
-
- if (op != REQ_OP_READ && op != REQ_OP_WRITE && op != REQ_OP_FLUSH) {
- switch (op) {
- case REQ_OP_DISCARD:
- case REQ_OP_SECURE_ERASE:
- case REQ_OP_WRITE_ZEROES:
- return true;
- default:
- break;
- }
+ switch (bio_op(bio)) {
+ case REQ_OP_READ:
+ case REQ_OP_WRITE:
+ case REQ_OP_FLUSH:
+ return false;
+ case REQ_OP_DISCARD:
+ case REQ_OP_SECURE_ERASE:
+ case REQ_OP_WRITE_ZEROES:
+ case REQ_OP_ZONE_RESET_ALL:
+ return true;
+ default:
+ return false;
}
-
- return false;
}
static blk_status_t __process_abnormal_io(struct clone_info *ci,
@@ -1776,6 +1775,119 @@ static inline bool dm_zone_plug_bio(struct mapped_device *md, struct bio *bio)
{
return dm_emulate_zone_append(md) && blk_zone_plug_bio(bio, 0);
}
+
+static blk_status_t __send_zone_reset_all_emulated(struct clone_info *ci,
+ struct dm_target *ti)
+{
+ struct bio_list blist = BIO_EMPTY_LIST;
+ struct mapped_device *md = ci->io->md;
+ unsigned int zone_sectors = md->disk->queue->limits.chunk_sectors;
+ unsigned long *need_reset;
+ unsigned int i, nr_zones, nr_reset;
+ unsigned int num_bios = 0;
+ blk_status_t sts = BLK_STS_OK;
+ sector_t sector = ti->begin;
+ struct bio *clone;
+ int ret;
+
+ nr_zones = ti->len >> ilog2(zone_sectors);
+ need_reset = bitmap_zalloc(nr_zones, GFP_NOIO);
+ if (!need_reset)
+ return BLK_STS_RESOURCE;
+
+ ret = dm_zone_get_reset_bitmap(md, ci->map, ti->begin,
+ nr_zones, need_reset);
+ if (ret) {
+ sts = BLK_STS_IOERR;
+ goto free_bitmap;
+ }
+
+ /* If we have no zone to reset, we are done. */
+ nr_reset = bitmap_weight(need_reset, nr_zones);
+ if (!nr_reset)
+ goto free_bitmap;
+
+ atomic_add(nr_zones, &ci->io->io_count);
+
+ for (i = 0; i < nr_zones; i++) {
+
+ if (!test_bit(i, need_reset)) {
+ sector += zone_sectors;
+ continue;
+ }
+
+ if (bio_list_empty(&blist)) {
+ /* This may take a while, so be nice to others */
+ if (num_bios)
+ cond_resched();
+
+ /*
+ * We may need to reset thousands of zones, so let's
+ * not go crazy with the clone allocation.
+ */
+ alloc_multiple_bios(&blist, ci, ti, min(nr_reset, 32),
+ NULL, GFP_NOIO);
+ }
+
+ /* Get a clone and change it to a regular reset operation. */
+ clone = bio_list_pop(&blist);
+ clone->bi_opf &= ~REQ_OP_MASK;
+ clone->bi_opf |= REQ_OP_ZONE_RESET | REQ_SYNC;
+ clone->bi_iter.bi_sector = sector;
+ clone->bi_iter.bi_size = 0;
+ __map_bio(clone);
+
+ sector += zone_sectors;
+ num_bios++;
+ nr_reset--;
+ }
+
+ WARN_ON_ONCE(!bio_list_empty(&blist));
+ atomic_sub(nr_zones - num_bios, &ci->io->io_count);
+ ci->sector_count = 0;
+
+free_bitmap:
+ bitmap_free(need_reset);
+
+ return sts;
+}
+
+static void __send_zone_reset_all_native(struct clone_info *ci,
+ struct dm_target *ti)
+{
+ unsigned int bios;
+
+ atomic_add(1, &ci->io->io_count);
+ bios = __send_duplicate_bios(ci, ti, 1, NULL, GFP_NOIO);
+ atomic_sub(1 - bios, &ci->io->io_count);
+
+ ci->sector_count = 0;
+}
+
+static blk_status_t __send_zone_reset_all(struct clone_info *ci)
+{
+ struct dm_table *t = ci->map;
+ blk_status_t sts = BLK_STS_OK;
+
+ for (unsigned int i = 0; i < t->num_targets; i++) {
+ struct dm_target *ti = dm_table_get_target(t, i);
+
+ if (ti->zone_reset_all_supported) {
+ __send_zone_reset_all_native(ci, ti);
+ continue;
+ }
+
+ sts = __send_zone_reset_all_emulated(ci, ti);
+ if (sts != BLK_STS_OK)
+ break;
+ }
+
+ /* Release the reference that alloc_io() took for submission. */
+ atomic_sub(1, &ci->io->io_count);
+
+ return sts;
+}
+
#else
static inline bool dm_zone_bio_needs_split(struct mapped_device *md,
struct bio *bio)
@@ -1786,6 +1898,10 @@ static inline bool dm_zone_plug_bio(struct mapped_device *md, struct bio *bio)
{
return false;
}
+static blk_status_t __send_zone_reset_all(struct clone_info *ci)
+{
+ return BLK_STS_NOTSUPP;
+}
#endif
/*
@@ -1799,9 +1915,14 @@ static void dm_split_and_process_bio(struct mapped_device *md,
blk_status_t error = BLK_STS_OK;
bool is_abnormal, need_split;
- need_split = is_abnormal = is_abnormal_io(bio);
- if (static_branch_unlikely(&zoned_enabled))
- need_split = is_abnormal || dm_zone_bio_needs_split(md, bio);
+ is_abnormal = is_abnormal_io(bio);
+ if (static_branch_unlikely(&zoned_enabled)) {
+ /* Special case REQ_OP_ZONE_RESET_ALL as it cannot be split. */
+ need_split = (bio_op(bio) != REQ_OP_ZONE_RESET_ALL) &&
+ (is_abnormal || dm_zone_bio_needs_split(md, bio));
+ } else {
+ need_split = is_abnormal;
+ }
if (unlikely(need_split)) {
/*
@@ -1842,6 +1963,12 @@ static void dm_split_and_process_bio(struct mapped_device *md,
goto out;
}
+ if (static_branch_unlikely(&zoned_enabled) &&
+ (bio_op(bio) == REQ_OP_ZONE_RESET_ALL)) {
+ error = __send_zone_reset_all(&ci);
+ goto out;
+ }
+
error = __split_and_process_bio(&ci);
if (error || !ci.sector_count)
goto out;
@@ -2386,22 +2513,15 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
struct table_device *td;
int r;
- switch (type) {
- case DM_TYPE_REQUEST_BASED:
+ WARN_ON_ONCE(type == DM_TYPE_NONE);
+
+ if (type == DM_TYPE_REQUEST_BASED) {
md->disk->fops = &dm_rq_blk_dops;
r = dm_mq_init_request_queue(md, t);
if (r) {
DMERR("Cannot initialize queue for request-based dm mapped device");
return r;
}
- break;
- case DM_TYPE_BIO_BASED:
- case DM_TYPE_DAX_BIO_BASED:
- blk_queue_flag_set(QUEUE_FLAG_IO_STAT, md->queue);
- break;
- case DM_TYPE_NONE:
- WARN_ON_ONCE(true);
- break;
}
r = dm_calculate_queue_limits(t, &limits);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 53ef8207fe2c..cc466ad5cb1d 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -103,12 +103,16 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t);
*/
int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q,
struct queue_limits *lim);
+int dm_revalidate_zones(struct dm_table *t, struct request_queue *q);
void dm_zone_endio(struct dm_io *io, struct bio *clone);
#ifdef CONFIG_BLK_DEV_ZONED
int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
unsigned int nr_zones, report_zones_cb cb, void *data);
bool dm_is_zone_write(struct mapped_device *md, struct bio *bio);
int dm_zone_map_bio(struct dm_target_io *io);
+int dm_zone_get_reset_bitmap(struct mapped_device *md, struct dm_table *t,
+ sector_t sector, unsigned int nr_zones,
+ unsigned long *need_reset);
#else
#define dm_blk_report_zones NULL
static inline bool dm_is_zone_write(struct mapped_device *md, struct bio *bio)
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index 0a2d37eb38ef..08232d8dc815 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -227,6 +227,8 @@ static int __write_sb_page(struct md_rdev *rdev, struct bitmap *bitmap,
struct block_device *bdev;
struct mddev *mddev = bitmap->mddev;
struct bitmap_storage *store = &bitmap->storage;
+ unsigned int bitmap_limit = (bitmap->storage.file_pages - pg_index) <<
+ PAGE_SHIFT;
loff_t sboff, offset = mddev->bitmap_info.offset;
sector_t ps = pg_index * PAGE_SIZE / SECTOR_SIZE;
unsigned int size = PAGE_SIZE;
@@ -269,11 +271,9 @@ static int __write_sb_page(struct md_rdev *rdev, struct bitmap *bitmap,
if (size == 0)
/* bitmap runs in to data */
return -EINVAL;
- } else {
- /* DATA METADATA BITMAP - no problems */
}
- md_super_write(mddev, rdev, sboff + ps, (int) size, page);
+ md_super_write(mddev, rdev, sboff + ps, (int)min(size, bitmap_limit), page);
return 0;
}
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index 8e36a0feec09..139fe2019c1d 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -1570,7 +1570,7 @@ out:
return err;
}
-static struct md_cluster_operations cluster_ops = {
+static const struct md_cluster_operations cluster_ops = {
.join = join,
.leave = leave,
.slot_number = slot_number,
diff --git a/drivers/md/md.c b/drivers/md/md.c
index aff9118ff697..64693913ed18 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -69,13 +69,23 @@
#include "md-bitmap.h"
#include "md-cluster.h"
+static const char *action_name[NR_SYNC_ACTIONS] = {
+ [ACTION_RESYNC] = "resync",
+ [ACTION_RECOVER] = "recover",
+ [ACTION_CHECK] = "check",
+ [ACTION_REPAIR] = "repair",
+ [ACTION_RESHAPE] = "reshape",
+ [ACTION_FROZEN] = "frozen",
+ [ACTION_IDLE] = "idle",
+};
+
/* pers_list is a list of registered personalities protected by pers_lock. */
static LIST_HEAD(pers_list);
static DEFINE_SPINLOCK(pers_lock);
static const struct kobj_type md_ktype;
-struct md_cluster_operations *md_cluster_ops;
+const struct md_cluster_operations *md_cluster_ops;
EXPORT_SYMBOL(md_cluster_ops);
static struct module *md_cluster_mod;
@@ -479,7 +489,6 @@ int mddev_suspend(struct mddev *mddev, bool interruptible)
*/
WRITE_ONCE(mddev->suspended, mddev->suspended + 1);
- del_timer_sync(&mddev->safemode_timer);
/* restrict memory reclaim I/O during raid array is suspend */
mddev->noio_flag = memalloc_noio_save();
@@ -550,13 +559,9 @@ static void md_end_flush(struct bio *bio)
rdev_dec_pending(rdev, mddev);
- if (atomic_dec_and_test(&mddev->flush_pending)) {
- /* The pair is percpu_ref_get() from md_flush_request() */
- percpu_ref_put(&mddev->active_io);
-
+ if (atomic_dec_and_test(&mddev->flush_pending))
/* The pre-request flush has finished */
queue_work(md_wq, &mddev->flush_work);
- }
}
static void md_submit_flush_data(struct work_struct *ws);
@@ -587,12 +592,8 @@ static void submit_flushes(struct work_struct *ws)
rcu_read_lock();
}
rcu_read_unlock();
- if (atomic_dec_and_test(&mddev->flush_pending)) {
- /* The pair is percpu_ref_get() from md_flush_request() */
- percpu_ref_put(&mddev->active_io);
-
+ if (atomic_dec_and_test(&mddev->flush_pending))
queue_work(md_wq, &mddev->flush_work);
- }
}
static void md_submit_flush_data(struct work_struct *ws)
@@ -617,8 +618,20 @@ static void md_submit_flush_data(struct work_struct *ws)
bio_endio(bio);
} else {
bio->bi_opf &= ~REQ_PREFLUSH;
- md_handle_request(mddev, bio);
+
+ /*
+ * make_requst() will never return error here, it only
+ * returns error in raid5_make_request() by dm-raid.
+ * Since dm always splits data and flush operation into
+ * two separate io, io size of flush submitted by dm
+ * always is 0, make_request() will not be called here.
+ */
+ if (WARN_ON_ONCE(!mddev->pers->make_request(mddev, bio)))
+ bio_io_error(bio);
}
+
+ /* The pair is percpu_ref_get() from md_flush_request() */
+ percpu_ref_put(&mddev->active_io);
}
/*
@@ -654,24 +667,22 @@ bool md_flush_request(struct mddev *mddev, struct bio *bio)
WARN_ON(percpu_ref_is_zero(&mddev->active_io));
percpu_ref_get(&mddev->active_io);
mddev->flush_bio = bio;
- bio = NULL;
- }
- spin_unlock_irq(&mddev->lock);
-
- if (!bio) {
+ spin_unlock_irq(&mddev->lock);
INIT_WORK(&mddev->flush_work, submit_flushes);
queue_work(md_wq, &mddev->flush_work);
- } else {
- /* flush was performed for some other bio while we waited. */
- if (bio->bi_iter.bi_size == 0)
- /* an empty barrier - all done */
- bio_endio(bio);
- else {
- bio->bi_opf &= ~REQ_PREFLUSH;
- return false;
- }
+ return true;
}
- return true;
+
+ /* flush was performed for some other bio while we waited. */
+ spin_unlock_irq(&mddev->lock);
+ if (bio->bi_iter.bi_size == 0) {
+ /* pure flush without data - all done */
+ bio_endio(bio);
+ return true;
+ }
+
+ bio->bi_opf &= ~REQ_PREFLUSH;
+ return false;
}
EXPORT_SYMBOL(md_flush_request);
@@ -742,7 +753,6 @@ int mddev_init(struct mddev *mddev)
mutex_init(&mddev->open_mutex);
mutex_init(&mddev->reconfig_mutex);
- mutex_init(&mddev->sync_mutex);
mutex_init(&mddev->suspend_mutex);
mutex_init(&mddev->bitmap_info.mutex);
INIT_LIST_HEAD(&mddev->disks);
@@ -758,7 +768,7 @@ int mddev_init(struct mddev *mddev)
init_waitqueue_head(&mddev->recovery_wait);
mddev->reshape_position = MaxSector;
mddev->reshape_backwards = 0;
- mddev->last_sync_action = "none";
+ mddev->last_sync_action = ACTION_IDLE;
mddev->resync_min = 0;
mddev->resync_max = MaxSector;
mddev->level = LEVEL_NONE;
@@ -2410,36 +2420,10 @@ static LIST_HEAD(pending_raid_disks);
*/
int md_integrity_register(struct mddev *mddev)
{
- struct md_rdev *rdev, *reference = NULL;
-
if (list_empty(&mddev->disks))
return 0; /* nothing to do */
- if (mddev_is_dm(mddev) || blk_get_integrity(mddev->gendisk))
- return 0; /* shouldn't register, or already is */
- rdev_for_each(rdev, mddev) {
- /* skip spares and non-functional disks */
- if (test_bit(Faulty, &rdev->flags))
- continue;
- if (rdev->raid_disk < 0)
- continue;
- if (!reference) {
- /* Use the first rdev as the reference */
- reference = rdev;
- continue;
- }
- /* does this rdev's profile match the reference profile? */
- if (blk_integrity_compare(reference->bdev->bd_disk,
- rdev->bdev->bd_disk) < 0)
- return -EINVAL;
- }
- if (!reference || !bdev_get_integrity(reference->bdev))
- return 0;
- /*
- * All component devices are integrity capable and have matching
- * profiles, register the common profile for the md device.
- */
- blk_integrity_register(mddev->gendisk,
- bdev_get_integrity(reference->bdev));
+ if (mddev_is_dm(mddev) || !blk_get_integrity(mddev->gendisk))
+ return 0; /* shouldn't register */
pr_debug("md: data integrity enabled on %s\n", mdname(mddev));
if (bioset_integrity_create(&mddev->bio_set, BIO_POOL_SIZE) ||
@@ -2459,32 +2443,6 @@ int md_integrity_register(struct mddev *mddev)
}
EXPORT_SYMBOL(md_integrity_register);
-/*
- * Attempt to add an rdev, but only if it is consistent with the current
- * integrity profile
- */
-int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
-{
- struct blk_integrity *bi_mddev;
-
- if (mddev_is_dm(mddev))
- return 0;
-
- bi_mddev = blk_get_integrity(mddev->gendisk);
-
- if (!bi_mddev) /* nothing to do */
- return 0;
-
- if (blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) != 0) {
- pr_err("%s: incompatible integrity profile for %pg\n",
- mdname(mddev), rdev->bdev);
- return -ENXIO;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(md_integrity_add_rdev);
-
static bool rdev_read_only(struct md_rdev *rdev)
{
return bdev_read_only(rdev->bdev) ||
@@ -4867,30 +4825,81 @@ out_unlock:
static struct md_sysfs_entry md_metadata =
__ATTR_PREALLOC(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
-static ssize_t
-action_show(struct mddev *mddev, char *page)
+enum sync_action md_sync_action(struct mddev *mddev)
{
- char *type = "idle";
unsigned long recovery = mddev->recovery;
+
+ /*
+ * frozen has the highest priority, means running sync_thread will be
+ * stopped immediately, and no new sync_thread can start.
+ */
if (test_bit(MD_RECOVERY_FROZEN, &recovery))
- type = "frozen";
- else if (test_bit(MD_RECOVERY_RUNNING, &recovery) ||
- (md_is_rdwr(mddev) && test_bit(MD_RECOVERY_NEEDED, &recovery))) {
- if (test_bit(MD_RECOVERY_RESHAPE, &recovery))
- type = "reshape";
- else if (test_bit(MD_RECOVERY_SYNC, &recovery)) {
- if (!test_bit(MD_RECOVERY_REQUESTED, &recovery))
- type = "resync";
- else if (test_bit(MD_RECOVERY_CHECK, &recovery))
- type = "check";
- else
- type = "repair";
- } else if (test_bit(MD_RECOVERY_RECOVER, &recovery))
- type = "recover";
- else if (mddev->reshape_position != MaxSector)
- type = "reshape";
+ return ACTION_FROZEN;
+
+ /*
+ * read-only array can't register sync_thread, and it can only
+ * add/remove spares.
+ */
+ if (!md_is_rdwr(mddev))
+ return ACTION_IDLE;
+
+ /*
+ * idle means no sync_thread is running, and no new sync_thread is
+ * requested.
+ */
+ if (!test_bit(MD_RECOVERY_RUNNING, &recovery) &&
+ !test_bit(MD_RECOVERY_NEEDED, &recovery))
+ return ACTION_IDLE;
+
+ if (test_bit(MD_RECOVERY_RESHAPE, &recovery) ||
+ mddev->reshape_position != MaxSector)
+ return ACTION_RESHAPE;
+
+ if (test_bit(MD_RECOVERY_RECOVER, &recovery))
+ return ACTION_RECOVER;
+
+ if (test_bit(MD_RECOVERY_SYNC, &recovery)) {
+ /*
+ * MD_RECOVERY_CHECK must be paired with
+ * MD_RECOVERY_REQUESTED.
+ */
+ if (test_bit(MD_RECOVERY_CHECK, &recovery))
+ return ACTION_CHECK;
+ if (test_bit(MD_RECOVERY_REQUESTED, &recovery))
+ return ACTION_REPAIR;
+ return ACTION_RESYNC;
}
- return sprintf(page, "%s\n", type);
+
+ /*
+ * MD_RECOVERY_NEEDED or MD_RECOVERY_RUNNING is set, however, no
+ * sync_action is specified.
+ */
+ return ACTION_IDLE;
+}
+
+enum sync_action md_sync_action_by_name(const char *page)
+{
+ enum sync_action action;
+
+ for (action = 0; action < NR_SYNC_ACTIONS; ++action) {
+ if (cmd_match(page, action_name[action]))
+ return action;
+ }
+
+ return NR_SYNC_ACTIONS;
+}
+
+const char *md_sync_action_name(enum sync_action action)
+{
+ return action_name[action];
+}
+
+static ssize_t
+action_show(struct mddev *mddev, char *page)
+{
+ enum sync_action action = md_sync_action(mddev);
+
+ return sprintf(page, "%s\n", md_sync_action_name(action));
}
/**
@@ -4899,15 +4908,10 @@ action_show(struct mddev *mddev, char *page)
* @locked: if set, reconfig_mutex will still be held after this function
* return; if not set, reconfig_mutex will be released after this
* function return.
- * @check_seq: if set, only wait for curent running sync_thread to stop, noted
- * that new sync_thread can still start.
*/
-static void stop_sync_thread(struct mddev *mddev, bool locked, bool check_seq)
+static void stop_sync_thread(struct mddev *mddev, bool locked)
{
- int sync_seq;
-
- if (check_seq)
- sync_seq = atomic_read(&mddev->sync_seq);
+ int sync_seq = atomic_read(&mddev->sync_seq);
if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) {
if (!locked)
@@ -4928,7 +4932,8 @@ static void stop_sync_thread(struct mddev *mddev, bool locked, bool check_seq)
wait_event(resync_wait,
!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
- (check_seq && sync_seq != atomic_read(&mddev->sync_seq)));
+ (!test_bit(MD_RECOVERY_FROZEN, &mddev->recovery) &&
+ sync_seq != atomic_read(&mddev->sync_seq)));
if (locked)
mddev_lock_nointr(mddev);
@@ -4939,7 +4944,7 @@ void md_idle_sync_thread(struct mddev *mddev)
lockdep_assert_held(&mddev->reconfig_mutex);
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
- stop_sync_thread(mddev, true, true);
+ stop_sync_thread(mddev, true);
}
EXPORT_SYMBOL_GPL(md_idle_sync_thread);
@@ -4948,7 +4953,7 @@ void md_frozen_sync_thread(struct mddev *mddev)
lockdep_assert_held(&mddev->reconfig_mutex);
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
- stop_sync_thread(mddev, true, false);
+ stop_sync_thread(mddev, true);
}
EXPORT_SYMBOL_GPL(md_frozen_sync_thread);
@@ -4963,100 +4968,127 @@ void md_unfrozen_sync_thread(struct mddev *mddev)
}
EXPORT_SYMBOL_GPL(md_unfrozen_sync_thread);
-static void idle_sync_thread(struct mddev *mddev)
+static int mddev_start_reshape(struct mddev *mddev)
{
- mutex_lock(&mddev->sync_mutex);
- clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
-
- if (mddev_lock(mddev)) {
- mutex_unlock(&mddev->sync_mutex);
- return;
- }
-
- stop_sync_thread(mddev, false, true);
- mutex_unlock(&mddev->sync_mutex);
-}
+ int ret;
-static void frozen_sync_thread(struct mddev *mddev)
-{
- mutex_lock(&mddev->sync_mutex);
- set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+ if (mddev->pers->start_reshape == NULL)
+ return -EINVAL;
- if (mddev_lock(mddev)) {
- mutex_unlock(&mddev->sync_mutex);
- return;
+ if (mddev->reshape_position == MaxSector ||
+ mddev->pers->check_reshape == NULL ||
+ mddev->pers->check_reshape(mddev)) {
+ clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+ ret = mddev->pers->start_reshape(mddev);
+ if (ret)
+ return ret;
+ } else {
+ /*
+ * If reshape is still in progress, and md_check_recovery() can
+ * continue to reshape, don't restart reshape because data can
+ * be corrupted for raid456.
+ */
+ clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
}
- stop_sync_thread(mddev, false, false);
- mutex_unlock(&mddev->sync_mutex);
+ sysfs_notify_dirent_safe(mddev->sysfs_degraded);
+ return 0;
}
static ssize_t
action_store(struct mddev *mddev, const char *page, size_t len)
{
+ int ret;
+ enum sync_action action;
+
if (!mddev->pers || !mddev->pers->sync_request)
return -EINVAL;
+retry:
+ if (work_busy(&mddev->sync_work))
+ flush_work(&mddev->sync_work);
- if (cmd_match(page, "idle"))
- idle_sync_thread(mddev);
- else if (cmd_match(page, "frozen"))
- frozen_sync_thread(mddev);
- else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
- return -EBUSY;
- else if (cmd_match(page, "resync"))
- clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
- else if (cmd_match(page, "recover")) {
- clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
- set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
- } else if (cmd_match(page, "reshape")) {
- int err;
- if (mddev->pers->start_reshape == NULL)
- return -EINVAL;
- err = mddev_lock(mddev);
- if (!err) {
- if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) {
- err = -EBUSY;
- } else if (mddev->reshape_position == MaxSector ||
- mddev->pers->check_reshape == NULL ||
- mddev->pers->check_reshape(mddev)) {
- clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
- err = mddev->pers->start_reshape(mddev);
- } else {
- /*
- * If reshape is still in progress, and
- * md_check_recovery() can continue to reshape,
- * don't restart reshape because data can be
- * corrupted for raid456.
- */
- clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
- }
- mddev_unlock(mddev);
+ ret = mddev_lock(mddev);
+ if (ret)
+ return ret;
+
+ if (work_busy(&mddev->sync_work)) {
+ mddev_unlock(mddev);
+ goto retry;
+ }
+
+ action = md_sync_action_by_name(page);
+
+ /* TODO: mdadm rely on "idle" to start sync_thread. */
+ if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) {
+ switch (action) {
+ case ACTION_FROZEN:
+ md_frozen_sync_thread(mddev);
+ ret = len;
+ goto out;
+ case ACTION_IDLE:
+ md_idle_sync_thread(mddev);
+ break;
+ case ACTION_RESHAPE:
+ case ACTION_RECOVER:
+ case ACTION_CHECK:
+ case ACTION_REPAIR:
+ case ACTION_RESYNC:
+ ret = -EBUSY;
+ goto out;
+ default:
+ ret = -EINVAL;
+ goto out;
}
- if (err)
- return err;
- sysfs_notify_dirent_safe(mddev->sysfs_degraded);
} else {
- if (cmd_match(page, "check"))
+ switch (action) {
+ case ACTION_FROZEN:
+ set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+ ret = len;
+ goto out;
+ case ACTION_RESHAPE:
+ clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+ ret = mddev_start_reshape(mddev);
+ if (ret)
+ goto out;
+ break;
+ case ACTION_RECOVER:
+ clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+ set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
+ break;
+ case ACTION_CHECK:
set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
- else if (!cmd_match(page, "repair"))
- return -EINVAL;
- clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
- set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
- set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+ fallthrough;
+ case ACTION_REPAIR:
+ set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
+ set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+ fallthrough;
+ case ACTION_RESYNC:
+ case ACTION_IDLE:
+ clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+ break;
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
}
+
if (mddev->ro == MD_AUTO_READ) {
/* A write to sync_action is enough to justify
* canceling read-auto mode
*/
- flush_work(&mddev->sync_work);
mddev->ro = MD_RDWR;
md_wakeup_thread(mddev->sync_thread);
}
+
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
sysfs_notify_dirent_safe(mddev->sysfs_action);
- return len;
+ ret = len;
+
+out:
+ mddev_unlock(mddev);
+ return ret;
}
static struct md_sysfs_entry md_scan_mode =
@@ -5065,7 +5097,8 @@ __ATTR_PREALLOC(sync_action, S_IRUGO|S_IWUSR, action_show, action_store);
static ssize_t
last_sync_action_show(struct mddev *mddev, char *page)
{
- return sprintf(page, "%s\n", mddev->last_sync_action);
+ return sprintf(page, "%s\n",
+ md_sync_action_name(mddev->last_sync_action));
}
static struct md_sysfs_entry md_last_scan_mode = __ATTR_RO(last_sync_action);
@@ -5755,14 +5788,20 @@ static const struct kobj_type md_ktype = {
int mdp_major = 0;
/* stack the limit for all rdevs into lim */
-void mddev_stack_rdev_limits(struct mddev *mddev, struct queue_limits *lim)
+int mddev_stack_rdev_limits(struct mddev *mddev, struct queue_limits *lim,
+ unsigned int flags)
{
struct md_rdev *rdev;
rdev_for_each(rdev, mddev) {
queue_limits_stack_bdev(lim, rdev->bdev, rdev->data_offset,
mddev->gendisk->disk_name);
+ if ((flags & MDDEV_STACK_INTEGRITY) &&
+ !queue_limits_stack_integrity_bdev(lim, rdev->bdev))
+ return -EINVAL;
}
+
+ return 0;
}
EXPORT_SYMBOL_GPL(mddev_stack_rdev_limits);
@@ -5777,6 +5816,14 @@ int mddev_stack_new_rdev(struct mddev *mddev, struct md_rdev *rdev)
lim = queue_limits_start_update(mddev->gendisk->queue);
queue_limits_stack_bdev(&lim, rdev->bdev, rdev->data_offset,
mddev->gendisk->disk_name);
+
+ if (!queue_limits_stack_integrity_bdev(&lim, rdev->bdev)) {
+ pr_err("%s: incompatible integrity profile for %pg\n",
+ mdname(mddev), rdev->bdev);
+ queue_limits_cancel_update(mddev->gendisk->queue);
+ return -ENXIO;
+ }
+
return queue_limits_commit_update(mddev->gendisk->queue, &lim);
}
EXPORT_SYMBOL_GPL(mddev_stack_new_rdev);
@@ -5806,6 +5853,14 @@ static void mddev_delayed_delete(struct work_struct *ws)
kobject_put(&mddev->kobj);
}
+void md_init_stacking_limits(struct queue_limits *lim)
+{
+ blk_set_stacking_limits(lim);
+ lim->features = BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA |
+ BLK_FEAT_IO_STAT | BLK_FEAT_NOWAIT;
+}
+EXPORT_SYMBOL_GPL(md_init_stacking_limits);
+
struct mddev *md_alloc(dev_t dev, char *name)
{
/*
@@ -5823,7 +5878,7 @@ struct mddev *md_alloc(dev_t dev, char *name)
int partitioned;
int shift;
int unit;
- int error ;
+ int error;
/*
* Wait for any previous instance of this device to be completely
@@ -5881,7 +5936,6 @@ struct mddev *md_alloc(dev_t dev, char *name)
disk->fops = &md_fops;
disk->private_data = mddev;
- blk_queue_write_cache(disk->queue, true, true);
disk->events |= DISK_EVENT_MEDIA_CHANGE;
mddev->gendisk = disk;
error = add_disk(disk);
@@ -6185,28 +6239,6 @@ int md_run(struct mddev *mddev)
}
}
- if (!mddev_is_dm(mddev)) {
- struct request_queue *q = mddev->gendisk->queue;
- bool nonrot = true;
-
- rdev_for_each(rdev, mddev) {
- if (rdev->raid_disk >= 0 && !bdev_nonrot(rdev->bdev)) {
- nonrot = false;
- break;
- }
- }
- if (mddev->degraded)
- nonrot = false;
- if (nonrot)
- blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
- else
- blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
- blk_queue_flag_set(QUEUE_FLAG_IO_STAT, q);
-
- /* Set the NOWAIT flags if all underlying devices support it */
- if (nowait)
- blk_queue_flag_set(QUEUE_FLAG_NOWAIT, q);
- }
if (pers->sync_request) {
if (mddev->kobj.sd &&
sysfs_create_group(&mddev->kobj, &md_redundancy_group))
@@ -6437,7 +6469,7 @@ void md_stop_writes(struct mddev *mddev)
{
mddev_lock_nointr(mddev);
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
- stop_sync_thread(mddev, true, false);
+ stop_sync_thread(mddev, true);
__md_stop_writes(mddev);
mddev_unlock(mddev);
}
@@ -6505,7 +6537,7 @@ static int md_set_readonly(struct mddev *mddev)
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
}
- stop_sync_thread(mddev, false, false);
+ stop_sync_thread(mddev, false);
wait_event(mddev->sb_wait,
!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
mddev_lock_nointr(mddev);
@@ -6551,7 +6583,7 @@ static int do_md_stop(struct mddev *mddev, int mode)
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
}
- stop_sync_thread(mddev, true, false);
+ stop_sync_thread(mddev, true);
if (mddev->sysfs_active ||
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) {
@@ -7166,15 +7198,6 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
if (!mddev->thread)
md_update_sb(mddev, 1);
/*
- * If the new disk does not support REQ_NOWAIT,
- * disable on the whole MD.
- */
- if (!bdev_nowait(rdev->bdev)) {
- pr_info("%s: Disabling nowait because %pg does not support nowait\n",
- mdname(mddev), rdev->bdev);
- blk_queue_flag_clear(QUEUE_FLAG_NOWAIT, mddev->gendisk->queue);
- }
- /*
* Kick recovery, maybe this spare has to be added to the
* array immediately.
*/
@@ -7742,12 +7765,6 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
return get_bitmap_file(mddev, argp);
}
- if (cmd == HOT_REMOVE_DISK)
- /* need to ensure recovery thread has run */
- wait_event_interruptible_timeout(mddev->sb_wait,
- !test_bit(MD_RECOVERY_NEEDED,
- &mddev->recovery),
- msecs_to_jiffies(5000));
if (cmd == STOP_ARRAY || cmd == STOP_ARRAY_RO) {
/* Need to flush page cache, and ensure no-one else opens
* and writes
@@ -8520,7 +8537,7 @@ int unregister_md_personality(struct md_personality *p)
}
EXPORT_SYMBOL(unregister_md_personality);
-int register_md_cluster_operations(struct md_cluster_operations *ops,
+int register_md_cluster_operations(const struct md_cluster_operations *ops,
struct module *module)
{
int ret = 0;
@@ -8641,12 +8658,12 @@ EXPORT_SYMBOL(md_done_sync);
* A return value of 'false' means that the write wasn't recorded
* and cannot proceed as the array is being suspend.
*/
-bool md_write_start(struct mddev *mddev, struct bio *bi)
+void md_write_start(struct mddev *mddev, struct bio *bi)
{
int did_change = 0;
if (bio_data_dir(bi) != WRITE)
- return true;
+ return;
BUG_ON(mddev->ro == MD_RDONLY);
if (mddev->ro == MD_AUTO_READ) {
@@ -8679,15 +8696,9 @@ bool md_write_start(struct mddev *mddev, struct bio *bi)
if (did_change)
sysfs_notify_dirent_safe(mddev->sysfs_state);
if (!mddev->has_superblocks)
- return true;
+ return;
wait_event(mddev->sb_wait,
- !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) ||
- is_md_suspended(mddev));
- if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
- percpu_ref_put(&mddev->writes_pending);
- return false;
- }
- return true;
+ !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
}
EXPORT_SYMBOL(md_write_start);
@@ -8835,6 +8846,77 @@ void md_allow_write(struct mddev *mddev)
}
EXPORT_SYMBOL_GPL(md_allow_write);
+static sector_t md_sync_max_sectors(struct mddev *mddev,
+ enum sync_action action)
+{
+ switch (action) {
+ case ACTION_RESYNC:
+ case ACTION_CHECK:
+ case ACTION_REPAIR:
+ atomic64_set(&mddev->resync_mismatches, 0);
+ fallthrough;
+ case ACTION_RESHAPE:
+ return mddev->resync_max_sectors;
+ case ACTION_RECOVER:
+ return mddev->dev_sectors;
+ default:
+ return 0;
+ }
+}
+
+static sector_t md_sync_position(struct mddev *mddev, enum sync_action action)
+{
+ sector_t start = 0;
+ struct md_rdev *rdev;
+
+ switch (action) {
+ case ACTION_CHECK:
+ case ACTION_REPAIR:
+ return mddev->resync_min;
+ case ACTION_RESYNC:
+ if (!mddev->bitmap)
+ return mddev->recovery_cp;
+ return 0;
+ case ACTION_RESHAPE:
+ /*
+ * If the original node aborts reshaping then we continue the
+ * reshaping, so set again to avoid restart reshape from the
+ * first beginning
+ */
+ if (mddev_is_clustered(mddev) &&
+ mddev->reshape_position != MaxSector)
+ return mddev->reshape_position;
+ return 0;
+ case ACTION_RECOVER:
+ start = MaxSector;
+ rcu_read_lock();
+ rdev_for_each_rcu(rdev, mddev)
+ if (rdev->raid_disk >= 0 &&
+ !test_bit(Journal, &rdev->flags) &&
+ !test_bit(Faulty, &rdev->flags) &&
+ !test_bit(In_sync, &rdev->flags) &&
+ rdev->recovery_offset < start)
+ start = rdev->recovery_offset;
+ rcu_read_unlock();
+
+ /* If there is a bitmap, we need to make sure all
+ * writes that started before we added a spare
+ * complete before we start doing a recovery.
+ * Otherwise the write might complete and (via
+ * bitmap_endwrite) set a bit in the bitmap after the
+ * recovery has checked that bit and skipped that
+ * region.
+ */
+ if (mddev->bitmap) {
+ mddev->pers->quiesce(mddev, 1);
+ mddev->pers->quiesce(mddev, 0);
+ }
+ return start;
+ default:
+ return MaxSector;
+ }
+}
+
#define SYNC_MARKS 10
#define SYNC_MARK_STEP (3*HZ)
#define UPDATE_FREQUENCY (5*60*HZ)
@@ -8851,7 +8933,8 @@ void md_do_sync(struct md_thread *thread)
sector_t last_check;
int skipped = 0;
struct md_rdev *rdev;
- char *desc, *action = NULL;
+ enum sync_action action;
+ const char *desc;
struct blk_plug plug;
int ret;
@@ -8882,21 +8965,9 @@ void md_do_sync(struct md_thread *thread)
goto skip;
}
- if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
- if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) {
- desc = "data-check";
- action = "check";
- } else if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
- desc = "requested-resync";
- action = "repair";
- } else
- desc = "resync";
- } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
- desc = "reshape";
- else
- desc = "recovery";
-
- mddev->last_sync_action = action ?: desc;
+ action = md_sync_action(mddev);
+ desc = md_sync_action_name(action);
+ mddev->last_sync_action = action;
/*
* Before starting a resync we must have set curr_resync to
@@ -8964,56 +9035,8 @@ void md_do_sync(struct md_thread *thread)
spin_unlock(&all_mddevs_lock);
} while (mddev->curr_resync < MD_RESYNC_DELAYED);
- j = 0;
- if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
- /* resync follows the size requested by the personality,
- * which defaults to physical size, but can be virtual size
- */
- max_sectors = mddev->resync_max_sectors;
- atomic64_set(&mddev->resync_mismatches, 0);
- /* we don't use the checkpoint if there's a bitmap */
- if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
- j = mddev->resync_min;
- else if (!mddev->bitmap)
- j = mddev->recovery_cp;
-
- } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
- max_sectors = mddev->resync_max_sectors;
- /*
- * If the original node aborts reshaping then we continue the
- * reshaping, so set j again to avoid restart reshape from the
- * first beginning
- */
- if (mddev_is_clustered(mddev) &&
- mddev->reshape_position != MaxSector)
- j = mddev->reshape_position;
- } else {
- /* recovery follows the physical size of devices */
- max_sectors = mddev->dev_sectors;
- j = MaxSector;
- rcu_read_lock();
- rdev_for_each_rcu(rdev, mddev)
- if (rdev->raid_disk >= 0 &&
- !test_bit(Journal, &rdev->flags) &&
- !test_bit(Faulty, &rdev->flags) &&
- !test_bit(In_sync, &rdev->flags) &&
- rdev->recovery_offset < j)
- j = rdev->recovery_offset;
- rcu_read_unlock();
-
- /* If there is a bitmap, we need to make sure all
- * writes that started before we added a spare
- * complete before we start doing a recovery.
- * Otherwise the write might complete and (via
- * bitmap_endwrite) set a bit in the bitmap after the
- * recovery has checked that bit and skipped that
- * region.
- */
- if (mddev->bitmap) {
- mddev->pers->quiesce(mddev, 1);
- mddev->pers->quiesce(mddev, 0);
- }
- }
+ max_sectors = md_sync_max_sectors(mddev, action);
+ j = md_sync_position(mddev, action);
pr_info("md: %s of RAID array %s\n", desc, mdname(mddev));
pr_debug("md: minimum _guaranteed_ speed: %d KB/sec/disk.\n", speed_min(mddev));
@@ -9095,7 +9118,8 @@ void md_do_sync(struct md_thread *thread)
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
break;
- sectors = mddev->pers->sync_request(mddev, j, &skipped);
+ sectors = mddev->pers->sync_request(mddev, j, max_sectors,
+ &skipped);
if (sectors == 0) {
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
break;
@@ -9185,7 +9209,7 @@ void md_do_sync(struct md_thread *thread)
mddev->curr_resync_completed = mddev->curr_resync;
sysfs_notify_dirent_safe(mddev->sysfs_completed);
}
- mddev->pers->sync_request(mddev, max_sectors, &skipped);
+ mddev->pers->sync_request(mddev, max_sectors, max_sectors, &skipped);
if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
mddev->curr_resync > MD_RESYNC_ACTIVE) {
diff --git a/drivers/md/md.h b/drivers/md/md.h
index ca085ecad504..a0d6827dced9 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -34,6 +34,61 @@
*/
#define MD_FAILFAST (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT)
+/* Status of sync thread. */
+enum sync_action {
+ /*
+ * Represent by MD_RECOVERY_SYNC, start when:
+ * 1) after assemble, sync data from first rdev to other copies, this
+ * must be done first before other sync actions and will only execute
+ * once;
+ * 2) resize the array(notice that this is not reshape), sync data for
+ * the new range;
+ */
+ ACTION_RESYNC,
+ /*
+ * Represent by MD_RECOVERY_RECOVER, start when:
+ * 1) for new replacement, sync data based on the replace rdev or
+ * available copies from other rdev;
+ * 2) for new member disk while the array is degraded, sync data from
+ * other rdev;
+ * 3) reassemble after power failure or re-add a hot removed rdev, sync
+ * data from first rdev to other copies based on bitmap;
+ */
+ ACTION_RECOVER,
+ /*
+ * Represent by MD_RECOVERY_SYNC | MD_RECOVERY_REQUESTED |
+ * MD_RECOVERY_CHECK, start when user echo "check" to sysfs api
+ * sync_action, used to check if data copies from differenct rdev are
+ * the same. The number of mismatch sectors will be exported to user
+ * by sysfs api mismatch_cnt;
+ */
+ ACTION_CHECK,
+ /*
+ * Represent by MD_RECOVERY_SYNC | MD_RECOVERY_REQUESTED, start when
+ * user echo "repair" to sysfs api sync_action, usually paired with
+ * ACTION_CHECK, used to force syncing data once user found that there
+ * are inconsistent data,
+ */
+ ACTION_REPAIR,
+ /*
+ * Represent by MD_RECOVERY_RESHAPE, start when new member disk is added
+ * to the conf, notice that this is different from spares or
+ * replacement;
+ */
+ ACTION_RESHAPE,
+ /*
+ * Represent by MD_RECOVERY_FROZEN, can be set by sysfs api sync_action
+ * or internal usage like setting the array read-only, will forbid above
+ * actions.
+ */
+ ACTION_FROZEN,
+ /*
+ * All above actions don't match.
+ */
+ ACTION_IDLE,
+ NR_SYNC_ACTIONS,
+};
+
/*
* The struct embedded in rdev is used to serialize IO.
*/
@@ -371,13 +426,12 @@ struct mddev {
struct md_thread __rcu *thread; /* management thread */
struct md_thread __rcu *sync_thread; /* doing resync or reconstruct */
- /* 'last_sync_action' is initialized to "none". It is set when a
- * sync operation (i.e "data-check", "requested-resync", "resync",
- * "recovery", or "reshape") is started. It holds this value even
+ /*
+ * Set when a sync operation is started. It holds this value even
* when the sync thread is "frozen" (interrupted) or "idle" (stopped
- * or finished). It is overwritten when a new sync operation is begun.
+ * or finished). It is overwritten when a new sync operation is begun.
*/
- char *last_sync_action;
+ enum sync_action last_sync_action;
sector_t curr_resync; /* last block scheduled */
/* As resync requests can complete out of order, we cannot easily track
* how much resync has been completed. So we occasionally pause until
@@ -540,8 +594,6 @@ struct mddev {
*/
struct list_head deleting;
- /* Used to synchronize idle and frozen for action_store() */
- struct mutex sync_mutex;
/* The sequence number for sync thread */
atomic_t sync_seq;
@@ -551,22 +603,46 @@ struct mddev {
};
enum recovery_flags {
+ /* flags for sync thread running status */
+
+ /*
+ * set when one of sync action is set and new sync thread need to be
+ * registered, or just add/remove spares from conf.
+ */
+ MD_RECOVERY_NEEDED,
+ /* sync thread is running, or about to be started */
+ MD_RECOVERY_RUNNING,
+ /* sync thread needs to be aborted for some reason */
+ MD_RECOVERY_INTR,
+ /* sync thread is done and is waiting to be unregistered */
+ MD_RECOVERY_DONE,
+ /* running sync thread must abort immediately, and not restart */
+ MD_RECOVERY_FROZEN,
+ /* waiting for pers->start() to finish */
+ MD_RECOVERY_WAIT,
+ /* interrupted because io-error */
+ MD_RECOVERY_ERROR,
+
+ /* flags determines sync action, see details in enum sync_action */
+
+ /* if just this flag is set, action is resync. */
+ MD_RECOVERY_SYNC,
+ /*
+ * paired with MD_RECOVERY_SYNC, if MD_RECOVERY_CHECK is not set,
+ * action is repair, means user requested resync.
+ */
+ MD_RECOVERY_REQUESTED,
/*
- * If neither SYNC or RESHAPE are set, then it is a recovery.
+ * paired with MD_RECOVERY_SYNC and MD_RECOVERY_REQUESTED, action is
+ * check.
*/
- MD_RECOVERY_RUNNING, /* a thread is running, or about to be started */
- MD_RECOVERY_SYNC, /* actually doing a resync, not a recovery */
- MD_RECOVERY_RECOVER, /* doing recovery, or need to try it. */
- MD_RECOVERY_INTR, /* resync needs to be aborted for some reason */
- MD_RECOVERY_DONE, /* thread is done and is waiting to be reaped */
- MD_RECOVERY_NEEDED, /* we might need to start a resync/recover */
- MD_RECOVERY_REQUESTED, /* user-space has requested a sync (used with SYNC) */
- MD_RECOVERY_CHECK, /* user-space request for check-only, no repair */
- MD_RECOVERY_RESHAPE, /* A reshape is happening */
- MD_RECOVERY_FROZEN, /* User request to abort, and not restart, any action */
- MD_RECOVERY_ERROR, /* sync-action interrupted because io-error */
- MD_RECOVERY_WAIT, /* waiting for pers->start() to finish */
- MD_RESYNCING_REMOTE, /* remote node is running resync thread */
+ MD_RECOVERY_CHECK,
+ /* recovery, or need to try it */
+ MD_RECOVERY_RECOVER,
+ /* reshape */
+ MD_RECOVERY_RESHAPE,
+ /* remote node is running resync thread */
+ MD_RESYNCING_REMOTE,
};
enum md_ro_state {
@@ -653,7 +729,8 @@ struct md_personality
int (*hot_add_disk) (struct mddev *mddev, struct md_rdev *rdev);
int (*hot_remove_disk) (struct mddev *mddev, struct md_rdev *rdev);
int (*spare_active) (struct mddev *mddev);
- sector_t (*sync_request)(struct mddev *mddev, sector_t sector_nr, int *skipped);
+ sector_t (*sync_request)(struct mddev *mddev, sector_t sector_nr,
+ sector_t max_sector, int *skipped);
int (*resize) (struct mddev *mddev, sector_t sectors);
sector_t (*size) (struct mddev *mddev, sector_t sectors, int raid_disks);
int (*check_reshape) (struct mddev *mddev);
@@ -772,7 +849,7 @@ static inline void safe_put_page(struct page *p)
extern int register_md_personality(struct md_personality *p);
extern int unregister_md_personality(struct md_personality *p);
-extern int register_md_cluster_operations(struct md_cluster_operations *ops,
+extern int register_md_cluster_operations(const struct md_cluster_operations *ops,
struct module *module);
extern int unregister_md_cluster_operations(void);
extern int md_setup_cluster(struct mddev *mddev, int nodes);
@@ -785,7 +862,10 @@ extern void md_unregister_thread(struct mddev *mddev, struct md_thread __rcu **t
extern void md_wakeup_thread(struct md_thread __rcu *thread);
extern void md_check_recovery(struct mddev *mddev);
extern void md_reap_sync_thread(struct mddev *mddev);
-extern bool md_write_start(struct mddev *mddev, struct bio *bi);
+extern enum sync_action md_sync_action(struct mddev *mddev);
+extern enum sync_action md_sync_action_by_name(const char *page);
+extern const char *md_sync_action_name(enum sync_action action);
+extern void md_write_start(struct mddev *mddev, struct bio *bi);
extern void md_write_inc(struct mddev *mddev, struct bio *bi);
extern void md_write_end(struct mddev *mddev);
extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
@@ -809,11 +889,11 @@ extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
extern int md_check_no_bitmap(struct mddev *mddev);
extern int md_integrity_register(struct mddev *mddev);
-extern int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev);
extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
extern int mddev_init(struct mddev *mddev);
extern void mddev_destroy(struct mddev *mddev);
+void md_init_stacking_limits(struct queue_limits *lim);
struct mddev *md_alloc(dev_t dev, char *name);
void mddev_put(struct mddev *mddev);
extern int md_run(struct mddev *mddev);
@@ -852,7 +932,7 @@ static inline void rdev_dec_pending(struct md_rdev *rdev, struct mddev *mddev)
}
}
-extern struct md_cluster_operations *md_cluster_ops;
+extern const struct md_cluster_operations *md_cluster_ops;
static inline int mddev_is_clustered(struct mddev *mddev)
{
return mddev->cluster_info && mddev->bitmap_info.nodes > 1;
@@ -908,7 +988,9 @@ void md_autostart_arrays(int part);
int md_set_array_info(struct mddev *mddev, struct mdu_array_info_s *info);
int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info);
int do_md_run(struct mddev *mddev);
-void mddev_stack_rdev_limits(struct mddev *mddev, struct queue_limits *lim);
+#define MDDEV_STACK_INTEGRITY (1u << 0)
+int mddev_stack_rdev_limits(struct mddev *mddev, struct queue_limits *lim,
+ unsigned int flags);
int mddev_stack_new_rdev(struct mddev *mddev, struct md_rdev *rdev);
void mddev_update_io_opt(struct mddev *mddev, unsigned int nr_stripes);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index c5d4aeb68404..32d587524778 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -365,30 +365,30 @@ static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks
return array_sectors;
}
-static void free_conf(struct mddev *mddev, struct r0conf *conf)
-{
- kfree(conf->strip_zone);
- kfree(conf->devlist);
- kfree(conf);
-}
-
static void raid0_free(struct mddev *mddev, void *priv)
{
struct r0conf *conf = priv;
- free_conf(mddev, conf);
+ kfree(conf->strip_zone);
+ kfree(conf->devlist);
+ kfree(conf);
}
static int raid0_set_limits(struct mddev *mddev)
{
struct queue_limits lim;
+ int err;
- blk_set_stacking_limits(&lim);
+ md_init_stacking_limits(&lim);
lim.max_hw_sectors = mddev->chunk_sectors;
lim.max_write_zeroes_sectors = mddev->chunk_sectors;
lim.io_min = mddev->chunk_sectors << 9;
lim.io_opt = lim.io_min * mddev->raid_disks;
- mddev_stack_rdev_limits(mddev, &lim);
+ err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
+ if (err) {
+ queue_limits_cancel_update(mddev->gendisk->queue);
+ return err;
+ }
return queue_limits_set(mddev->gendisk->queue, &lim);
}
@@ -415,7 +415,7 @@ static int raid0_run(struct mddev *mddev)
if (!mddev_is_dm(mddev)) {
ret = raid0_set_limits(mddev);
if (ret)
- goto out_free_conf;
+ return ret;
}
/* calculate array device size */
@@ -427,13 +427,7 @@ static int raid0_run(struct mddev *mddev)
dump_zones(mddev);
- ret = md_integrity_register(mddev);
- if (ret)
- goto out_free_conf;
- return 0;
-out_free_conf:
- free_conf(mddev, conf);
- return ret;
+ return md_integrity_register(mddev);
}
/*
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 7b8a71ca66dd..04a0c2ca1732 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1687,8 +1687,7 @@ static bool raid1_make_request(struct mddev *mddev, struct bio *bio)
if (bio_data_dir(bio) == READ)
raid1_read_request(mddev, bio, sectors, NULL);
else {
- if (!md_write_start(mddev,bio))
- return false;
+ md_write_start(mddev,bio);
raid1_write_request(mddev, bio, sectors);
}
return true;
@@ -1907,9 +1906,6 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
if (mddev->recovery_disabled == conf->recovery_disabled)
return -EBUSY;
- if (md_integrity_add_rdev(rdev, mddev))
- return -ENXIO;
-
if (rdev->raid_disk >= 0)
first = last = rdev->raid_disk;
@@ -2757,12 +2753,12 @@ static struct r1bio *raid1_alloc_init_r1buf(struct r1conf *conf)
*/
static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
- int *skipped)
+ sector_t max_sector, int *skipped)
{
struct r1conf *conf = mddev->private;
struct r1bio *r1_bio;
struct bio *bio;
- sector_t max_sector, nr_sectors;
+ sector_t nr_sectors;
int disk = -1;
int i;
int wonly = -1;
@@ -2778,7 +2774,6 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
if (init_resync(conf))
return 0;
- max_sector = mddev->dev_sectors;
if (sector_nr >= max_sector) {
/* If we aborted, we need to abort the
* sync on the 'current' bitmap chunk (there will
@@ -3197,14 +3192,18 @@ static struct r1conf *setup_conf(struct mddev *mddev)
static int raid1_set_limits(struct mddev *mddev)
{
struct queue_limits lim;
+ int err;
- blk_set_stacking_limits(&lim);
+ md_init_stacking_limits(&lim);
lim.max_write_zeroes_sectors = 0;
- mddev_stack_rdev_limits(mddev, &lim);
+ err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
+ if (err) {
+ queue_limits_cancel_update(mddev->gendisk->queue);
+ return err;
+ }
return queue_limits_set(mddev->gendisk->queue, &lim);
}
-static void raid1_free(struct mddev *mddev, void *priv);
static int raid1_run(struct mddev *mddev)
{
struct r1conf *conf;
@@ -3238,7 +3237,7 @@ static int raid1_run(struct mddev *mddev)
if (!mddev_is_dm(mddev)) {
ret = raid1_set_limits(mddev);
if (ret)
- goto abort;
+ return ret;
}
mddev->degraded = 0;
@@ -3252,8 +3251,7 @@ static int raid1_run(struct mddev *mddev)
*/
if (conf->raid_disks - mddev->degraded < 1) {
md_unregister_thread(mddev, &conf->thread);
- ret = -EINVAL;
- goto abort;
+ return -EINVAL;
}
if (conf->raid_disks - mddev->degraded == 1)
@@ -3277,14 +3275,8 @@ static int raid1_run(struct mddev *mddev)
md_set_array_sectors(mddev, raid1_size(mddev, 0, 0));
ret = md_integrity_register(mddev);
- if (ret) {
+ if (ret)
md_unregister_thread(mddev, &mddev->thread);
- goto abort;
- }
- return 0;
-
-abort:
- raid1_free(mddev, conf);
return ret;
}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index a4556d2e46bf..2a9c4ee982e0 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1836,8 +1836,7 @@ static bool raid10_make_request(struct mddev *mddev, struct bio *bio)
&& md_flush_request(mddev, bio))
return true;
- if (!md_write_start(mddev, bio))
- return false;
+ md_write_start(mddev, bio);
if (unlikely(bio_op(bio) == REQ_OP_DISCARD))
if (!raid10_handle_discard(mddev, bio))
@@ -2083,9 +2082,6 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
if (rdev->saved_raid_disk < 0 && !_enough(conf, 1, -1))
return -EINVAL;
- if (md_integrity_add_rdev(rdev, mddev))
- return -ENXIO;
-
if (rdev->raid_disk >= 0)
first = last = rdev->raid_disk;
@@ -3140,12 +3136,12 @@ static void raid10_set_cluster_sync_high(struct r10conf *conf)
*/
static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
- int *skipped)
+ sector_t max_sector, int *skipped)
{
struct r10conf *conf = mddev->private;
struct r10bio *r10_bio;
struct bio *biolist = NULL, *bio;
- sector_t max_sector, nr_sectors;
+ sector_t nr_sectors;
int i;
int max_sync;
sector_t sync_blocks;
@@ -3175,10 +3171,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
return 0;
skipped:
- max_sector = mddev->dev_sectors;
- if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
- test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
- max_sector = mddev->resync_max_sectors;
if (sector_nr >= max_sector) {
conf->cluster_sync_low = 0;
conf->cluster_sync_high = 0;
@@ -3980,12 +3972,17 @@ static int raid10_set_queue_limits(struct mddev *mddev)
{
struct r10conf *conf = mddev->private;
struct queue_limits lim;
+ int err;
- blk_set_stacking_limits(&lim);
+ md_init_stacking_limits(&lim);
lim.max_write_zeroes_sectors = 0;
lim.io_min = mddev->chunk_sectors << 9;
lim.io_opt = lim.io_min * raid10_nr_stripes(conf);
- mddev_stack_rdev_limits(mddev, &lim);
+ err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
+ if (err) {
+ queue_limits_cancel_update(mddev->gendisk->queue);
+ return err;
+ }
return queue_limits_set(mddev->gendisk->queue, &lim);
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 2bd1ce9b3922..c14cf2410365 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -155,7 +155,7 @@ static int raid6_idx_to_slot(int idx, struct stripe_head *sh,
return slot;
}
-static void print_raid5_conf (struct r5conf *conf);
+static void print_raid5_conf(struct r5conf *conf);
static int stripe_operations_active(struct stripe_head *sh)
{
@@ -5899,6 +5899,39 @@ out:
return ret;
}
+enum reshape_loc {
+ LOC_NO_RESHAPE,
+ LOC_AHEAD_OF_RESHAPE,
+ LOC_INSIDE_RESHAPE,
+ LOC_BEHIND_RESHAPE,
+};
+
+static enum reshape_loc get_reshape_loc(struct mddev *mddev,
+ struct r5conf *conf, sector_t logical_sector)
+{
+ sector_t reshape_progress, reshape_safe;
+ /*
+ * Spinlock is needed as reshape_progress may be
+ * 64bit on a 32bit platform, and so it might be
+ * possible to see a half-updated value
+ * Of course reshape_progress could change after
+ * the lock is dropped, so once we get a reference
+ * to the stripe that we think it is, we will have
+ * to check again.
+ */
+ spin_lock_irq(&conf->device_lock);
+ reshape_progress = conf->reshape_progress;
+ reshape_safe = conf->reshape_safe;
+ spin_unlock_irq(&conf->device_lock);
+ if (reshape_progress == MaxSector)
+ return LOC_NO_RESHAPE;
+ if (ahead_of_reshape(mddev, logical_sector, reshape_progress))
+ return LOC_AHEAD_OF_RESHAPE;
+ if (ahead_of_reshape(mddev, logical_sector, reshape_safe))
+ return LOC_INSIDE_RESHAPE;
+ return LOC_BEHIND_RESHAPE;
+}
+
static enum stripe_result make_stripe_request(struct mddev *mddev,
struct r5conf *conf, struct stripe_request_ctx *ctx,
sector_t logical_sector, struct bio *bi)
@@ -5913,28 +5946,14 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
seq = read_seqcount_begin(&conf->gen_lock);
if (unlikely(conf->reshape_progress != MaxSector)) {
- /*
- * Spinlock is needed as reshape_progress may be
- * 64bit on a 32bit platform, and so it might be
- * possible to see a half-updated value
- * Of course reshape_progress could change after
- * the lock is dropped, so once we get a reference
- * to the stripe that we think it is, we will have
- * to check again.
- */
- spin_lock_irq(&conf->device_lock);
- if (ahead_of_reshape(mddev, logical_sector,
- conf->reshape_progress)) {
- previous = 1;
- } else {
- if (ahead_of_reshape(mddev, logical_sector,
- conf->reshape_safe)) {
- spin_unlock_irq(&conf->device_lock);
- ret = STRIPE_SCHEDULE_AND_RETRY;
- goto out;
- }
+ enum reshape_loc loc = get_reshape_loc(mddev, conf,
+ logical_sector);
+ if (loc == LOC_INSIDE_RESHAPE) {
+ ret = STRIPE_SCHEDULE_AND_RETRY;
+ goto out;
}
- spin_unlock_irq(&conf->device_lock);
+ if (loc == LOC_AHEAD_OF_RESHAPE)
+ previous = 1;
}
new_sector = raid5_compute_sector(conf, logical_sector, previous,
@@ -6078,8 +6097,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
ctx.do_flush = bi->bi_opf & REQ_PREFLUSH;
}
- if (!md_write_start(mddev, bi))
- return false;
+ md_write_start(mddev, bi);
/*
* If array is degraded, better not do chunk aligned read because
* later we might have to read it again in order to reconstruct
@@ -6113,8 +6131,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
/* Bail out if conflicts with reshape and REQ_NOWAIT is set */
if ((bi->bi_opf & REQ_NOWAIT) &&
(conf->reshape_progress != MaxSector) &&
- !ahead_of_reshape(mddev, logical_sector, conf->reshape_progress) &&
- ahead_of_reshape(mddev, logical_sector, conf->reshape_safe)) {
+ get_reshape_loc(mddev, conf, logical_sector) == LOC_INSIDE_RESHAPE) {
bio_wouldblock_error(bi);
if (rw == WRITE)
md_write_end(mddev);
@@ -6255,7 +6272,9 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
safepos = conf->reshape_safe;
sector_div(safepos, data_disks);
if (mddev->reshape_backwards) {
- BUG_ON(writepos < reshape_sectors);
+ if (WARN_ON(writepos < reshape_sectors))
+ return MaxSector;
+
writepos -= reshape_sectors;
readpos += reshape_sectors;
safepos += reshape_sectors;
@@ -6273,14 +6292,18 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
* to set 'stripe_addr' which is where we will write to.
*/
if (mddev->reshape_backwards) {
- BUG_ON(conf->reshape_progress == 0);
+ if (WARN_ON(conf->reshape_progress == 0))
+ return MaxSector;
+
stripe_addr = writepos;
- BUG_ON((mddev->dev_sectors &
- ~((sector_t)reshape_sectors - 1))
- - reshape_sectors - stripe_addr
- != sector_nr);
+ if (WARN_ON((mddev->dev_sectors &
+ ~((sector_t)reshape_sectors - 1)) -
+ reshape_sectors - stripe_addr != sector_nr))
+ return MaxSector;
} else {
- BUG_ON(writepos != sector_nr + reshape_sectors);
+ if (WARN_ON(writepos != sector_nr + reshape_sectors))
+ return MaxSector;
+
stripe_addr = sector_nr;
}
@@ -6458,11 +6481,10 @@ ret:
}
static inline sector_t raid5_sync_request(struct mddev *mddev, sector_t sector_nr,
- int *skipped)
+ sector_t max_sector, int *skipped)
{
struct r5conf *conf = mddev->private;
struct stripe_head *sh;
- sector_t max_sector = mddev->dev_sectors;
sector_t sync_blocks;
int still_degraded = 0;
int i;
@@ -7082,12 +7104,14 @@ raid5_store_skip_copy(struct mddev *mddev, const char *page, size_t len)
err = -ENODEV;
else if (new != conf->skip_copy) {
struct request_queue *q = mddev->gendisk->queue;
+ struct queue_limits lim = queue_limits_start_update(q);
conf->skip_copy = new;
if (new)
- blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, q);
+ lim.features |= BLK_FEAT_STABLE_WRITES;
else
- blk_queue_flag_clear(QUEUE_FLAG_STABLE_WRITES, q);
+ lim.features &= ~BLK_FEAT_STABLE_WRITES;
+ err = queue_limits_commit_update(q, &lim);
}
mddev_unlock_and_resume(mddev);
return err ?: len;
@@ -7562,11 +7586,11 @@ static struct r5conf *setup_conf(struct mddev *mddev)
if (test_bit(Replacement, &rdev->flags)) {
if (disk->replacement)
goto abort;
- RCU_INIT_POINTER(disk->replacement, rdev);
+ disk->replacement = rdev;
} else {
if (disk->rdev)
goto abort;
- RCU_INIT_POINTER(disk->rdev, rdev);
+ disk->rdev = rdev;
}
if (test_bit(In_sync, &rdev->flags)) {
@@ -7702,13 +7726,13 @@ static int raid5_set_limits(struct mddev *mddev)
*/
stripe = roundup_pow_of_two(data_disks * (mddev->chunk_sectors << 9));
- blk_set_stacking_limits(&lim);
+ md_init_stacking_limits(&lim);
lim.io_min = mddev->chunk_sectors << 9;
lim.io_opt = lim.io_min * (conf->raid_disks - conf->max_degraded);
- lim.raid_partial_stripes_expensive = 1;
+ lim.features |= BLK_FEAT_RAID_PARTIAL_STRIPES_EXPENSIVE;
lim.discard_granularity = stripe;
lim.max_write_zeroes_sectors = 0;
- mddev_stack_rdev_limits(mddev, &lim);
+ mddev_stack_rdev_limits(mddev, &lim, 0);
rdev_for_each(rdev, mddev)
queue_limits_stack_bdev(&lim, rdev->bdev, rdev->new_data_offset,
mddev->gendisk->disk_name);
@@ -8048,7 +8072,7 @@ static void raid5_status(struct seq_file *seq, struct mddev *mddev)
seq_printf (seq, "]");
}
-static void print_raid5_conf (struct r5conf *conf)
+static void print_raid5_conf(struct r5conf *conf)
{
struct md_rdev *rdev;
int i;
@@ -8062,15 +8086,13 @@ static void print_raid5_conf (struct r5conf *conf)
conf->raid_disks,
conf->raid_disks - conf->mddev->degraded);
- rcu_read_lock();
for (i = 0; i < conf->raid_disks; i++) {
- rdev = rcu_dereference(conf->disks[i].rdev);
+ rdev = conf->disks[i].rdev;
if (rdev)
pr_debug(" disk %d, o:%d, dev:%pg\n",
i, !test_bit(Faulty, &rdev->flags),
rdev->bdev);
}
- rcu_read_unlock();
}
static int raid5_spare_active(struct mddev *mddev)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index c8a33e1e910c..06090cc0a476 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -943,7 +943,7 @@ ipu6_isys_query_stream_by_source(struct ipu6_isys *isys, int source, u8 vc)
return NULL;
if (source < 0) {
- dev_err(&stream->isys->adev->auxdev.dev,
+ dev_err(&isys->adev->auxdev.dev,
"query stream with invalid port number\n");
return NULL;
}
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index 8b9b77719bb1..c4aff2e2009b 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -799,7 +799,7 @@ static int isys_register_devices(struct ipu6_isys *isys)
isys->v4l2_dev.mdev = &isys->media_dev;
isys->v4l2_dev.ctrl_handler = NULL;
- ret = v4l2_device_register(&pdev->dev, &isys->v4l2_dev);
+ ret = v4l2_device_register(dev, &isys->v4l2_dev);
if (ret < 0)
goto out_media_device_unregister;
diff --git a/drivers/media/pci/intel/ivsc/Kconfig b/drivers/media/pci/intel/ivsc/Kconfig
index 407a800c81bc..a7d9607ecdc6 100644
--- a/drivers/media/pci/intel/ivsc/Kconfig
+++ b/drivers/media/pci/intel/ivsc/Kconfig
@@ -4,6 +4,7 @@
config INTEL_VSC
tristate "Intel Visual Sensing Controller"
depends on INTEL_MEI && ACPI && VIDEO_DEV
+ depends on IPU_BRIDGE || !IPU_BRIDGE
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c
index 502822059498..4ce76ce6dd4d 100644
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
+++ b/drivers/media/platform/qcom/venus/pm_helpers.c
@@ -412,10 +412,9 @@ static int vcodec_control_v4(struct venus_core *core, u32 coreid, bool enable)
u32 val;
int ret;
- if (IS_V6(core)) {
- ctrl = core->wrapper_base + WRAPPER_CORE_POWER_CONTROL_V6;
- stat = core->wrapper_base + WRAPPER_CORE_POWER_STATUS_V6;
- } else if (coreid == VIDC_CORE_ID_1) {
+ if (IS_V6(core))
+ return dev_pm_genpd_set_hwmode(core->pmdomains->pd_devs[coreid], !enable);
+ else if (coreid == VIDC_CORE_ID_1) {
ctrl = core->wrapper_base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL;
stat = core->wrapper_base + WRAPPER_VCODEC0_MMCC_POWER_STATUS;
} else {
@@ -451,9 +450,11 @@ static int poweroff_coreid(struct venus_core *core, unsigned int coreid_mask)
vcodec_clks_disable(core, core->vcodec0_clks);
- ret = vcodec_control_v4(core, VIDC_CORE_ID_1, false);
- if (ret)
- return ret;
+ if (!IS_V6(core)) {
+ ret = vcodec_control_v4(core, VIDC_CORE_ID_1, false);
+ if (ret)
+ return ret;
+ }
ret = pm_runtime_put_sync(core->pmdomains->pd_devs[1]);
if (ret < 0)
@@ -467,9 +468,11 @@ static int poweroff_coreid(struct venus_core *core, unsigned int coreid_mask)
vcodec_clks_disable(core, core->vcodec1_clks);
- ret = vcodec_control_v4(core, VIDC_CORE_ID_2, false);
- if (ret)
- return ret;
+ if (!IS_V6(core)) {
+ ret = vcodec_control_v4(core, VIDC_CORE_ID_2, false);
+ if (ret)
+ return ret;
+ }
ret = pm_runtime_put_sync(core->pmdomains->pd_devs[2]);
if (ret < 0)
@@ -488,9 +491,11 @@ static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask)
if (ret < 0)
return ret;
- ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true);
- if (ret)
- return ret;
+ if (!IS_V6(core)) {
+ ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true);
+ if (ret)
+ return ret;
+ }
ret = vcodec_clks_enable(core, core->vcodec0_clks);
if (ret)
@@ -506,9 +511,11 @@ static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask)
if (ret < 0)
return ret;
- ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true);
- if (ret)
- return ret;
+ if (!IS_V6(core)) {
+ ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true);
+ if (ret)
+ return ret;
+ }
ret = vcodec_clks_enable(core, core->vcodec1_clks);
if (ret)
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 8efdd1f97139..c82d8d8a16ea 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -167,7 +167,7 @@ config FSL_CORENET_CF
represents a coherency violation.
config FSL_IFC
- bool "Freescale IFC driver" if COMPILE_TEST
+ bool "Freescale IFC driver"
depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST
depends on HAS_IOMEM
diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig
index 4113343da056..fcd2c2cc3cb4 100644
--- a/drivers/memstick/host/Kconfig
+++ b/drivers/memstick/host/Kconfig
@@ -44,16 +44,6 @@ config MEMSTICK_R592
To compile this driver as a module, choose M here: the module will
be called r592.
-config MEMSTICK_REALTEK_PCI
- tristate "Realtek PCI-E Memstick Card Interface Driver"
- depends on MISC_RTSX_PCI
- help
- Say Y here to include driver code to support Memstick card interface
- of Realtek PCI-E card reader
-
- To compile this driver as a module, choose M here: the module will
- be called rtsx_pci_ms.
-
config MEMSTICK_REALTEK_USB
tristate "Realtek USB Memstick Card Interface Driver"
depends on MISC_RTSX_USB
diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile
index 1abaa03ee68c..0c90df33165d 100644
--- a/drivers/memstick/host/Makefile
+++ b/drivers/memstick/host/Makefile
@@ -6,5 +6,4 @@
obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o
obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o
obj-$(CONFIG_MEMSTICK_R592) += r592.o
-obj-$(CONFIG_MEMSTICK_REALTEK_PCI) += rtsx_pci_ms.o
obj-$(CONFIG_MEMSTICK_REALTEK_USB) += rtsx_usb_ms.o
diff --git a/drivers/memstick/host/rtsx_pci_ms.c b/drivers/memstick/host/rtsx_pci_ms.c
deleted file mode 100644
index 980a54513e6c..000000000000
--- a/drivers/memstick/host/rtsx_pci_ms.c
+++ /dev/null
@@ -1,638 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/* Realtek PCI-Express Memstick Card Interface driver
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG <[email protected]>
- */
-
-#include <linux/module.h>
-#include <linux/highmem.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/memstick.h>
-#include <linux/rtsx_pci.h>
-#include <asm/unaligned.h>
-
-struct realtek_pci_ms {
- struct platform_device *pdev;
- struct rtsx_pcr *pcr;
- struct memstick_host *msh;
- struct memstick_request *req;
-
- struct mutex host_mutex;
- struct work_struct handle_req;
-
- u8 ssc_depth;
- unsigned int clock;
- unsigned char ifmode;
- bool eject;
-};
-
-static inline struct device *ms_dev(struct realtek_pci_ms *host)
-{
- return &(host->pdev->dev);
-}
-
-static inline void ms_clear_error(struct realtek_pci_ms *host)
-{
- rtsx_pci_write_register(host->pcr, CARD_STOP,
- MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
-}
-
-#ifdef DEBUG
-
-static void ms_print_debug_regs(struct realtek_pci_ms *host)
-{
- struct rtsx_pcr *pcr = host->pcr;
- u16 i;
- u8 *ptr;
-
- /* Print MS host internal registers */
- rtsx_pci_init_cmd(pcr);
- for (i = 0xFD40; i <= 0xFD44; i++)
- rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
- for (i = 0xFD52; i <= 0xFD69; i++)
- rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
- rtsx_pci_send_cmd(pcr, 100);
-
- ptr = rtsx_pci_get_cmd_data(pcr);
- for (i = 0xFD40; i <= 0xFD44; i++)
- dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
- for (i = 0xFD52; i <= 0xFD69; i++)
- dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
-}
-
-#else
-
-#define ms_print_debug_regs(host)
-
-#endif
-
-static int ms_power_on(struct realtek_pci_ms *host)
-{
- struct rtsx_pcr *pcr = host->pcr;
- int err;
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
- CARD_SHARE_MASK, CARD_SHARE_48_MS);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN,
- MS_CLK_EN, MS_CLK_EN);
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_MS_CARD);
- if (err < 0)
- return err;
-
- err = rtsx_pci_card_power_on(pcr, RTSX_MS_CARD);
- if (err < 0)
- return err;
-
- /* Wait ms power stable */
- msleep(150);
-
- err = rtsx_pci_write_register(pcr, CARD_OE,
- MS_OUTPUT_EN, MS_OUTPUT_EN);
- if (err < 0)
- return err;
-
- return 0;
-}
-
-static int ms_power_off(struct realtek_pci_ms *host)
-{
- struct rtsx_pcr *pcr = host->pcr;
- int err;
-
- rtsx_pci_init_cmd(pcr);
-
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);
-
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- err = rtsx_pci_card_power_off(pcr, RTSX_MS_CARD);
- if (err < 0)
- return err;
-
- return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD);
-}
-
-static int ms_transfer_data(struct realtek_pci_ms *host, unsigned char data_dir,
- u8 tpc, u8 cfg, struct scatterlist *sg)
-{
- struct rtsx_pcr *pcr = host->pcr;
- int err;
- unsigned int length = sg->length;
- u16 sec_cnt = (u16)(length / 512);
- u8 val, trans_mode, dma_dir;
- struct memstick_dev *card = host->msh->card;
- bool pro_card = card->id.type == MEMSTICK_TYPE_PRO;
-
- dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n",
- __func__, tpc, (data_dir == READ) ? "READ" : "WRITE",
- length);
-
- if (data_dir == READ) {
- dma_dir = DMA_DIR_FROM_CARD;
- trans_mode = pro_card ? MS_TM_AUTO_READ : MS_TM_NORMAL_READ;
- } else {
- dma_dir = DMA_DIR_TO_CARD;
- trans_mode = pro_card ? MS_TM_AUTO_WRITE : MS_TM_NORMAL_WRITE;
- }
-
- rtsx_pci_init_cmd(pcr);
-
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- if (pro_card) {
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_H,
- 0xFF, (u8)(sec_cnt >> 8));
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_L,
- 0xFF, (u8)sec_cnt);
- }
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
-
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
- DMA_DONE_INT, DMA_DONE_INT);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(length >> 24));
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(length >> 16));
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(length >> 8));
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)length);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
- 0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, RING_BUFFER);
-
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
- 0xFF, MS_TRANSFER_START | trans_mode);
- rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_pci_send_cmd_no_wait(pcr);
-
- err = rtsx_pci_transfer_data(pcr, sg, 1, data_dir == READ, 10000);
- if (err < 0) {
- ms_clear_error(host);
- return err;
- }
-
- rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
- if (pro_card) {
- if (val & (MS_INT_CMDNK | MS_INT_ERR |
- MS_CRC16_ERR | MS_RDY_TIMEOUT))
- return -EIO;
- } else {
- if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT))
- return -EIO;
- }
-
- return 0;
-}
-
-static int ms_write_bytes(struct realtek_pci_ms *host, u8 tpc,
- u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
-{
- struct rtsx_pcr *pcr = host->pcr;
- int err, i;
-
- dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
-
- if (!data)
- return -EINVAL;
-
- rtsx_pci_init_cmd(pcr);
-
- for (i = 0; i < cnt; i++)
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
- PPBUF_BASE2 + i, 0xFF, data[i]);
- if (cnt % 2)
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
- PPBUF_BASE2 + i, 0xFF, 0xFF);
-
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
-
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
- 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
- rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
- if (int_reg)
- rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
-
- err = rtsx_pci_send_cmd(pcr, 5000);
- if (err < 0) {
- u8 val;
-
- rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
- dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
-
- if (int_reg)
- *int_reg = val & 0x0F;
-
- ms_print_debug_regs(host);
-
- ms_clear_error(host);
-
- if (!(tpc & 0x08)) {
- if (val & MS_CRC16_ERR)
- return -EIO;
- } else {
- if (!(val & 0x80)) {
- if (val & (MS_INT_ERR | MS_INT_CMDNK))
- return -EIO;
- }
- }
-
- return -ETIMEDOUT;
- }
-
- if (int_reg) {
- u8 *ptr = rtsx_pci_get_cmd_data(pcr) + 1;
- *int_reg = *ptr & 0x0F;
- }
-
- return 0;
-}
-
-static int ms_read_bytes(struct realtek_pci_ms *host, u8 tpc,
- u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
-{
- struct rtsx_pcr *pcr = host->pcr;
- int err, i;
- u8 *ptr;
-
- dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
-
- if (!data)
- return -EINVAL;
-
- rtsx_pci_init_cmd(pcr);
-
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
-
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
- 0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES);
- rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
- for (i = 0; i < cnt - 1; i++)
- rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
- if (cnt % 2)
- rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0);
- else
- rtsx_pci_add_cmd(pcr, READ_REG_CMD,
- PPBUF_BASE2 + cnt - 1, 0, 0);
- if (int_reg)
- rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
-
- err = rtsx_pci_send_cmd(pcr, 5000);
- if (err < 0) {
- u8 val;
-
- rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
- dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
-
- if (int_reg)
- *int_reg = val & 0x0F;
-
- ms_print_debug_regs(host);
-
- ms_clear_error(host);
-
- if (!(tpc & 0x08)) {
- if (val & MS_CRC16_ERR)
- return -EIO;
- } else {
- if (!(val & 0x80)) {
- if (val & (MS_INT_ERR | MS_INT_CMDNK))
- return -EIO;
- }
- }
-
- return -ETIMEDOUT;
- }
-
- ptr = rtsx_pci_get_cmd_data(pcr) + 1;
- for (i = 0; i < cnt; i++)
- data[i] = *ptr++;
-
- if (int_reg)
- *int_reg = *ptr & 0x0F;
-
- return 0;
-}
-
-static int rtsx_pci_ms_issue_cmd(struct realtek_pci_ms *host)
-{
- struct memstick_request *req = host->req;
- int err = 0;
- u8 cfg = 0, int_reg;
-
- dev_dbg(ms_dev(host), "%s\n", __func__);
-
- if (req->need_card_int) {
- if (host->ifmode != MEMSTICK_SERIAL)
- cfg = WAIT_INT;
- }
-
- if (req->long_data) {
- err = ms_transfer_data(host, req->data_dir,
- req->tpc, cfg, &(req->sg));
- } else {
- if (req->data_dir == READ) {
- err = ms_read_bytes(host, req->tpc, cfg,
- req->data_len, req->data, &int_reg);
- } else {
- err = ms_write_bytes(host, req->tpc, cfg,
- req->data_len, req->data, &int_reg);
- }
- }
- if (err < 0)
- return err;
-
- if (req->need_card_int && (host->ifmode == MEMSTICK_SERIAL)) {
- err = ms_read_bytes(host, MS_TPC_GET_INT,
- NO_WAIT_INT, 1, &int_reg, NULL);
- if (err < 0)
- return err;
- }
-
- if (req->need_card_int) {
- dev_dbg(ms_dev(host), "int_reg: 0x%02x\n", int_reg);
-
- if (int_reg & MS_INT_CMDNK)
- req->int_reg |= MEMSTICK_INT_CMDNAK;
- if (int_reg & MS_INT_BREQ)
- req->int_reg |= MEMSTICK_INT_BREQ;
- if (int_reg & MS_INT_ERR)
- req->int_reg |= MEMSTICK_INT_ERR;
- if (int_reg & MS_INT_CED)
- req->int_reg |= MEMSTICK_INT_CED;
- }
-
- return 0;
-}
-
-static void rtsx_pci_ms_handle_req(struct work_struct *work)
-{
- struct realtek_pci_ms *host = container_of(work,
- struct realtek_pci_ms, handle_req);
- struct rtsx_pcr *pcr = host->pcr;
- struct memstick_host *msh = host->msh;
- int rc;
-
- mutex_lock(&pcr->pcr_mutex);
-
- rtsx_pci_start_run(pcr);
-
- rtsx_pci_switch_clock(host->pcr, host->clock, host->ssc_depth,
- false, true, false);
- rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, MS_MOD_SEL);
- rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
- CARD_SHARE_MASK, CARD_SHARE_48_MS);
-
- if (!host->req) {
- do {
- rc = memstick_next_req(msh, &host->req);
- dev_dbg(ms_dev(host), "next req %d\n", rc);
-
- if (!rc)
- host->req->error = rtsx_pci_ms_issue_cmd(host);
- } while (!rc);
- }
-
- mutex_unlock(&pcr->pcr_mutex);
-}
-
-static void rtsx_pci_ms_request(struct memstick_host *msh)
-{
- struct realtek_pci_ms *host = memstick_priv(msh);
-
- dev_dbg(ms_dev(host), "--> %s\n", __func__);
-
- if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD))
- return;
-
- schedule_work(&host->handle_req);
-}
-
-static int rtsx_pci_ms_set_param(struct memstick_host *msh,
- enum memstick_param param, int value)
-{
- struct realtek_pci_ms *host = memstick_priv(msh);
- struct rtsx_pcr *pcr = host->pcr;
- unsigned int clock = 0;
- u8 ssc_depth = 0;
- int err;
-
- dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
- __func__, param, value);
-
- err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD);
- if (err)
- return err;
-
- switch (param) {
- case MEMSTICK_POWER:
- if (value == MEMSTICK_POWER_ON)
- err = ms_power_on(host);
- else if (value == MEMSTICK_POWER_OFF)
- err = ms_power_off(host);
- else
- return -EINVAL;
- break;
-
- case MEMSTICK_INTERFACE:
- if (value == MEMSTICK_SERIAL) {
- clock = 19000000;
- ssc_depth = RTSX_SSC_DEPTH_500K;
-
- err = rtsx_pci_write_register(pcr, MS_CFG, 0x58,
- MS_BUS_WIDTH_1 | PUSH_TIME_DEFAULT);
- if (err < 0)
- return err;
- } else if (value == MEMSTICK_PAR4) {
- clock = 39000000;
- ssc_depth = RTSX_SSC_DEPTH_1M;
-
- err = rtsx_pci_write_register(pcr, MS_CFG,
- 0x58, MS_BUS_WIDTH_4 | PUSH_TIME_ODD);
- if (err < 0)
- return err;
- } else {
- return -EINVAL;
- }
-
- err = rtsx_pci_switch_clock(pcr, clock,
- ssc_depth, false, true, false);
- if (err < 0)
- return err;
-
- host->ssc_depth = ssc_depth;
- host->clock = clock;
- host->ifmode = value;
- break;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int rtsx_pci_ms_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct realtek_pci_ms *host = platform_get_drvdata(pdev);
- struct memstick_host *msh = host->msh;
-
- dev_dbg(ms_dev(host), "--> %s\n", __func__);
-
- memstick_suspend_host(msh);
- return 0;
-}
-
-static int rtsx_pci_ms_resume(struct platform_device *pdev)
-{
- struct realtek_pci_ms *host = platform_get_drvdata(pdev);
- struct memstick_host *msh = host->msh;
-
- dev_dbg(ms_dev(host), "--> %s\n", __func__);
-
- memstick_resume_host(msh);
- return 0;
-}
-
-#else /* CONFIG_PM */
-
-#define rtsx_pci_ms_suspend NULL
-#define rtsx_pci_ms_resume NULL
-
-#endif /* CONFIG_PM */
-
-static void rtsx_pci_ms_card_event(struct platform_device *pdev)
-{
- struct realtek_pci_ms *host = platform_get_drvdata(pdev);
-
- memstick_detect_change(host->msh);
-}
-
-static int rtsx_pci_ms_drv_probe(struct platform_device *pdev)
-{
- struct memstick_host *msh;
- struct realtek_pci_ms *host;
- struct rtsx_pcr *pcr;
- struct pcr_handle *handle = pdev->dev.platform_data;
- int rc;
-
- if (!handle)
- return -ENXIO;
-
- pcr = handle->pcr;
- if (!pcr)
- return -ENXIO;
-
- dev_dbg(&(pdev->dev),
- ": Realtek PCI-E Memstick controller found\n");
-
- msh = memstick_alloc_host(sizeof(*host), &pdev->dev);
- if (!msh)
- return -ENOMEM;
-
- host = memstick_priv(msh);
- host->pcr = pcr;
- host->msh = msh;
- host->pdev = pdev;
- platform_set_drvdata(pdev, host);
- pcr->slots[RTSX_MS_CARD].p_dev = pdev;
- pcr->slots[RTSX_MS_CARD].card_event = rtsx_pci_ms_card_event;
-
- mutex_init(&host->host_mutex);
-
- INIT_WORK(&host->handle_req, rtsx_pci_ms_handle_req);
- msh->request = rtsx_pci_ms_request;
- msh->set_param = rtsx_pci_ms_set_param;
- msh->caps = MEMSTICK_CAP_PAR4;
-
- rc = memstick_add_host(msh);
- if (rc) {
- memstick_free_host(msh);
- return rc;
- }
-
- return 0;
-}
-
-static void rtsx_pci_ms_drv_remove(struct platform_device *pdev)
-{
- struct realtek_pci_ms *host = platform_get_drvdata(pdev);
- struct rtsx_pcr *pcr;
- struct memstick_host *msh;
- int rc;
-
- pcr = host->pcr;
- pcr->slots[RTSX_MS_CARD].p_dev = NULL;
- pcr->slots[RTSX_MS_CARD].card_event = NULL;
- msh = host->msh;
- host->eject = true;
- cancel_work_sync(&host->handle_req);
-
- mutex_lock(&host->host_mutex);
- if (host->req) {
- dev_dbg(&(pdev->dev),
- "%s: Controller removed during transfer\n",
- dev_name(&msh->dev));
-
- rtsx_pci_complete_unfinished_transfer(pcr);
-
- host->req->error = -ENOMEDIUM;
- do {
- rc = memstick_next_req(msh, &host->req);
- if (!rc)
- host->req->error = -ENOMEDIUM;
- } while (!rc);
- }
- mutex_unlock(&host->host_mutex);
-
- memstick_remove_host(msh);
- memstick_free_host(msh);
-
- dev_dbg(&(pdev->dev),
- ": Realtek PCI-E Memstick controller has been removed\n");
-}
-
-static struct platform_device_id rtsx_pci_ms_ids[] = {
- {
- .name = DRV_NAME_RTSX_PCI_MS,
- }, {
- /* sentinel */
- }
-};
-MODULE_DEVICE_TABLE(platform, rtsx_pci_ms_ids);
-
-static struct platform_driver rtsx_pci_ms_driver = {
- .probe = rtsx_pci_ms_drv_probe,
- .remove_new = rtsx_pci_ms_drv_remove,
- .id_table = rtsx_pci_ms_ids,
- .suspend = rtsx_pci_ms_suspend,
- .resume = rtsx_pci_ms_resume,
- .driver = {
- .name = DRV_NAME_RTSX_PCI_MS,
- },
-};
-module_platform_driver(rtsx_pci_ms_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Wei WANG <[email protected]>");
-MODULE_DESCRIPTION("Realtek PCI-E Memstick Card Host Driver");
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 4c67e2c5a82e..a7a2bcedb37e 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -1238,6 +1238,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
struct fastrpc_phy_page pages[1];
char *name;
int err;
+ bool scm_done = false;
struct {
int pgid;
u32 namelen;
@@ -1289,6 +1290,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
goto err_map;
}
+ scm_done = true;
}
}
@@ -1320,10 +1322,11 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
goto err_invoke;
kfree(args);
+ kfree(name);
return 0;
err_invoke:
- if (fl->cctx->vmcount) {
+ if (fl->cctx->vmcount && scm_done) {
u64 src_perms = 0;
struct qcom_scm_vmperm dst_perms;
u32 i;
@@ -1693,16 +1696,20 @@ static int fastrpc_get_info_from_dsp(struct fastrpc_user *fl, uint32_t *dsp_attr
{
struct fastrpc_invoke_args args[2] = { 0 };
- /* Capability filled in userspace */
+ /*
+ * Capability filled in userspace. This carries the information
+ * about the remoteproc support which is fetched from the remoteproc
+ * sysfs node by userspace.
+ */
dsp_attr_buf[0] = 0;
+ dsp_attr_buf_len -= 1;
args[0].ptr = (u64)(uintptr_t)&dsp_attr_buf_len;
args[0].length = sizeof(dsp_attr_buf_len);
args[0].fd = -1;
args[1].ptr = (u64)(uintptr_t)&dsp_attr_buf[1];
- args[1].length = dsp_attr_buf_len;
+ args[1].length = dsp_attr_buf_len * sizeof(u32);
args[1].fd = -1;
- fl->pd = USER_PD;
return fastrpc_internal_invoke(fl, true, FASTRPC_DSP_UTILITIES_HANDLE,
FASTRPC_SCALARS(0, 1, 1), args);
@@ -1730,7 +1737,7 @@ static int fastrpc_get_info_from_kernel(struct fastrpc_ioctl_capability *cap,
if (!dsp_attributes)
return -ENOMEM;
- err = fastrpc_get_info_from_dsp(fl, dsp_attributes, FASTRPC_MAX_DSP_ATTRIBUTES_LEN);
+ err = fastrpc_get_info_from_dsp(fl, dsp_attributes, FASTRPC_MAX_DSP_ATTRIBUTES);
if (err == DSP_UNSUPPORTED_API) {
dev_info(&cctx->rpdev->dev,
"Warning: DSP capabilities not supported on domain: %d\n", domain);
@@ -1783,7 +1790,7 @@ static int fastrpc_get_dsp_info(struct fastrpc_user *fl, char __user *argp)
if (err)
return err;
- if (copy_to_user(argp, &cap.capability, sizeof(cap.capability)))
+ if (copy_to_user(argp, &cap, sizeof(cap)))
return -EFAULT;
return 0;
@@ -2080,6 +2087,16 @@ err_invoke:
return err;
}
+static int is_attach_rejected(struct fastrpc_user *fl)
+{
+ /* Check if the device node is non-secure */
+ if (!fl->is_secure_dev) {
+ dev_dbg(&fl->cctx->rpdev->dev, "untrusted app trying to attach to privileged DSP PD\n");
+ return -EACCES;
+ }
+ return 0;
+}
+
static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -2092,13 +2109,19 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
err = fastrpc_invoke(fl, argp);
break;
case FASTRPC_IOCTL_INIT_ATTACH:
- err = fastrpc_init_attach(fl, ROOT_PD);
+ err = is_attach_rejected(fl);
+ if (!err)
+ err = fastrpc_init_attach(fl, ROOT_PD);
break;
case FASTRPC_IOCTL_INIT_ATTACH_SNS:
- err = fastrpc_init_attach(fl, SENSORS_PD);
+ err = is_attach_rejected(fl);
+ if (!err)
+ err = fastrpc_init_attach(fl, SENSORS_PD);
break;
case FASTRPC_IOCTL_INIT_CREATE_STATIC:
- err = fastrpc_init_create_static_process(fl, argp);
+ err = is_attach_rejected(fl);
+ if (!err)
+ err = fastrpc_init_create_static_process(fl, argp);
break;
case FASTRPC_IOCTL_INIT_CREATE:
err = fastrpc_init_create_process(fl, argp);
diff --git a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_otpe2p.c b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_otpe2p.c
index 16695cb5e69c..7c3d8bedf90b 100644
--- a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_otpe2p.c
+++ b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_otpe2p.c
@@ -153,7 +153,6 @@ static int pci1xxxx_eeprom_read(void *priv_t, unsigned int off,
buf[byte] = readl(rb + MMAP_EEPROM_OFFSET(EEPROM_DATA_REG));
}
- ret = byte;
error:
release_sys_lock(priv);
return ret;
@@ -197,7 +196,6 @@ static int pci1xxxx_eeprom_write(void *priv_t, unsigned int off,
goto error;
}
}
- ret = byte;
error:
release_sys_lock(priv);
return ret;
@@ -258,7 +256,6 @@ static int pci1xxxx_otp_read(void *priv_t, unsigned int off,
buf[byte] = readl(rb + MMAP_OTP_OFFSET(OTP_RD_DATA_OFFSET));
}
- ret = byte;
error:
release_sys_lock(priv);
return ret;
@@ -315,7 +312,6 @@ static int pci1xxxx_otp_write(void *priv_t, unsigned int off,
goto error;
}
}
- ret = byte;
error:
release_sys_lock(priv);
return ret;
diff --git a/drivers/misc/mei/platform-vsc.c b/drivers/misc/mei/platform-vsc.c
index 1ec65d87488a..d02f6e881139 100644
--- a/drivers/misc/mei/platform-vsc.c
+++ b/drivers/misc/mei/platform-vsc.c
@@ -28,8 +28,8 @@
#define MEI_VSC_MAX_MSG_SIZE 512
-#define MEI_VSC_POLL_DELAY_US (50 * USEC_PER_MSEC)
-#define MEI_VSC_POLL_TIMEOUT_US (200 * USEC_PER_MSEC)
+#define MEI_VSC_POLL_DELAY_US (100 * USEC_PER_MSEC)
+#define MEI_VSC_POLL_TIMEOUT_US (400 * USEC_PER_MSEC)
#define mei_dev_to_vsc_hw(dev) ((struct mei_vsc_hw *)((dev)->hw))
diff --git a/drivers/misc/mei/vsc-fw-loader.c b/drivers/misc/mei/vsc-fw-loader.c
index 596a9d695dfc..084d0205f97d 100644
--- a/drivers/misc/mei/vsc-fw-loader.c
+++ b/drivers/misc/mei/vsc-fw-loader.c
@@ -204,7 +204,7 @@ struct vsc_img_frag {
/**
* struct vsc_fw_loader - represent vsc firmware loader
- * @dev: device used to request fimware
+ * @dev: device used to request firmware
* @tp: transport layer used with the firmware loader
* @csi: CSI image
* @ace: ACE image
diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c
index e6a98dba8a73..1618cca9a731 100644
--- a/drivers/misc/mei/vsc-tp.c
+++ b/drivers/misc/mei/vsc-tp.c
@@ -331,12 +331,12 @@ int vsc_tp_rom_xfer(struct vsc_tp *tp, const void *obuf, void *ibuf, size_t len)
return ret;
}
- ret = vsc_tp_dev_xfer(tp, tp->tx_buf, tp->rx_buf, len);
+ ret = vsc_tp_dev_xfer(tp, tp->tx_buf, ibuf ? tp->rx_buf : NULL, len);
if (ret)
return ret;
if (ibuf)
- cpu_to_be32_array(ibuf, tp->rx_buf, words);
+ be32_to_cpu_array(ibuf, tp->rx_buf, words);
return ret;
}
@@ -568,6 +568,19 @@ static void vsc_tp_remove(struct spi_device *spi)
free_irq(spi->irq, tp);
}
+static void vsc_tp_shutdown(struct spi_device *spi)
+{
+ struct vsc_tp *tp = spi_get_drvdata(spi);
+
+ platform_device_unregister(tp->pdev);
+
+ mutex_destroy(&tp->mutex);
+
+ vsc_tp_reset(tp);
+
+ free_irq(spi->irq, tp);
+}
+
static const struct acpi_device_id vsc_tp_acpi_ids[] = {
{ "INTC1009" }, /* Raptor Lake */
{ "INTC1058" }, /* Tiger Lake */
@@ -580,6 +593,7 @@ MODULE_DEVICE_TABLE(acpi, vsc_tp_acpi_ids);
static struct spi_driver vsc_tp_driver = {
.probe = vsc_tp_probe,
.remove = vsc_tp_remove,
+ .shutdown = vsc_tp_shutdown,
.driver = {
.name = "vsc-tp",
.acpi_match_table = vsc_tp_acpi_ids,
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 367509b5b646..2c9963248fcb 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -2466,8 +2466,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
struct mmc_blk_data *md;
int devidx, ret;
char cap_str[10];
- bool cache_enabled = false;
- bool fua_enabled = false;
+ unsigned int features = 0;
devidx = ida_alloc_max(&mmc_blk_ida, max_devices - 1, GFP_KERNEL);
if (devidx < 0) {
@@ -2499,7 +2498,24 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
*/
md->read_only = mmc_blk_readonly(card);
- md->disk = mmc_init_queue(&md->queue, card);
+ if (mmc_host_cmd23(card->host)) {
+ if ((mmc_card_mmc(card) &&
+ card->csd.mmca_vsn >= CSD_SPEC_VER_3) ||
+ (mmc_card_sd(card) &&
+ card->scr.cmds & SD_SCR_CMD23_SUPPORT))
+ md->flags |= MMC_BLK_CMD23;
+ }
+
+ if (md->flags & MMC_BLK_CMD23 &&
+ ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
+ card->ext_csd.rel_sectors)) {
+ md->flags |= MMC_BLK_REL_WR;
+ features |= (BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA);
+ } else if (mmc_cache_enabled(card->host)) {
+ features |= BLK_FEAT_WRITE_CACHE;
+ }
+
+ md->disk = mmc_init_queue(&md->queue, card, features);
if (IS_ERR(md->disk)) {
ret = PTR_ERR(md->disk);
goto err_kfree;
@@ -2539,26 +2555,6 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
set_capacity(md->disk, size);
- if (mmc_host_cmd23(card->host)) {
- if ((mmc_card_mmc(card) &&
- card->csd.mmca_vsn >= CSD_SPEC_VER_3) ||
- (mmc_card_sd(card) &&
- card->scr.cmds & SD_SCR_CMD23_SUPPORT))
- md->flags |= MMC_BLK_CMD23;
- }
-
- if (md->flags & MMC_BLK_CMD23 &&
- ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
- card->ext_csd.rel_sectors)) {
- md->flags |= MMC_BLK_REL_WR;
- fua_enabled = true;
- cache_enabled = true;
- }
- if (mmc_cache_enabled(card->host))
- cache_enabled = true;
-
- blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled);
-
string_get_size((u64)size, 512, STRING_UNITS_2,
cap_str, sizeof(cap_str));
pr_info("%s: %s %s %s%s\n",
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index a8c17b4cd737..d6c819dd68ed 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2362,4 +2362,5 @@ static void __exit mmc_exit(void)
subsys_initcall(mmc_init);
module_exit(mmc_exit);
+MODULE_DESCRIPTION("MMC core driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c
index 3b6d69cefb4e..96fa4c508900 100644
--- a/drivers/mmc/core/pwrseq_emmc.c
+++ b/drivers/mmc/core/pwrseq_emmc.c
@@ -115,4 +115,5 @@ static struct platform_driver mmc_pwrseq_emmc_driver = {
};
module_platform_driver(mmc_pwrseq_emmc_driver);
+MODULE_DESCRIPTION("Hardware reset support for eMMC");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/core/pwrseq_sd8787.c b/drivers/mmc/core/pwrseq_sd8787.c
index 0c5808fc3206..f24bbd68e251 100644
--- a/drivers/mmc/core/pwrseq_sd8787.c
+++ b/drivers/mmc/core/pwrseq_sd8787.c
@@ -130,4 +130,5 @@ static struct platform_driver mmc_pwrseq_sd8787_driver = {
};
module_platform_driver(mmc_pwrseq_sd8787_driver);
+MODULE_DESCRIPTION("Power sequence support for Marvell SD8787 BT + Wifi chip");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index df9588503ad0..154a8921ae75 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -159,4 +159,5 @@ static struct platform_driver mmc_pwrseq_simple_driver = {
};
module_platform_driver(mmc_pwrseq_simple_driver);
+MODULE_DESCRIPTION("Simple power sequence management for MMC");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index 241cdc2b2a2a..d0b3ca8a11f0 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -344,10 +344,12 @@ static const struct blk_mq_ops mmc_mq_ops = {
};
static struct gendisk *mmc_alloc_disk(struct mmc_queue *mq,
- struct mmc_card *card)
+ struct mmc_card *card, unsigned int features)
{
struct mmc_host *host = card->host;
- struct queue_limits lim = { };
+ struct queue_limits lim = {
+ .features = features,
+ };
struct gendisk *disk;
if (mmc_can_erase(card))
@@ -376,18 +378,16 @@ static struct gendisk *mmc_alloc_disk(struct mmc_queue *mq,
lim.max_segments = host->max_segs;
}
+ if (mmc_host_is_spi(host) && host->use_spi_crc)
+ lim.features |= BLK_FEAT_STABLE_WRITES;
+
disk = blk_mq_alloc_disk(&mq->tag_set, &lim, mq);
if (IS_ERR(disk))
return disk;
mq->queue = disk->queue;
- if (mmc_host_is_spi(host) && host->use_spi_crc)
- blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, mq->queue);
blk_queue_rq_timeout(mq->queue, 60 * HZ);
- blk_queue_flag_set(QUEUE_FLAG_NONROT, mq->queue);
- blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, mq->queue);
-
dma_set_max_seg_size(mmc_dev(host), queue_max_segment_size(mq->queue));
INIT_WORK(&mq->recovery_work, mmc_mq_recovery_handler);
@@ -413,10 +413,12 @@ static inline bool mmc_merge_capable(struct mmc_host *host)
* mmc_init_queue - initialise a queue structure.
* @mq: mmc queue
* @card: mmc card to attach this queue
+ * @features: block layer features (BLK_FEAT_*)
*
* Initialise a MMC card request queue.
*/
-struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card)
+struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
+ unsigned int features)
{
struct mmc_host *host = card->host;
struct gendisk *disk;
@@ -460,7 +462,7 @@ struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card)
return ERR_PTR(ret);
- disk = mmc_alloc_disk(mq, card);
+ disk = mmc_alloc_disk(mq, card, features);
if (IS_ERR(disk))
blk_mq_free_tag_set(&mq->tag_set);
return disk;
diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h
index 9ade3bcbb714..1498840a4ea0 100644
--- a/drivers/mmc/core/queue.h
+++ b/drivers/mmc/core/queue.h
@@ -94,7 +94,8 @@ struct mmc_queue {
struct work_struct complete_work;
};
-struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card);
+struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
+ unsigned int features);
extern void mmc_cleanup_queue(struct mmc_queue *);
extern void mmc_queue_suspend(struct mmc_queue *);
extern void mmc_queue_resume(struct mmc_queue *);
diff --git a/drivers/mmc/core/sdio_uart.c b/drivers/mmc/core/sdio_uart.c
index 575ebbce378e..6b7471dba3bf 100644
--- a/drivers/mmc/core/sdio_uart.c
+++ b/drivers/mmc/core/sdio_uart.c
@@ -1162,4 +1162,5 @@ module_init(sdio_uart_init);
module_exit(sdio_uart_exit);
MODULE_AUTHOR("Nicolas Pitre");
+MODULE_DESCRIPTION("SDIO UART/GPS driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index bb0d4fb0892a..eb3ecfe05591 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -1016,7 +1016,7 @@ config MMC_SDHCI_MICROCHIP_PIC32
config MMC_SDHCI_BRCMSTB
tristate "Broadcom SDIO/SD/MMC support"
- depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
+ depends on ARCH_BRCMSTB || ARCH_BCM2835 || BMIPS_GENERIC || COMPILE_TEST
depends on MMC_SDHCI_PLTFM
select MMC_CQHCI
default ARCH_BRCMSTB || BMIPS_GENERIC
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 8199d9620075..6490df54a6f5 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -33,6 +33,7 @@
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/workqueue.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
@@ -272,12 +273,12 @@ struct atmel_mci_dma {
* EVENT_DATA_ERROR is pending.
* @stop_cmdr: Value to be loaded into CMDR when the stop command is
* to be sent.
- * @tasklet: Tasklet running the request state machine.
+ * @bh_work: Work running the request state machine.
* @pending_events: Bitmask of events flagged by the interrupt handler
- * to be processed by the tasklet.
+ * to be processed by the work.
* @completed_events: Bitmask of events which the state machine has
* processed.
- * @state: Tasklet state.
+ * @state: Work state.
* @queue: List of slots waiting for access to the controller.
* @need_clock_update: Update the clock rate before the next request.
* @need_reset: Reset controller before next request.
@@ -352,7 +353,7 @@ struct atmel_mci {
u32 data_status;
u32 stop_cmdr;
- struct tasklet_struct tasklet;
+ struct work_struct bh_work;
unsigned long pending_events;
unsigned long completed_events;
enum atmel_mci_state state;
@@ -735,7 +736,7 @@ static void atmci_timeout_timer(struct timer_list *t)
host->need_reset = 1;
host->state = STATE_END_REQUEST;
smp_wmb();
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
}
static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
@@ -958,7 +959,7 @@ static void atmci_pdc_complete(struct atmel_mci *host)
dev_dbg(dev, "(%s) set pending xfer complete\n", __func__);
atmci_set_pending(host, EVENT_XFER_COMPLETE);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
}
static void atmci_dma_cleanup(struct atmel_mci *host)
@@ -972,7 +973,7 @@ static void atmci_dma_cleanup(struct atmel_mci *host)
}
/*
- * This function is called by the DMA driver from tasklet context.
+ * This function is called by the DMA driver from bh context.
*/
static void atmci_dma_complete(void *arg)
{
@@ -995,7 +996,7 @@ static void atmci_dma_complete(void *arg)
if (data) {
dev_dbg(dev, "(%s) set pending xfer complete\n", __func__);
atmci_set_pending(host, EVENT_XFER_COMPLETE);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
/*
* Regardless of what the documentation says, we have
@@ -1008,7 +1009,7 @@ static void atmci_dma_complete(void *arg)
* haven't seen all the potential error bits yet.
*
* The interrupt handler will schedule a different
- * tasklet to finish things up when the data transfer
+ * bh work to finish things up when the data transfer
* is completely done.
*
* We may not complete the mmc request here anyway
@@ -1745,9 +1746,9 @@ static void atmci_detect_change(struct timer_list *t)
}
}
-static void atmci_tasklet_func(struct tasklet_struct *t)
+static void atmci_work_func(struct work_struct *t)
{
- struct atmel_mci *host = from_tasklet(host, t, tasklet);
+ struct atmel_mci *host = from_work(host, t, bh_work);
struct mmc_request *mrq = host->mrq;
struct mmc_data *data = host->data;
struct device *dev = host->dev;
@@ -1759,7 +1760,7 @@ static void atmci_tasklet_func(struct tasklet_struct *t)
state = host->state;
- dev_vdbg(dev, "tasklet: state %u pending/completed/mask %lx/%lx/%x\n",
+ dev_vdbg(dev, "bh_work: state %u pending/completed/mask %lx/%lx/%x\n",
state, host->pending_events, host->completed_events,
atmci_readl(host, ATMCI_IMR));
@@ -2118,7 +2119,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
dev_dbg(dev, "set pending data error\n");
smp_wmb();
atmci_set_pending(host, EVENT_DATA_ERROR);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
}
if (pending & ATMCI_TXBUFE) {
@@ -2187,7 +2188,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
smp_wmb();
dev_dbg(dev, "set pending notbusy\n");
atmci_set_pending(host, EVENT_NOTBUSY);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
}
if (pending & ATMCI_NOTBUSY) {
@@ -2196,7 +2197,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
smp_wmb();
dev_dbg(dev, "set pending notbusy\n");
atmci_set_pending(host, EVENT_NOTBUSY);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
}
if (pending & ATMCI_RXRDY)
@@ -2211,7 +2212,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
smp_wmb();
dev_dbg(dev, "set pending cmd rdy\n");
atmci_set_pending(host, EVENT_CMD_RDY);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
}
if (pending & (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB))
@@ -2487,7 +2488,7 @@ static int atmci_probe(struct platform_device *pdev)
host->mapbase = regs->start;
- tasklet_setup(&host->tasklet, atmci_tasklet_func);
+ INIT_WORK(&host->bh_work, atmci_work_func);
ret = request_irq(irq, atmci_interrupt, 0, dev_name(dev), host);
if (ret) {
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index b5a5c6a2fe8b..6e80bcb668ec 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -42,6 +42,7 @@
#include <linux/leds.h>
#include <linux/mmc/host.h>
#include <linux/slab.h>
+#include <linux/workqueue.h>
#include <asm/io.h>
#include <asm/mach-au1x00/au1000.h>
@@ -113,8 +114,8 @@ struct au1xmmc_host {
int irq;
- struct tasklet_struct finish_task;
- struct tasklet_struct data_task;
+ struct work_struct finish_bh_work;
+ struct work_struct data_bh_work;
struct au1xmmc_platform_data *platdata;
struct platform_device *pdev;
struct resource *ioarea;
@@ -253,9 +254,9 @@ static void au1xmmc_finish_request(struct au1xmmc_host *host)
mmc_request_done(host->mmc, mrq);
}
-static void au1xmmc_tasklet_finish(struct tasklet_struct *t)
+static void au1xmmc_finish_bh_work(struct work_struct *t)
{
- struct au1xmmc_host *host = from_tasklet(host, t, finish_task);
+ struct au1xmmc_host *host = from_work(host, t, finish_bh_work);
au1xmmc_finish_request(host);
}
@@ -363,9 +364,9 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
au1xmmc_finish_request(host);
}
-static void au1xmmc_tasklet_data(struct tasklet_struct *t)
+static void au1xmmc_data_bh_work(struct work_struct *t)
{
- struct au1xmmc_host *host = from_tasklet(host, t, data_task);
+ struct au1xmmc_host *host = from_work(host, t, data_bh_work);
u32 status = __raw_readl(HOST_STATUS(host));
au1xmmc_data_complete(host, status);
@@ -425,7 +426,7 @@ static void au1xmmc_send_pio(struct au1xmmc_host *host)
if (host->flags & HOST_F_STOP)
SEND_STOP(host);
- tasklet_schedule(&host->data_task);
+ queue_work(system_bh_wq, &host->data_bh_work);
}
}
@@ -505,7 +506,7 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
if (host->flags & HOST_F_STOP)
SEND_STOP(host);
- tasklet_schedule(&host->data_task);
+ queue_work(system_bh_wq, &host->data_bh_work);
}
}
@@ -561,7 +562,7 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
if (!trans || cmd->error) {
IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA | SD_CONFIG_RF);
- tasklet_schedule(&host->finish_task);
+ queue_work(system_bh_wq, &host->finish_bh_work);
return;
}
@@ -797,7 +798,7 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
/* IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA | SD_CONFIG_RF); */
- tasklet_schedule(&host->finish_task);
+ queue_work(system_bh_wq, &host->finish_bh_work);
}
#if 0
else if (status & SD_STATUS_DD) {
@@ -806,7 +807,7 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
au1xmmc_receive_pio(host);
else {
au1xmmc_data_complete(host, status);
- /* tasklet_schedule(&host->data_task); */
+ /* queue_work(system_bh_wq, &host->data_bh_work); */
}
}
#endif
@@ -854,7 +855,7 @@ static void au1xmmc_dbdma_callback(int irq, void *dev_id)
if (host->flags & HOST_F_STOP)
SEND_STOP(host);
- tasklet_schedule(&host->data_task);
+ queue_work(system_bh_wq, &host->data_bh_work);
}
static int au1xmmc_dbdma_init(struct au1xmmc_host *host)
@@ -1039,9 +1040,9 @@ static int au1xmmc_probe(struct platform_device *pdev)
if (host->platdata)
mmc->caps &= ~(host->platdata->mask_host_caps);
- tasklet_setup(&host->data_task, au1xmmc_tasklet_data);
+ INIT_WORK(&host->data_bh_work, au1xmmc_data_bh_work);
- tasklet_setup(&host->finish_task, au1xmmc_tasklet_finish);
+ INIT_WORK(&host->finish_bh_work, au1xmmc_finish_bh_work);
if (has_dbdma()) {
ret = au1xmmc_dbdma_init(host);
@@ -1091,8 +1092,8 @@ out5:
if (host->flags & HOST_F_DBDMA)
au1xmmc_dbdma_shutdown(host);
- tasklet_kill(&host->data_task);
- tasklet_kill(&host->finish_task);
+ cancel_work_sync(&host->data_bh_work);
+ cancel_work_sync(&host->finish_bh_work);
if (host->platdata && host->platdata->cd_setup &&
!(mmc->caps & MMC_CAP_NEEDS_POLL))
@@ -1135,8 +1136,8 @@ static void au1xmmc_remove(struct platform_device *pdev)
__raw_writel(0, HOST_CONFIG2(host));
wmb(); /* drain writebuffer */
- tasklet_kill(&host->data_task);
- tasklet_kill(&host->finish_task);
+ cancel_work_sync(&host->data_bh_work);
+ cancel_work_sync(&host->finish_bh_work);
if (host->flags & HOST_F_DBDMA)
au1xmmc_dbdma_shutdown(host);
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
index 0aec33b88bef..902f7f20abaa 100644
--- a/drivers/mmc/host/cb710-mmc.c
+++ b/drivers/mmc/host/cb710-mmc.c
@@ -493,7 +493,7 @@ static void cb710_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
if (!cb710_mmc_command(mmc, mrq->cmd) && mrq->stop)
cb710_mmc_command(mmc, mrq->stop);
- tasklet_schedule(&reader->finish_req_tasklet);
+ queue_work(system_bh_wq, &reader->finish_req_bh_work);
}
static int cb710_mmc_powerup(struct cb710_slot *slot)
@@ -646,10 +646,10 @@ static int cb710_mmc_irq_handler(struct cb710_slot *slot)
return 1;
}
-static void cb710_mmc_finish_request_tasklet(struct tasklet_struct *t)
+static void cb710_mmc_finish_request_bh_work(struct work_struct *t)
{
- struct cb710_mmc_reader *reader = from_tasklet(reader, t,
- finish_req_tasklet);
+ struct cb710_mmc_reader *reader = from_work(reader, t,
+ finish_req_bh_work);
struct mmc_request *mrq = reader->mrq;
reader->mrq = NULL;
@@ -718,8 +718,8 @@ static int cb710_mmc_init(struct platform_device *pdev)
reader = mmc_priv(mmc);
- tasklet_setup(&reader->finish_req_tasklet,
- cb710_mmc_finish_request_tasklet);
+ INIT_WORK(&reader->finish_req_bh_work,
+ cb710_mmc_finish_request_bh_work);
spin_lock_init(&reader->irq_lock);
cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
@@ -763,7 +763,7 @@ static void cb710_mmc_exit(struct platform_device *pdev)
cb710_write_port_32(slot, CB710_MMC_CONFIG_PORT, 0);
cb710_write_port_16(slot, CB710_MMC_CONFIGB_PORT, 0);
- tasklet_kill(&reader->finish_req_tasklet);
+ cancel_work_sync(&reader->finish_req_bh_work);
mmc_free_host(mmc);
}
diff --git a/drivers/mmc/host/cb710-mmc.h b/drivers/mmc/host/cb710-mmc.h
index 5e053077dbed..59abaccaad10 100644
--- a/drivers/mmc/host/cb710-mmc.h
+++ b/drivers/mmc/host/cb710-mmc.h
@@ -8,10 +8,11 @@
#define LINUX_CB710_MMC_H
#include <linux/cb710.h>
+#include <linux/workqueue.h>
/* per-MMC-reader structure */
struct cb710_mmc_reader {
- struct tasklet_struct finish_req_tasklet;
+ struct work_struct finish_req_bh_work;
struct mmc_request *mrq;
spinlock_t irq_lock;
unsigned char last_power_mode;
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index d7427894e0bc..9cbde800685d 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -224,6 +224,9 @@ static void davinci_fifo_data_trans(struct mmc_davinci_host *host,
}
p = sgm->addr;
+ if (n > sgm->length)
+ n = sgm->length;
+
/* NOTE: we never transfer more than rw_threshold bytes
* to/from the fifo here; there's no I/O overlap.
* This also assumes that access width( i.e. ACCWD) is 4 bytes
@@ -1184,7 +1187,7 @@ static int davinci_mmcsd_probe(struct platform_device *pdev)
struct mmc_davinci_host *host = NULL;
struct mmc_host *mmc = NULL;
struct resource *r, *mem = NULL;
- int ret, irq;
+ int ret, irq, bus_width;
size_t mem_size;
const struct platform_device_id *id_entry;
@@ -1314,9 +1317,14 @@ static int davinci_mmcsd_probe(struct platform_device *pdev)
rename_region(mem, mmc_hostname(mmc));
+ if (mmc->caps & MMC_CAP_8_BIT_DATA)
+ bus_width = 8;
+ else if (mmc->caps & MMC_CAP_4_BIT_DATA)
+ bus_width = 4;
+ else
+ bus_width = 1;
dev_info(mmc_dev(host->mmc), "Using %s, %d-bit mode\n",
- host->use_dma ? "DMA" : "PIO",
- (mmc->caps & MMC_CAP_4_BIT_DATA) ? 4 : 1);
+ host->use_dma ? "DMA" : "PIO", bus_width);
return 0;
diff --git a/drivers/mmc/host/dw_mmc-bluefield.c b/drivers/mmc/host/dw_mmc-bluefield.c
index 4747e5698f48..24e0b604b405 100644
--- a/drivers/mmc/host/dw_mmc-bluefield.c
+++ b/drivers/mmc/host/dw_mmc-bluefield.c
@@ -3,6 +3,7 @@
* Copyright (C) 2018 Mellanox Technologies.
*/
+#include <linux/arm-smccc.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/mmc/host.h>
@@ -20,6 +21,9 @@
#define BLUEFIELD_UHS_REG_EXT_SAMPLE 2
#define BLUEFIELD_UHS_REG_EXT_DRIVE 4
+/* SMC call for RST_N */
+#define BLUEFIELD_SMC_SET_EMMC_RST_N 0x82000007
+
static void dw_mci_bluefield_set_ios(struct dw_mci *host, struct mmc_ios *ios)
{
u32 reg;
@@ -34,8 +38,20 @@ static void dw_mci_bluefield_set_ios(struct dw_mci *host, struct mmc_ios *ios)
mci_writel(host, UHS_REG_EXT, reg);
}
+static void dw_mci_bluefield_hw_reset(struct dw_mci *host)
+{
+ struct arm_smccc_res res = { 0 };
+
+ arm_smccc_smc(BLUEFIELD_SMC_SET_EMMC_RST_N, 0, 0, 0, 0, 0, 0, 0,
+ &res);
+
+ if (res.a0)
+ pr_err("RST_N failed.\n");
+}
+
static const struct dw_mci_drv_data bluefield_drv_data = {
- .set_ios = dw_mci_bluefield_set_ios
+ .set_ios = dw_mci_bluefield_set_ios,
+ .hw_reset = dw_mci_bluefield_hw_reset
};
static const struct of_device_id dw_mci_bluefield_match[] = {
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 8e2d676b9239..2333ef4893ee 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -493,7 +493,7 @@ static void dw_mci_dmac_complete_dma(void *arg)
*/
if (data) {
set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
}
}
@@ -1617,6 +1617,7 @@ static void dw_mci_hw_reset(struct mmc_host *mmc)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci *host = slot->host;
+ const struct dw_mci_drv_data *drv_data = host->drv_data;
int reset;
if (host->use_dma == TRANS_MODE_IDMAC)
@@ -1626,6 +1627,11 @@ static void dw_mci_hw_reset(struct mmc_host *mmc)
SDMMC_CTRL_FIFO_RESET))
return;
+ if (drv_data && drv_data->hw_reset) {
+ drv_data->hw_reset(host);
+ return;
+ }
+
/*
* According to eMMC spec, card reset procedure:
* tRstW >= 1us: RST_n pulse width
@@ -1834,7 +1840,7 @@ static enum hrtimer_restart dw_mci_fault_timer(struct hrtimer *t)
if (!host->data_status) {
host->data_status = SDMMC_INT_DCRC;
set_bit(EVENT_DATA_ERROR, &host->pending_events);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
}
spin_unlock_irqrestore(&host->irq_lock, flags);
@@ -2056,9 +2062,9 @@ static bool dw_mci_clear_pending_data_complete(struct dw_mci *host)
return true;
}
-static void dw_mci_tasklet_func(struct tasklet_struct *t)
+static void dw_mci_work_func(struct work_struct *t)
{
- struct dw_mci *host = from_tasklet(host, t, tasklet);
+ struct dw_mci *host = from_work(host, t, bh_work);
struct mmc_data *data;
struct mmc_command *cmd;
struct mmc_request *mrq;
@@ -2113,7 +2119,7 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t)
* will waste a bit of time (we already know
* the command was bad), it can't cause any
* errors since it's possible it would have
- * taken place anyway if this tasklet got
+ * taken place anyway if this bh work got
* delayed. Allowing the transfer to take place
* avoids races and keeps things simple.
*/
@@ -2706,7 +2712,7 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
smp_wmb(); /* drain writebuffer */
set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
dw_mci_start_fault_timer(host);
}
@@ -2774,7 +2780,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
set_bit(EVENT_DATA_COMPLETE,
&host->pending_events);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
spin_unlock(&host->irq_lock);
}
@@ -2793,7 +2799,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
dw_mci_read_data_pio(host, true);
}
set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
spin_unlock(&host->irq_lock);
}
@@ -3098,7 +3104,7 @@ static void dw_mci_cmd11_timer(struct timer_list *t)
host->cmd_status = SDMMC_INT_RTO;
set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
}
static void dw_mci_cto_timer(struct timer_list *t)
@@ -3144,7 +3150,7 @@ static void dw_mci_cto_timer(struct timer_list *t)
*/
host->cmd_status = SDMMC_INT_RTO;
set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
break;
default:
dev_warn(host->dev, "Unexpected command timeout, state %d\n",
@@ -3195,7 +3201,7 @@ static void dw_mci_dto_timer(struct timer_list *t)
host->data_status = SDMMC_INT_DRTO;
set_bit(EVENT_DATA_ERROR, &host->pending_events);
set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
- tasklet_schedule(&host->tasklet);
+ queue_work(system_bh_wq, &host->bh_work);
break;
default:
dev_warn(host->dev, "Unexpected data timeout, state %d\n",
@@ -3435,7 +3441,7 @@ int dw_mci_probe(struct dw_mci *host)
else
host->fifo_reg = host->regs + DATA_240A_OFFSET;
- tasklet_setup(&host->tasklet, dw_mci_tasklet_func);
+ INIT_WORK(&host->bh_work, dw_mci_work_func);
ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
host->irq_flags, "dw-mci", host);
if (ret)
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 4ed81f94f7ca..6447b916990d 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -17,6 +17,7 @@
#include <linux/fault-inject.h>
#include <linux/hrtimer.h>
#include <linux/interrupt.h>
+#include <linux/workqueue.h>
enum dw_mci_state {
STATE_IDLE = 0,
@@ -89,12 +90,12 @@ struct dw_mci_dma_slave {
* @stop_cmdr: Value to be loaded into CMDR when the stop command is
* to be sent.
* @dir_status: Direction of current transfer.
- * @tasklet: Tasklet running the request state machine.
+ * @bh_work: Work running the request state machine.
* @pending_events: Bitmask of events flagged by the interrupt handler
- * to be processed by the tasklet.
+ * to be processed by bh work.
* @completed_events: Bitmask of events which the state machine has
* processed.
- * @state: Tasklet state.
+ * @state: BH work state.
* @queue: List of slots waiting for access to the controller.
* @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus
* rate and timeout calculations.
@@ -194,7 +195,7 @@ struct dw_mci {
u32 data_status;
u32 stop_cmdr;
u32 dir_status;
- struct tasklet_struct tasklet;
+ struct work_struct bh_work;
unsigned long pending_events;
unsigned long completed_events;
enum dw_mci_state state;
@@ -565,6 +566,7 @@ struct dw_mci_slot {
* @execute_tuning: implementation specific tuning procedure.
* @set_data_timeout: implementation specific timeout.
* @get_drto_clks: implementation specific cycle count for data read timeout.
+ * @hw_reset: implementation specific HW reset.
*
* Provide controller implementation specific extensions. The usage of this
* data structure is fully optional and usage of each member in this structure
@@ -585,5 +587,6 @@ struct dw_mci_drv_data {
void (*set_data_timeout)(struct dw_mci *host,
unsigned int timeout_ns);
u32 (*get_drto_clks)(struct dw_mci *host);
+ void (*hw_reset)(struct dw_mci *host);
};
#endif /* _DW_MMC_H_ */
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 09d7a6a0dc1a..c9caa1ece7ef 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1208,7 +1208,10 @@ static int mmc_spi_probe(struct spi_device *spi)
* that's the only reason not to use a few MHz for f_min (until
* the upper layer reads the target frequency from the CSD).
*/
- mmc->f_min = 400000;
+ if (spi->controller->min_speed_hz > 400000)
+ dev_warn(&spi->dev,"Controller unable to reduce bus clock to 400 KHz\n");
+
+ mmc->f_min = max(spi->controller->min_speed_hz, 400000);
mmc->f_max = spi->max_speed_hz;
host = mmc_priv(mmc);
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index bf54776fb26c..05939f30a5ae 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -19,6 +19,7 @@
#include <linux/mmc/core.h>
#include <linux/mmc/host.h>
+MODULE_DESCRIPTION("OpenFirmware bindings for the MMC-over-SPI driver");
MODULE_LICENSE("GPL");
struct of_mmc_spi {
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index a8ee0df47148..335350a4e99a 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_data/mmc-omap.h>
+#include <linux/workqueue.h>
#define OMAP_MMC_REG_CMD 0x00
@@ -105,7 +106,7 @@ struct mmc_omap_slot {
u16 power_mode;
unsigned int fclk_freq;
- struct tasklet_struct cover_tasklet;
+ struct work_struct cover_bh_work;
struct timer_list cover_timer;
unsigned cover_open;
@@ -873,18 +874,18 @@ void omap_mmc_notify_cover_event(struct device *dev, int num, int is_closed)
sysfs_notify(&slot->mmc->class_dev.kobj, NULL, "cover_switch");
}
- tasklet_hi_schedule(&slot->cover_tasklet);
+ queue_work(system_bh_highpri_wq, &slot->cover_bh_work);
}
static void mmc_omap_cover_timer(struct timer_list *t)
{
struct mmc_omap_slot *slot = from_timer(slot, t, cover_timer);
- tasklet_schedule(&slot->cover_tasklet);
+ queue_work(system_bh_wq, &slot->cover_bh_work);
}
-static void mmc_omap_cover_handler(struct tasklet_struct *t)
+static void mmc_omap_cover_bh_handler(struct work_struct *t)
{
- struct mmc_omap_slot *slot = from_tasklet(slot, t, cover_tasklet);
+ struct mmc_omap_slot *slot = from_work(slot, t, cover_bh_work);
int cover_open = mmc_omap_cover_is_open(slot);
mmc_detect_change(slot->mmc, 0);
@@ -1314,7 +1315,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
if (slot->pdata->get_cover_state != NULL) {
timer_setup(&slot->cover_timer, mmc_omap_cover_timer, 0);
- tasklet_setup(&slot->cover_tasklet, mmc_omap_cover_handler);
+ INIT_WORK(&slot->cover_bh_work, mmc_omap_cover_bh_handler);
}
r = mmc_add_host(mmc);
@@ -1333,7 +1334,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
&dev_attr_cover_switch);
if (r < 0)
goto err_remove_slot_name;
- tasklet_schedule(&slot->cover_tasklet);
+ queue_work(system_bh_wq, &slot->cover_bh_work);
}
return 0;
@@ -1356,7 +1357,7 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
if (slot->pdata->get_cover_state != NULL)
device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
- tasklet_kill(&slot->cover_tasklet);
+ cancel_work_sync(&slot->cover_bh_work);
del_timer_sync(&slot->cover_timer);
flush_workqueue(slot->host->mmc_omap_wq);
diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index 586f94d4dbfd..f12a87442338 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -11,6 +11,7 @@
#include <linux/dmaengine.h>
#include <linux/platform_device.h>
+#include <linux/workqueue.h>
#include "tmio_mmc.h"
struct renesas_sdhi_scc {
@@ -67,7 +68,7 @@ struct renesas_sdhi_dma {
dma_filter_fn filter;
void (*enable)(struct tmio_mmc_host *host, bool enable);
struct completion dma_dataend;
- struct tasklet_struct dma_complete;
+ struct work_struct dma_complete;
};
struct renesas_sdhi {
@@ -93,6 +94,7 @@ struct renesas_sdhi {
unsigned int tap_set;
struct reset_control *rstc;
+ struct tmio_mmc_host *host;
};
#define host_to_priv(host) \
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index 12f4faaaf4ee..04874791541f 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -970,6 +970,8 @@ int renesas_sdhi_probe(struct platform_device *pdev,
if (IS_ERR(host))
return PTR_ERR(host);
+ priv->host = host;
+
if (of_data) {
mmc_data->flags |= of_data->tmio_flags;
mmc_data->ocr_mask = of_data->tmio_ocr_mask;
@@ -1162,4 +1164,5 @@ void renesas_sdhi_remove(struct platform_device *pdev)
}
EXPORT_SYMBOL_GPL(renesas_sdhi_remove);
+MODULE_DESCRIPTION("Renesas SDHI core driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index 422fa63a2e99..d4b66daeda66 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -337,7 +337,7 @@ static bool renesas_sdhi_internal_dmac_dma_irq(struct tmio_mmc_host *host)
writel(status ^ dma_irqs, host->ctl + DM_CM_INFO1);
set_bit(SDHI_DMA_END_FLAG_DMA, &dma_priv->end_flags);
if (test_bit(SDHI_DMA_END_FLAG_ACCESS, &dma_priv->end_flags))
- tasklet_schedule(&dma_priv->dma_complete);
+ queue_work(system_bh_wq, &dma_priv->dma_complete);
}
return status & dma_irqs;
@@ -352,7 +352,7 @@ renesas_sdhi_internal_dmac_dataend_dma(struct tmio_mmc_host *host)
set_bit(SDHI_DMA_END_FLAG_ACCESS, &dma_priv->end_flags);
if (test_bit(SDHI_DMA_END_FLAG_DMA, &dma_priv->end_flags) ||
host->data->error)
- tasklet_schedule(&dma_priv->dma_complete);
+ queue_work(system_bh_wq, &dma_priv->dma_complete);
}
/*
@@ -440,9 +440,9 @@ force_pio:
renesas_sdhi_internal_dmac_enable_dma(host, false);
}
-static void renesas_sdhi_internal_dmac_issue_tasklet_fn(unsigned long arg)
+static void renesas_sdhi_internal_dmac_issue_work_fn(struct work_struct *work)
{
- struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
+ struct tmio_mmc_host *host = from_work(host, work, dma_issue);
struct renesas_sdhi *priv = host_to_priv(host);
tmio_mmc_enable_mmc_irqs(host, TMIO_STAT_DATAEND);
@@ -454,7 +454,7 @@ static void renesas_sdhi_internal_dmac_issue_tasklet_fn(unsigned long arg)
/* on CMD errors, simulate DMA end immediately */
set_bit(SDHI_DMA_END_FLAG_DMA, &priv->dma_priv.end_flags);
if (test_bit(SDHI_DMA_END_FLAG_ACCESS, &priv->dma_priv.end_flags))
- tasklet_schedule(&priv->dma_priv.dma_complete);
+ queue_work(system_bh_wq, &priv->dma_priv.dma_complete);
}
}
@@ -484,9 +484,11 @@ static bool renesas_sdhi_internal_dmac_complete(struct tmio_mmc_host *host)
return true;
}
-static void renesas_sdhi_internal_dmac_complete_tasklet_fn(unsigned long arg)
+static void renesas_sdhi_internal_dmac_complete_work_fn(struct work_struct *work)
{
- struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
+ struct renesas_sdhi_dma *dma_priv = from_work(dma_priv, work, dma_complete);
+ struct renesas_sdhi *priv = container_of(dma_priv, typeof(*priv), dma_priv);
+ struct tmio_mmc_host *host = priv->host;
spin_lock_irq(&host->lock);
if (!renesas_sdhi_internal_dmac_complete(host))
@@ -544,12 +546,10 @@ renesas_sdhi_internal_dmac_request_dma(struct tmio_mmc_host *host,
/* Each value is set to non-zero to assume "enabling" each DMA */
host->chan_rx = host->chan_tx = (void *)0xdeadbeaf;
- tasklet_init(&priv->dma_priv.dma_complete,
- renesas_sdhi_internal_dmac_complete_tasklet_fn,
- (unsigned long)host);
- tasklet_init(&host->dma_issue,
- renesas_sdhi_internal_dmac_issue_tasklet_fn,
- (unsigned long)host);
+ INIT_WORK(&priv->dma_priv.dma_complete,
+ renesas_sdhi_internal_dmac_complete_work_fn);
+ INIT_WORK(&host->dma_issue,
+ renesas_sdhi_internal_dmac_issue_work_fn);
/* Add pre_req and post_req */
host->ops.pre_req = renesas_sdhi_internal_dmac_pre_req;
diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
index 9cf7f9feab72..5a6f41318645 100644
--- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
@@ -312,9 +312,9 @@ static void renesas_sdhi_sys_dmac_start_dma(struct tmio_mmc_host *host,
}
}
-static void renesas_sdhi_sys_dmac_issue_tasklet_fn(unsigned long priv)
+static void renesas_sdhi_sys_dmac_issue_work_fn(struct work_struct *work)
{
- struct tmio_mmc_host *host = (struct tmio_mmc_host *)priv;
+ struct tmio_mmc_host *host = from_work(host, work, dma_issue);
struct dma_chan *chan = NULL;
spin_lock_irq(&host->lock);
@@ -401,9 +401,8 @@ static void renesas_sdhi_sys_dmac_request_dma(struct tmio_mmc_host *host,
goto ebouncebuf;
init_completion(&priv->dma_priv.dma_dataend);
- tasklet_init(&host->dma_issue,
- renesas_sdhi_sys_dmac_issue_tasklet_fn,
- (unsigned long)host);
+ INIT_WORK(&host->dma_issue,
+ renesas_sdhi_sys_dmac_issue_work_fn);
}
renesas_sdhi_sys_dmac_enable_dma(host, true);
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c
index cb9152c6a65d..e067c7f5c537 100644
--- a/drivers/mmc/host/sdhci-bcm-kona.c
+++ b/drivers/mmc/host/sdhci-bcm-kona.c
@@ -107,7 +107,7 @@ static void sdhci_bcm_kona_sd_init(struct sdhci_host *host)
* Software emulation of the SD card insertion/removal. Set insert=1 for insert
* and insert=0 for removal. The card detection is done by GPIO. For Broadcom
* IP to function properly the bit 0 of CORESTAT register needs to be set/reset
- * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet.
+* to generate the CD IRQ handled in sdhci.c
*/
static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
{
diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 150fb477b7cc..031a4b514d16 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -31,6 +31,21 @@
#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
+#define SDIO_CFG_CQ_CAPABILITY 0x4c
+#define SDIO_CFG_CQ_CAPABILITY_FMUL GENMASK(13, 12)
+
+#define SDIO_CFG_CTRL 0x0
+#define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31)
+#define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30)
+
+#define SDIO_CFG_MAX_50MHZ_MODE 0x1ac
+#define SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE BIT(31)
+#define SDIO_CFG_MAX_50MHZ_MODE_ENABLE BIT(0)
+
+#define MMC_CAP_HSE_MASK (MMC_CAP2_HSX00_1_2V | MMC_CAP2_HSX00_1_8V)
+/* Select all SD UHS type I SDR speed above 50MB/s */
+#define MMC_CAP_UHS_I_SDR_MASK (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104)
+
struct sdhci_brcmstb_priv {
void __iomem *cfg_regs;
unsigned int flags;
@@ -39,6 +54,7 @@ struct sdhci_brcmstb_priv {
};
struct brcmstb_match_priv {
+ void (*cfginit)(struct sdhci_host *host);
void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
struct sdhci_ops *ops;
const unsigned int flags;
@@ -169,6 +185,33 @@ static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
}
+static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
+ u32 reg;
+
+ /*
+ * If we support a speed that requires tuning,
+ * then select the delay line PHY as the clock source.
+ */
+ if ((host->mmc->caps & MMC_CAP_UHS_I_SDR_MASK) || (host->mmc->caps2 & MMC_CAP_HSE_MASK)) {
+ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
+ reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE;
+ reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE;
+ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
+ }
+
+ if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
+ (host->mmc->caps & MMC_CAP_NEEDS_POLL)) {
+ /* Force presence */
+ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
+ reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV;
+ reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN;
+ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
+ }
+}
+
static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc)
{
sdhci_dumpregs(mmc_priv(mmc));
@@ -201,6 +244,14 @@ static struct sdhci_ops sdhci_brcmstb_ops = {
.set_uhs_signaling = sdhci_set_uhs_signaling,
};
+static struct sdhci_ops sdhci_brcmstb_ops_2712 = {
+ .set_clock = sdhci_set_clock,
+ .set_power = sdhci_set_power_and_bus_voltage,
+ .set_bus_width = sdhci_set_bus_width,
+ .reset = sdhci_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
.set_clock = sdhci_brcmstb_set_clock,
.set_bus_width = sdhci_set_bus_width,
@@ -215,6 +266,11 @@ static struct sdhci_ops sdhci_brcmstb_ops_74165b0 = {
.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
};
+static const struct brcmstb_match_priv match_priv_2712 = {
+ .cfginit = sdhci_brcmstb_cfginit_2712,
+ .ops = &sdhci_brcmstb_ops_2712,
+};
+
static struct brcmstb_match_priv match_priv_7425 = {
.flags = BRCMSTB_MATCH_FLAGS_NO_64BIT |
BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT,
@@ -239,6 +295,7 @@ static struct brcmstb_match_priv match_priv_74165b0 = {
};
static const struct of_device_id __maybe_unused sdhci_brcm_of_match[] = {
+ { .compatible = "brcm,bcm2712-sdhci", .data = &match_priv_2712 },
{ .compatible = "brcm,bcm7425-sdhci", .data = &match_priv_7425 },
{ .compatible = "brcm,bcm7445-sdhci", .data = &match_priv_7445 },
{ .compatible = "brcm,bcm7216-sdhci", .data = &match_priv_7216 },
@@ -371,6 +428,9 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
(host->mmc->caps2 & MMC_CAP2_HS400_ES))
host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es;
+ if (match_priv->cfginit)
+ match_priv->cfginit(host);
+
/*
* Supply the existing CAPS, but clear the UHS modes. This
* will allow these modes to be specified by device tree
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 40a6e2f8145a..8f0bc6dca2b0 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -201,6 +201,9 @@
/* ERR004536 is not applicable for the IP */
#define ESDHC_FLAG_SKIP_ERR004536 BIT(17)
+/* The IP does not have GPIO CD wake capabilities */
+#define ESDHC_FLAG_SKIP_CD_WAKE BIT(18)
+
enum wp_types {
ESDHC_WP_NONE, /* no WP, neither controller nor gpio */
ESDHC_WP_CONTROLLER, /* mmc controller internal WP */
@@ -298,7 +301,7 @@ static struct esdhc_soc_data usdhc_s32g2_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
| ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES
- | ESDHC_FLAG_SKIP_ERR004536,
+ | ESDHC_FLAG_SKIP_ERR004536 | ESDHC_FLAG_SKIP_CD_WAKE,
};
static struct esdhc_soc_data usdhc_imx7ulp_data = {
@@ -1706,7 +1709,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
}
pltfm_host->clk = imx_data->clk_per;
- pltfm_host->clock = clk_get_rate(pltfm_host->clk);
err = clk_prepare_enable(imx_data->clk_per);
if (err)
goto free_sdhci;
@@ -1717,6 +1719,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (err)
goto disable_ipg_clk;
+ pltfm_host->clock = clk_get_rate(pltfm_host->clk);
+ if (!pltfm_host->clock) {
+ dev_err(mmc_dev(host->mmc), "could not get clk rate\n");
+ err = -EINVAL;
+ goto disable_ahb_clk;
+ }
+
imx_data->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(imx_data->pinctrl))
dev_warn(mmc_dev(host->mmc), "could not get pinctrl\n");
@@ -1726,7 +1735,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR;
/* GPIO CD can be set as a wakeup source */
- host->mmc->caps |= MMC_CAP_CD_WAKE;
+ if (!(imx_data->socdata->flags & ESDHC_FLAG_SKIP_CD_WAKE))
+ host->mmc->caps |= MMC_CAP_CD_WAKE;
if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
index 39edf04fedcf..e79aa4b3b6c3 100644
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
@@ -908,6 +908,7 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
.get_max_clock = rk35xx_get_max_clock,
.reset = rk35xx_sdhci_reset,
.adma_write_desc = dwcmshc_adma_write_desc,
+ .irq = dwcmshc_cqe_irq_handler,
};
static const struct sdhci_ops sdhci_dwcmshc_th1520_ops = {
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 23e6ba70144c..ed45ed0bdafd 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -1319,6 +1319,23 @@ static const struct sdhci_pci_fixes sdhci_intel_mrfld_mmc = {
.probe_slot = intel_mrfld_mmc_probe_slot,
};
+#define JMB388_SAMPLE_COUNT 5
+
+static int jmicron_jmb388_get_ro(struct mmc_host *mmc)
+{
+ int i, ro_count;
+
+ ro_count = 0;
+ for (i = 0; i < JMB388_SAMPLE_COUNT; i++) {
+ if (sdhci_get_ro(mmc) > 0) {
+ if (++ro_count > JMB388_SAMPLE_COUNT / 2)
+ return 1;
+ }
+ msleep(30);
+ }
+ return 0;
+}
+
static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
{
u8 scratch;
@@ -1403,11 +1420,6 @@ static int jmicron_probe(struct sdhci_pci_chip *chip)
return ret;
}
- /* quirk for unsable RO-detection on JM388 chips */
- if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_SD ||
- chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD)
- chip->quirks |= SDHCI_QUIRK_UNSTABLE_RO_DETECT;
-
return 0;
}
@@ -1462,6 +1474,11 @@ static int jmicron_probe_slot(struct sdhci_pci_slot *slot)
slot->host->mmc->caps |= MMC_CAP_BUS_WIDTH_TEST;
+ /* Handle unstable RO-detection on JM388 chips */
+ if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_SD ||
+ slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD)
+ slot->host->mmc_host_ops.get_ro = jmicron_jmb388_get_ro;
+
return 0;
}
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 112584aa0772..4b91c9e96635 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2513,8 +2513,9 @@ out:
}
EXPORT_SYMBOL_GPL(sdhci_get_cd_nogpio);
-static int sdhci_check_ro(struct sdhci_host *host)
+int sdhci_get_ro(struct mmc_host *mmc)
{
+ struct sdhci_host *host = mmc_priv(mmc);
bool allow_invert = false;
int is_readonly;
@@ -2522,10 +2523,10 @@ static int sdhci_check_ro(struct sdhci_host *host)
is_readonly = 0;
} else if (host->ops->get_ro) {
is_readonly = host->ops->get_ro(host);
- } else if (mmc_can_gpio_ro(host->mmc)) {
- is_readonly = mmc_gpio_get_ro(host->mmc);
+ } else if (mmc_can_gpio_ro(mmc)) {
+ is_readonly = mmc_gpio_get_ro(mmc);
/* Do not invert twice */
- allow_invert = !(host->mmc->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
+ allow_invert = !(mmc->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
} else {
is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
& SDHCI_WRITE_PROTECT);
@@ -2539,27 +2540,7 @@ static int sdhci_check_ro(struct sdhci_host *host)
return is_readonly;
}
-
-#define SAMPLE_COUNT 5
-
-static int sdhci_get_ro(struct mmc_host *mmc)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- int i, ro_count;
-
- if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
- return sdhci_check_ro(host);
-
- ro_count = 0;
- for (i = 0; i < SAMPLE_COUNT; i++) {
- if (sdhci_check_ro(host)) {
- if (++ro_count > SAMPLE_COUNT / 2)
- return 1;
- }
- msleep(30);
- }
- return 0;
-}
+EXPORT_SYMBOL_GPL(sdhci_get_ro);
static void sdhci_hw_reset(struct mmc_host *mmc)
{
@@ -4727,6 +4708,21 @@ int sdhci_setup_host(struct sdhci_host *host)
if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) {
host->max_adma = 65532; /* 32-bit alignment */
mmc->max_seg_size = 65535;
+ /*
+ * sdhci_adma_table_pre() expects to define 1 DMA
+ * descriptor per segment, so the maximum segment size
+ * is set accordingly. SDHCI allows up to 64KiB per DMA
+ * descriptor (16-bit field), but some controllers do
+ * not support "zero means 65536" reducing the maximum
+ * for them to 65535. That is a problem if PAGE_SIZE is
+ * 64KiB because the block layer does not support
+ * max_seg_size < PAGE_SIZE, however
+ * sdhci_adma_table_pre() has a workaround to handle
+ * that case, and split the descriptor. Refer also
+ * comment in sdhci_adma_table_pre().
+ */
+ if (mmc->max_seg_size < PAGE_SIZE)
+ mmc->max_seg_size = PAGE_SIZE;
} else {
mmc->max_seg_size = 65536;
}
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 957c7a917ffb..f531b617f28d 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -437,8 +437,6 @@ struct sdhci_host {
#define SDHCI_QUIRK_NO_HISPD_BIT (1<<29)
/* Controller treats ADMA descriptors with length 0000h incorrectly */
#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30)
-/* The read-only detection via SDHCI_PRESENT_STATE register is unstable */
-#define SDHCI_QUIRK_UNSTABLE_RO_DETECT (1<<31)
unsigned int quirks2; /* More deviations from spec. */
@@ -788,6 +786,7 @@ void sdhci_set_power_and_bus_voltage(struct sdhci_host *host,
void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
unsigned short vdd);
int sdhci_get_cd_nogpio(struct mmc_host *mmc);
+int sdhci_get_ro(struct mmc_host *mmc);
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);
diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
index 17ad32cfc0c3..64e10f7c9faa 100644
--- a/drivers/mmc/host/sdhci_am654.c
+++ b/drivers/mmc/host/sdhci_am654.c
@@ -90,7 +90,7 @@
/* Command Queue Host Controller Interface Base address */
#define SDHCI_AM654_CQE_BASE_ADDR 0x200
-static struct regmap_config sdhci_am654_regmap_config = {
+static const struct regmap_config sdhci_am654_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c
index b5a2f2f25ad9..aea14bf3e2e8 100644
--- a/drivers/mmc/host/tifm_sd.c
+++ b/drivers/mmc/host/tifm_sd.c
@@ -13,6 +13,7 @@
#include <linux/highmem.h>
#include <linux/scatterlist.h>
#include <linux/module.h>
+#include <linux/workqueue.h>
#include <asm/io.h>
#define DRIVER_NAME "tifm_sd"
@@ -97,7 +98,7 @@ struct tifm_sd {
unsigned int clk_div;
unsigned long timeout_jiffies;
- struct tasklet_struct finish_tasklet;
+ struct work_struct finish_bh_work;
struct timer_list timer;
struct mmc_request *req;
@@ -463,7 +464,7 @@ static void tifm_sd_check_status(struct tifm_sd *host)
}
}
finish_request:
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
}
/* Called from interrupt handler */
@@ -723,9 +724,9 @@ err_out:
mmc_request_done(mmc, mrq);
}
-static void tifm_sd_end_cmd(struct tasklet_struct *t)
+static void tifm_sd_end_cmd(struct work_struct *t)
{
- struct tifm_sd *host = from_tasklet(host, t, finish_tasklet);
+ struct tifm_sd *host = from_work(host, t, finish_bh_work);
struct tifm_dev *sock = host->dev;
struct mmc_host *mmc = tifm_get_drvdata(sock);
struct mmc_request *mrq;
@@ -960,7 +961,7 @@ static int tifm_sd_probe(struct tifm_dev *sock)
*/
mmc->max_busy_timeout = TIFM_MMCSD_REQ_TIMEOUT_MS;
- tasklet_setup(&host->finish_tasklet, tifm_sd_end_cmd);
+ INIT_WORK(&host->finish_bh_work, tifm_sd_end_cmd);
timer_setup(&host->timer, tifm_sd_abort, 0);
mmc->ops = &tifm_sd_ops;
@@ -999,7 +1000,7 @@ static void tifm_sd_remove(struct tifm_dev *sock)
writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
spin_unlock_irqrestore(&sock->lock, flags);
- tasklet_kill(&host->finish_tasklet);
+ cancel_work_sync(&host->finish_bh_work);
spin_lock_irqsave(&sock->lock, flags);
if (host->req) {
@@ -1009,7 +1010,7 @@ static void tifm_sd_remove(struct tifm_dev *sock)
host->req->cmd->error = -ENOMEDIUM;
if (host->req->stop)
host->req->stop->error = -ENOMEDIUM;
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
}
spin_unlock_irqrestore(&sock->lock, flags);
mmc_remove_host(mmc);
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index de56e6534aea..a75755f31d31 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -21,6 +21,7 @@
#include <linux/scatterlist.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
+#include <linux/workqueue.h>
#define CTL_SD_CMD 0x00
#define CTL_ARG_REG 0x04
@@ -139,9 +140,6 @@ struct tmio_mmc_host {
struct mmc_host *mmc;
struct mmc_host_ops ops;
- /* Callbacks for clock / power control */
- void (*set_pwr)(struct platform_device *host, int state);
-
/* pio related stuff */
struct scatterlist *sg_ptr;
struct scatterlist *sg_orig;
@@ -156,7 +154,7 @@ struct tmio_mmc_host {
bool dma_on;
struct dma_chan *chan_rx;
struct dma_chan *chan_tx;
- struct tasklet_struct dma_issue;
+ struct work_struct dma_issue;
struct scatterlist bounce_sg;
u8 *bounce_buf;
diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c
index 93e912afd3ae..b61a6310311d 100644
--- a/drivers/mmc/host/tmio_mmc_core.c
+++ b/drivers/mmc/host/tmio_mmc_core.c
@@ -608,7 +608,7 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, unsigned int stat)
} else {
tmio_mmc_disable_mmc_irqs(host,
TMIO_MASK_READOP);
- tasklet_schedule(&host->dma_issue);
+ queue_work(system_bh_wq, &host->dma_issue);
}
} else {
if (!host->dma_on) {
@@ -616,7 +616,7 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, unsigned int stat)
} else {
tmio_mmc_disable_mmc_irqs(host,
TMIO_MASK_WRITEOP);
- tasklet_schedule(&host->dma_issue);
+ queue_work(system_bh_wq, &host->dma_issue);
}
}
} else {
@@ -880,9 +880,6 @@ static void tmio_mmc_power_on(struct tmio_mmc_host *host, unsigned short vdd)
/* .set_ios() is returning void, so, no chance to report an error */
- if (host->set_pwr)
- host->set_pwr(host->pdev, 1);
-
if (!IS_ERR(mmc->supply.vmmc)) {
ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
/*
@@ -916,9 +913,6 @@ static void tmio_mmc_power_off(struct tmio_mmc_host *host)
if (!IS_ERR(mmc->supply.vmmc))
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
-
- if (host->set_pwr)
- host->set_pwr(host->pdev, 0);
}
static unsigned int tmio_mmc_get_timeout_cycles(struct tmio_mmc_host *host)
@@ -1160,8 +1154,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
if (pdata->flags & TMIO_MMC_USE_BUSY_TIMEOUT && !_host->get_timeout_cycles)
_host->get_timeout_cycles = tmio_mmc_get_timeout_cycles;
- _host->set_pwr = pdata->set_pwr;
-
ret = tmio_mmc_init_ocr(_host);
if (ret < 0)
return ret;
@@ -1319,4 +1311,5 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
EXPORT_SYMBOL_GPL(tmio_mmc_host_runtime_resume);
#endif
+MODULE_DESCRIPTION("TMIO MMC core driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c
index 1404989e6151..417fd13efdfd 100644
--- a/drivers/mmc/host/uniphier-sd.c
+++ b/drivers/mmc/host/uniphier-sd.c
@@ -90,9 +90,9 @@ static void uniphier_sd_dma_endisable(struct tmio_mmc_host *host, int enable)
}
/* external DMA engine */
-static void uniphier_sd_external_dma_issue(struct tasklet_struct *t)
+static void uniphier_sd_external_dma_issue(struct work_struct *t)
{
- struct tmio_mmc_host *host = from_tasklet(host, t, dma_issue);
+ struct tmio_mmc_host *host = from_work(host, t, dma_issue);
struct uniphier_sd_priv *priv = uniphier_sd_priv(host);
uniphier_sd_dma_endisable(host, 1);
@@ -199,7 +199,7 @@ static void uniphier_sd_external_dma_request(struct tmio_mmc_host *host,
host->chan_rx = chan;
host->chan_tx = chan;
- tasklet_setup(&host->dma_issue, uniphier_sd_external_dma_issue);
+ INIT_WORK(&host->dma_issue, uniphier_sd_external_dma_issue);
}
static void uniphier_sd_external_dma_release(struct tmio_mmc_host *host)
@@ -236,9 +236,9 @@ static const struct tmio_mmc_dma_ops uniphier_sd_external_dma_ops = {
.dataend = uniphier_sd_external_dma_dataend,
};
-static void uniphier_sd_internal_dma_issue(struct tasklet_struct *t)
+static void uniphier_sd_internal_dma_issue(struct work_struct *t)
{
- struct tmio_mmc_host *host = from_tasklet(host, t, dma_issue);
+ struct tmio_mmc_host *host = from_work(host, t, dma_issue);
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
@@ -317,7 +317,7 @@ static void uniphier_sd_internal_dma_request(struct tmio_mmc_host *host,
host->chan_tx = (void *)0xdeadbeaf;
- tasklet_setup(&host->dma_issue, uniphier_sd_internal_dma_issue);
+ INIT_WORK(&host->dma_issue, uniphier_sd_internal_dma_issue);
}
static void uniphier_sd_internal_dma_release(struct tmio_mmc_host *host)
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index ba6044b16e07..f77457105ec3 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <linux/mmc/host.h>
+#include <linux/workqueue.h>
#define DRV_NAME "via_sdmmc"
@@ -307,7 +308,7 @@ struct via_crdr_mmc_host {
struct sdhcreg pm_sdhc_reg;
struct work_struct carddet_work;
- struct tasklet_struct finish_tasklet;
+ struct work_struct finish_bh_work;
struct timer_list timer;
spinlock_t lock;
@@ -643,7 +644,7 @@ static void via_sdc_finish_data(struct via_crdr_mmc_host *host)
if (data->stop)
via_sdc_send_command(host, data->stop);
else
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
}
static void via_sdc_finish_command(struct via_crdr_mmc_host *host)
@@ -653,7 +654,7 @@ static void via_sdc_finish_command(struct via_crdr_mmc_host *host)
host->cmd->error = 0;
if (!host->cmd->data)
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
host->cmd = NULL;
}
@@ -682,7 +683,7 @@ static void via_sdc_request(struct mmc_host *mmc, struct mmc_request *mrq)
status = readw(host->sdhc_mmiobase + VIA_CRDR_SDSTATUS);
if (!(status & VIA_CRDR_SDSTS_SLOTG) || host->reject) {
host->mrq->cmd->error = -ENOMEDIUM;
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
} else {
via_sdc_send_command(host, mrq->cmd);
}
@@ -848,7 +849,7 @@ static void via_sdc_cmd_isr(struct via_crdr_mmc_host *host, u16 intmask)
host->cmd->error = -EILSEQ;
if (host->cmd->error)
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
else if (intmask & VIA_CRDR_SDSTS_CRD)
via_sdc_finish_command(host);
}
@@ -955,16 +956,16 @@ static void via_sdc_timeout(struct timer_list *t)
sdhost->cmd->error = -ETIMEDOUT;
else
sdhost->mrq->cmd->error = -ETIMEDOUT;
- tasklet_schedule(&sdhost->finish_tasklet);
+ queue_work(system_bh_wq, &sdhost->finish_bh_work);
}
}
spin_unlock_irqrestore(&sdhost->lock, flags);
}
-static void via_sdc_tasklet_finish(struct tasklet_struct *t)
+static void via_sdc_finish_bh_work(struct work_struct *t)
{
- struct via_crdr_mmc_host *host = from_tasklet(host, t, finish_tasklet);
+ struct via_crdr_mmc_host *host = from_work(host, t, finish_bh_work);
unsigned long flags;
struct mmc_request *mrq;
@@ -1005,7 +1006,7 @@ static void via_sdc_card_detect(struct work_struct *work)
pr_err("%s: Card removed during transfer!\n",
mmc_hostname(host->mmc));
host->mrq->cmd->error = -ENOMEDIUM;
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
}
spin_unlock_irqrestore(&host->lock, flags);
@@ -1051,7 +1052,7 @@ static void via_init_mmc_host(struct via_crdr_mmc_host *host)
INIT_WORK(&host->carddet_work, via_sdc_card_detect);
- tasklet_setup(&host->finish_tasklet, via_sdc_tasklet_finish);
+ INIT_WORK(&host->finish_bh_work, via_sdc_finish_bh_work);
addrbase = host->sdhc_mmiobase;
writel(0x0, addrbase + VIA_CRDR_SDINTMASK);
@@ -1193,7 +1194,7 @@ static void via_sd_remove(struct pci_dev *pcidev)
sdhost->mrq->cmd->error = -ENOMEDIUM;
if (sdhost->mrq->stop)
sdhost->mrq->stop->error = -ENOMEDIUM;
- tasklet_schedule(&sdhost->finish_tasklet);
+ queue_work(system_bh_wq, &sdhost->finish_bh_work);
}
spin_unlock_irqrestore(&sdhost->lock, flags);
@@ -1203,7 +1204,7 @@ static void via_sd_remove(struct pci_dev *pcidev)
del_timer_sync(&sdhost->timer);
- tasklet_kill(&sdhost->finish_tasklet);
+ cancel_work_sync(&sdhost->finish_bh_work);
/* switch off power */
gatt = readb(sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index f0562f712d98..6e20405d0430 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -459,7 +459,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
* FIFO threshold interrupts properly.
*/
if ((data->blocks * data->blksz - data->bytes_xfered) < 16)
- tasklet_schedule(&host->fifo_tasklet);
+ queue_work(system_bh_wq, &host->fifo_bh_work);
}
static void wbsd_fill_fifo(struct wbsd_host *host)
@@ -524,7 +524,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
* 'FIFO empty' under certain conditions. So we
* need to be a bit more pro-active.
*/
- tasklet_schedule(&host->fifo_tasklet);
+ queue_work(system_bh_wq, &host->fifo_bh_work);
}
static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
@@ -746,7 +746,7 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
struct mmc_command *cmd;
/*
- * Disable tasklets to avoid a deadlock.
+ * Disable bh works to avoid a deadlock.
*/
spin_lock_bh(&host->lock);
@@ -821,7 +821,7 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
* Dirty fix for hardware bug.
*/
if (host->dma == -1)
- tasklet_schedule(&host->fifo_tasklet);
+ queue_work(system_bh_wq, &host->fifo_bh_work);
spin_unlock_bh(&host->lock);
@@ -961,13 +961,13 @@ static void wbsd_reset_ignore(struct timer_list *t)
* Card status might have changed during the
* blackout.
*/
- tasklet_schedule(&host->card_tasklet);
+ queue_work(system_bh_wq, &host->card_bh_work);
spin_unlock_bh(&host->lock);
}
/*
- * Tasklets
+ * BH Works
*/
static inline struct mmc_data *wbsd_get_data(struct wbsd_host *host)
@@ -987,9 +987,9 @@ static inline struct mmc_data *wbsd_get_data(struct wbsd_host *host)
return host->mrq->cmd->data;
}
-static void wbsd_tasklet_card(struct tasklet_struct *t)
+static void wbsd_card_bh_work(struct work_struct *t)
{
- struct wbsd_host *host = from_tasklet(host, t, card_tasklet);
+ struct wbsd_host *host = from_work(host, t, card_bh_work);
u8 csr;
int delay = -1;
@@ -1020,7 +1020,7 @@ static void wbsd_tasklet_card(struct tasklet_struct *t)
wbsd_reset(host);
host->mrq->cmd->error = -ENOMEDIUM;
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
}
delay = 0;
@@ -1036,9 +1036,9 @@ static void wbsd_tasklet_card(struct tasklet_struct *t)
mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
}
-static void wbsd_tasklet_fifo(struct tasklet_struct *t)
+static void wbsd_fifo_bh_work(struct work_struct *t)
{
- struct wbsd_host *host = from_tasklet(host, t, fifo_tasklet);
+ struct wbsd_host *host = from_work(host, t, fifo_bh_work);
struct mmc_data *data;
spin_lock(&host->lock);
@@ -1060,16 +1060,16 @@ static void wbsd_tasklet_fifo(struct tasklet_struct *t)
*/
if (host->num_sg == 0) {
wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
}
end:
spin_unlock(&host->lock);
}
-static void wbsd_tasklet_crc(struct tasklet_struct *t)
+static void wbsd_crc_bh_work(struct work_struct *t)
{
- struct wbsd_host *host = from_tasklet(host, t, crc_tasklet);
+ struct wbsd_host *host = from_work(host, t, crc_bh_work);
struct mmc_data *data;
spin_lock(&host->lock);
@@ -1085,15 +1085,15 @@ static void wbsd_tasklet_crc(struct tasklet_struct *t)
data->error = -EILSEQ;
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
end:
spin_unlock(&host->lock);
}
-static void wbsd_tasklet_timeout(struct tasklet_struct *t)
+static void wbsd_timeout_bh_work(struct work_struct *t)
{
- struct wbsd_host *host = from_tasklet(host, t, timeout_tasklet);
+ struct wbsd_host *host = from_work(host, t, timeout_bh_work);
struct mmc_data *data;
spin_lock(&host->lock);
@@ -1109,15 +1109,15 @@ static void wbsd_tasklet_timeout(struct tasklet_struct *t)
data->error = -ETIMEDOUT;
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
end:
spin_unlock(&host->lock);
}
-static void wbsd_tasklet_finish(struct tasklet_struct *t)
+static void wbsd_finish_bh_work(struct work_struct *t)
{
- struct wbsd_host *host = from_tasklet(host, t, finish_tasklet);
+ struct wbsd_host *host = from_work(host, t, finish_bh_work);
struct mmc_data *data;
spin_lock(&host->lock);
@@ -1156,18 +1156,18 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id)
host->isr |= isr;
/*
- * Schedule tasklets as needed.
+ * Schedule bh work as needed.
*/
if (isr & WBSD_INT_CARD)
- tasklet_schedule(&host->card_tasklet);
+ queue_work(system_bh_wq, &host->card_bh_work);
if (isr & WBSD_INT_FIFO_THRE)
- tasklet_schedule(&host->fifo_tasklet);
+ queue_work(system_bh_wq, &host->fifo_bh_work);
if (isr & WBSD_INT_CRC)
- tasklet_hi_schedule(&host->crc_tasklet);
+ queue_work(system_bh_highpri_wq, &host->crc_bh_work);
if (isr & WBSD_INT_TIMEOUT)
- tasklet_hi_schedule(&host->timeout_tasklet);
+ queue_work(system_bh_highpri_wq, &host->timeout_bh_work);
if (isr & WBSD_INT_TC)
- tasklet_schedule(&host->finish_tasklet);
+ queue_work(system_bh_wq, &host->finish_bh_work);
return IRQ_HANDLED;
}
@@ -1443,13 +1443,13 @@ static int wbsd_request_irq(struct wbsd_host *host, int irq)
int ret;
/*
- * Set up tasklets. Must be done before requesting interrupt.
+ * Set up bh works. Must be done before requesting interrupt.
*/
- tasklet_setup(&host->card_tasklet, wbsd_tasklet_card);
- tasklet_setup(&host->fifo_tasklet, wbsd_tasklet_fifo);
- tasklet_setup(&host->crc_tasklet, wbsd_tasklet_crc);
- tasklet_setup(&host->timeout_tasklet, wbsd_tasklet_timeout);
- tasklet_setup(&host->finish_tasklet, wbsd_tasklet_finish);
+ INIT_WORK(&host->card_bh_work, wbsd_card_bh_work);
+ INIT_WORK(&host->fifo_bh_work, wbsd_fifo_bh_work);
+ INIT_WORK(&host->crc_bh_work, wbsd_crc_bh_work);
+ INIT_WORK(&host->timeout_bh_work, wbsd_timeout_bh_work);
+ INIT_WORK(&host->finish_bh_work, wbsd_finish_bh_work);
/*
* Allocate interrupt.
@@ -1472,11 +1472,11 @@ static void wbsd_release_irq(struct wbsd_host *host)
host->irq = 0;
- tasklet_kill(&host->card_tasklet);
- tasklet_kill(&host->fifo_tasklet);
- tasklet_kill(&host->crc_tasklet);
- tasklet_kill(&host->timeout_tasklet);
- tasklet_kill(&host->finish_tasklet);
+ cancel_work_sync(&host->card_bh_work);
+ cancel_work_sync(&host->fifo_bh_work);
+ cancel_work_sync(&host->crc_bh_work);
+ cancel_work_sync(&host->timeout_bh_work);
+ cancel_work_sync(&host->finish_bh_work);
}
/*
diff --git a/drivers/mmc/host/wbsd.h b/drivers/mmc/host/wbsd.h
index be30b4d8ce4c..970886831305 100644
--- a/drivers/mmc/host/wbsd.h
+++ b/drivers/mmc/host/wbsd.h
@@ -171,11 +171,11 @@ struct wbsd_host
int irq; /* Interrupt */
int dma; /* DMA channel */
- struct tasklet_struct card_tasklet; /* Tasklet structures */
- struct tasklet_struct fifo_tasklet;
- struct tasklet_struct crc_tasklet;
- struct tasklet_struct timeout_tasklet;
- struct tasklet_struct finish_tasklet;
+ struct work_struct card_bh_work; /* Work structures */
+ struct work_struct fifo_bh_work;
+ struct work_struct crc_bh_work;
+ struct work_struct timeout_bh_work;
+ struct work_struct finish_bh_work;
struct timer_list ignore_timer; /* Ignore detection timer */
};
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 3caa0717d46c..47ead84407cd 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -336,6 +336,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
lim.logical_block_size = tr->blksize;
if (tr->discard)
lim.max_hw_discard_sectors = UINT_MAX;
+ if (tr->flush)
+ lim.features |= BLK_FEAT_WRITE_CACHE;
/* Create gendisk */
gd = blk_mq_alloc_disk(new->tag_set, &lim, new);
@@ -372,13 +374,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
/* Create the request queue */
spin_lock_init(&new->queue_lock);
INIT_LIST_HEAD(&new->rq_list);
-
- if (tr->flush)
- blk_queue_write_cache(new->rq, true, false);
-
- blk_queue_flag_set(QUEUE_FLAG_NONROT, new->rq);
- blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, new->rq);
-
gd->queue = new->rq;
if (new->readonly)
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index cbf8ae85e1ae..614257308516 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -234,8 +234,7 @@ config MTD_NAND_FSL_IFC
tristate "Freescale IFC NAND controller"
depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST
depends on HAS_IOMEM
- select FSL_IFC
- select MEMORY
+ depends on FSL_IFC
help
Various Freescale chips e.g P1010, include a NAND Flash machine
with built-in hardware ECC capabilities.
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index d7dbbd469b89..53e16d39af4b 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -1093,28 +1093,32 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs,
unsigned int offset_in_page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
+ bool ident_stage = !mtd->writesize;
- /* Make sure the offset is less than the actual page size. */
- if (offset_in_page > mtd->writesize + mtd->oobsize)
- return -EINVAL;
+ /* Bypass all checks during NAND identification */
+ if (likely(!ident_stage)) {
+ /* Make sure the offset is less than the actual page size. */
+ if (offset_in_page > mtd->writesize + mtd->oobsize)
+ return -EINVAL;
- /*
- * On small page NANDs, there's a dedicated command to access the OOB
- * area, and the column address is relative to the start of the OOB
- * area, not the start of the page. Asjust the address accordingly.
- */
- if (mtd->writesize <= 512 && offset_in_page >= mtd->writesize)
- offset_in_page -= mtd->writesize;
+ /*
+ * On small page NANDs, there's a dedicated command to access the OOB
+ * area, and the column address is relative to the start of the OOB
+ * area, not the start of the page. Asjust the address accordingly.
+ */
+ if (mtd->writesize <= 512 && offset_in_page >= mtd->writesize)
+ offset_in_page -= mtd->writesize;
- /*
- * The offset in page is expressed in bytes, if the NAND bus is 16-bit
- * wide, then it must be divided by 2.
- */
- if (chip->options & NAND_BUSWIDTH_16) {
- if (WARN_ON(offset_in_page % 2))
- return -EINVAL;
+ /*
+ * The offset in page is expressed in bytes, if the NAND bus is 16-bit
+ * wide, then it must be divided by 2.
+ */
+ if (chip->options & NAND_BUSWIDTH_16) {
+ if (WARN_ON(offset_in_page % 2))
+ return -EINVAL;
- offset_in_page /= 2;
+ offset_in_page /= 2;
+ }
}
addrs[0] = offset_in_page;
@@ -1123,7 +1127,7 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs,
* Small page NANDs use 1 cycle for the columns, while large page NANDs
* need 2
*/
- if (mtd->writesize <= 512)
+ if (!ident_stage && mtd->writesize <= 512)
return 1;
addrs[1] = offset_in_page >> 8;
@@ -1436,16 +1440,19 @@ int nand_change_read_column_op(struct nand_chip *chip,
unsigned int len, bool force_8bit)
{
struct mtd_info *mtd = nand_to_mtd(chip);
+ bool ident_stage = !mtd->writesize;
if (len && !buf)
return -EINVAL;
- if (offset_in_page + len > mtd->writesize + mtd->oobsize)
- return -EINVAL;
+ if (!ident_stage) {
+ if (offset_in_page + len > mtd->writesize + mtd->oobsize)
+ return -EINVAL;
- /* Small page NANDs do not support column change. */
- if (mtd->writesize <= 512)
- return -ENOTSUPP;
+ /* Small page NANDs do not support column change. */
+ if (mtd->writesize <= 512)
+ return -ENOTSUPP;
+ }
if (nand_has_exec_op(chip)) {
const struct nand_interface_config *conf =
@@ -2173,7 +2180,7 @@ EXPORT_SYMBOL_GPL(nand_reset_op);
int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
bool force_8bit, bool check_only)
{
- if (!len || !buf)
+ if (!len || (!check_only && !buf))
return -EINVAL;
if (nand_has_exec_op(chip)) {
@@ -6301,6 +6308,7 @@ static const struct nand_ops rawnand_ops = {
static int nand_scan_tail(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
+ struct nand_device *base = &chip->base;
struct nand_ecc_ctrl *ecc = &chip->ecc;
int ret, i;
@@ -6445,9 +6453,13 @@ static int nand_scan_tail(struct nand_chip *chip)
if (!ecc->write_oob_raw)
ecc->write_oob_raw = ecc->write_oob;
- /* propagate ecc info to mtd_info */
+ /* Propagate ECC info to the generic NAND and MTD layers */
mtd->ecc_strength = ecc->strength;
+ if (!base->ecc.ctx.conf.strength)
+ base->ecc.ctx.conf.strength = ecc->strength;
mtd->ecc_step_size = ecc->size;
+ if (!base->ecc.ctx.conf.step_size)
+ base->ecc.ctx.conf.step_size = ecc->size;
/*
* Set the number of read / write steps for one page depending on ECC
@@ -6455,6 +6467,8 @@ static int nand_scan_tail(struct nand_chip *chip)
*/
if (!ecc->steps)
ecc->steps = mtd->writesize / ecc->size;
+ if (!base->ecc.ctx.nsteps)
+ base->ecc.ctx.nsteps = ecc->steps;
if (ecc->steps * ecc->size != mtd->writesize) {
WARN(1, "Invalid ECC parameters\n");
ret = -EINVAL;
diff --git a/drivers/mtd/nand/raw/rockchip-nand-controller.c b/drivers/mtd/nand/raw/rockchip-nand-controller.c
index 7baaef69d70a..55580447633b 100644
--- a/drivers/mtd/nand/raw/rockchip-nand-controller.c
+++ b/drivers/mtd/nand/raw/rockchip-nand-controller.c
@@ -420,13 +420,13 @@ static int rk_nfc_setup_interface(struct nand_chip *chip, int target,
u32 rate, tc2rw, trwpw, trw2c;
u32 temp;
- if (target < 0)
- return 0;
-
timings = nand_get_sdr_timings(conf);
if (IS_ERR(timings))
return -EOPNOTSUPP;
+ if (target < 0)
+ return 0;
+
if (IS_ERR(nfc->nfc_clk))
rate = clk_get_rate(nfc->ahb_clk);
else
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 0cacd7027e35..bc80fb6397dc 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1214,9 +1214,9 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond,
__be32 target;
if (newval->string) {
- if (!in4_pton(newval->string+1, -1, (u8 *)&target, -1, NULL)) {
- netdev_err(bond->dev, "invalid ARP target %pI4 specified\n",
- &target);
+ if (strlen(newval->string) < 1 ||
+ !in4_pton(newval->string + 1, -1, (u8 *)&target, -1, NULL)) {
+ netdev_err(bond->dev, "invalid ARP target specified\n");
return ret;
}
if (newval->string[0] == '+')
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
index 7292c81fc0cd..024169461cad 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -125,6 +125,7 @@ static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err_liste
static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leafimx = {
.quirks = 0,
+ .family = KVASER_LEAF,
.ops = &kvaser_usb_leaf_dev_ops,
};
diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
index 02f07b870f10..268949939636 100644
--- a/drivers/net/dsa/lan9303-core.c
+++ b/drivers/net/dsa/lan9303-core.c
@@ -1047,31 +1047,31 @@ static int lan9303_get_sset_count(struct dsa_switch *ds, int port, int sset)
return ARRAY_SIZE(lan9303_mib);
}
-static int lan9303_phy_read(struct dsa_switch *ds, int phy, int regnum)
+static int lan9303_phy_read(struct dsa_switch *ds, int port, int regnum)
{
struct lan9303 *chip = ds->priv;
int phy_base = chip->phy_addr_base;
- if (phy == phy_base)
+ if (port == 0)
return lan9303_virt_phy_reg_read(chip, regnum);
- if (phy > phy_base + 2)
+ if (port > 2)
return -ENODEV;
- return chip->ops->phy_read(chip, phy, regnum);
+ return chip->ops->phy_read(chip, phy_base + port, regnum);
}
-static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum,
+static int lan9303_phy_write(struct dsa_switch *ds, int port, int regnum,
u16 val)
{
struct lan9303 *chip = ds->priv;
int phy_base = chip->phy_addr_base;
- if (phy == phy_base)
+ if (port == 0)
return lan9303_virt_phy_reg_write(chip, regnum, val);
- if (phy > phy_base + 2)
+ if (port > 2)
return -ENODEV;
- return chip->ops->phy_write(chip, phy, regnum, val);
+ return chip->ops->phy_write(chip, phy_base + port, regnum, val);
}
static int lan9303_port_enable(struct dsa_switch *ds, int port,
@@ -1099,7 +1099,7 @@ static void lan9303_port_disable(struct dsa_switch *ds, int port)
vlan_vid_del(dsa_port_to_conduit(dp), htons(ETH_P_8021Q), port);
lan9303_disable_processing_port(chip, port);
- lan9303_phy_write(ds, chip->phy_addr_base + port, MII_BMCR, BMCR_PDOWN);
+ lan9303_phy_write(ds, port, MII_BMCR, BMCR_PDOWN);
}
static int lan9303_port_bridge_join(struct dsa_switch *ds, int port,
@@ -1374,8 +1374,6 @@ static const struct dsa_switch_ops lan9303_switch_ops = {
static int lan9303_register_switch(struct lan9303 *chip)
{
- int base;
-
chip->ds = devm_kzalloc(chip->dev, sizeof(*chip->ds), GFP_KERNEL);
if (!chip->ds)
return -ENOMEM;
@@ -1385,8 +1383,7 @@ static int lan9303_register_switch(struct lan9303 *chip)
chip->ds->priv = chip;
chip->ds->ops = &lan9303_switch_ops;
chip->ds->phylink_mac_ops = &lan9303_phylink_mac_ops;
- base = chip->phy_addr_base;
- chip->ds->phys_mii_mask = GENMASK(LAN9303_NUM_PORTS - 1 + base, base);
+ chip->ds->phys_mii_mask = GENMASK(LAN9303_NUM_PORTS - 1, 0);
return dsa_register_switch(chip->ds);
}
diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c
index a806dadc4196..20c6529ec135 100644
--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c
+++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c
@@ -1380,6 +1380,7 @@ static int bcmasp_probe(struct platform_device *pdev)
dev_err(dev, "Cannot create eth interface %d\n", i);
bcmasp_remove_intfs(priv);
of_node_put(intf_node);
+ ret = -ENOMEM;
goto of_put_exit;
}
list_add_tail(&intf->list, &priv->intfs);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index e2a4e1088b7f..9580ab83d387 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1262,7 +1262,7 @@ enum {
struct bnx2x_fw_stats_req {
struct stats_query_header hdr;
- struct stats_query_entry query[FP_SB_MAX_E1x+
+ struct stats_query_entry query[FP_SB_MAX_E2 +
BNX2X_FIRST_QUEUE_QUERY_IDX];
};
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index a6d69a45fa01..43952689bfb0 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -6146,6 +6146,24 @@ static u16 bnxt_get_max_rss_ring(struct bnxt *bp)
return max_ring;
}
+u16 bnxt_get_max_rss_ctx_ring(struct bnxt *bp)
+{
+ u16 i, tbl_size, max_ring = 0;
+ struct bnxt_rss_ctx *rss_ctx;
+
+ if (!BNXT_SUPPORTS_MULTI_RSS_CTX(bp))
+ return 0;
+
+ tbl_size = bnxt_get_rxfh_indir_size(bp->dev);
+
+ list_for_each_entry(rss_ctx, &bp->rss_ctx_list, list) {
+ for (i = 0; i < tbl_size; i++)
+ max_ring = max(max_ring, rss_ctx->rss_indir_tbl[i]);
+ }
+
+ return max_ring;
+}
+
int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings)
{
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
@@ -12669,7 +12687,11 @@ bool bnxt_rfs_capable(struct bnxt *bp, bool new_rss_ctx)
if (!BNXT_NEW_RM(bp))
return true;
- if (hwr.vnic == bp->hw_resc.resv_vnics &&
+ /* Do not reduce VNIC and RSS ctx reservations. There is a FW
+ * issue that will mess up the default VNIC if we reduce the
+ * reservations.
+ */
+ if (hwr.vnic <= bp->hw_resc.resv_vnics &&
hwr.rss_ctx <= bp->hw_resc.resv_rsscos_ctxs)
return true;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 9cf0acfa04e5..6b10a09ee1af 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -2776,6 +2776,7 @@ int bnxt_hwrm_vnic_set_tpa(struct bnxt *bp, struct bnxt_vnic_info *vnic,
void bnxt_fill_ipv6_mask(__be32 mask[4]);
int bnxt_alloc_rss_indir_tbl(struct bnxt *bp, struct bnxt_rss_ctx *rss_ctx);
void bnxt_set_dflt_rss_indir_tbl(struct bnxt *bp, struct bnxt_rss_ctx *rss_ctx);
+u16 bnxt_get_max_rss_ctx_ring(struct bnxt *bp);
int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings);
int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic);
int bnxt_hwrm_vnic_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic,
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 8763f8a01457..79c09c1cdf93 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -961,6 +961,12 @@ static int bnxt_set_channels(struct net_device *dev,
return rc;
}
+ if (req_rx_rings < bp->rx_nr_rings &&
+ req_rx_rings <= bnxt_get_max_rss_ctx_ring(bp)) {
+ netdev_warn(dev, "Can't deactivate rings used by RSS contexts\n");
+ return -EINVAL;
+ }
+
if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) !=
bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) &&
netif_is_rxfh_configured(dev)) {
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 2e98a2a0bead..ce227b56cf72 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -1109,6 +1109,46 @@ static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
}
/**
+ * e1000e_force_smbus - Force interfaces to transition to SMBUS mode.
+ * @hw: pointer to the HW structure
+ *
+ * Force the MAC and the PHY to SMBUS mode. Assumes semaphore already
+ * acquired.
+ *
+ * Return: 0 on success, negative errno on failure.
+ **/
+static s32 e1000e_force_smbus(struct e1000_hw *hw)
+{
+ u16 smb_ctrl = 0;
+ u32 ctrl_ext;
+ s32 ret_val;
+
+ /* Switching PHY interface always returns MDI error
+ * so disable retry mechanism to avoid wasting time
+ */
+ e1000e_disable_phy_retry(hw);
+
+ /* Force SMBus mode in the PHY */
+ ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &smb_ctrl);
+ if (ret_val) {
+ e1000e_enable_phy_retry(hw);
+ return ret_val;
+ }
+
+ smb_ctrl |= CV_SMB_CTRL_FORCE_SMBUS;
+ e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, smb_ctrl);
+
+ e1000e_enable_phy_retry(hw);
+
+ /* Force SMBus mode in the MAC */
+ ctrl_ext = er32(CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_FORCE_SMBUS;
+ ew32(CTRL_EXT, ctrl_ext);
+
+ return 0;
+}
+
+/**
* e1000_enable_ulp_lpt_lp - configure Ultra Low Power mode for LynxPoint-LP
* @hw: pointer to the HW structure
* @to_sx: boolean indicating a system power state transition to Sx
@@ -1165,6 +1205,14 @@ 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;
+ }
+ }
+
/* Si workaround for ULP entry flow on i127/rev6 h/w. Enable
* LPLU and disable Gig speed when entering ULP
*/
@@ -1225,27 +1273,12 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
}
release:
- /* Switching PHY interface always returns MDI error
- * so disable retry mechanism to avoid wasting time
- */
- e1000e_disable_phy_retry(hw);
-
- /* Force SMBus mode in PHY */
- ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
- if (ret_val) {
- e1000e_enable_phy_retry(hw);
- hw->phy.ops.release(hw);
- goto out;
+ 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);
}
- phy_reg |= CV_SMB_CTRL_FORCE_SMBUS;
- e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
-
- e1000e_enable_phy_retry(hw);
-
- /* Force SMBus mode in MAC */
- mac_reg = er32(CTRL_EXT);
- mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
- ew32(CTRL_EXT, mac_reg);
hw->phy.ops.release(hw);
out:
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index da5c59daf8ba..3cd161c6672b 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -6363,49 +6363,49 @@ static void e1000e_s0ix_entry_flow(struct e1000_adapter *adapter)
mac_data |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
ew32(EXTCNF_CTRL, mac_data);
- /* Enable the Dynamic Power Gating in the MAC */
- mac_data = er32(FEXTNVM7);
- mac_data |= BIT(22);
- ew32(FEXTNVM7, mac_data);
-
/* Disable disconnected cable conditioning for Power Gating */
mac_data = er32(DPGFR);
mac_data |= BIT(2);
ew32(DPGFR, mac_data);
- /* Don't wake from dynamic Power Gating with clock request */
- mac_data = er32(FEXTNVM12);
- mac_data |= BIT(12);
- ew32(FEXTNVM12, mac_data);
-
- /* Ungate PGCB clock */
- mac_data = er32(FEXTNVM9);
- mac_data &= ~BIT(28);
- ew32(FEXTNVM9, mac_data);
-
- /* Enable K1 off to enable mPHY Power Gating */
- mac_data = er32(FEXTNVM6);
- mac_data |= BIT(31);
- ew32(FEXTNVM6, mac_data);
-
- /* Enable mPHY power gating for any link and speed */
- mac_data = er32(FEXTNVM8);
- mac_data |= BIT(9);
- ew32(FEXTNVM8, mac_data);
-
/* Enable the Dynamic Clock Gating in the DMA and MAC */
mac_data = er32(CTRL_EXT);
mac_data |= E1000_CTRL_EXT_DMA_DYN_CLK_EN;
ew32(CTRL_EXT, mac_data);
-
- /* No MAC DPG gating SLP_S0 in modern standby
- * Switch the logic of the lanphypc to use PMC counter
- */
- mac_data = er32(FEXTNVM5);
- mac_data |= BIT(7);
- ew32(FEXTNVM5, mac_data);
}
+ /* Enable the Dynamic Power Gating in the MAC */
+ mac_data = er32(FEXTNVM7);
+ mac_data |= BIT(22);
+ ew32(FEXTNVM7, mac_data);
+
+ /* Don't wake from dynamic Power Gating with clock request */
+ mac_data = er32(FEXTNVM12);
+ mac_data |= BIT(12);
+ ew32(FEXTNVM12, mac_data);
+
+ /* Ungate PGCB clock */
+ mac_data = er32(FEXTNVM9);
+ mac_data &= ~BIT(28);
+ ew32(FEXTNVM9, mac_data);
+
+ /* Enable K1 off to enable mPHY Power Gating */
+ mac_data = er32(FEXTNVM6);
+ mac_data |= BIT(31);
+ ew32(FEXTNVM6, mac_data);
+
+ /* Enable mPHY power gating for any link and speed */
+ mac_data = er32(FEXTNVM8);
+ mac_data |= BIT(9);
+ ew32(FEXTNVM8, mac_data);
+
+ /* No MAC DPG gating SLP_S0 in modern standby
+ * Switch the logic of the lanphypc to use PMC counter
+ */
+ mac_data = er32(FEXTNVM5);
+ mac_data |= BIT(7);
+ ew32(FEXTNVM5, mac_data);
+
/* Disable the time synchronization clock */
mac_data = er32(FEXTNVM7);
mac_data |= BIT(31);
@@ -6498,33 +6498,6 @@ static void e1000e_s0ix_exit_flow(struct e1000_adapter *adapter)
} else {
/* Request driver unconfigure the device from S0ix */
- /* Disable the Dynamic Power Gating in the MAC */
- mac_data = er32(FEXTNVM7);
- mac_data &= 0xFFBFFFFF;
- ew32(FEXTNVM7, mac_data);
-
- /* Disable mPHY power gating for any link and speed */
- mac_data = er32(FEXTNVM8);
- mac_data &= ~BIT(9);
- ew32(FEXTNVM8, mac_data);
-
- /* Disable K1 off */
- mac_data = er32(FEXTNVM6);
- mac_data &= ~BIT(31);
- ew32(FEXTNVM6, mac_data);
-
- /* Disable Ungate PGCB clock */
- mac_data = er32(FEXTNVM9);
- mac_data |= BIT(28);
- ew32(FEXTNVM9, mac_data);
-
- /* Cancel not waking from dynamic
- * Power Gating with clock request
- */
- mac_data = er32(FEXTNVM12);
- mac_data &= ~BIT(12);
- ew32(FEXTNVM12, mac_data);
-
/* Cancel disable disconnected cable conditioning
* for Power Gating
*/
@@ -6537,13 +6510,6 @@ static void e1000e_s0ix_exit_flow(struct e1000_adapter *adapter)
mac_data &= 0xFFF7FFFF;
ew32(CTRL_EXT, mac_data);
- /* Revert the lanphypc logic to use the internal Gbe counter
- * and not the PMC counter
- */
- mac_data = er32(FEXTNVM5);
- mac_data &= 0xFFFFFF7F;
- ew32(FEXTNVM5, mac_data);
-
/* Enable the periodic inband message,
* Request PCIe clock in K1 page770_17[10:9] =01b
*/
@@ -6581,6 +6547,40 @@ static void e1000e_s0ix_exit_flow(struct e1000_adapter *adapter)
mac_data &= ~BIT(31);
mac_data |= BIT(0);
ew32(FEXTNVM7, mac_data);
+
+ /* Disable the Dynamic Power Gating in the MAC */
+ mac_data = er32(FEXTNVM7);
+ mac_data &= 0xFFBFFFFF;
+ ew32(FEXTNVM7, mac_data);
+
+ /* Disable mPHY power gating for any link and speed */
+ mac_data = er32(FEXTNVM8);
+ mac_data &= ~BIT(9);
+ ew32(FEXTNVM8, mac_data);
+
+ /* Disable K1 off */
+ mac_data = er32(FEXTNVM6);
+ mac_data &= ~BIT(31);
+ ew32(FEXTNVM6, mac_data);
+
+ /* Disable Ungate PGCB clock */
+ mac_data = er32(FEXTNVM9);
+ mac_data |= BIT(28);
+ ew32(FEXTNVM9, mac_data);
+
+ /* Cancel not waking from dynamic
+ * Power Gating with clock request
+ */
+ mac_data = er32(FEXTNVM12);
+ mac_data &= ~BIT(12);
+ ew32(FEXTNVM12, mac_data);
+
+ /* Revert the lanphypc logic to use the internal Gbe counter
+ * and not the PMC counter
+ */
+ mac_data = er32(FEXTNVM5);
+ mac_data &= 0xFFFFFF7F;
+ ew32(FEXTNVM5, mac_data);
}
static int e1000e_pm_freeze(struct device *dev)
diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c
index bbcfd529399b..89d57dd911dc 100644
--- a/drivers/net/ethernet/intel/e1000e/ptp.c
+++ b/drivers/net/ethernet/intel/e1000e/ptp.c
@@ -124,7 +124,8 @@ static int e1000e_phc_get_syncdevicetime(ktime_t *device,
sys_cycles = er32(PLTSTMPH);
sys_cycles <<= 32;
sys_cycles |= er32(PLTSTMPL);
- *system = convert_art_to_tsc(sys_cycles);
+ system->cycles = sys_cycles;
+ system->cs_id = CSID_X86_ART;
return 0;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h
index ee86d2c53079..55b5bb884d73 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h
@@ -109,10 +109,6 @@ static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc)
-EFBIG, /* I40E_AQ_RC_EFBIG */
};
- /* aq_rc is invalid if AQ timed out */
- if (aq_ret == -EIO)
- return -EAGAIN;
-
if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))))
return -ERANGE;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 284c3fad5a6e..310513d9321b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13293,6 +13293,10 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog,
bool need_reset;
int i;
+ /* VSI shall be deleted in a moment, block loading new programs */
+ if (prog && test_bit(__I40E_IN_REMOVE, pf->state))
+ return -EINVAL;
+
/* Don't allow frames that span over multiple buffers */
if (vsi->netdev->mtu > frame_size - I40E_PACKET_HDR_PAD) {
NL_SET_ERR_MSG_MOD(extack, "MTU too large for linear frames and XDP prog does not support frags");
@@ -13301,14 +13305,9 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog,
/* When turning XDP on->off/off->on we reset and rebuild the rings. */
need_reset = (i40e_enabled_xdp_vsi(vsi) != !!prog);
-
if (need_reset)
i40e_prep_for_reset(pf);
- /* VSI shall be deleted in a moment, just return EINVAL */
- if (test_bit(__I40E_IN_REMOVE, pf->state))
- return -EINVAL;
-
old_prog = xchg(&vsi->xdp_prog, prog);
if (need_reset) {
diff --git a/drivers/net/ethernet/intel/ice/ice_hwmon.c b/drivers/net/ethernet/intel/ice/ice_hwmon.c
index e4c2c1bff6c0..b7aa6812510a 100644
--- a/drivers/net/ethernet/intel/ice/ice_hwmon.c
+++ b/drivers/net/ethernet/intel/ice/ice_hwmon.c
@@ -96,7 +96,7 @@ static bool ice_is_internal_reading_supported(struct ice_pf *pf)
unsigned long sensors = pf->hw.dev_caps.supported_sensors;
- return _test_bit(ICE_SENSOR_SUPPORT_E810_INT_TEMP_BIT, &sensors);
+ return test_bit(ICE_SENSOR_SUPPORT_E810_INT_TEMP_BIT, &sensors);
};
void ice_hwmon_init(struct ice_pf *pf)
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 0f17fc1181d2..927b623cedd5 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -1559,6 +1559,10 @@ void ice_ptp_extts_event(struct ice_pf *pf)
u8 chan, tmr_idx;
u32 hi, lo;
+ /* Don't process timestamp events if PTP is not ready */
+ if (pf->ptp.state != ICE_PTP_READY)
+ return;
+
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
/* Event time is captured by one of the two matched registers
* GLTSYN_EVNT_L: 32 LSB of sampled time event
@@ -1584,27 +1588,33 @@ void ice_ptp_extts_event(struct ice_pf *pf)
/**
* ice_ptp_cfg_extts - Configure EXTTS pin and channel
* @pf: Board private structure
- * @ena: true to enable; false to disable
* @chan: GPIO channel (0-3)
- * @gpio_pin: GPIO pin
- * @extts_flags: request flags from the ptp_extts_request.flags
+ * @config: desired EXTTS configuration.
+ * @store: If set to true, the values will be stored
+ *
+ * Configure an external timestamp event on the requested channel.
+ *
+ * Return: 0 on success, -EOPNOTUSPP on unsupported flags
*/
-static int
-ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin,
- unsigned int extts_flags)
+static int ice_ptp_cfg_extts(struct ice_pf *pf, unsigned int chan,
+ struct ice_extts_channel *config, bool store)
{
u32 func, aux_reg, gpio_reg, irq_reg;
struct ice_hw *hw = &pf->hw;
u8 tmr_idx;
- if (chan > (unsigned int)pf->ptp.info.n_ext_ts)
- return -EINVAL;
+ /* Reject requests with unsupported flags */
+ if (config->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;
irq_reg = rd32(hw, PFINT_OICR_ENA);
- if (ena) {
+ if (config->ena) {
/* Enable the interrupt */
irq_reg |= PFINT_OICR_TSYN_EVNT_M;
aux_reg = GLTSYN_AUX_IN_0_INT_ENA_M;
@@ -1613,9 +1623,9 @@ ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin,
#define GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE BIT(1)
/* set event level to requested edge */
- if (extts_flags & PTP_FALLING_EDGE)
+ if (config->flags & PTP_FALLING_EDGE)
aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE;
- if (extts_flags & PTP_RISING_EDGE)
+ if (config->flags & PTP_RISING_EDGE)
aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_RISING_EDGE;
/* Write GPIO CTL reg.
@@ -1636,12 +1646,52 @@ ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin,
wr32(hw, PFINT_OICR_ENA, irq_reg);
wr32(hw, GLTSYN_AUX_IN(chan, tmr_idx), aux_reg);
- wr32(hw, GLGEN_GPIO_CTL(gpio_pin), gpio_reg);
+ wr32(hw, GLGEN_GPIO_CTL(config->gpio_pin), gpio_reg);
+
+ if (store)
+ memcpy(&pf->ptp.extts_channels[chan], config, sizeof(*config));
return 0;
}
/**
+ * ice_ptp_disable_all_extts - Disable all EXTTS channels
+ * @pf: Board private structure
+ */
+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);
+ }
+ }
+
+ synchronize_irq(pf->oicr_irq.virq);
+}
+
+/**
+ * ice_ptp_enable_all_extts - Enable all EXTTS channels
+ * @pf: Board private structure
+ *
+ * Called during reset to restore user configuration.
+ */
+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);
+ }
+}
+
+/**
* ice_ptp_cfg_clkout - Configure clock to generate periodic wave
* @pf: Board private structure
* @chan: GPIO channel (0-3)
@@ -1659,6 +1709,9 @@ static int ice_ptp_cfg_clkout(struct ice_pf *pf, unsigned int chan,
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;
/* 0. Reset mode & out_en in AUX_OUT */
@@ -1795,17 +1848,18 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info,
struct ptp_clock_request *rq, int on)
{
struct ice_pf *pf = ptp_info_to_pf(info);
- struct ice_perout_channel clk_cfg = {0};
bool sma_pres = false;
unsigned int chan;
u32 gpio_pin;
- int err;
if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL))
sma_pres = true;
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)
@@ -1825,15 +1879,19 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info,
clk_cfg.gpio_pin = 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;
- err = ice_ptp_cfg_clkout(pf, chan, &clk_cfg, true);
- break;
+ 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)
@@ -1849,14 +1907,15 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info,
gpio_pin = chan;
}
- err = ice_ptp_cfg_extts(pf, !!on, chan, gpio_pin,
- rq->extts.flags);
- break;
+ extts_cfg.flags = rq->extts.flags;
+ extts_cfg.gpio_pin = gpio_pin;
+ extts_cfg.ena = !!on;
+
+ return ice_ptp_cfg_extts(pf, chan, &extts_cfg, true);
+ }
default:
return -EOPNOTSUPP;
}
-
- return err;
}
/**
@@ -1869,26 +1928,32 @@ static int ice_ptp_gpio_enable_e823(struct ptp_clock_info *info,
struct ptp_clock_request *rq, int on)
{
struct ice_pf *pf = ptp_info_to_pf(info);
- struct ice_perout_channel clk_cfg = {0};
- int err;
switch (rq->type) {
case PTP_CLK_REQ_PPS:
+ {
+ struct ice_perout_channel clk_cfg = {};
+
+ clk_cfg.flags = rq->perout.flags;
clk_cfg.gpio_pin = PPS_PIN_INDEX;
clk_cfg.period = NSEC_PER_SEC;
clk_cfg.ena = !!on;
- err = ice_ptp_cfg_clkout(pf, PPS_CLK_GEN_CHAN, &clk_cfg, true);
- break;
+ return ice_ptp_cfg_clkout(pf, PPS_CLK_GEN_CHAN, &clk_cfg, true);
+ }
case PTP_CLK_REQ_EXTTS:
- err = ice_ptp_cfg_extts(pf, !!on, rq->extts.index,
- TIME_SYNC_PIN_INDEX, rq->extts.flags);
- break;
+ {
+ struct ice_extts_channel extts_cfg = {};
+
+ extts_cfg.flags = rq->extts.flags;
+ extts_cfg.gpio_pin = TIME_SYNC_PIN_INDEX;
+ extts_cfg.ena = !!on;
+
+ return ice_ptp_cfg_extts(pf, rq->extts.index, &extts_cfg, true);
+ }
default:
return -EOPNOTSUPP;
}
-
- return err;
}
/**
@@ -2091,7 +2156,8 @@ ice_ptp_get_syncdevicetime(ktime_t *device,
hh_ts_lo = rd32(hw, GLHH_ART_TIME_L);
hh_ts_hi = rd32(hw, GLHH_ART_TIME_H);
hh_ts = ((u64)hh_ts_hi << 32) | hh_ts_lo;
- *system = convert_art_ns_to_tsc(hh_ts);
+ system->cycles = hh_ts;
+ system->cs_id = CSID_X86_ART;
/* Read Device source clock time */
hh_ts_lo = rd32(hw, GLTSYN_HHTIME_L(tmr_idx));
hh_ts_hi = rd32(hw, GLTSYN_HHTIME_H(tmr_idx));
@@ -2720,6 +2786,10 @@ static int ice_ptp_rebuild_owner(struct ice_pf *pf)
ice_ptp_restart_all_phy(pf);
}
+ /* Re-enable all periodic outputs and external timestamp events */
+ ice_ptp_enable_all_clkout(pf);
+ ice_ptp_enable_all_extts(pf);
+
return 0;
}
@@ -3275,6 +3345,8 @@ void ice_ptp_release(struct ice_pf *pf)
ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
+ ice_ptp_disable_all_extts(pf);
+
kthread_cancel_delayed_work_sync(&pf->ptp.work);
ice_ptp_port_phy_stop(&pf->ptp.port);
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index 3af20025043a..e2af9749061c 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -29,10 +29,17 @@ enum ice_ptp_pin_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.
@@ -226,6 +233,7 @@ enum ice_ptp_state {
* @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
* @info: structure defining PTP hardware capabilities
* @clock: pointer to registered PTP clock device
* @tstamp_config: hardware timestamping configuration
@@ -249,6 +257,7 @@ struct ice_ptp {
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];
struct ptp_clock_info info;
struct ptp_clock *clock;
struct hwtstamp_config tstamp_config;
diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c
index 1bb026232efc..946edbad4302 100644
--- a/drivers/net/ethernet/intel/igc/igc_ptp.c
+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
@@ -938,7 +938,11 @@ static bool igc_is_crosststamp_supported(struct igc_adapter *adapter)
static struct system_counterval_t igc_device_tstamp_to_system(u64 tstamp)
{
#if IS_ENABLED(CONFIG_X86_TSC) && !defined(CONFIG_UML)
- return convert_art_ns_to_tsc(tstamp);
+ return (struct system_counterval_t) {
+ .cs_id = CSID_X86_ART,
+ .cycles = tstamp,
+ .use_nsecs = true,
+ };
#else
return (struct system_counterval_t) { };
#endif
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 5352fee62d2b..0b9982804370 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -217,9 +217,9 @@ ltq_etop_free_channel(struct net_device *dev, struct ltq_etop_chan *ch)
if (ch->dma.irq)
free_irq(ch->dma.irq, priv);
if (IS_RX(ch->idx)) {
- int desc;
+ struct ltq_dma_channel *dma = &ch->dma;
- for (desc = 0; desc < LTQ_DESC_NUM; desc++)
+ for (dma->desc = 0; dma->desc < LTQ_DESC_NUM; dma->desc++)
dev_kfree_skb_any(ch->skb[ch->dma.desc]);
}
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index 4a77f6fe2622..05b84581d5c5 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -1745,7 +1745,7 @@ struct cpt_lf_alloc_req_msg {
u16 nix_pf_func;
u16 sso_pf_func;
u16 eng_grpmsk;
- int blkaddr;
+ u8 blkaddr;
u8 ctx_ilen_valid : 1;
u8 ctx_ilen : 7;
};
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
index d883157393ea..6c3aca6f278d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
@@ -63,8 +63,13 @@ enum npc_kpu_lb_ltype {
NPC_LT_LB_CUSTOM1 = 0xF,
};
+/* Don't modify ltypes up to IP6_EXT, otherwise length and checksum of IP
+ * headers may not be checked correctly. IPv4 ltypes and IPv6 ltypes must
+ * differ only at bit 0 so mask 0xE can be used to detect extended headers.
+ */
enum npc_kpu_lc_ltype {
- NPC_LT_LC_IP = 1,
+ NPC_LT_LC_PTP = 1,
+ NPC_LT_LC_IP,
NPC_LT_LC_IP_OPT,
NPC_LT_LC_IP6,
NPC_LT_LC_IP6_EXT,
@@ -72,7 +77,6 @@ enum npc_kpu_lc_ltype {
NPC_LT_LC_RARP,
NPC_LT_LC_MPLS,
NPC_LT_LC_NSH,
- NPC_LT_LC_PTP,
NPC_LT_LC_FCOE,
NPC_LT_LC_NGIO,
NPC_LT_LC_CUSTOM0 = 0xE,
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index ff78251f92d4..5f661e67ccbc 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -1643,7 +1643,7 @@ static int rvu_check_rsrc_availability(struct rvu *rvu,
if (req->ssow > block->lf.max) {
dev_err(&rvu->pdev->dev,
"Func 0x%x: Invalid SSOW req, %d > max %d\n",
- pcifunc, req->sso, block->lf.max);
+ pcifunc, req->ssow, block->lf.max);
return -EINVAL;
}
mappedlfs = rvu_get_rsrc_mapcount(pfvf, block->addr);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c
index f047185f38e0..3e09d2285814 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c
@@ -696,7 +696,8 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu,
struct cpt_rd_wr_reg_msg *req,
struct cpt_rd_wr_reg_msg *rsp)
{
- int blkaddr;
+ u64 offset = req->reg_offset;
+ int blkaddr, lf;
blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
if (blkaddr < 0)
@@ -707,17 +708,25 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu,
!is_cpt_vf(rvu, req->hdr.pcifunc))
return CPT_AF_ERR_ACCESS_DENIED;
- rsp->reg_offset = req->reg_offset;
- rsp->ret_val = req->ret_val;
- rsp->is_write = req->is_write;
-
if (!is_valid_offset(rvu, req))
return CPT_AF_ERR_ACCESS_DENIED;
+ /* Translate local LF used by VFs to global CPT LF */
+ lf = rvu_get_lf(rvu, &rvu->hw->block[blkaddr], req->hdr.pcifunc,
+ (offset & 0xFFF) >> 3);
+
+ /* Translate local LF's offset to global CPT LF's offset */
+ offset &= 0xFF000;
+ offset += lf << 3;
+
+ rsp->reg_offset = offset;
+ rsp->ret_val = req->ret_val;
+ rsp->is_write = req->is_write;
+
if (req->is_write)
- rvu_write64(rvu, blkaddr, req->reg_offset, req->val);
+ rvu_write64(rvu, blkaddr, offset, req->val);
else
- rsp->val = rvu_read64(rvu, blkaddr, req->reg_offset);
+ rsp->val = rvu_read64(rvu, blkaddr, offset);
return 0;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index 00af8888e329..3dc828cf6c5a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -3864,6 +3864,11 @@ static int get_flowkey_alg_idx(struct nix_hw *nix_hw, u32 flow_cfg)
return -ERANGE;
}
+/* Mask to match ipv6(NPC_LT_LC_IP6) and ipv6 ext(NPC_LT_LC_IP6_EXT) */
+#define NPC_LT_LC_IP6_MATCH_MSK ((~(NPC_LT_LC_IP6 ^ NPC_LT_LC_IP6_EXT)) & 0xf)
+/* Mask to match both ipv4(NPC_LT_LC_IP) and ipv4 ext(NPC_LT_LC_IP_OPT) */
+#define NPC_LT_LC_IP_MATCH_MSK ((~(NPC_LT_LC_IP ^ NPC_LT_LC_IP_OPT)) & 0xf)
+
static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
{
int idx, nr_field, key_off, field_marker, keyoff_marker;
@@ -3933,7 +3938,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
field->hdr_offset = 9; /* offset */
field->bytesm1 = 0; /* 1 byte */
field->ltype_match = NPC_LT_LC_IP;
- field->ltype_mask = 0xF;
+ field->ltype_mask = NPC_LT_LC_IP_MATCH_MSK;
break;
case NIX_FLOW_KEY_TYPE_IPV4:
case NIX_FLOW_KEY_TYPE_INNR_IPV4:
@@ -3960,8 +3965,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
field->bytesm1 = 3; /* DIP, 4 bytes */
}
}
-
- field->ltype_mask = 0xF; /* Match only IPv4 */
+ field->ltype_mask = NPC_LT_LC_IP_MATCH_MSK;
keyoff_marker = false;
break;
case NIX_FLOW_KEY_TYPE_IPV6:
@@ -3990,7 +3994,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
field->bytesm1 = 15; /* DIP,16 bytes */
}
}
- field->ltype_mask = 0xF; /* Match only IPv6 */
+ field->ltype_mask = NPC_LT_LC_IP6_MATCH_MSK;
break;
case NIX_FLOW_KEY_TYPE_TCP:
case NIX_FLOW_KEY_TYPE_UDP:
diff --git a/drivers/net/ethernet/mediatek/mtk_star_emac.c b/drivers/net/ethernet/mediatek/mtk_star_emac.c
index 31aebeb2e285..25989c79c92e 100644
--- a/drivers/net/ethernet/mediatek/mtk_star_emac.c
+++ b/drivers/net/ethernet/mediatek/mtk_star_emac.c
@@ -1524,6 +1524,7 @@ static int mtk_star_probe(struct platform_device *pdev)
{
struct device_node *of_node;
struct mtk_star_priv *priv;
+ struct phy_device *phydev;
struct net_device *ndev;
struct device *dev;
void __iomem *base;
@@ -1649,6 +1650,12 @@ static int mtk_star_probe(struct platform_device *pdev)
netif_napi_add(ndev, &priv->rx_napi, mtk_star_rx_poll);
netif_napi_add_tx(ndev, &priv->tx_napi, mtk_star_tx_poll);
+ phydev = of_phy_find_device(priv->phy_node);
+ if (phydev) {
+ phydev->mac_managed_pm = true;
+ put_device(&phydev->mdio.dev);
+ }
+
return devm_register_netdev(dev, ndev);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
index c54fd01ea635..3d274599015b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
@@ -989,7 +989,12 @@ static void mlx5e_xfrm_update_stats(struct xfrm_state *x)
struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
struct mlx5e_ipsec_rule *ipsec_rule = &sa_entry->ipsec_rule;
struct net *net = dev_net(x->xso.dev);
+ u64 trailer_packets = 0, trailer_bytes = 0;
+ u64 replay_packets = 0, replay_bytes = 0;
+ u64 auth_packets = 0, auth_bytes = 0;
+ u64 success_packets, success_bytes;
u64 packets, bytes, lastuse;
+ size_t headers;
lockdep_assert(lockdep_is_held(&x->lock) ||
lockdep_is_held(&dev_net(x->xso.real_dev)->xfrm.xfrm_cfg_mutex) ||
@@ -999,26 +1004,43 @@ static void mlx5e_xfrm_update_stats(struct xfrm_state *x)
return;
if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_IN) {
- mlx5_fc_query_cached(ipsec_rule->auth.fc, &bytes, &packets, &lastuse);
- x->stats.integrity_failed += packets;
- XFRM_ADD_STATS(net, LINUX_MIB_XFRMINSTATEPROTOERROR, packets);
-
- mlx5_fc_query_cached(ipsec_rule->trailer.fc, &bytes, &packets, &lastuse);
- XFRM_ADD_STATS(net, LINUX_MIB_XFRMINHDRERROR, packets);
+ mlx5_fc_query_cached(ipsec_rule->auth.fc, &auth_bytes,
+ &auth_packets, &lastuse);
+ x->stats.integrity_failed += auth_packets;
+ XFRM_ADD_STATS(net, LINUX_MIB_XFRMINSTATEPROTOERROR, auth_packets);
+
+ mlx5_fc_query_cached(ipsec_rule->trailer.fc, &trailer_bytes,
+ &trailer_packets, &lastuse);
+ XFRM_ADD_STATS(net, LINUX_MIB_XFRMINHDRERROR, trailer_packets);
}
if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET)
return;
- mlx5_fc_query_cached(ipsec_rule->fc, &bytes, &packets, &lastuse);
- x->curlft.packets += packets;
- x->curlft.bytes += bytes;
-
if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_IN) {
- mlx5_fc_query_cached(ipsec_rule->replay.fc, &bytes, &packets, &lastuse);
- x->stats.replay += packets;
- XFRM_ADD_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR, packets);
+ mlx5_fc_query_cached(ipsec_rule->replay.fc, &replay_bytes,
+ &replay_packets, &lastuse);
+ x->stats.replay += replay_packets;
+ XFRM_ADD_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR, replay_packets);
}
+
+ mlx5_fc_query_cached(ipsec_rule->fc, &bytes, &packets, &lastuse);
+ success_packets = packets - auth_packets - trailer_packets - replay_packets;
+ x->curlft.packets += success_packets;
+ /* NIC counts all bytes passed through flow steering and doesn't have
+ * an ability to count payload data size which is needed for SA.
+ *
+ * To overcome HW limitestion, let's approximate the payload size
+ * by removing always available headers.
+ */
+ headers = sizeof(struct ethhdr);
+ if (sa_entry->attrs.family == AF_INET)
+ headers += sizeof(struct iphdr);
+ else
+ headers += sizeof(struct ipv6hdr);
+
+ success_bytes = bytes - auth_bytes - trailer_bytes - replay_bytes;
+ x->curlft.bytes += success_bytes - headers * success_packets;
}
static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index a605eae56685..eedbcba22689 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -5868,6 +5868,11 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv)
kfree(priv->htb_qos_sq_stats[i]);
kvfree(priv->htb_qos_sq_stats);
+ if (priv->mqprio_rl) {
+ mlx5e_mqprio_rl_cleanup(priv->mqprio_rl);
+ mlx5e_mqprio_rl_free(priv->mqprio_rl);
+ }
+
memset(priv, 0, sizeof(*priv));
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index 5693986ae656..ac1565c0c8af 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -1197,9 +1197,7 @@ static int get_num_eqs(struct mlx5_core_dev *dev)
if (!mlx5_core_is_eth_enabled(dev) && mlx5_eth_supported(dev))
return 1;
- max_dev_eqs = MLX5_CAP_GEN(dev, max_num_eqs) ?
- MLX5_CAP_GEN(dev, max_num_eqs) :
- 1 << MLX5_CAP_GEN(dev, log_max_eq);
+ max_dev_eqs = mlx5_max_eq_cap_get(dev);
num_eqs = min_t(int, mlx5_irq_table_get_num_comp(eq_table->irq_table),
max_dev_eqs - MLX5_MAX_ASYNC_EQS);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c
index 50d2ea323979..a436ce895e45 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c
@@ -6,6 +6,9 @@
#include "helper.h"
#include "ofld.h"
+static int
+acl_ingress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
+
static bool
esw_acl_ingress_prio_tag_enabled(struct mlx5_eswitch *esw,
const struct mlx5_vport *vport)
@@ -123,18 +126,31 @@ static int esw_acl_ingress_src_port_drop_create(struct mlx5_eswitch *esw,
{
struct mlx5_flow_act flow_act = {};
struct mlx5_flow_handle *flow_rule;
+ bool created = false;
int err = 0;
+ if (!vport->ingress.acl) {
+ err = acl_ingress_ofld_setup(esw, vport);
+ if (err)
+ return err;
+ created = true;
+ }
+
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
flow_act.fg = vport->ingress.offloads.drop_grp;
flow_rule = mlx5_add_flow_rules(vport->ingress.acl, NULL, &flow_act, NULL, 0);
if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
- goto out;
+ goto err_out;
}
vport->ingress.offloads.drop_rule = flow_rule;
-out:
+
+ return 0;
+err_out:
+ /* Only destroy ingress acl created in this function. */
+ if (created)
+ esw_acl_ingress_ofld_cleanup(esw, vport);
return err;
}
@@ -299,16 +315,12 @@ static void esw_acl_ingress_ofld_groups_destroy(struct mlx5_vport *vport)
}
}
-int esw_acl_ingress_ofld_setup(struct mlx5_eswitch *esw,
- struct mlx5_vport *vport)
+static int
+acl_ingress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
{
int num_ftes = 0;
int err;
- if (!mlx5_eswitch_vport_match_metadata_enabled(esw) &&
- !esw_acl_ingress_prio_tag_enabled(esw, vport))
- return 0;
-
esw_acl_ingress_allow_rule_destroy(vport);
if (mlx5_eswitch_vport_match_metadata_enabled(esw))
@@ -347,6 +359,15 @@ group_err:
return err;
}
+int esw_acl_ingress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
+{
+ if (!mlx5_eswitch_vport_match_metadata_enabled(esw) &&
+ !esw_acl_ingress_prio_tag_enabled(esw, vport))
+ return 0;
+
+ return acl_ingress_ofld_setup(esw, vport);
+}
+
void esw_acl_ingress_ofld_cleanup(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 592143d5e1da..72949cb85244 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -4600,20 +4600,26 @@ mlx5_devlink_port_fn_max_io_eqs_get(struct devlink_port *port, u32 *max_io_eqs,
return -EOPNOTSUPP;
}
+ if (!MLX5_CAP_GEN_2(esw->dev, max_num_eqs_24b)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Device doesn't support getting the max number of EQs");
+ return -EOPNOTSUPP;
+ }
+
query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
if (!query_ctx)
return -ENOMEM;
mutex_lock(&esw->state_lock);
err = mlx5_vport_get_other_func_cap(esw->dev, vport_num, query_ctx,
- MLX5_CAP_GENERAL);
+ MLX5_CAP_GENERAL_2);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Failed getting HCA caps");
goto out;
}
hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
- max_eqs = MLX5_GET(cmd_hca_cap, hca_caps, max_num_eqs);
+ max_eqs = MLX5_GET(cmd_hca_cap_2, hca_caps, max_num_eqs_24b);
if (max_eqs < MLX5_ESW_MAX_CTRL_EQS)
*max_io_eqs = 0;
else
@@ -4644,6 +4650,12 @@ mlx5_devlink_port_fn_max_io_eqs_set(struct devlink_port *port, u32 max_io_eqs,
return -EOPNOTSUPP;
}
+ if (!MLX5_CAP_GEN_2(esw->dev, max_num_eqs_24b)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Device doesn't support changing the max number of EQs");
+ return -EOPNOTSUPP;
+ }
+
if (check_add_overflow(max_io_eqs, MLX5_ESW_MAX_CTRL_EQS, &max_eqs)) {
NL_SET_ERR_MSG_MOD(extack, "Supplied value out of range");
return -EINVAL;
@@ -4655,17 +4667,17 @@ mlx5_devlink_port_fn_max_io_eqs_set(struct devlink_port *port, u32 max_io_eqs,
mutex_lock(&esw->state_lock);
err = mlx5_vport_get_other_func_cap(esw->dev, vport_num, query_ctx,
- MLX5_CAP_GENERAL);
+ MLX5_CAP_GENERAL_2);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Failed getting HCA caps");
goto out;
}
hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
- MLX5_SET(cmd_hca_cap, hca_caps, max_num_eqs, max_eqs);
+ MLX5_SET(cmd_hca_cap_2, hca_caps, max_num_eqs_24b, max_eqs);
err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport_num,
- MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE);
+ MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE2);
if (err)
NL_SET_ERR_MSG_MOD(extack, "Failed setting HCA caps");
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index c38342b9f320..a7fd18888b6e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -383,4 +383,14 @@ static inline int mlx5_vport_to_func_id(const struct mlx5_core_dev *dev, u16 vpo
: vport;
}
+static inline int mlx5_max_eq_cap_get(const struct mlx5_core_dev *dev)
+{
+ if (MLX5_CAP_GEN_2(dev, max_num_eqs_24b))
+ return MLX5_CAP_GEN_2(dev, max_num_eqs_24b);
+
+ if (MLX5_CAP_GEN(dev, max_num_eqs))
+ return MLX5_CAP_GEN(dev, max_num_eqs);
+
+ return 1 << MLX5_CAP_GEN(dev, log_max_eq);
+}
#endif /* __MLX5_CORE_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
index fb8787e30d3f..401d39069680 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
@@ -711,9 +711,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_CAP_GEN(dev, max_num_eqs) ?
- MLX5_CAP_GEN(dev, max_num_eqs) :
- 1 << MLX5_CAP_GEN(dev, log_max_eq);
+ int num_eqs = mlx5_max_eq_cap_get(dev);
int total_vec;
int pcif_vec;
int req_vec;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
index 025e0db983fe..b032d5a4b3b8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
@@ -1484,6 +1484,7 @@ err_type_file_file_validate:
vfree(types_info->data);
err_data_alloc:
kfree(types_info);
+ linecards->types_info = NULL;
return err;
}
diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c
index 6453c92f0fa7..7fa1820db9cc 100644
--- a/drivers/net/ethernet/micrel/ks8851_common.c
+++ b/drivers/net/ethernet/micrel/ks8851_common.c
@@ -352,11 +352,11 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
netif_dbg(ks, intr, ks->netdev,
"%s: txspace %d\n", __func__, tx_space);
- spin_lock(&ks->statelock);
+ spin_lock_bh(&ks->statelock);
ks->tx_space = tx_space;
if (netif_queue_stopped(ks->netdev))
netif_wake_queue(ks->netdev);
- spin_unlock(&ks->statelock);
+ spin_unlock_bh(&ks->statelock);
}
if (status & IRQ_SPIBEI) {
@@ -482,6 +482,7 @@ static int ks8851_net_open(struct net_device *dev)
ks8851_wrreg16(ks, KS_IER, ks->rc_ier);
ks->queued_len = 0;
+ ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
netif_start_queue(ks->netdev);
netif_dbg(ks, ifup, ks->netdev, "network device up\n");
@@ -635,14 +636,14 @@ static void ks8851_set_rx_mode(struct net_device *dev)
/* schedule work to do the actual set of the data if needed */
- spin_lock(&ks->statelock);
+ spin_lock_bh(&ks->statelock);
if (memcmp(&rxctrl, &ks->rxctrl, sizeof(rxctrl)) != 0) {
memcpy(&ks->rxctrl, &rxctrl, sizeof(ks->rxctrl));
schedule_work(&ks->rxctrl_work);
}
- spin_unlock(&ks->statelock);
+ spin_unlock_bh(&ks->statelock);
}
static int ks8851_set_mac_address(struct net_device *dev, void *addr)
@@ -1101,7 +1102,6 @@ int ks8851_probe_common(struct net_device *netdev, struct device *dev,
int ret;
ks->netdev = netdev;
- ks->tx_space = 6144;
ks->gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
ret = PTR_ERR_OR_ZERO(ks->gpio);
diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c b/drivers/net/ethernet/micrel/ks8851_spi.c
index 670c1de966db..3062cc0f9199 100644
--- a/drivers/net/ethernet/micrel/ks8851_spi.c
+++ b/drivers/net/ethernet/micrel/ks8851_spi.c
@@ -340,10 +340,10 @@ static void ks8851_tx_work(struct work_struct *work)
tx_space = ks8851_rdreg16_spi(ks, KS_TXMIR);
- spin_lock(&ks->statelock);
+ spin_lock_bh(&ks->statelock);
ks->queued_len -= dequeued_len;
ks->tx_space = tx_space;
- spin_unlock(&ks->statelock);
+ spin_unlock_bh(&ks->statelock);
ks8851_unlock_spi(ks, &flags);
}
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
index dcab638c57fe..24c90d8f5a44 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -871,13 +871,13 @@ static void rswitch_tx_free(struct net_device *ndev)
dma_rmb();
skb = gq->skbs[gq->dirty];
if (skb) {
+ rdev->ndev->stats.tx_packets++;
+ rdev->ndev->stats.tx_bytes += skb->len;
dma_unmap_single(ndev->dev.parent,
gq->unmap_addrs[gq->dirty],
skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(gq->skbs[gq->dirty]);
gq->skbs[gq->dirty] = NULL;
- rdev->ndev->stats.tx_packets++;
- rdev->ndev->stats.tx_bytes += skb->len;
}
desc->desc.die_dt = DT_EEMPTY;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 60283543ffc8..e73fa34237d3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -390,10 +390,11 @@ static int intel_crosststamp(ktime_t *device,
*device = ns_to_ktime(ptp_time);
read_unlock_irqrestore(&priv->ptp_lock, flags);
get_arttime(priv->mii, intel_priv->mdio_adhoc_addr, &art_time);
- *system = convert_art_to_tsc(art_time);
+ system->cycles = art_time;
}
system->cycles *= intel_priv->crossts_adj;
+ system->cs_id = CSID_X86_ART;
priv->plat->flags &= ~STMMAC_FLAG_INT_SNAPSHOT_EN;
return 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 65d7370b47d5..466c4002f00d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -272,7 +272,7 @@ static const struct ethqos_emac_por emac_v4_0_0_por[] = {
static const struct ethqos_emac_driver_data emac_v4_0_0_data = {
.por = emac_v4_0_0_por,
- .num_por = ARRAY_SIZE(emac_v3_0_0_por),
+ .num_por = ARRAY_SIZE(emac_v4_0_0_por),
.rgmii_config_loopback_en = false,
.has_emac_ge_3 = true,
.link_clk_name = "phyaux",
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index b3afc7cb7d72..c58782c41417 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7662,9 +7662,10 @@ int stmmac_dvr_probe(struct device *device,
#ifdef STMMAC_VLAN_TAG_USED
/* Both mac100 and gmac support receive VLAN tag detection */
ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX;
- ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
- priv->hw->hw_vlan_en = true;
-
+ if (priv->plat->has_gmac4) {
+ ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+ priv->hw->hw_vlan_en = true;
+ }
if (priv->dma_cap.vlhash) {
ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
ndev->features |= NETIF_F_HW_VLAN_STAG_FILTER;
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 7c4b6881a93f..d1b682ce9c6d 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -1959,6 +1959,7 @@ int wx_sw_init(struct wx *wx)
}
bitmap_zero(wx->state, WX_STATE_NBITS);
+ wx->misc_irq_domain = false;
return 0;
}
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 68bde91b67a0..81bedc8ee8d4 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -1686,6 +1686,7 @@ static int wx_set_interrupt_capability(struct wx *wx)
}
pdev->irq = pci_irq_vector(pdev, 0);
+ wx->num_q_vectors = 1;
return 0;
}
@@ -1996,7 +1997,8 @@ void wx_free_irq(struct wx *wx)
int vector;
if (!(pdev->msix_enabled)) {
- free_irq(pdev->irq, wx);
+ if (!wx->misc_irq_domain)
+ free_irq(pdev->irq, wx);
return;
}
@@ -2011,7 +2013,7 @@ void wx_free_irq(struct wx *wx)
free_irq(entry->vector, q_vector);
}
- if (wx->mac.type == wx_mac_em)
+ if (!wx->misc_irq_domain)
free_irq(wx->msix_entry->vector, wx);
}
EXPORT_SYMBOL(wx_free_irq);
@@ -2026,6 +2028,9 @@ int wx_setup_isb_resources(struct wx *wx)
{
struct pci_dev *pdev = wx->pdev;
+ if (wx->isb_mem)
+ return 0;
+
wx->isb_mem = dma_alloc_coherent(&pdev->dev,
sizeof(u32) * 4,
&wx->isb_dma,
@@ -2385,7 +2390,6 @@ static void wx_free_all_tx_resources(struct wx *wx)
void wx_free_resources(struct wx *wx)
{
- wx_free_isb_resources(wx);
wx_free_all_rx_resources(wx);
wx_free_all_tx_resources(wx);
}
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 5aaf7b1fa2db..0df7f5712b6f 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1058,6 +1058,7 @@ struct wx {
dma_addr_t isb_dma;
u32 *isb_mem;
u32 isb_tag[WX_ISB_MAX];
+ bool misc_irq_domain;
#define WX_MAX_RETA_ENTRIES 128
#define WX_RSS_INDIR_TBL_MAX 64
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index e894e01d030d..af30ca0312b8 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -387,6 +387,7 @@ err_dis_phy:
err_free_irq:
wx_free_irq(wx);
err_free_resources:
+ wx_free_isb_resources(wx);
wx_free_resources(wx);
return err;
}
@@ -408,6 +409,7 @@ static int ngbe_close(struct net_device *netdev)
ngbe_down(wx);
wx_free_irq(wx);
+ wx_free_isb_resources(wx);
wx_free_resources(wx);
phylink_disconnect_phy(wx->phylink);
wx_control_hw(wx, false);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
index b3e3605d1edb..a4cf682dca65 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
@@ -27,57 +27,19 @@ void txgbe_irq_enable(struct wx *wx, bool queues)
}
/**
- * txgbe_intr - msi/legacy mode Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- **/
-static irqreturn_t txgbe_intr(int __always_unused irq, void *data)
-{
- struct wx_q_vector *q_vector;
- struct wx *wx = data;
- struct pci_dev *pdev;
- u32 eicr;
-
- q_vector = wx->q_vector[0];
- pdev = wx->pdev;
-
- eicr = wx_misc_isb(wx, WX_ISB_VEC0);
- if (!eicr) {
- /* shared interrupt alert!
- * the interrupt that we masked before the ICR read.
- */
- if (netif_running(wx->netdev))
- txgbe_irq_enable(wx, true);
- return IRQ_NONE; /* Not our interrupt */
- }
- wx->isb_mem[WX_ISB_VEC0] = 0;
- if (!(pdev->msi_enabled))
- wr32(wx, WX_PX_INTA, 1);
-
- wx->isb_mem[WX_ISB_MISC] = 0;
- /* would disable interrupts here but it is auto disabled */
- napi_schedule_irqoff(&q_vector->napi);
-
- /* re-enable link(maybe) and non-queue interrupts, no flush.
- * txgbe_poll will re-enable the queue interrupts
- */
- if (netif_running(wx->netdev))
- txgbe_irq_enable(wx, false);
-
- return IRQ_HANDLED;
-}
-
-/**
- * txgbe_request_msix_irqs - Initialize MSI-X interrupts
+ * txgbe_request_queue_irqs - Initialize MSI-X queue interrupts
* @wx: board private structure
*
- * Allocate MSI-X vectors and request interrupts from the kernel.
+ * Allocate MSI-X queue vectors and request interrupts from the kernel.
**/
-static int txgbe_request_msix_irqs(struct wx *wx)
+int txgbe_request_queue_irqs(struct wx *wx)
{
struct net_device *netdev = wx->netdev;
int vector, err;
+ if (!wx->pdev->msix_enabled)
+ return 0;
+
for (vector = 0; vector < wx->num_q_vectors; vector++) {
struct wx_q_vector *q_vector = wx->q_vector[vector];
struct msix_entry *entry = &wx->msix_q_entries[vector];
@@ -110,34 +72,6 @@ free_queue_irqs:
return err;
}
-/**
- * txgbe_request_irq - initialize interrupts
- * @wx: board private structure
- *
- * Attempt to configure interrupts using the best available
- * capabilities of the hardware and kernel.
- **/
-int txgbe_request_irq(struct wx *wx)
-{
- struct net_device *netdev = wx->netdev;
- struct pci_dev *pdev = wx->pdev;
- int err;
-
- if (pdev->msix_enabled)
- err = txgbe_request_msix_irqs(wx);
- else if (pdev->msi_enabled)
- err = request_irq(wx->pdev->irq, &txgbe_intr, 0,
- netdev->name, wx);
- else
- err = request_irq(wx->pdev->irq, &txgbe_intr, IRQF_SHARED,
- netdev->name, wx);
-
- if (err)
- wx_err(wx, "request_irq failed, Error %d\n", err);
-
- return err;
-}
-
static int txgbe_request_gpio_irq(struct txgbe *txgbe)
{
txgbe->gpio_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_GPIO);
@@ -178,6 +112,36 @@ static const struct irq_domain_ops txgbe_misc_irq_domain_ops = {
static irqreturn_t txgbe_misc_irq_handle(int irq, void *data)
{
+ struct wx_q_vector *q_vector;
+ struct txgbe *txgbe = data;
+ struct wx *wx = txgbe->wx;
+ u32 eicr;
+
+ if (wx->pdev->msix_enabled)
+ return IRQ_WAKE_THREAD;
+
+ eicr = wx_misc_isb(wx, WX_ISB_VEC0);
+ if (!eicr) {
+ /* shared interrupt alert!
+ * the interrupt that we masked before the ICR read.
+ */
+ if (netif_running(wx->netdev))
+ txgbe_irq_enable(wx, true);
+ return IRQ_NONE; /* Not our interrupt */
+ }
+ wx->isb_mem[WX_ISB_VEC0] = 0;
+ if (!(wx->pdev->msi_enabled))
+ wr32(wx, WX_PX_INTA, 1);
+
+ /* would disable interrupts here but it is auto disabled */
+ q_vector = wx->q_vector[0];
+ napi_schedule_irqoff(&q_vector->napi);
+
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t txgbe_misc_irq_thread_fn(int irq, void *data)
+{
struct txgbe *txgbe = data;
struct wx *wx = txgbe->wx;
unsigned int nhandled = 0;
@@ -223,6 +187,7 @@ void txgbe_free_misc_irq(struct txgbe *txgbe)
int txgbe_setup_misc_irq(struct txgbe *txgbe)
{
+ unsigned long flags = IRQF_ONESHOT;
struct wx *wx = txgbe->wx;
int hwirq, err;
@@ -236,14 +201,17 @@ int txgbe_setup_misc_irq(struct txgbe *txgbe)
irq_create_mapping(txgbe->misc.domain, hwirq);
txgbe->misc.chip = txgbe_irq_chip;
- if (wx->pdev->msix_enabled)
+ if (wx->pdev->msix_enabled) {
txgbe->misc.irq = wx->msix_entry->vector;
- else
+ } else {
txgbe->misc.irq = wx->pdev->irq;
+ if (!wx->pdev->msi_enabled)
+ flags |= IRQF_SHARED;
+ }
- err = request_threaded_irq(txgbe->misc.irq, NULL,
- txgbe_misc_irq_handle,
- IRQF_ONESHOT,
+ err = request_threaded_irq(txgbe->misc.irq, txgbe_misc_irq_handle,
+ txgbe_misc_irq_thread_fn,
+ flags,
wx->netdev->name, txgbe);
if (err)
goto del_misc_irq;
@@ -256,6 +224,8 @@ int txgbe_setup_misc_irq(struct txgbe *txgbe)
if (err)
goto free_gpio_irq;
+ wx->misc_irq_domain = true;
+
return 0;
free_gpio_irq:
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.h
index b77945e7a0f2..e6285b94625e 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.h
@@ -2,6 +2,6 @@
/* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */
void txgbe_irq_enable(struct wx *wx, bool queues);
-int txgbe_request_irq(struct wx *wx);
+int txgbe_request_queue_irqs(struct wx *wx);
void txgbe_free_misc_irq(struct txgbe *txgbe);
int txgbe_setup_misc_irq(struct txgbe *txgbe);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 8c7a74981b90..ca74d9422065 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -294,9 +294,9 @@ static int txgbe_open(struct net_device *netdev)
wx_configure(wx);
- err = txgbe_request_irq(wx);
+ err = txgbe_request_queue_irqs(wx);
if (err)
- goto err_free_isb;
+ goto err_free_resources;
/* Notify the stack of the actual queue counts. */
err = netif_set_real_num_tx_queues(netdev, wx->num_tx_queues);
@@ -313,8 +313,8 @@ static int txgbe_open(struct net_device *netdev)
err_free_irq:
wx_free_irq(wx);
-err_free_isb:
- wx_free_isb_resources(wx);
+err_free_resources:
+ wx_free_resources(wx);
err_reset:
txgbe_reset(wx);
@@ -729,6 +729,7 @@ static void txgbe_remove(struct pci_dev *pdev)
txgbe_remove_phy(txgbe);
txgbe_free_misc_irq(txgbe);
+ wx_free_isb_resources(wx);
pci_release_selected_regions(pdev,
pci_select_bars(pdev, IORESOURCE_MEM));
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index ffe7f463e16e..ef6df0e37bea 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -119,7 +119,7 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
skb->protocol = eth_type_trans(skb, ndev);
skb->ip_summed = CHECKSUM_NONE;
- if (__netif_rx(skb) == NET_RX_DROP) {
+ if (netif_rx(skb) == NET_RX_DROP) {
ndev->stats.rx_errors++;
ndev->stats.rx_dropped++;
} else {
diff --git a/drivers/net/phy/aquantia/aquantia.h b/drivers/net/phy/aquantia/aquantia.h
index 1c19ae74ad2b..4830b25e6c7d 100644
--- a/drivers/net/phy/aquantia/aquantia.h
+++ b/drivers/net/phy/aquantia/aquantia.h
@@ -6,6 +6,9 @@
* Author: Heiner Kallweit <[email protected]>
*/
+#ifndef AQUANTIA_H
+#define AQUANTIA_H
+
#include <linux/device.h>
#include <linux/phy.h>
@@ -120,3 +123,5 @@ static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; }
#endif
int aqr_firmware_load(struct phy_device *phydev);
+
+#endif /* AQUANTIA_H */
diff --git a/drivers/net/phy/microchip_t1.c b/drivers/net/phy/microchip_t1.c
index a838b61cd844..a35528497a57 100644
--- a/drivers/net/phy/microchip_t1.c
+++ b/drivers/net/phy/microchip_t1.c
@@ -748,7 +748,7 @@ static int lan87xx_cable_test_report(struct phy_device *phydev)
ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
lan87xx_cable_test_report_trans(detect));
- return 0;
+ return phy_init_hw(phydev);
}
static int lan87xx_cable_test_get_status(struct phy_device *phydev,
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 0a65b6d690fe..eb9acfcaeb09 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -70,6 +70,7 @@
#define MPHDRLEN_SSN 4 /* ditto with short sequence numbers */
#define PPP_PROTO_LEN 2
+#define PPP_LCP_HDRLEN 4
/*
* An instance of /dev/ppp can be associated with either a ppp
@@ -493,6 +494,15 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
return ret;
}
+static bool ppp_check_packet(struct sk_buff *skb, size_t count)
+{
+ /* LCP packets must include LCP header which 4 bytes long:
+ * 1-byte code, 1-byte identifier, and 2-byte length.
+ */
+ return get_unaligned_be16(skb->data) != PPP_LCP ||
+ count >= PPP_PROTO_LEN + PPP_LCP_HDRLEN;
+}
+
static ssize_t ppp_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
@@ -515,6 +525,11 @@ static ssize_t ppp_write(struct file *file, const char __user *buf,
kfree_skb(skb);
goto out;
}
+ ret = -EINVAL;
+ if (unlikely(!ppp_check_packet(skb, count))) {
+ kfree_skb(skb);
+ goto out;
+ }
switch (pf->kind) {
case INTERFACE:
diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c
index 0ba714ca5185..4b8528206cc8 100644
--- a/drivers/net/wireguard/allowedips.c
+++ b/drivers/net/wireguard/allowedips.c
@@ -15,8 +15,8 @@ static void swap_endian(u8 *dst, const u8 *src, u8 bits)
if (bits == 32) {
*(u32 *)dst = be32_to_cpu(*(const __be32 *)src);
} else if (bits == 128) {
- ((u64 *)dst)[0] = be64_to_cpu(((const __be64 *)src)[0]);
- ((u64 *)dst)[1] = be64_to_cpu(((const __be64 *)src)[1]);
+ ((u64 *)dst)[0] = get_unaligned_be64(src);
+ ((u64 *)dst)[1] = get_unaligned_be64(src + 8);
}
}
diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h
index 1ea4f874e367..7eb76724b3ed 100644
--- a/drivers/net/wireguard/queueing.h
+++ b/drivers/net/wireguard/queueing.h
@@ -124,10 +124,10 @@ static inline int wg_cpumask_choose_online(int *stored_cpu, unsigned int id)
*/
static inline int wg_cpumask_next_online(int *last_cpu)
{
- int cpu = cpumask_next(*last_cpu, cpu_online_mask);
+ int cpu = cpumask_next(READ_ONCE(*last_cpu), cpu_online_mask);
if (cpu >= nr_cpu_ids)
cpu = cpumask_first(cpu_online_mask);
- *last_cpu = cpu;
+ WRITE_ONCE(*last_cpu, cpu);
return cpu;
}
diff --git a/drivers/net/wireguard/send.c b/drivers/net/wireguard/send.c
index 0d48e0f4a1ba..26e09c30d596 100644
--- a/drivers/net/wireguard/send.c
+++ b/drivers/net/wireguard/send.c
@@ -222,7 +222,7 @@ void wg_packet_send_keepalive(struct wg_peer *peer)
{
struct sk_buff *skb;
- if (skb_queue_empty(&peer->staged_packet_queue)) {
+ if (skb_queue_empty_lockless(&peer->staged_packet_queue)) {
skb = alloc_skb(DATA_PACKET_HEAD_ROOM + MESSAGE_MINIMUM_LENGTH,
GFP_ATOMIC);
if (unlikely(!skb))
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 18ce060df9b5..dac6155ae1bd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -654,7 +654,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->features |= NL80211_FEATURE_WFA_TPC_IE_IN_PROBES;
if (iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_KEK_KCK_MATERIAL,
- IWL_FW_CMD_VER_UNKNOWN) == 3)
+ IWL_FW_CMD_VER_UNKNOWN) >= 3)
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK;
if (fw_has_api(&mvm->fw->ucode_capa,
@@ -1656,7 +1656,8 @@ static void iwl_mvm_prevent_esr_done_wk(struct wiphy *wiphy,
struct iwl_mvm_vif *mvmvif =
container_of(wk, struct iwl_mvm_vif, prevent_esr_done_wk.work);
struct iwl_mvm *mvm = mvmvif->mvm;
- struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(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_PREVENTION);
@@ -1682,7 +1683,8 @@ static void iwl_mvm_unblock_esr_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
struct iwl_mvm_vif *mvmvif =
container_of(wk, struct iwl_mvm_vif, unblock_esr_tpt_wk);
struct iwl_mvm *mvm = mvmvif->mvm;
- struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(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_TPT);
@@ -6410,11 +6412,9 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
if (sync) {
lockdep_assert_held(&mvm->mutex);
ret = wait_event_timeout(mvm->rx_sync_waitq,
- READ_ONCE(mvm->queue_sync_state) == 0 ||
- iwl_mvm_is_radio_hw_killed(mvm),
+ READ_ONCE(mvm->queue_sync_state) == 0,
SYNC_RX_QUEUE_TIMEOUT);
- WARN_ONCE(!ret && !iwl_mvm_is_radio_hw_killed(mvm),
- "queue sync: failed to sync, state is 0x%lx, cookie %d\n",
+ WARN_ONCE(!ret, "queue sync: failed to sync, state is 0x%lx, cookie %d\n",
mvm->queue_sync_state,
mvm->queue_sync_cookie);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 53283d052e18..d343432474db 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -153,7 +153,7 @@ static void iwl_mvm_rx_esr_mode_notif(struct iwl_mvm *mvm,
struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm);
/* FW recommendations is only for entering EMLSR */
- if (!vif || iwl_mvm_vif_from_mac80211(vif)->esr_active)
+ if (IS_ERR_OR_NULL(vif) || iwl_mvm_vif_from_mac80211(vif)->esr_active)
return;
if (le32_to_cpu(notif->action) == ESR_RECOMMEND_ENTER)
@@ -1912,12 +1912,10 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
bool rfkill_safe_init_done = READ_ONCE(mvm->rfkill_safe_init_done);
bool unified = iwl_mvm_has_unified_ucode(mvm);
- if (state) {
+ if (state)
set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
- wake_up(&mvm->rx_sync_waitq);
- } else {
+ else
clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
- }
iwl_mvm_set_rfkill_state(mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 4fa8066a89b6..6e933907f985 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -557,12 +557,10 @@ struct iwl_mvm_stat_data_all_macs {
};
static void iwl_mvm_update_link_sig(struct ieee80211_vif *vif, int sig,
- struct iwl_mvm_vif_link_info *link_info)
+ 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 ieee80211_bss_conf *bss_conf =
- iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, link_info->fw_link_id,
- false);
int thold = bss_conf->cqm_rssi_thold;
int hyst = bss_conf->cqm_rssi_hyst;
int last_event;
@@ -670,7 +668,7 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
mvmvif->deflink.beacon_stats.num_beacons;
/* This is used in pre-MLO API so use deflink */
- iwl_mvm_update_link_sig(vif, sig, &mvmvif->deflink);
+ iwl_mvm_update_link_sig(vif, sig, &mvmvif->deflink, &vif->bss_conf);
}
static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
@@ -705,7 +703,7 @@ static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
sig = -le32_to_cpu(mac_stats->beacon_filter_average_energy);
/* This is used in pre-MLO API so use deflink */
- iwl_mvm_update_link_sig(vif, sig, &mvmvif->deflink);
+ iwl_mvm_update_link_sig(vif, sig, &mvmvif->deflink, &vif->bss_conf);
}
static inline void
@@ -921,7 +919,8 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
mvmvif->link[link_id]->beacon_stats.num_beacons;
sig = -le32_to_cpu(link_stats->beacon_filter_average_energy);
- iwl_mvm_update_link_sig(bss_conf->vif, sig, link_info);
+ iwl_mvm_update_link_sig(bss_conf->vif, sig, link_info,
+ bss_conf);
if (WARN_ONCE(mvmvif->id >= MAC_INDEX_AUX,
"invalid mvmvif id: %d", mvmvif->id))
@@ -967,7 +966,7 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
- if (!bss_vif)
+ if (IS_ERR_OR_NULL(bss_vif))
return;
mvmvif = iwl_mvm_vif_from_mac80211(bss_vif);
diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c
index f1085ccb7eed..7719e4f3e2a2 100644
--- a/drivers/net/wireless/microchip/wilc1000/hif.c
+++ b/drivers/net/wireless/microchip/wilc1000/hif.c
@@ -382,7 +382,8 @@ wilc_parse_join_bss_param(struct cfg80211_bss *bss,
struct ieee80211_p2p_noa_attr noa_attr;
const struct cfg80211_bss_ies *ies;
struct wilc_join_bss_param *param;
- u8 rates_len = 0, ies_len;
+ u8 rates_len = 0;
+ int ies_len;
int ret;
param = kzalloc(sizeof(*param), GFP_KERNEL);
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index a939fd89a7f5..92fc2d456c2c 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -1566,13 +1566,6 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates,
wlvif->band));
- if (!cmd->supported_rates) {
- wl1271_debug(DEBUG_CMD,
- "peer has no supported rates yet, configuring basic rates: 0x%x",
- wlvif->basic_rate_set);
- cmd->supported_rates = cpu_to_le32(wlvif->basic_rate_set);
- }
-
wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x",
cmd->supported_rates, sta->uapsd_queues);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index ef12169f8044..492cd7aef44f 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5139,19 +5139,23 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
/* Add station (AP mode) */
if (is_ap &&
- old_state == IEEE80211_STA_NOTEXIST &&
- new_state == IEEE80211_STA_NONE) {
+ old_state == IEEE80211_STA_AUTH &&
+ new_state == IEEE80211_STA_ASSOC) {
ret = wl12xx_sta_add(wl, wlvif, sta);
if (ret)
return ret;
+ wl_sta->fw_added = true;
+
wlcore_update_inconn_sta(wl, wlvif, wl_sta, true);
}
/* Remove station (AP mode) */
if (is_ap &&
- old_state == IEEE80211_STA_NONE &&
- new_state == IEEE80211_STA_NOTEXIST) {
+ old_state == IEEE80211_STA_ASSOC &&
+ new_state == IEEE80211_STA_AUTH) {
+ wl_sta->fw_added = false;
+
/* must not fail */
wl12xx_sta_remove(wl, wlvif, sta);
@@ -5165,11 +5169,6 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
if (ret < 0)
return ret;
- /* reconfigure rates */
- ret = wl12xx_cmd_add_peer(wl, wlvif, sta, wl_sta->hlid);
- if (ret < 0)
- return ret;
-
ret = wl1271_acx_set_ht_capabilities(wl, &sta->deflink.ht_cap,
true,
wl_sta->hlid);
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 7bd3ce2f0804..464587d16ab2 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -140,11 +140,8 @@ EXPORT_SYMBOL(wl12xx_is_dummy_packet);
static u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct sk_buff *skb, struct ieee80211_sta *sta)
{
- if (sta) {
- struct wl1271_station *wl_sta;
-
- wl_sta = (struct wl1271_station *)sta->drv_priv;
- return wl_sta->hlid;
+ if (sta && wl1271_station(sta)->fw_added) {
+ return wl1271_station(sta)->hlid;
} else {
struct ieee80211_hdr *hdr;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index eefae3f867b9..817a8a61cac6 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -324,6 +324,7 @@ struct wl12xx_rx_filter {
struct wl1271_station {
u8 hlid;
+ bool fw_added;
bool in_connection;
/*
@@ -335,6 +336,11 @@ struct wl1271_station {
u64 total_freed_pkts;
};
+static inline struct wl1271_station *wl1271_station(struct ieee80211_sta *sta)
+{
+ return (struct wl1271_station *)sta->drv_priv;
+}
+
struct wl12xx_vif {
struct wl1271 *wl;
struct list_head list;
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 1e5aedaf8c7b..e79c06d65bb7 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1501,9 +1501,15 @@ static int btt_blk_init(struct btt *btt)
.logical_block_size = btt->sector_size,
.max_hw_sectors = UINT_MAX,
.max_integrity_segments = 1,
+ .features = BLK_FEAT_SYNCHRONOUS,
};
int rc;
+ if (btt_meta_size(btt) && IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) {
+ lim.integrity.tuple_size = btt_meta_size(btt);
+ lim.integrity.tag_size = btt_meta_size(btt);
+ }
+
btt->btt_disk = blk_alloc_disk(&lim, NUMA_NO_NODE);
if (IS_ERR(btt->btt_disk))
return PTR_ERR(btt->btt_disk);
@@ -1513,17 +1519,6 @@ static int btt_blk_init(struct btt *btt)
btt->btt_disk->fops = &btt_fops;
btt->btt_disk->private_data = btt;
- blk_queue_flag_set(QUEUE_FLAG_NONROT, btt->btt_disk->queue);
- blk_queue_flag_set(QUEUE_FLAG_SYNCHRONOUS, btt->btt_disk->queue);
-
- if (btt_meta_size(btt) && IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) {
- struct blk_integrity bi = {
- .tuple_size = btt_meta_size(btt),
- .tag_size = btt_meta_size(btt),
- };
- blk_integrity_register(btt->btt_disk, &bi);
- }
-
set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9);
rc = device_add_disk(&btt->nd_btt->dev, btt->btt_disk, NULL);
if (rc)
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 598fe2e89bda..1dd74c969d5a 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -455,6 +455,8 @@ static int pmem_attach_disk(struct device *dev,
.logical_block_size = pmem_sector_size(ndns),
.physical_block_size = PAGE_SIZE,
.max_hw_sectors = UINT_MAX,
+ .features = BLK_FEAT_WRITE_CACHE |
+ BLK_FEAT_SYNCHRONOUS,
};
int nid = dev_to_node(dev), fua;
struct resource *res = &nsio->res;
@@ -463,7 +465,6 @@ static int pmem_attach_disk(struct device *dev,
struct dax_device *dax_dev;
struct nd_pfn_sb *pfn_sb;
struct pmem_device *pmem;
- struct request_queue *q;
struct gendisk *disk;
void *addr;
int rc;
@@ -495,6 +496,10 @@ static int pmem_attach_disk(struct device *dev,
dev_warn(dev, "unable to guarantee persistence of writes\n");
fua = 0;
}
+ if (fua)
+ lim.features |= BLK_FEAT_FUA;
+ if (is_nd_pfn(dev))
+ lim.features |= BLK_FEAT_DAX;
if (!devm_request_mem_region(dev, res->start, resource_size(res),
dev_name(&ndns->dev))) {
@@ -505,7 +510,6 @@ static int pmem_attach_disk(struct device *dev,
disk = blk_alloc_disk(&lim, nid);
if (IS_ERR(disk))
return PTR_ERR(disk);
- q = disk->queue;
pmem->disk = disk;
pmem->pgmap.owner = pmem;
@@ -543,12 +547,6 @@ static int pmem_attach_disk(struct device *dev,
}
pmem->virt_addr = addr;
- blk_queue_write_cache(q, true, fua);
- blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
- blk_queue_flag_set(QUEUE_FLAG_SYNCHRONOUS, q);
- if (pmem->pfn_flags & PFN_MAP)
- blk_queue_flag_set(QUEUE_FLAG_DAX, q);
-
disk->fops = &pmem_fops;
disk->private_data = pmem;
nvdimm_namespace_disk_name(ndns, disk->disk_name);
diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig
index b309c8be720f..a3caef75aa0a 100644
--- a/drivers/nvme/host/Kconfig
+++ b/drivers/nvme/host/Kconfig
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config NVME_CORE
tristate
- select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY
config BLK_DEV_NVME
tristate "NVM Express block device"
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
index 0cfa39361d3b..b1387dc459a3 100644
--- a/drivers/nvme/host/apple.c
+++ b/drivers/nvme/host/apple.c
@@ -1388,7 +1388,7 @@ static void devm_apple_nvme_mempool_destroy(void *data)
mempool_destroy(data);
}
-static int apple_nvme_probe(struct platform_device *pdev)
+static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct apple_nvme *anv;
@@ -1396,7 +1396,7 @@ static int apple_nvme_probe(struct platform_device *pdev)
anv = devm_kzalloc(dev, sizeof(*anv), GFP_KERNEL);
if (!anv)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
anv->dev = get_device(dev);
anv->adminq.is_adminq = true;
@@ -1516,10 +1516,30 @@ static int apple_nvme_probe(struct platform_device *pdev)
goto put_dev;
}
+ return anv;
+put_dev:
+ put_device(anv->dev);
+ return ERR_PTR(ret);
+}
+
+static int apple_nvme_probe(struct platform_device *pdev)
+{
+ struct apple_nvme *anv;
+ int ret;
+
+ anv = apple_nvme_alloc(pdev);
+ if (IS_ERR(anv))
+ return PTR_ERR(anv);
+
+ ret = nvme_add_ctrl(&anv->ctrl);
+ if (ret)
+ goto out_put_ctrl;
+
anv->ctrl.admin_q = blk_mq_alloc_queue(&anv->admin_tagset, NULL, NULL);
if (IS_ERR(anv->ctrl.admin_q)) {
ret = -ENOMEM;
- goto put_dev;
+ anv->ctrl.admin_q = NULL;
+ goto out_uninit_ctrl;
}
nvme_reset_ctrl(&anv->ctrl);
@@ -1527,8 +1547,10 @@ static int apple_nvme_probe(struct platform_device *pdev)
return 0;
-put_dev:
- put_device(anv->dev);
+out_uninit_ctrl:
+ nvme_uninit_ctrl(&anv->ctrl);
+out_put_ctrl:
+ nvme_put_ctrl(&anv->ctrl);
return ret;
}
diff --git a/drivers/nvme/host/constants.c b/drivers/nvme/host/constants.c
index 6f2ebb5fcdb0..2b9e6cfaf2a8 100644
--- a/drivers/nvme/host/constants.c
+++ b/drivers/nvme/host/constants.c
@@ -173,7 +173,7 @@ static const char * const nvme_statuses[] = {
const char *nvme_get_error_status_str(u16 status)
{
- status &= 0x7ff;
+ status &= NVME_SCT_SC_MASK;
if (status < ARRAY_SIZE(nvme_statuses) && nvme_statuses[status])
return nvme_statuses[status];
return "Unknown";
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 782090ce0bc1..19917253ba7b 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -110,7 +110,7 @@ struct workqueue_struct *nvme_delete_wq;
EXPORT_SYMBOL_GPL(nvme_delete_wq);
static LIST_HEAD(nvme_subsystems);
-static DEFINE_MUTEX(nvme_subsystems_lock);
+DEFINE_MUTEX(nvme_subsystems_lock);
static DEFINE_IDA(nvme_instance_ida);
static dev_t nvme_ctrl_base_chr_devt;
@@ -261,7 +261,7 @@ void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl)
static blk_status_t nvme_error_status(u16 status)
{
- switch (status & 0x7ff) {
+ switch (status & NVME_SCT_SC_MASK) {
case NVME_SC_SUCCESS:
return BLK_STS_OK;
case NVME_SC_CAP_EXCEEDED:
@@ -307,7 +307,7 @@ static void nvme_retry_req(struct request *req)
u16 crd;
/* The mask and shift result must be <= 3 */
- crd = (nvme_req(req)->status & NVME_SC_CRD) >> 11;
+ crd = (nvme_req(req)->status & NVME_STATUS_CRD) >> 11;
if (crd)
delay = nvme_req(req)->ctrl->crdt[crd - 1] * 100;
@@ -329,10 +329,10 @@ static void nvme_log_error(struct request *req)
nvme_sect_to_lba(ns->head, blk_rq_pos(req)),
blk_rq_bytes(req) >> ns->head->lba_shift,
nvme_get_error_status_str(nr->status),
- nr->status >> 8 & 7, /* Status Code Type */
- nr->status & 0xff, /* Status Code */
- nr->status & NVME_SC_MORE ? "MORE " : "",
- nr->status & NVME_SC_DNR ? "DNR " : "");
+ NVME_SCT(nr->status), /* Status Code Type */
+ nr->status & NVME_SC_MASK, /* Status Code */
+ nr->status & NVME_STATUS_MORE ? "MORE " : "",
+ nr->status & NVME_STATUS_DNR ? "DNR " : "");
return;
}
@@ -341,10 +341,10 @@ static void nvme_log_error(struct request *req)
nvme_get_admin_opcode_str(nr->cmd->common.opcode),
nr->cmd->common.opcode,
nvme_get_error_status_str(nr->status),
- nr->status >> 8 & 7, /* Status Code Type */
- nr->status & 0xff, /* Status Code */
- nr->status & NVME_SC_MORE ? "MORE " : "",
- nr->status & NVME_SC_DNR ? "DNR " : "");
+ NVME_SCT(nr->status), /* Status Code Type */
+ nr->status & NVME_SC_MASK, /* Status Code */
+ nr->status & NVME_STATUS_MORE ? "MORE " : "",
+ nr->status & NVME_STATUS_DNR ? "DNR " : "");
}
static void nvme_log_err_passthru(struct request *req)
@@ -359,10 +359,10 @@ static void nvme_log_err_passthru(struct request *req)
nvme_get_admin_opcode_str(nr->cmd->common.opcode),
nr->cmd->common.opcode,
nvme_get_error_status_str(nr->status),
- nr->status >> 8 & 7, /* Status Code Type */
- nr->status & 0xff, /* Status Code */
- nr->status & NVME_SC_MORE ? "MORE " : "",
- nr->status & NVME_SC_DNR ? "DNR " : "",
+ NVME_SCT(nr->status), /* Status Code Type */
+ nr->status & NVME_SC_MASK, /* Status Code */
+ nr->status & NVME_STATUS_MORE ? "MORE " : "",
+ nr->status & NVME_STATUS_DNR ? "DNR " : "",
nr->cmd->common.cdw10,
nr->cmd->common.cdw11,
nr->cmd->common.cdw12,
@@ -384,11 +384,11 @@ static inline enum nvme_disposition nvme_decide_disposition(struct request *req)
return COMPLETE;
if (blk_noretry_request(req) ||
- (nvme_req(req)->status & NVME_SC_DNR) ||
+ (nvme_req(req)->status & NVME_STATUS_DNR) ||
nvme_req(req)->retries >= nvme_max_retries)
return COMPLETE;
- if ((nvme_req(req)->status & 0x7ff) == NVME_SC_AUTH_REQUIRED)
+ if ((nvme_req(req)->status & NVME_SCT_SC_MASK) == NVME_SC_AUTH_REQUIRED)
return AUTHENTICATE;
if (req->cmd_flags & REQ_NVME_MPATH) {
@@ -927,6 +927,36 @@ static inline blk_status_t nvme_setup_write_zeroes(struct nvme_ns *ns,
return BLK_STS_OK;
}
+/*
+ * NVMe does not support a dedicated command to issue an atomic write. A write
+ * which does adhere to the device atomic limits will silently be executed
+ * non-atomically. The request issuer should ensure that the write is within
+ * the queue atomic writes limits, but just validate this in case it is not.
+ */
+static bool nvme_valid_atomic_write(struct request *req)
+{
+ struct request_queue *q = req->q;
+ u32 boundary_bytes = queue_atomic_write_boundary_bytes(q);
+
+ if (blk_rq_bytes(req) > queue_atomic_write_unit_max_bytes(q))
+ return false;
+
+ if (boundary_bytes) {
+ u64 mask = boundary_bytes - 1, imask = ~mask;
+ u64 start = blk_rq_pos(req) << SECTOR_SHIFT;
+ u64 end = start + blk_rq_bytes(req) - 1;
+
+ /* If greater then must be crossing a boundary */
+ if (blk_rq_bytes(req) > boundary_bytes)
+ return false;
+
+ if ((start & imask) != (end & imask))
+ return false;
+ }
+
+ return true;
+}
+
static inline blk_status_t nvme_setup_rw(struct nvme_ns *ns,
struct request *req, struct nvme_command *cmnd,
enum nvme_opcode op)
@@ -942,6 +972,9 @@ static inline blk_status_t nvme_setup_rw(struct nvme_ns *ns,
if (req->cmd_flags & REQ_RAHEAD)
dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH;
+ if (req->cmd_flags & REQ_ATOMIC && !nvme_valid_atomic_write(req))
+ return BLK_STS_INVAL;
+
cmnd->rw.opcode = op;
cmnd->rw.flags = 0;
cmnd->rw.nsid = cpu_to_le32(ns->head->ns_id);
@@ -1224,7 +1257,7 @@ EXPORT_SYMBOL_NS_GPL(nvme_passthru_end, NVME_TARGET_PASSTHRU);
/*
* Recommended frequency for KATO commands per NVMe 1.4 section 7.12.1:
- *
+ *
* The host should send Keep Alive commands at half of the Keep Alive Timeout
* accounting for transport roundtrip times [..].
*/
@@ -1724,11 +1757,12 @@ int nvme_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static bool nvme_init_integrity(struct gendisk *disk, struct nvme_ns_head *head)
+static bool nvme_init_integrity(struct gendisk *disk, struct nvme_ns_head *head,
+ struct queue_limits *lim)
{
- struct blk_integrity integrity = { };
+ struct blk_integrity *bi = &lim->integrity;
- blk_integrity_unregister(disk);
+ memset(bi, 0, sizeof(*bi));
if (!head->ms)
return true;
@@ -1745,17 +1779,16 @@ static bool nvme_init_integrity(struct gendisk *disk, struct nvme_ns_head *head)
case NVME_NS_DPS_PI_TYPE3:
switch (head->guard_type) {
case NVME_NVM_NS_16B_GUARD:
- integrity.profile = &t10_pi_type3_crc;
- integrity.tag_size = sizeof(u16) + sizeof(u32);
- integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
+ bi->csum_type = BLK_INTEGRITY_CSUM_CRC;
+ bi->tag_size = sizeof(u16) + sizeof(u32);
+ bi->flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
break;
case NVME_NVM_NS_64B_GUARD:
- integrity.profile = &ext_pi_type3_crc64;
- integrity.tag_size = sizeof(u16) + 6;
- integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
+ bi->csum_type = BLK_INTEGRITY_CSUM_CRC64;
+ bi->tag_size = sizeof(u16) + 6;
+ bi->flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
break;
default:
- integrity.profile = NULL;
break;
}
break;
@@ -1763,28 +1796,27 @@ static bool nvme_init_integrity(struct gendisk *disk, struct nvme_ns_head *head)
case NVME_NS_DPS_PI_TYPE2:
switch (head->guard_type) {
case NVME_NVM_NS_16B_GUARD:
- integrity.profile = &t10_pi_type1_crc;
- integrity.tag_size = sizeof(u16);
- integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
+ bi->csum_type = BLK_INTEGRITY_CSUM_CRC;
+ bi->tag_size = sizeof(u16);
+ bi->flags |= BLK_INTEGRITY_DEVICE_CAPABLE |
+ BLK_INTEGRITY_REF_TAG;
break;
case NVME_NVM_NS_64B_GUARD:
- integrity.profile = &ext_pi_type1_crc64;
- integrity.tag_size = sizeof(u16);
- integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
+ bi->csum_type = BLK_INTEGRITY_CSUM_CRC64;
+ bi->tag_size = sizeof(u16);
+ bi->flags |= BLK_INTEGRITY_DEVICE_CAPABLE |
+ BLK_INTEGRITY_REF_TAG;
break;
default:
- integrity.profile = NULL;
break;
}
break;
default:
- integrity.profile = NULL;
break;
}
- integrity.tuple_size = head->ms;
- integrity.pi_offset = head->pi_offset;
- blk_integrity_register(disk, &integrity);
+ bi->tuple_size = head->ms;
+ bi->pi_offset = head->pi_offset;
return true;
}
@@ -1922,6 +1954,23 @@ static void nvme_configure_metadata(struct nvme_ctrl *ctrl,
}
}
+
+static void nvme_update_atomic_write_disk_info(struct nvme_ns *ns,
+ struct nvme_id_ns *id, struct queue_limits *lim,
+ u32 bs, u32 atomic_bs)
+{
+ unsigned int boundary = 0;
+
+ if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf) {
+ if (le16_to_cpu(id->nabspf))
+ boundary = (le16_to_cpu(id->nabspf) + 1) * bs;
+ }
+ lim->atomic_write_hw_max = atomic_bs;
+ lim->atomic_write_hw_boundary = boundary;
+ lim->atomic_write_hw_unit_min = bs;
+ lim->atomic_write_hw_unit_max = rounddown_pow_of_two(atomic_bs);
+}
+
static u32 nvme_max_drv_segments(struct nvme_ctrl *ctrl)
{
return ctrl->max_hw_sectors / (NVME_CTRL_PAGE_SIZE >> SECTOR_SHIFT) + 1;
@@ -1968,13 +2017,16 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id,
atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs;
else
atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs;
+
+ nvme_update_atomic_write_disk_info(ns, id, lim, bs, atomic_bs);
}
if (id->nsfeat & NVME_NS_FEAT_IO_OPT) {
/* NPWG = Namespace Preferred Write Granularity */
phys_bs = bs * (1 + le16_to_cpu(id->npwg));
/* NOWS = Namespace Optimal Write Size */
- io_opt = bs * (1 + le16_to_cpu(id->nows));
+ if (id->nows)
+ io_opt = bs * (1 + le16_to_cpu(id->nows));
}
/*
@@ -2058,7 +2110,6 @@ static int nvme_update_ns_info_generic(struct nvme_ns *ns,
static int nvme_update_ns_info_block(struct nvme_ns *ns,
struct nvme_ns_info *info)
{
- bool vwc = ns->ctrl->vwc & NVME_CTRL_VWC_PRESENT;
struct queue_limits lim;
struct nvme_id_ns_nvm *nvm = NULL;
struct nvme_zone_info zi = {};
@@ -2107,11 +2158,11 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
ns->head->ids.csi == NVME_CSI_ZNS)
nvme_update_zone_info(ns, &lim, &zi);
- ret = queue_limits_commit_update(ns->disk->queue, &lim);
- if (ret) {
- blk_mq_unfreeze_queue(ns->disk->queue);
- goto out;
- }
+
+ if (ns->ctrl->vwc & NVME_CTRL_VWC_PRESENT)
+ lim.features |= BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA;
+ else
+ lim.features &= ~(BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA);
/*
* Register a metadata profile for PI, or the plain non-integrity NVMe
@@ -2119,9 +2170,15 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
* I/O to namespaces with metadata except when the namespace supports
* PI, as it can strip/insert in that case.
*/
- if (!nvme_init_integrity(ns->disk, ns->head))
+ if (!nvme_init_integrity(ns->disk, ns->head, &lim))
capacity = 0;
+ ret = queue_limits_commit_update(ns->disk->queue, &lim);
+ if (ret) {
+ blk_mq_unfreeze_queue(ns->disk->queue);
+ goto out;
+ }
+
set_capacity_and_notify(ns->disk, capacity);
/*
@@ -2133,7 +2190,6 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
if ((id->dlfeat & 0x7) == 0x1 && (id->dlfeat & (1 << 3)))
ns->head->features |= NVME_NS_DEAC;
set_disk_ro(ns->disk, nvme_ns_is_readonly(ns, info));
- blk_queue_write_cache(ns->disk->queue, vwc, vwc);
set_bit(NVME_NS_READY, &ns->flags);
blk_mq_unfreeze_queue(ns->disk->queue);
@@ -2193,14 +2249,6 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info)
struct queue_limits lim;
blk_mq_freeze_queue(ns->head->disk->queue);
- if (unsupported)
- ns->head->disk->flags |= GENHD_FL_HIDDEN;
- else
- nvme_init_integrity(ns->head->disk, ns->head);
- set_capacity_and_notify(ns->head->disk, get_capacity(ns->disk));
- set_disk_ro(ns->head->disk, nvme_ns_is_readonly(ns, info));
- nvme_mpath_revalidate_paths(ns);
-
/*
* queue_limits mixes values that are the hardware limitations
* for bio splitting with what is the device configuration.
@@ -2223,13 +2271,48 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info)
lim.io_opt = ns_lim->io_opt;
queue_limits_stack_bdev(&lim, ns->disk->part0, 0,
ns->head->disk->disk_name);
+ if (unsupported)
+ ns->head->disk->flags |= GENHD_FL_HIDDEN;
+ else
+ nvme_init_integrity(ns->head->disk, ns->head, &lim);
ret = queue_limits_commit_update(ns->head->disk->queue, &lim);
+
+ set_capacity_and_notify(ns->head->disk, get_capacity(ns->disk));
+ set_disk_ro(ns->head->disk, nvme_ns_is_readonly(ns, info));
+ nvme_mpath_revalidate_paths(ns);
+
blk_mq_unfreeze_queue(ns->head->disk->queue);
}
return ret;
}
+int nvme_ns_get_unique_id(struct nvme_ns *ns, u8 id[16],
+ enum blk_unique_id type)
+{
+ struct nvme_ns_ids *ids = &ns->head->ids;
+
+ if (type != BLK_UID_EUI64)
+ return -EINVAL;
+
+ if (memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) {
+ memcpy(id, &ids->nguid, sizeof(ids->nguid));
+ return sizeof(ids->nguid);
+ }
+ if (memchr_inv(ids->eui64, 0, sizeof(ids->eui64))) {
+ memcpy(id, &ids->eui64, sizeof(ids->eui64));
+ return sizeof(ids->eui64);
+ }
+
+ return -EINVAL;
+}
+
+static int nvme_get_unique_id(struct gendisk *disk, u8 id[16],
+ enum blk_unique_id type)
+{
+ return nvme_ns_get_unique_id(disk->private_data, id, type);
+}
+
#ifdef CONFIG_BLK_SED_OPAL
static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len,
bool send)
@@ -2285,6 +2368,7 @@ const struct block_device_operations nvme_bdev_ops = {
.open = nvme_open,
.release = nvme_release,
.getgeo = nvme_getgeo,
+ .get_unique_id = nvme_get_unique_id,
.report_zones = nvme_report_zones,
.pr_ops = &nvme_pr_ops,
};
@@ -3721,6 +3805,7 @@ static void nvme_ns_add_to_ctrl_list(struct nvme_ns *ns)
static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
{
+ struct queue_limits lim = { };
struct nvme_ns *ns;
struct gendisk *disk;
int node = ctrl->numa_node;
@@ -3729,7 +3814,13 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
if (!ns)
return;
- disk = blk_mq_alloc_disk(ctrl->tagset, NULL, ns);
+ if (ctrl->opts && ctrl->opts->data_digest)
+ lim.features |= BLK_FEAT_STABLE_WRITES;
+ if (ctrl->ops->supports_pci_p2pdma &&
+ ctrl->ops->supports_pci_p2pdma(ctrl))
+ lim.features |= BLK_FEAT_PCI_P2PDMA;
+
+ disk = blk_mq_alloc_disk(ctrl->tagset, &lim, ns);
if (IS_ERR(disk))
goto out_free_ns;
disk->fops = &nvme_bdev_ops;
@@ -3737,15 +3828,6 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
ns->disk = disk;
ns->queue = disk->queue;
-
- if (ctrl->opts && ctrl->opts->data_digest)
- blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, ns->queue);
-
- blk_queue_flag_set(QUEUE_FLAG_NONROT, ns->queue);
- if (ctrl->ops->supports_pci_p2pdma &&
- ctrl->ops->supports_pci_p2pdma(ctrl))
- blk_queue_flag_set(QUEUE_FLAG_PCI_P2PDMA, ns->queue);
-
ns->ctrl = ctrl;
kref_init(&ns->kref);
@@ -3887,7 +3969,7 @@ static void nvme_ns_remove_by_nsid(struct nvme_ctrl *ctrl, u32 nsid)
static void nvme_validate_ns(struct nvme_ns *ns, struct nvme_ns_info *info)
{
- int ret = NVME_SC_INVALID_NS | NVME_SC_DNR;
+ int ret = NVME_SC_INVALID_NS | NVME_STATUS_DNR;
if (!nvme_ns_ids_equal(&ns->head->ids, &info->ids)) {
dev_err(ns->ctrl->device,
@@ -3903,7 +3985,7 @@ out:
*
* TODO: we should probably schedule a delayed retry here.
*/
- if (ret > 0 && (ret & NVME_SC_DNR))
+ if (ret > 0 && (ret & NVME_STATUS_DNR))
nvme_ns_remove(ns);
}
@@ -4095,7 +4177,7 @@ static void nvme_scan_work(struct work_struct *work)
* they report) but don't actually support it.
*/
ret = nvme_scan_ns_list(ctrl);
- if (ret > 0 && ret & NVME_SC_DNR)
+ if (ret > 0 && ret & NVME_STATUS_DNR)
nvme_scan_ns_sequential(ctrl);
}
mutex_unlock(&ctrl->scan_lock);
@@ -4489,13 +4571,15 @@ int nvme_alloc_io_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set,
return ret;
if (ctrl->ops->flags & NVME_F_FABRICS) {
- ctrl->connect_q = blk_mq_alloc_queue(set, NULL, NULL);
+ struct queue_limits lim = {
+ .features = BLK_FEAT_SKIP_TAGSET_QUIESCE,
+ };
+
+ ctrl->connect_q = blk_mq_alloc_queue(set, &lim, NULL);
if (IS_ERR(ctrl->connect_q)) {
ret = PTR_ERR(ctrl->connect_q);
goto out_free_tag_set;
}
- blk_queue_flag_set(QUEUE_FLAG_SKIP_TAGSET_QUIESCE,
- ctrl->connect_q);
}
ctrl->tagset = set;
@@ -4613,6 +4697,9 @@ static void nvme_free_ctrl(struct device *dev)
* Initialize a NVMe controller structures. This needs to be called during
* earliest initialization so that we have the initialized structured around
* during probing.
+ *
+ * On success, the caller must use the nvme_put_ctrl() to release this when
+ * needed, which also invokes the ops->free_ctrl() callback.
*/
int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
const struct nvme_ctrl_ops *ops, unsigned long quirks)
@@ -4661,6 +4748,12 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
goto out;
ctrl->instance = ret;
+ ret = nvme_auth_init_ctrl(ctrl);
+ if (ret)
+ goto out_release_instance;
+
+ nvme_mpath_init_ctrl(ctrl);
+
device_initialize(&ctrl->ctrl_device);
ctrl->device = &ctrl->ctrl_device;
ctrl->device->devt = MKDEV(MAJOR(nvme_ctrl_base_chr_devt),
@@ -4673,16 +4766,36 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
ctrl->device->groups = nvme_dev_attr_groups;
ctrl->device->release = nvme_free_ctrl;
dev_set_drvdata(ctrl->device, ctrl);
+
+ return ret;
+
+out_release_instance:
+ ida_free(&nvme_instance_ida, ctrl->instance);
+out:
+ if (ctrl->discard_page)
+ __free_page(ctrl->discard_page);
+ cleanup_srcu_struct(&ctrl->srcu);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nvme_init_ctrl);
+
+/*
+ * On success, returns with an elevated controller reference and caller must
+ * use nvme_uninit_ctrl() to properly free resources associated with the ctrl.
+ */
+int nvme_add_ctrl(struct nvme_ctrl *ctrl)
+{
+ int ret;
+
ret = dev_set_name(ctrl->device, "nvme%d", ctrl->instance);
if (ret)
- goto out_release_instance;
+ return ret;
- nvme_get_ctrl(ctrl);
cdev_init(&ctrl->cdev, &nvme_dev_fops);
- ctrl->cdev.owner = ops->module;
+ ctrl->cdev.owner = ctrl->ops->module;
ret = cdev_device_add(&ctrl->cdev, ctrl->device);
if (ret)
- goto out_free_name;
+ return ret;
/*
* Initialize latency tolerance controls. The sysfs files won't
@@ -4693,28 +4806,11 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
min(default_ps_max_latency_us, (unsigned long)S32_MAX));
nvme_fault_inject_init(&ctrl->fault_inject, dev_name(ctrl->device));
- nvme_mpath_init_ctrl(ctrl);
- ret = nvme_auth_init_ctrl(ctrl);
- if (ret)
- goto out_free_cdev;
+ nvme_get_ctrl(ctrl);
return 0;
-out_free_cdev:
- nvme_fault_inject_fini(&ctrl->fault_inject);
- dev_pm_qos_hide_latency_tolerance(ctrl->device);
- cdev_device_del(&ctrl->cdev, ctrl->device);
-out_free_name:
- nvme_put_ctrl(ctrl);
- kfree_const(ctrl->device->kobj.name);
-out_release_instance:
- ida_free(&nvme_instance_ida, ctrl->instance);
-out:
- if (ctrl->discard_page)
- __free_page(ctrl->discard_page);
- cleanup_srcu_struct(&ctrl->srcu);
- return ret;
}
-EXPORT_SYMBOL_GPL(nvme_init_ctrl);
+EXPORT_SYMBOL_GPL(nvme_add_ctrl);
/* let I/O to all namespaces fail in preparation for surprise removal */
void nvme_mark_namespaces_dead(struct nvme_ctrl *ctrl)
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index ceb9c0ed3120..44e342a46f39 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -187,7 +187,7 @@ int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val)
if (unlikely(ret != 0))
dev_err(ctrl->device,
"Property Get error: %d, offset %#x\n",
- ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
+ ret > 0 ? ret & ~NVME_STATUS_DNR : ret, off);
return ret;
}
@@ -233,7 +233,7 @@ int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val)
if (unlikely(ret != 0))
dev_err(ctrl->device,
"Property Get error: %d, offset %#x\n",
- ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
+ ret > 0 ? ret & ~NVME_STATUS_DNR : ret, off);
return ret;
}
EXPORT_SYMBOL_GPL(nvmf_reg_read64);
@@ -275,11 +275,26 @@ int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val)
if (unlikely(ret))
dev_err(ctrl->device,
"Property Set error: %d, offset %#x\n",
- ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
+ ret > 0 ? ret & ~NVME_STATUS_DNR : ret, off);
return ret;
}
EXPORT_SYMBOL_GPL(nvmf_reg_write32);
+int nvmf_subsystem_reset(struct nvme_ctrl *ctrl)
+{
+ int ret;
+
+ if (!nvme_wait_reset(ctrl))
+ return -EBUSY;
+
+ ret = ctrl->ops->reg_write32(ctrl, NVME_REG_NSSR, NVME_SUBSYS_RESET);
+ if (ret)
+ return ret;
+
+ return nvme_try_sched_reset(ctrl);
+}
+EXPORT_SYMBOL_GPL(nvmf_subsystem_reset);
+
/**
* nvmf_log_connect_error() - Error-parsing-diagnostic print out function for
* connect() errors.
@@ -295,7 +310,7 @@ static void nvmf_log_connect_error(struct nvme_ctrl *ctrl,
int errval, int offset, struct nvme_command *cmd,
struct nvmf_connect_data *data)
{
- int err_sctype = errval & ~NVME_SC_DNR;
+ int err_sctype = errval & ~NVME_STATUS_DNR;
if (errval < 0) {
dev_err(ctrl->device,
@@ -573,7 +588,7 @@ EXPORT_SYMBOL_GPL(nvmf_connect_io_queue);
*/
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl, int status)
{
- if (status > 0 && (status & NVME_SC_DNR))
+ if (status > 0 && (status & NVME_STATUS_DNR))
return false;
if (status == -EKEYREJECTED)
diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h
index 602135910ae9..21d75dc4a3a0 100644
--- a/drivers/nvme/host/fabrics.h
+++ b/drivers/nvme/host/fabrics.h
@@ -217,6 +217,7 @@ static inline unsigned int nvmf_nr_io_queues(struct nvmf_ctrl_options *opts)
int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val);
int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val);
int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val);
+int nvmf_subsystem_reset(struct nvme_ctrl *ctrl);
int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl);
int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid);
int nvmf_register_transport(struct nvmf_transport_ops *ops);
diff --git a/drivers/nvme/host/fault_inject.c b/drivers/nvme/host/fault_inject.c
index 1ba10a5c656d..1d1b6441a339 100644
--- a/drivers/nvme/host/fault_inject.c
+++ b/drivers/nvme/host/fault_inject.c
@@ -75,7 +75,7 @@ void nvme_should_fail(struct request *req)
/* inject status code and DNR bit */
status = fault_inject->status;
if (fault_inject->dont_retry)
- status |= NVME_SC_DNR;
+ status |= NVME_STATUS_DNR;
nvme_req(req)->status = status;
}
}
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index f0b081332749..b81af7919e94 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -3132,7 +3132,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
if (ctrl->ctrl.icdoff) {
dev_err(ctrl->ctrl.device, "icdoff %d is not supported!\n",
ctrl->ctrl.icdoff);
- ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ ret = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto out_stop_keep_alive;
}
@@ -3140,7 +3140,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
if (!nvme_ctrl_sgl_supported(&ctrl->ctrl)) {
dev_err(ctrl->ctrl.device,
"Mandatory sgls are not supported!\n");
- ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ ret = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto out_stop_keep_alive;
}
@@ -3325,7 +3325,7 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
queue_delayed_work(nvme_wq, &ctrl->connect_work, recon_delay);
} else {
if (portptr->port_state == FC_OBJSTATE_ONLINE) {
- if (status > 0 && (status & NVME_SC_DNR))
+ if (status > 0 && (status & NVME_STATUS_DNR))
dev_warn(ctrl->ctrl.device,
"NVME-FC{%d}: reconnect failure\n",
ctrl->cnum);
@@ -3382,6 +3382,7 @@ static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = {
.reg_read32 = nvmf_reg_read32,
.reg_read64 = nvmf_reg_read64,
.reg_write32 = nvmf_reg_write32,
+ .subsystem_reset = nvmf_subsystem_reset,
.free_ctrl = nvme_fc_free_ctrl,
.submit_async_event = nvme_fc_submit_async_event,
.delete_ctrl = nvme_fc_delete_ctrl,
@@ -3444,12 +3445,11 @@ nvme_fc_existing_controller(struct nvme_fc_rport *rport,
return found;
}
-static struct nvme_ctrl *
-nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
+static struct nvme_fc_ctrl *
+nvme_fc_alloc_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
struct nvme_fc_lport *lport, struct nvme_fc_rport *rport)
{
struct nvme_fc_ctrl *ctrl;
- unsigned long flags;
int ret, idx, ctrl_loss_tmo;
if (!(rport->remoteport.port_role &
@@ -3538,7 +3538,35 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
if (lport->dev)
ctrl->ctrl.numa_node = dev_to_node(lport->dev);
- /* at this point, teardown path changes to ref counting on nvme ctrl */
+ return ctrl;
+
+out_free_queues:
+ kfree(ctrl->queues);
+out_free_ida:
+ put_device(ctrl->dev);
+ ida_free(&nvme_fc_ctrl_cnt, ctrl->cnum);
+out_free_ctrl:
+ kfree(ctrl);
+out_fail:
+ /* exit via here doesn't follow ctlr ref points */
+ return ERR_PTR(ret);
+}
+
+static struct nvme_ctrl *
+nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
+ struct nvme_fc_lport *lport, struct nvme_fc_rport *rport)
+{
+ struct nvme_fc_ctrl *ctrl;
+ unsigned long flags;
+ int ret;
+
+ ctrl = nvme_fc_alloc_ctrl(dev, opts, lport, rport);
+ if (IS_ERR(ctrl))
+ return ERR_CAST(ctrl);
+
+ ret = nvme_add_ctrl(&ctrl->ctrl);
+ if (ret)
+ goto out_put_ctrl;
ret = nvme_alloc_admin_tag_set(&ctrl->ctrl, &ctrl->admin_tag_set,
&nvme_fc_admin_mq_ops,
@@ -3584,6 +3612,7 @@ fail_ctrl:
/* initiate nvme ctrl ref counting teardown */
nvme_uninit_ctrl(&ctrl->ctrl);
+out_put_ctrl:
/* Remove core ctrl ref. */
nvme_put_ctrl(&ctrl->ctrl);
@@ -3597,20 +3626,8 @@ fail_ctrl:
nvme_fc_rport_get(rport);
return ERR_PTR(-EIO);
-
-out_free_queues:
- kfree(ctrl->queues);
-out_free_ida:
- put_device(ctrl->dev);
- ida_free(&nvme_fc_ctrl_cnt, ctrl->cnum);
-out_free_ctrl:
- kfree(ctrl);
-out_fail:
- /* exit via here doesn't follow ctlr ref points */
- return ERR_PTR(ret);
}
-
struct nvmet_fc_traddr {
u64 nn;
u64 pn;
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index d8b6b4648eaf..91d9eb3c22ef 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -17,6 +17,7 @@ MODULE_PARM_DESC(multipath,
static const char *nvme_iopolicy_names[] = {
[NVME_IOPOLICY_NUMA] = "numa",
[NVME_IOPOLICY_RR] = "round-robin",
+ [NVME_IOPOLICY_QD] = "queue-depth",
};
static int iopolicy = NVME_IOPOLICY_NUMA;
@@ -29,6 +30,8 @@ static int nvme_set_iopolicy(const char *val, const struct kernel_param *kp)
iopolicy = NVME_IOPOLICY_NUMA;
else if (!strncmp(val, "round-robin", 11))
iopolicy = NVME_IOPOLICY_RR;
+ else if (!strncmp(val, "queue-depth", 11))
+ iopolicy = NVME_IOPOLICY_QD;
else
return -EINVAL;
@@ -43,7 +46,7 @@ static int nvme_get_iopolicy(char *buf, const struct kernel_param *kp)
module_param_call(iopolicy, nvme_set_iopolicy, nvme_get_iopolicy,
&iopolicy, 0644);
MODULE_PARM_DESC(iopolicy,
- "Default multipath I/O policy; 'numa' (default) or 'round-robin'");
+ "Default multipath I/O policy; 'numa' (default), 'round-robin' or 'queue-depth'");
void nvme_mpath_default_iopolicy(struct nvme_subsystem *subsys)
{
@@ -83,7 +86,7 @@ void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
void nvme_failover_req(struct request *req)
{
struct nvme_ns *ns = req->q->queuedata;
- u16 status = nvme_req(req)->status & 0x7ff;
+ u16 status = nvme_req(req)->status & NVME_SCT_SC_MASK;
unsigned long flags;
struct bio *bio;
@@ -128,6 +131,11 @@ void nvme_mpath_start_request(struct request *rq)
struct nvme_ns *ns = rq->q->queuedata;
struct gendisk *disk = ns->head->disk;
+ if (READ_ONCE(ns->head->subsys->iopolicy) == NVME_IOPOLICY_QD) {
+ atomic_inc(&ns->ctrl->nr_active);
+ nvme_req(rq)->flags |= NVME_MPATH_CNT_ACTIVE;
+ }
+
if (!blk_queue_io_stat(disk->queue) || blk_rq_is_passthrough(rq))
return;
@@ -141,6 +149,9 @@ void nvme_mpath_end_request(struct request *rq)
{
struct nvme_ns *ns = rq->q->queuedata;
+ if (nvme_req(rq)->flags & NVME_MPATH_CNT_ACTIVE)
+ atomic_dec_if_positive(&ns->ctrl->nr_active);
+
if (!(nvme_req(rq)->flags & NVME_MPATH_IO_STATS))
return;
bdev_end_io_acct(ns->head->disk->part0, req_op(rq),
@@ -291,10 +302,15 @@ static struct nvme_ns *nvme_next_ns(struct nvme_ns_head *head,
return list_first_or_null_rcu(&head->list, struct nvme_ns, siblings);
}
-static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head,
- int node, struct nvme_ns *old)
+static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head)
{
struct nvme_ns *ns, *found = NULL;
+ int node = numa_node_id();
+ struct nvme_ns *old = srcu_dereference(head->current_path[node],
+ &head->srcu);
+
+ if (unlikely(!old))
+ return __nvme_find_path(head, node);
if (list_is_singular(&head->list)) {
if (nvme_path_is_disabled(old))
@@ -334,13 +350,49 @@ out:
return found;
}
+static struct nvme_ns *nvme_queue_depth_path(struct nvme_ns_head *head)
+{
+ struct nvme_ns *best_opt = NULL, *best_nonopt = NULL, *ns;
+ unsigned int min_depth_opt = UINT_MAX, min_depth_nonopt = UINT_MAX;
+ unsigned int depth;
+
+ list_for_each_entry_rcu(ns, &head->list, siblings) {
+ if (nvme_path_is_disabled(ns))
+ continue;
+
+ depth = atomic_read(&ns->ctrl->nr_active);
+
+ switch (ns->ana_state) {
+ case NVME_ANA_OPTIMIZED:
+ if (depth < min_depth_opt) {
+ min_depth_opt = depth;
+ best_opt = ns;
+ }
+ break;
+ case NVME_ANA_NONOPTIMIZED:
+ if (depth < min_depth_nonopt) {
+ min_depth_nonopt = depth;
+ best_nonopt = ns;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (min_depth_opt == 0)
+ return best_opt;
+ }
+
+ return best_opt ? best_opt : best_nonopt;
+}
+
static inline bool nvme_path_is_optimized(struct nvme_ns *ns)
{
return nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE &&
ns->ana_state == NVME_ANA_OPTIMIZED;
}
-inline struct nvme_ns *nvme_find_path(struct nvme_ns_head *head)
+static struct nvme_ns *nvme_numa_path(struct nvme_ns_head *head)
{
int node = numa_node_id();
struct nvme_ns *ns;
@@ -348,14 +400,23 @@ inline struct nvme_ns *nvme_find_path(struct nvme_ns_head *head)
ns = srcu_dereference(head->current_path[node], &head->srcu);
if (unlikely(!ns))
return __nvme_find_path(head, node);
-
- if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_RR)
- return nvme_round_robin_path(head, node, ns);
if (unlikely(!nvme_path_is_optimized(ns)))
return __nvme_find_path(head, node);
return ns;
}
+inline struct nvme_ns *nvme_find_path(struct nvme_ns_head *head)
+{
+ switch (READ_ONCE(head->subsys->iopolicy)) {
+ case NVME_IOPOLICY_QD:
+ return nvme_queue_depth_path(head);
+ case NVME_IOPOLICY_RR:
+ return nvme_round_robin_path(head);
+ default:
+ return nvme_numa_path(head);
+ }
+}
+
static bool nvme_available_path(struct nvme_ns_head *head)
{
struct nvme_ns *ns;
@@ -427,6 +488,21 @@ static void nvme_ns_head_release(struct gendisk *disk)
nvme_put_ns_head(disk->private_data);
}
+static int nvme_ns_head_get_unique_id(struct gendisk *disk, u8 id[16],
+ enum blk_unique_id type)
+{
+ struct nvme_ns_head *head = disk->private_data;
+ struct nvme_ns *ns;
+ int srcu_idx, ret = -EWOULDBLOCK;
+
+ srcu_idx = srcu_read_lock(&head->srcu);
+ ns = nvme_find_path(head);
+ if (ns)
+ ret = nvme_ns_get_unique_id(ns, id, type);
+ srcu_read_unlock(&head->srcu, srcu_idx);
+ return ret;
+}
+
#ifdef CONFIG_BLK_DEV_ZONED
static int nvme_ns_head_report_zones(struct gendisk *disk, sector_t sector,
unsigned int nr_zones, report_zones_cb cb, void *data)
@@ -454,6 +530,7 @@ const struct block_device_operations nvme_ns_head_ops = {
.ioctl = nvme_ns_head_ioctl,
.compat_ioctl = blkdev_compat_ptr_ioctl,
.getgeo = nvme_getgeo,
+ .get_unique_id = nvme_ns_head_get_unique_id,
.report_zones = nvme_ns_head_report_zones,
.pr_ops = &nvme_pr_ops,
};
@@ -521,7 +598,6 @@ static void nvme_requeue_work(struct work_struct *work)
int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head)
{
struct queue_limits lim;
- bool vwc = false;
mutex_init(&head->lock);
bio_list_init(&head->requeue_list);
@@ -539,6 +615,7 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head)
blk_set_stacking_limits(&lim);
lim.dma_alignment = 3;
+ lim.features |= BLK_FEAT_IO_STAT | BLK_FEAT_NOWAIT | BLK_FEAT_POLL;
if (head->ids.csi != NVME_CSI_ZNS)
lim.max_zone_append_sectors = 0;
@@ -549,24 +626,6 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head)
head->disk->private_data = head;
sprintf(head->disk->disk_name, "nvme%dn%d",
ctrl->subsys->instance, head->instance);
-
- blk_queue_flag_set(QUEUE_FLAG_NONROT, head->disk->queue);
- blk_queue_flag_set(QUEUE_FLAG_NOWAIT, head->disk->queue);
- blk_queue_flag_set(QUEUE_FLAG_IO_STAT, head->disk->queue);
- /*
- * This assumes all controllers that refer to a namespace either
- * support poll queues or not. That is not a strict guarantee,
- * but if the assumption is wrong the effect is only suboptimal
- * performance but not correctness problem.
- */
- if (ctrl->tagset->nr_maps > HCTX_TYPE_POLL &&
- ctrl->tagset->map[HCTX_TYPE_POLL].nr_queues)
- blk_queue_flag_set(QUEUE_FLAG_POLL, head->disk->queue);
-
- /* we need to propagate up the VMC settings */
- if (ctrl->vwc & NVME_CTRL_VWC_PRESENT)
- vwc = true;
- blk_queue_write_cache(head->disk->queue, vwc, vwc);
return 0;
}
@@ -803,6 +862,29 @@ static ssize_t nvme_subsys_iopolicy_show(struct device *dev,
nvme_iopolicy_names[READ_ONCE(subsys->iopolicy)]);
}
+static void nvme_subsys_iopolicy_update(struct nvme_subsystem *subsys,
+ int iopolicy)
+{
+ struct nvme_ctrl *ctrl;
+ int old_iopolicy = READ_ONCE(subsys->iopolicy);
+
+ if (old_iopolicy == iopolicy)
+ return;
+
+ WRITE_ONCE(subsys->iopolicy, iopolicy);
+
+ /* iopolicy changes clear the mpath by design */
+ mutex_lock(&nvme_subsystems_lock);
+ list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
+ nvme_mpath_clear_ctrl_paths(ctrl);
+ mutex_unlock(&nvme_subsystems_lock);
+
+ pr_notice("subsysnqn %s iopolicy changed from %s to %s\n",
+ subsys->subnqn,
+ nvme_iopolicy_names[old_iopolicy],
+ nvme_iopolicy_names[iopolicy]);
+}
+
static ssize_t nvme_subsys_iopolicy_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -812,7 +894,7 @@ static ssize_t nvme_subsys_iopolicy_store(struct device *dev,
for (i = 0; i < ARRAY_SIZE(nvme_iopolicy_names); i++) {
if (sysfs_streq(buf, nvme_iopolicy_names[i])) {
- WRITE_ONCE(subsys->iopolicy, i);
+ nvme_subsys_iopolicy_update(subsys, i);
return count;
}
}
@@ -875,9 +957,6 @@ void nvme_mpath_add_disk(struct nvme_ns *ns, __le32 anagrpid)
nvme_mpath_set_live(ns);
}
- if (blk_queue_stable_writes(ns->queue) && ns->head->disk)
- blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES,
- ns->head->disk->queue);
#ifdef CONFIG_BLK_DEV_ZONED
if (blk_queue_is_zoned(ns->queue) && ns->head->disk)
ns->head->disk->nr_zones = ns->disk->nr_zones;
@@ -923,6 +1002,9 @@ int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
!(ctrl->subsys->cmic & NVME_CTRL_CMIC_ANA))
return 0;
+ /* initialize this in the identify path to cover controller resets */
+ atomic_set(&ctrl->nr_active, 0);
+
if (!ctrl->max_namespaces ||
ctrl->max_namespaces > le32_to_cpu(id->nn)) {
dev_err(ctrl->device,
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 68b400f9c42d..f900e44243ae 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -49,6 +49,7 @@ extern unsigned int admin_timeout;
extern struct workqueue_struct *nvme_wq;
extern struct workqueue_struct *nvme_reset_wq;
extern struct workqueue_struct *nvme_delete_wq;
+extern struct mutex nvme_subsystems_lock;
/*
* List of workarounds for devices that required behavior not specified in
@@ -195,6 +196,7 @@ enum {
NVME_REQ_CANCELLED = (1 << 0),
NVME_REQ_USERCMD = (1 << 1),
NVME_MPATH_IO_STATS = (1 << 2),
+ NVME_MPATH_CNT_ACTIVE = (1 << 3),
};
static inline struct nvme_request *nvme_req(struct request *req)
@@ -360,6 +362,7 @@ struct nvme_ctrl {
size_t ana_log_size;
struct timer_list anatt_timer;
struct work_struct ana_work;
+ atomic_t nr_active;
#endif
#ifdef CONFIG_NVME_HOST_AUTH
@@ -408,6 +411,7 @@ static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl)
enum nvme_iopolicy {
NVME_IOPOLICY_NUMA,
NVME_IOPOLICY_RR,
+ NVME_IOPOLICY_QD,
};
struct nvme_subsystem {
@@ -551,6 +555,7 @@ struct nvme_ctrl_ops {
int (*reg_read64)(struct nvme_ctrl *ctrl, u32 off, u64 *val);
void (*free_ctrl)(struct nvme_ctrl *ctrl);
void (*submit_async_event)(struct nvme_ctrl *ctrl);
+ int (*subsystem_reset)(struct nvme_ctrl *ctrl);
void (*delete_ctrl)(struct nvme_ctrl *ctrl);
void (*stop_ctrl)(struct nvme_ctrl *ctrl);
int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
@@ -649,18 +654,9 @@ int nvme_try_sched_reset(struct nvme_ctrl *ctrl);
static inline int nvme_reset_subsystem(struct nvme_ctrl *ctrl)
{
- int ret;
-
- if (!ctrl->subsystem)
+ if (!ctrl->subsystem || !ctrl->ops->subsystem_reset)
return -ENOTTY;
- if (!nvme_wait_reset(ctrl))
- return -EBUSY;
-
- ret = ctrl->ops->reg_write32(ctrl, NVME_REG_NSSR, 0x4E564D65);
- if (ret)
- return ret;
-
- return nvme_try_sched_reset(ctrl);
+ return ctrl->ops->subsystem_reset(ctrl);
}
/*
@@ -689,7 +685,7 @@ static inline u32 nvme_bytes_to_numd(size_t len)
static inline bool nvme_is_ana_error(u16 status)
{
- switch (status & 0x7ff) {
+ switch (status & NVME_SCT_SC_MASK) {
case NVME_SC_ANA_TRANSITION:
case NVME_SC_ANA_INACCESSIBLE:
case NVME_SC_ANA_PERSISTENT_LOSS:
@@ -702,7 +698,7 @@ static inline bool nvme_is_ana_error(u16 status)
static inline bool nvme_is_path_error(u16 status)
{
/* check for a status code type of 'path related status' */
- return (status & 0x700) == 0x300;
+ return (status & NVME_SCT_MASK) == NVME_SCT_PATH;
}
/*
@@ -792,6 +788,7 @@ int nvme_disable_ctrl(struct nvme_ctrl *ctrl, bool shutdown);
int nvme_enable_ctrl(struct nvme_ctrl *ctrl);
int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
const struct nvme_ctrl_ops *ops, unsigned long quirks);
+int nvme_add_ctrl(struct nvme_ctrl *ctrl);
void nvme_uninit_ctrl(struct nvme_ctrl *ctrl);
void nvme_start_ctrl(struct nvme_ctrl *ctrl);
void nvme_stop_ctrl(struct nvme_ctrl *ctrl);
@@ -877,7 +874,7 @@ enum {
NVME_SUBMIT_NOWAIT = (__force nvme_submit_flags_t)(1 << 1),
/* Set BLK_MQ_REQ_RESERVED when allocating request */
NVME_SUBMIT_RESERVED = (__force nvme_submit_flags_t)(1 << 2),
- /* Retry command when NVME_SC_DNR is not set in the result */
+ /* Retry command when NVME_STATUS_DNR is not set in the result */
NVME_SUBMIT_RETRY = (__force nvme_submit_flags_t)(1 << 3),
};
@@ -1062,6 +1059,9 @@ static inline bool nvme_disk_is_ns_head(struct gendisk *disk)
}
#endif /* CONFIG_NVME_MULTIPATH */
+int nvme_ns_get_unique_id(struct nvme_ns *ns, u8 id[16],
+ enum blk_unique_id type);
+
struct nvme_zone_info {
u64 zone_size;
unsigned int max_open_zones;
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 102a9fb0c65f..21f8e1b9801f 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -826,9 +826,9 @@ static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req,
struct nvme_command *cmnd)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+ struct bio_vec bv = rq_integrity_vec(req);
- iod->meta_dma = dma_map_bvec(dev->dev, rq_integrity_vec(req),
- rq_dma_dir(req), 0);
+ iod->meta_dma = dma_map_bvec(dev->dev, &bv, rq_dma_dir(req), 0);
if (dma_mapping_error(dev->dev, iod->meta_dma))
return BLK_STS_IOERR;
cmnd->rw.metadata = cpu_to_le64(iod->meta_dma);
@@ -967,7 +967,7 @@ static __always_inline void nvme_pci_unmap_rq(struct request *req)
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
dma_unmap_page(dev->dev, iod->meta_dma,
- rq_integrity_vec(req)->bv_len, rq_dma_dir(req));
+ rq_integrity_vec(req).bv_len, rq_dma_dir(req));
}
if (blk_rq_nr_phys_segments(req))
@@ -1143,6 +1143,41 @@ static void nvme_pci_submit_async_event(struct nvme_ctrl *ctrl)
spin_unlock(&nvmeq->sq_lock);
}
+static int nvme_pci_subsystem_reset(struct nvme_ctrl *ctrl)
+{
+ struct nvme_dev *dev = to_nvme_dev(ctrl);
+ int ret = 0;
+
+ /*
+ * Taking the shutdown_lock ensures the BAR mapping is not being
+ * altered by reset_work. Holding this lock before the RESETTING state
+ * change, if successful, also ensures nvme_remove won't be able to
+ * proceed to iounmap until we're done.
+ */
+ mutex_lock(&dev->shutdown_lock);
+ if (!dev->bar_mapped_size) {
+ ret = -ENODEV;
+ goto unlock;
+ }
+
+ if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) {
+ ret = -EBUSY;
+ goto unlock;
+ }
+
+ writel(NVME_SUBSYS_RESET, dev->bar + NVME_REG_NSSR);
+ nvme_change_ctrl_state(ctrl, NVME_CTRL_LIVE);
+
+ /*
+ * Read controller status to flush the previous write and trigger a
+ * pcie read error.
+ */
+ readl(dev->bar + NVME_REG_CSTS);
+unlock:
+ mutex_unlock(&dev->shutdown_lock);
+ return ret;
+}
+
static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id)
{
struct nvme_command c = { };
@@ -2859,6 +2894,7 @@ static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
.reg_read64 = nvme_pci_reg_read64,
.free_ctrl = nvme_pci_free_ctrl,
.submit_async_event = nvme_pci_submit_async_event,
+ .subsystem_reset = nvme_pci_subsystem_reset,
.get_address = nvme_pci_get_address,
.print_device_info = nvme_pci_print_device_info,
.supports_pci_p2pdma = nvme_pci_supports_pci_p2pdma,
@@ -3015,6 +3051,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (IS_ERR(dev))
return PTR_ERR(dev);
+ result = nvme_add_ctrl(&dev->ctrl);
+ if (result)
+ goto out_put_ctrl;
+
result = nvme_dev_map(dev);
if (result)
goto out_uninit_ctrl;
@@ -3101,6 +3141,7 @@ out_dev_unmap:
nvme_dev_unmap(dev);
out_uninit_ctrl:
nvme_uninit_ctrl(&dev->ctrl);
+out_put_ctrl:
nvme_put_ctrl(&dev->ctrl);
return result;
}
diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c
index 8fa1ffcdaed4..7347ddf85f00 100644
--- a/drivers/nvme/host/pr.c
+++ b/drivers/nvme/host/pr.c
@@ -72,12 +72,12 @@ static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c,
return nvme_submit_sync_cmd(ns->queue, c, data, data_len);
}
-static int nvme_sc_to_pr_err(int nvme_sc)
+static int nvme_status_to_pr_err(int status)
{
- if (nvme_is_path_error(nvme_sc))
+ if (nvme_is_path_error(status))
return PR_STS_PATH_FAILED;
- switch (nvme_sc & 0x7ff) {
+ switch (status & NVME_SCT_SC_MASK) {
case NVME_SC_SUCCESS:
return PR_STS_SUCCESS;
case NVME_SC_RESERVATION_CONFLICT:
@@ -121,7 +121,7 @@ static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
if (ret < 0)
return ret;
- return nvme_sc_to_pr_err(ret);
+ return nvme_status_to_pr_err(ret);
}
static int nvme_pr_register(struct block_device *bdev, u64 old,
@@ -196,7 +196,7 @@ retry:
if (ret < 0)
return ret;
- return nvme_sc_to_pr_err(ret);
+ return 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 51a62b0c645a..2eb33842f971 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -2201,6 +2201,7 @@ static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
.reg_read32 = nvmf_reg_read32,
.reg_read64 = nvmf_reg_read64,
.reg_write32 = nvmf_reg_write32,
+ .subsystem_reset = nvmf_subsystem_reset,
.free_ctrl = nvme_rdma_free_ctrl,
.submit_async_event = nvme_rdma_submit_async_event,
.delete_ctrl = nvme_rdma_delete_ctrl,
@@ -2237,12 +2238,11 @@ nvme_rdma_existing_controller(struct nvmf_ctrl_options *opts)
return found;
}
-static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
+static struct nvme_rdma_ctrl *nvme_rdma_alloc_ctrl(struct device *dev,
struct nvmf_ctrl_options *opts)
{
struct nvme_rdma_ctrl *ctrl;
int ret;
- bool changed;
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
if (!ctrl)
@@ -2304,6 +2304,30 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
if (ret)
goto out_kfree_queues;
+ return ctrl;
+
+out_kfree_queues:
+ kfree(ctrl->queues);
+out_free_ctrl:
+ kfree(ctrl);
+ return ERR_PTR(ret);
+}
+
+static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
+ struct nvmf_ctrl_options *opts)
+{
+ struct nvme_rdma_ctrl *ctrl;
+ bool changed;
+ int ret;
+
+ ctrl = nvme_rdma_alloc_ctrl(dev, opts);
+ if (IS_ERR(ctrl))
+ return ERR_CAST(ctrl);
+
+ ret = nvme_add_ctrl(&ctrl->ctrl);
+ if (ret)
+ goto out_put_ctrl;
+
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING);
WARN_ON_ONCE(!changed);
@@ -2322,15 +2346,11 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
out_uninit_ctrl:
nvme_uninit_ctrl(&ctrl->ctrl);
+out_put_ctrl:
nvme_put_ctrl(&ctrl->ctrl);
if (ret > 0)
ret = -EIO;
return ERR_PTR(ret);
-out_kfree_queues:
- kfree(ctrl->queues);
-out_free_ctrl:
- kfree(ctrl);
- return ERR_PTR(ret);
}
static struct nvmf_transport_ops nvme_rdma_transport = {
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 8b5e4327fe83..a2a47d3ab99f 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -2662,6 +2662,7 @@ static const struct nvme_ctrl_ops nvme_tcp_ctrl_ops = {
.reg_read32 = nvmf_reg_read32,
.reg_read64 = nvmf_reg_read64,
.reg_write32 = nvmf_reg_write32,
+ .subsystem_reset = nvmf_subsystem_reset,
.free_ctrl = nvme_tcp_free_ctrl,
.submit_async_event = nvme_tcp_submit_async_event,
.delete_ctrl = nvme_tcp_delete_ctrl,
@@ -2686,7 +2687,7 @@ nvme_tcp_existing_controller(struct nvmf_ctrl_options *opts)
return found;
}
-static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
+static struct nvme_tcp_ctrl *nvme_tcp_alloc_ctrl(struct device *dev,
struct nvmf_ctrl_options *opts)
{
struct nvme_tcp_ctrl *ctrl;
@@ -2761,6 +2762,28 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
if (ret)
goto out_kfree_queues;
+ return ctrl;
+out_kfree_queues:
+ kfree(ctrl->queues);
+out_free_ctrl:
+ kfree(ctrl);
+ return ERR_PTR(ret);
+}
+
+static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
+ struct nvmf_ctrl_options *opts)
+{
+ struct nvme_tcp_ctrl *ctrl;
+ int ret;
+
+ ctrl = nvme_tcp_alloc_ctrl(dev, opts);
+ if (IS_ERR(ctrl))
+ return ERR_CAST(ctrl);
+
+ ret = nvme_add_ctrl(&ctrl->ctrl);
+ if (ret)
+ goto out_put_ctrl;
+
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) {
WARN_ON_ONCE(1);
ret = -EINTR;
@@ -2782,15 +2805,11 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
out_uninit_ctrl:
nvme_uninit_ctrl(&ctrl->ctrl);
+out_put_ctrl:
nvme_put_ctrl(&ctrl->ctrl);
if (ret > 0)
ret = -EIO;
return ERR_PTR(ret);
-out_kfree_queues:
- kfree(ctrl->queues);
-out_free_ctrl:
- kfree(ctrl);
- return ERR_PTR(ret);
}
static struct nvmf_transport_ops nvme_tcp_transport = {
diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c
index 77aa0f440a6d..9a06f9d98cd6 100644
--- a/drivers/nvme/host/zns.c
+++ b/drivers/nvme/host/zns.c
@@ -108,13 +108,12 @@ free_data:
void nvme_update_zone_info(struct nvme_ns *ns, struct queue_limits *lim,
struct nvme_zone_info *zi)
{
- lim->zoned = 1;
+ 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->chunk_sectors = ns->head->zsze =
nvme_lba_to_sect(ns->head, zi->zone_size);
- blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, ns->queue);
}
static void *nvme_zns_alloc_report_buffer(struct nvme_ns *ns,
diff --git a/drivers/nvme/target/Kconfig b/drivers/nvme/target/Kconfig
index 872dd1a0acd8..46be031f91b4 100644
--- a/drivers/nvme/target/Kconfig
+++ b/drivers/nvme/target/Kconfig
@@ -6,7 +6,6 @@ config NVME_TARGET
depends on CONFIGFS_FS
select NVME_KEYRING if NVME_TARGET_TCP_TLS
select KEYS if NVME_TARGET_TCP_TLS
- select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY
select SGL_ALLOC
help
This enabled target side support for the NVMe protocol, that is
@@ -18,6 +17,15 @@ config NVME_TARGET
To configure the NVMe target you probably want to use the nvmetcli
tool from http://git.infradead.org/users/hch/nvmetcli.git.
+config NVME_TARGET_DEBUGFS
+ bool "NVMe Target debugfs support"
+ depends on NVME_TARGET
+ help
+ This enables debugfs support to display the connected controllers
+ to each subsystem
+
+ If unsure, say N.
+
config NVME_TARGET_PASSTHRU
bool "NVMe Target Passthrough support"
depends on NVME_TARGET
diff --git a/drivers/nvme/target/Makefile b/drivers/nvme/target/Makefile
index c66820102493..c402c44350b2 100644
--- a/drivers/nvme/target/Makefile
+++ b/drivers/nvme/target/Makefile
@@ -11,6 +11,7 @@ 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
+nvmet-$(CONFIG_NVME_TARGET_DEBUGFS) += debugfs.o
nvmet-$(CONFIG_NVME_TARGET_PASSTHRU) += passthru.o
nvmet-$(CONFIG_BLK_DEV_ZONED) += zns.o
nvmet-$(CONFIG_NVME_TARGET_AUTH) += fabrics-cmd-auth.o auth.o
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index f5b7054a4a05..f7e1156ac7ec 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -344,7 +344,7 @@ static void nvmet_execute_get_log_page(struct nvmet_req *req)
pr_debug("unhandled lid %d on qid %d\n",
req->cmd->get_log_page.lid, req->sq->qid);
req->error_loc = offsetof(struct nvme_get_log_page_command, lid);
- nvmet_req_complete(req, NVME_SC_INVALID_FIELD | NVME_SC_DNR);
+ nvmet_req_complete(req, NVME_SC_INVALID_FIELD | NVME_STATUS_DNR);
}
static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
@@ -496,7 +496,7 @@ static void nvmet_execute_identify_ns(struct nvmet_req *req)
if (le32_to_cpu(req->cmd->identify.nsid) == NVME_NSID_ALL) {
req->error_loc = offsetof(struct nvme_identify, nsid);
- status = NVME_SC_INVALID_NS | NVME_SC_DNR;
+ status = NVME_SC_INVALID_NS | NVME_STATUS_DNR;
goto out;
}
@@ -662,7 +662,7 @@ static void nvmet_execute_identify_desclist(struct nvmet_req *req)
if (sg_zero_buffer(req->sg, req->sg_cnt, NVME_IDENTIFY_DATA_SIZE - off,
off) != NVME_IDENTIFY_DATA_SIZE - off)
- status = NVME_SC_INTERNAL | NVME_SC_DNR;
+ status = NVME_SC_INTERNAL | NVME_STATUS_DNR;
out:
nvmet_req_complete(req, status);
@@ -724,7 +724,7 @@ static void nvmet_execute_identify(struct nvmet_req *req)
pr_debug("unhandled identify cns %d on qid %d\n",
req->cmd->identify.cns, req->sq->qid);
req->error_loc = offsetof(struct nvme_identify, cns);
- nvmet_req_complete(req, NVME_SC_INVALID_FIELD | NVME_SC_DNR);
+ nvmet_req_complete(req, NVME_SC_INVALID_FIELD | NVME_STATUS_DNR);
}
/*
@@ -807,7 +807,7 @@ u16 nvmet_set_feat_async_event(struct nvmet_req *req, u32 mask)
if (val32 & ~mask) {
req->error_loc = offsetof(struct nvme_common_command, cdw11);
- return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
WRITE_ONCE(req->sq->ctrl->aen_enabled, val32);
@@ -833,7 +833,7 @@ void nvmet_execute_set_features(struct nvmet_req *req)
ncqr = (cdw11 >> 16) & 0xffff;
nsqr = cdw11 & 0xffff;
if (ncqr == 0xffff || nsqr == 0xffff) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
break;
}
nvmet_set_result(req,
@@ -846,14 +846,14 @@ void nvmet_execute_set_features(struct nvmet_req *req)
status = nvmet_set_feat_async_event(req, NVMET_AEN_CFG_ALL);
break;
case NVME_FEAT_HOST_ID:
- status = NVME_SC_CMD_SEQ_ERROR | NVME_SC_DNR;
+ status = NVME_SC_CMD_SEQ_ERROR | NVME_STATUS_DNR;
break;
case NVME_FEAT_WRITE_PROTECT:
status = nvmet_set_feat_write_protect(req);
break;
default:
req->error_loc = offsetof(struct nvme_common_command, cdw10);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
break;
}
@@ -939,7 +939,7 @@ void nvmet_execute_get_features(struct nvmet_req *req)
if (!(req->cmd->common.cdw11 & cpu_to_le32(1 << 0))) {
req->error_loc =
offsetof(struct nvme_common_command, cdw11);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
break;
}
@@ -952,7 +952,7 @@ void nvmet_execute_get_features(struct nvmet_req *req)
default:
req->error_loc =
offsetof(struct nvme_common_command, cdw10);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
break;
}
@@ -969,7 +969,7 @@ void nvmet_execute_async_event(struct nvmet_req *req)
mutex_lock(&ctrl->lock);
if (ctrl->nr_async_event_cmds >= NVMET_ASYNC_EVENTS) {
mutex_unlock(&ctrl->lock);
- nvmet_req_complete(req, NVME_SC_ASYNC_LIMIT | NVME_SC_DNR);
+ nvmet_req_complete(req, NVME_SC_ASYNC_LIMIT | NVME_STATUS_DNR);
return;
}
ctrl->async_event_cmds[ctrl->nr_async_event_cmds++] = req;
@@ -1006,7 +1006,7 @@ u16 nvmet_parse_admin_cmd(struct nvmet_req *req)
if (nvme_is_fabrics(cmd))
return nvmet_parse_fabrics_admin_cmd(req);
if (unlikely(!nvmet_check_auth_status(req)))
- return NVME_SC_AUTH_REQUIRED | NVME_SC_DNR;
+ return NVME_SC_AUTH_REQUIRED | NVME_STATUS_DNR;
if (nvmet_is_disc_subsys(nvmet_req_subsys(req)))
return nvmet_parse_discovery_cmd(req);
diff --git a/drivers/nvme/target/auth.c b/drivers/nvme/target/auth.c
index 7d2633940f9b..8bc3f431c77f 100644
--- a/drivers/nvme/target/auth.c
+++ b/drivers/nvme/target/auth.c
@@ -314,7 +314,7 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
req->sq->dhchap_c1,
challenge, shash_len);
if (ret)
- goto out_free_response;
+ goto out_free_challenge;
}
pr_debug("ctrl %d qid %d host response seq %u transaction %d\n",
@@ -325,7 +325,7 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
GFP_KERNEL);
if (!shash) {
ret = -ENOMEM;
- goto out_free_response;
+ goto out_free_challenge;
}
shash->tfm = shash_tfm;
ret = crypto_shash_init(shash);
@@ -361,9 +361,10 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
goto out;
ret = crypto_shash_final(shash, response);
out:
+ kfree(shash);
+out_free_challenge:
if (challenge != req->sq->dhchap_c1)
kfree(challenge);
- kfree(shash);
out_free_response:
nvme_auth_free_key(transformed_key);
out_free_tfm:
@@ -427,14 +428,14 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
req->sq->dhchap_c2,
challenge, shash_len);
if (ret)
- goto out_free_response;
+ goto out_free_challenge;
}
shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(shash_tfm),
GFP_KERNEL);
if (!shash) {
ret = -ENOMEM;
- goto out_free_response;
+ goto out_free_challenge;
}
shash->tfm = shash_tfm;
@@ -471,9 +472,10 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
goto out;
ret = crypto_shash_final(shash, response);
out:
+ kfree(shash);
+out_free_challenge:
if (challenge != req->sq->dhchap_c2)
kfree(challenge);
- kfree(shash);
out_free_response:
nvme_auth_free_key(transformed_key);
out_free_tfm:
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 4ff460ba2826..ed2424f8a396 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -16,6 +16,7 @@
#include "trace.h"
#include "nvmet.h"
+#include "debugfs.h"
struct kmem_cache *nvmet_bvec_cache;
struct workqueue_struct *buffered_io_wq;
@@ -55,18 +56,18 @@ inline u16 errno_to_nvme_status(struct nvmet_req *req, int errno)
return NVME_SC_SUCCESS;
case -ENOSPC:
req->error_loc = offsetof(struct nvme_rw_command, length);
- return NVME_SC_CAP_EXCEEDED | NVME_SC_DNR;
+ return NVME_SC_CAP_EXCEEDED | NVME_STATUS_DNR;
case -EREMOTEIO:
req->error_loc = offsetof(struct nvme_rw_command, slba);
- return NVME_SC_LBA_RANGE | NVME_SC_DNR;
+ return NVME_SC_LBA_RANGE | NVME_STATUS_DNR;
case -EOPNOTSUPP:
req->error_loc = offsetof(struct nvme_common_command, opcode);
switch (req->cmd->common.opcode) {
case nvme_cmd_dsm:
case nvme_cmd_write_zeroes:
- return NVME_SC_ONCS_NOT_SUPPORTED | NVME_SC_DNR;
+ return NVME_SC_ONCS_NOT_SUPPORTED | NVME_STATUS_DNR;
default:
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
break;
case -ENODATA:
@@ -76,7 +77,7 @@ inline u16 errno_to_nvme_status(struct nvmet_req *req, int errno)
fallthrough;
default:
req->error_loc = offsetof(struct nvme_common_command, opcode);
- return NVME_SC_INTERNAL | NVME_SC_DNR;
+ return NVME_SC_INTERNAL | NVME_STATUS_DNR;
}
}
@@ -86,7 +87,7 @@ u16 nvmet_report_invalid_opcode(struct nvmet_req *req)
req->sq->qid);
req->error_loc = offsetof(struct nvme_common_command, opcode);
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
static struct nvmet_subsys *nvmet_find_get_subsys(struct nvmet_port *port,
@@ -97,7 +98,7 @@ u16 nvmet_copy_to_sgl(struct nvmet_req *req, off_t off, const void *buf,
{
if (sg_pcopy_from_buffer(req->sg, req->sg_cnt, buf, len, off) != len) {
req->error_loc = offsetof(struct nvme_common_command, dptr);
- return NVME_SC_SGL_INVALID_DATA | NVME_SC_DNR;
+ return NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR;
}
return 0;
}
@@ -106,7 +107,7 @@ u16 nvmet_copy_from_sgl(struct nvmet_req *req, off_t off, void *buf, size_t len)
{
if (sg_pcopy_to_buffer(req->sg, req->sg_cnt, buf, len, off) != len) {
req->error_loc = offsetof(struct nvme_common_command, dptr);
- return NVME_SC_SGL_INVALID_DATA | NVME_SC_DNR;
+ return NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR;
}
return 0;
}
@@ -115,7 +116,7 @@ u16 nvmet_zero_sgl(struct nvmet_req *req, off_t off, size_t len)
{
if (sg_zero_buffer(req->sg, req->sg_cnt, len, off) != len) {
req->error_loc = offsetof(struct nvme_common_command, dptr);
- return NVME_SC_SGL_INVALID_DATA | NVME_SC_DNR;
+ return NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR;
}
return 0;
}
@@ -145,7 +146,7 @@ static void nvmet_async_events_failall(struct nvmet_ctrl *ctrl)
while (ctrl->nr_async_event_cmds) {
req = ctrl->async_event_cmds[--ctrl->nr_async_event_cmds];
mutex_unlock(&ctrl->lock);
- nvmet_req_complete(req, NVME_SC_INTERNAL | NVME_SC_DNR);
+ nvmet_req_complete(req, NVME_SC_INTERNAL | NVME_STATUS_DNR);
mutex_lock(&ctrl->lock);
}
mutex_unlock(&ctrl->lock);
@@ -444,7 +445,7 @@ u16 nvmet_req_find_ns(struct nvmet_req *req)
req->error_loc = offsetof(struct nvme_common_command, nsid);
if (nvmet_subsys_nsid_exists(subsys, nsid))
return NVME_SC_INTERNAL_PATH_ERROR;
- return NVME_SC_INVALID_NS | NVME_SC_DNR;
+ return NVME_SC_INVALID_NS | NVME_STATUS_DNR;
}
percpu_ref_get(&req->ns->ref);
@@ -904,7 +905,7 @@ static u16 nvmet_parse_io_cmd(struct nvmet_req *req)
return nvmet_parse_fabrics_io_cmd(req);
if (unlikely(!nvmet_check_auth_status(req)))
- return NVME_SC_AUTH_REQUIRED | NVME_SC_DNR;
+ return NVME_SC_AUTH_REQUIRED | NVME_STATUS_DNR;
ret = nvmet_check_ctrl_status(req);
if (unlikely(ret))
@@ -967,7 +968,7 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
/* no support for fused commands yet */
if (unlikely(flags & (NVME_CMD_FUSE_FIRST | NVME_CMD_FUSE_SECOND))) {
req->error_loc = offsetof(struct nvme_common_command, flags);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto fail;
}
@@ -978,7 +979,7 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
*/
if (unlikely((flags & NVME_CMD_SGL_ALL) != NVME_CMD_SGL_METABUF)) {
req->error_loc = offsetof(struct nvme_common_command, flags);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto fail;
}
@@ -996,7 +997,7 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
trace_nvmet_req_init(req, req->cmd);
if (unlikely(!percpu_ref_tryget_live(&sq->ref))) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto fail;
}
@@ -1023,7 +1024,7 @@ bool nvmet_check_transfer_len(struct nvmet_req *req, size_t len)
{
if (unlikely(len != req->transfer_len)) {
req->error_loc = offsetof(struct nvme_common_command, dptr);
- nvmet_req_complete(req, NVME_SC_SGL_INVALID_DATA | NVME_SC_DNR);
+ nvmet_req_complete(req, NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR);
return false;
}
@@ -1035,7 +1036,7 @@ bool nvmet_check_data_len_lte(struct nvmet_req *req, size_t data_len)
{
if (unlikely(data_len > req->transfer_len)) {
req->error_loc = offsetof(struct nvme_common_command, dptr);
- nvmet_req_complete(req, NVME_SC_SGL_INVALID_DATA | NVME_SC_DNR);
+ nvmet_req_complete(req, NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR);
return false;
}
@@ -1304,18 +1305,18 @@ u16 nvmet_check_ctrl_status(struct nvmet_req *req)
if (unlikely(!(req->sq->ctrl->cc & NVME_CC_ENABLE))) {
pr_err("got cmd %d while CC.EN == 0 on qid = %d\n",
req->cmd->common.opcode, req->sq->qid);
- return NVME_SC_CMD_SEQ_ERROR | NVME_SC_DNR;
+ return NVME_SC_CMD_SEQ_ERROR | NVME_STATUS_DNR;
}
if (unlikely(!(req->sq->ctrl->csts & NVME_CSTS_RDY))) {
pr_err("got cmd %d while CSTS.RDY == 0 on qid = %d\n",
req->cmd->common.opcode, req->sq->qid);
- return NVME_SC_CMD_SEQ_ERROR | NVME_SC_DNR;
+ return NVME_SC_CMD_SEQ_ERROR | NVME_STATUS_DNR;
}
if (unlikely(!nvmet_check_auth_status(req))) {
pr_warn("qid %d not authenticated\n", req->sq->qid);
- return NVME_SC_AUTH_REQUIRED | NVME_SC_DNR;
+ return NVME_SC_AUTH_REQUIRED | NVME_STATUS_DNR;
}
return 0;
}
@@ -1389,7 +1390,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
int ret;
u16 status;
- status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
+ status = NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR;
subsys = nvmet_find_get_subsys(req->port, subsysnqn);
if (!subsys) {
pr_warn("connect request for invalid subsystem %s!\n",
@@ -1405,7 +1406,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
hostnqn, subsysnqn);
req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(hostnqn);
up_read(&nvmet_config_sem);
- status = NVME_SC_CONNECT_INVALID_HOST | NVME_SC_DNR;
+ status = NVME_SC_CONNECT_INVALID_HOST | NVME_STATUS_DNR;
req->error_loc = offsetof(struct nvme_common_command, dptr);
goto out_put_subsystem;
}
@@ -1456,7 +1457,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
subsys->cntlid_min, subsys->cntlid_max,
GFP_KERNEL);
if (ret < 0) {
- status = NVME_SC_CONNECT_CTRL_BUSY | NVME_SC_DNR;
+ status = NVME_SC_CONNECT_CTRL_BUSY | NVME_STATUS_DNR;
goto out_free_sqs;
}
ctrl->cntlid = ret;
@@ -1479,6 +1480,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
mutex_lock(&subsys->lock);
list_add_tail(&ctrl->subsys_entry, &subsys->ctrls);
nvmet_setup_p2p_ns_map(ctrl, req);
+ nvmet_debugfs_ctrl_setup(ctrl);
mutex_unlock(&subsys->lock);
*ctrlp = ctrl;
@@ -1513,6 +1515,8 @@ static void nvmet_ctrl_free(struct kref *ref)
nvmet_destroy_auth(ctrl);
+ nvmet_debugfs_ctrl_free(ctrl);
+
ida_free(&cntlid_ida, ctrl->cntlid);
nvmet_async_events_free(ctrl);
@@ -1539,6 +1543,14 @@ void nvmet_ctrl_fatal_error(struct nvmet_ctrl *ctrl)
}
EXPORT_SYMBOL_GPL(nvmet_ctrl_fatal_error);
+ssize_t nvmet_ctrl_host_traddr(struct nvmet_ctrl *ctrl,
+ char *traddr, size_t traddr_len)
+{
+ if (!ctrl->ops->host_traddr)
+ return -EOPNOTSUPP;
+ return ctrl->ops->host_traddr(ctrl, traddr, traddr_len);
+}
+
static struct nvmet_subsys *nvmet_find_get_subsys(struct nvmet_port *port,
const char *subsysnqn)
{
@@ -1633,8 +1645,14 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
INIT_LIST_HEAD(&subsys->ctrls);
INIT_LIST_HEAD(&subsys->hosts);
+ ret = nvmet_debugfs_subsys_setup(subsys);
+ if (ret)
+ goto free_subsysnqn;
+
return subsys;
+free_subsysnqn:
+ kfree(subsys->subsysnqn);
free_fr:
kfree(subsys->firmware_rev);
free_mn:
@@ -1651,6 +1669,8 @@ static void nvmet_subsys_free(struct kref *ref)
WARN_ON_ONCE(!xa_empty(&subsys->namespaces));
+ nvmet_debugfs_subsys_free(subsys);
+
xa_destroy(&subsys->namespaces);
nvmet_passthru_subsys_free(subsys);
@@ -1705,11 +1725,18 @@ static int __init nvmet_init(void)
if (error)
goto out_free_nvmet_work_queue;
- error = nvmet_init_configfs();
+ error = nvmet_init_debugfs();
if (error)
goto out_exit_discovery;
+
+ error = nvmet_init_configfs();
+ if (error)
+ goto out_exit_debugfs;
+
return 0;
+out_exit_debugfs:
+ nvmet_exit_debugfs();
out_exit_discovery:
nvmet_exit_discovery();
out_free_nvmet_work_queue:
@@ -1726,6 +1753,7 @@ out_destroy_bvec_cache:
static void __exit nvmet_exit(void)
{
nvmet_exit_configfs();
+ nvmet_exit_debugfs();
nvmet_exit_discovery();
ida_destroy(&cntlid_ida);
destroy_workqueue(nvmet_wq);
diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c
new file mode 100644
index 000000000000..cb2befc8619e
--- /dev/null
+++ b/drivers/nvme/target/debugfs.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DebugFS interface for the NVMe target.
+ * Copyright (c) 2022-2024 Shadow
+ * Copyright (c) 2024 SUSE LLC
+ */
+
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include "nvmet.h"
+#include "debugfs.h"
+
+struct dentry *nvmet_debugfs;
+
+#define NVMET_DEBUGFS_ATTR(field) \
+ static int field##_open(struct inode *inode, struct file *file) \
+ { return single_open(file, field##_show, inode->i_private); } \
+ \
+ static const struct file_operations field##_fops = { \
+ .open = field##_open, \
+ .read = seq_read, \
+ .release = single_release, \
+ }
+
+#define NVMET_DEBUGFS_RW_ATTR(field) \
+ static int field##_open(struct inode *inode, struct file *file) \
+ { return single_open(file, field##_show, inode->i_private); } \
+ \
+ static const struct file_operations field##_fops = { \
+ .open = field##_open, \
+ .read = seq_read, \
+ .write = field##_write, \
+ .release = single_release, \
+ }
+
+static int nvmet_ctrl_hostnqn_show(struct seq_file *m, void *p)
+{
+ struct nvmet_ctrl *ctrl = m->private;
+
+ seq_puts(m, ctrl->hostnqn);
+ return 0;
+}
+NVMET_DEBUGFS_ATTR(nvmet_ctrl_hostnqn);
+
+static int nvmet_ctrl_kato_show(struct seq_file *m, void *p)
+{
+ struct nvmet_ctrl *ctrl = m->private;
+
+ seq_printf(m, "%d\n", ctrl->kato);
+ return 0;
+}
+NVMET_DEBUGFS_ATTR(nvmet_ctrl_kato);
+
+static int nvmet_ctrl_port_show(struct seq_file *m, void *p)
+{
+ struct nvmet_ctrl *ctrl = m->private;
+
+ seq_printf(m, "%d\n", le16_to_cpu(ctrl->port->disc_addr.portid));
+ return 0;
+}
+NVMET_DEBUGFS_ATTR(nvmet_ctrl_port);
+
+static const char *const csts_state_names[] = {
+ [NVME_CSTS_RDY] = "ready",
+ [NVME_CSTS_CFS] = "fatal",
+ [NVME_CSTS_NSSRO] = "reset",
+ [NVME_CSTS_SHST_OCCUR] = "shutdown",
+ [NVME_CSTS_SHST_CMPLT] = "completed",
+ [NVME_CSTS_PP] = "paused",
+};
+
+static int nvmet_ctrl_state_show(struct seq_file *m, void *p)
+{
+ struct nvmet_ctrl *ctrl = m->private;
+ bool sep = false;
+ int i;
+
+ for (i = 0; i < 7; i++) {
+ int state = BIT(i);
+
+ if (!(ctrl->csts & state))
+ continue;
+ if (sep)
+ seq_puts(m, "|");
+ sep = true;
+ if (csts_state_names[state])
+ seq_puts(m, csts_state_names[state]);
+ else
+ seq_printf(m, "%d", state);
+ }
+ if (sep)
+ seq_printf(m, "\n");
+ return 0;
+}
+
+static ssize_t nvmet_ctrl_state_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *m = file->private_data;
+ struct nvmet_ctrl *ctrl = m->private;
+ char reset[16];
+
+ if (count >= sizeof(reset))
+ return -EINVAL;
+ if (copy_from_user(reset, buf, count))
+ return -EFAULT;
+ if (!memcmp(reset, "fatal", 5))
+ nvmet_ctrl_fatal_error(ctrl);
+ else
+ return -EINVAL;
+ return count;
+}
+NVMET_DEBUGFS_RW_ATTR(nvmet_ctrl_state);
+
+static int nvmet_ctrl_host_traddr_show(struct seq_file *m, void *p)
+{
+ struct nvmet_ctrl *ctrl = m->private;
+ ssize_t size;
+ char buf[NVMF_TRADDR_SIZE + 1];
+
+ size = nvmet_ctrl_host_traddr(ctrl, buf, NVMF_TRADDR_SIZE);
+ if (size < 0) {
+ buf[0] = '\0';
+ size = 0;
+ }
+ buf[size] = '\0';
+ seq_printf(m, "%s\n", buf);
+ return 0;
+}
+NVMET_DEBUGFS_ATTR(nvmet_ctrl_host_traddr);
+
+int nvmet_debugfs_ctrl_setup(struct nvmet_ctrl *ctrl)
+{
+ char name[32];
+ struct dentry *parent = ctrl->subsys->debugfs_dir;
+ int ret;
+
+ if (!parent)
+ return -ENODEV;
+ snprintf(name, sizeof(name), "ctrl%d", ctrl->cntlid);
+ ctrl->debugfs_dir = debugfs_create_dir(name, parent);
+ if (IS_ERR(ctrl->debugfs_dir)) {
+ ret = PTR_ERR(ctrl->debugfs_dir);
+ ctrl->debugfs_dir = NULL;
+ return ret;
+ }
+ debugfs_create_file("port", S_IRUSR, ctrl->debugfs_dir, ctrl,
+ &nvmet_ctrl_port_fops);
+ debugfs_create_file("hostnqn", S_IRUSR, ctrl->debugfs_dir, ctrl,
+ &nvmet_ctrl_hostnqn_fops);
+ debugfs_create_file("kato", S_IRUSR, ctrl->debugfs_dir, ctrl,
+ &nvmet_ctrl_kato_fops);
+ debugfs_create_file("state", S_IRUSR | S_IWUSR, ctrl->debugfs_dir, ctrl,
+ &nvmet_ctrl_state_fops);
+ debugfs_create_file("host_traddr", S_IRUSR, ctrl->debugfs_dir, ctrl,
+ &nvmet_ctrl_host_traddr_fops);
+ return 0;
+}
+
+void nvmet_debugfs_ctrl_free(struct nvmet_ctrl *ctrl)
+{
+ debugfs_remove_recursive(ctrl->debugfs_dir);
+}
+
+int nvmet_debugfs_subsys_setup(struct nvmet_subsys *subsys)
+{
+ int ret = 0;
+
+ subsys->debugfs_dir = debugfs_create_dir(subsys->subsysnqn,
+ nvmet_debugfs);
+ if (IS_ERR(subsys->debugfs_dir)) {
+ ret = PTR_ERR(subsys->debugfs_dir);
+ subsys->debugfs_dir = NULL;
+ }
+ return ret;
+}
+
+void nvmet_debugfs_subsys_free(struct nvmet_subsys *subsys)
+{
+ debugfs_remove_recursive(subsys->debugfs_dir);
+}
+
+int __init nvmet_init_debugfs(void)
+{
+ struct dentry *parent;
+
+ parent = debugfs_create_dir("nvmet", NULL);
+ if (IS_ERR(parent)) {
+ pr_warn("%s: failed to create debugfs directory\n", "nvmet");
+ return PTR_ERR(parent);
+ }
+ nvmet_debugfs = parent;
+ return 0;
+}
+
+void nvmet_exit_debugfs(void)
+{
+ debugfs_remove_recursive(nvmet_debugfs);
+}
diff --git a/drivers/nvme/target/debugfs.h b/drivers/nvme/target/debugfs.h
new file mode 100644
index 000000000000..cfb8bbf6a297
--- /dev/null
+++ b/drivers/nvme/target/debugfs.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * DebugFS interface for the NVMe target.
+ * Copyright (c) 2022-2024 Shadow
+ * Copyright (c) 2024 SUSE LLC
+ */
+#ifndef NVMET_DEBUGFS_H
+#define NVMET_DEBUGFS_H
+
+#include <linux/types.h>
+
+#ifdef CONFIG_NVME_TARGET_DEBUGFS
+int nvmet_debugfs_subsys_setup(struct nvmet_subsys *subsys);
+void nvmet_debugfs_subsys_free(struct nvmet_subsys *subsys);
+int nvmet_debugfs_ctrl_setup(struct nvmet_ctrl *ctrl);
+void nvmet_debugfs_ctrl_free(struct nvmet_ctrl *ctrl);
+
+int __init nvmet_init_debugfs(void);
+void nvmet_exit_debugfs(void);
+#else
+static inline int nvmet_debugfs_subsys_setup(struct nvmet_subsys *subsys)
+{
+ return 0;
+}
+static inline void nvmet_debugfs_subsys_free(struct nvmet_subsys *subsys){}
+
+static inline int nvmet_debugfs_ctrl_setup(struct nvmet_ctrl *ctrl)
+{
+ return 0;
+}
+static inline void nvmet_debugfs_ctrl_free(struct nvmet_ctrl *ctrl) {}
+
+static inline int __init nvmet_init_debugfs(void)
+{
+ return 0;
+}
+
+static inline void nvmet_exit_debugfs(void) {}
+
+#endif
+
+#endif /* NVMET_DEBUGFS_H */
diff --git a/drivers/nvme/target/discovery.c b/drivers/nvme/target/discovery.c
index ce54da8c6b36..28843df5fa7c 100644
--- a/drivers/nvme/target/discovery.c
+++ b/drivers/nvme/target/discovery.c
@@ -179,7 +179,7 @@ static void nvmet_execute_disc_get_log_page(struct nvmet_req *req)
if (req->cmd->get_log_page.lid != NVME_LOG_DISC) {
req->error_loc =
offsetof(struct nvme_get_log_page_command, lid);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto out;
}
@@ -187,7 +187,7 @@ static void nvmet_execute_disc_get_log_page(struct nvmet_req *req)
if (offset & 0x3) {
req->error_loc =
offsetof(struct nvme_get_log_page_command, lpo);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto out;
}
@@ -256,7 +256,7 @@ static void nvmet_execute_disc_identify(struct nvmet_req *req)
if (req->cmd->identify.cns != NVME_ID_CNS_CTRL) {
req->error_loc = offsetof(struct nvme_identify, cns);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto out;
}
@@ -320,7 +320,7 @@ static void nvmet_execute_disc_set_features(struct nvmet_req *req)
default:
req->error_loc =
offsetof(struct nvme_common_command, cdw10);
- stat = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ stat = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
break;
}
@@ -345,7 +345,7 @@ static void nvmet_execute_disc_get_features(struct nvmet_req *req)
default:
req->error_loc =
offsetof(struct nvme_common_command, cdw10);
- stat = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ stat = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
break;
}
@@ -361,7 +361,7 @@ u16 nvmet_parse_discovery_cmd(struct nvmet_req *req)
cmd->common.opcode);
req->error_loc =
offsetof(struct nvme_common_command, opcode);
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
switch (cmd->common.opcode) {
@@ -386,7 +386,7 @@ u16 nvmet_parse_discovery_cmd(struct nvmet_req *req)
default:
pr_debug("unhandled cmd %d\n", cmd->common.opcode);
req->error_loc = offsetof(struct nvme_common_command, opcode);
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
}
diff --git a/drivers/nvme/target/fabrics-cmd-auth.c b/drivers/nvme/target/fabrics-cmd-auth.c
index cb34d644ed08..3f2857c17d95 100644
--- a/drivers/nvme/target/fabrics-cmd-auth.c
+++ b/drivers/nvme/target/fabrics-cmd-auth.c
@@ -189,26 +189,26 @@ void nvmet_execute_auth_send(struct nvmet_req *req)
u8 dhchap_status;
if (req->cmd->auth_send.secp != NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc =
offsetof(struct nvmf_auth_send_command, secp);
goto done;
}
if (req->cmd->auth_send.spsp0 != 0x01) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc =
offsetof(struct nvmf_auth_send_command, spsp0);
goto done;
}
if (req->cmd->auth_send.spsp1 != 0x01) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc =
offsetof(struct nvmf_auth_send_command, spsp1);
goto done;
}
tl = le32_to_cpu(req->cmd->auth_send.tl);
if (!tl) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc =
offsetof(struct nvmf_auth_send_command, tl);
goto done;
@@ -437,26 +437,26 @@ void nvmet_execute_auth_receive(struct nvmet_req *req)
u16 status = 0;
if (req->cmd->auth_receive.secp != NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc =
offsetof(struct nvmf_auth_receive_command, secp);
goto done;
}
if (req->cmd->auth_receive.spsp0 != 0x01) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc =
offsetof(struct nvmf_auth_receive_command, spsp0);
goto done;
}
if (req->cmd->auth_receive.spsp1 != 0x01) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc =
offsetof(struct nvmf_auth_receive_command, spsp1);
goto done;
}
al = le32_to_cpu(req->cmd->auth_receive.al);
if (!al) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc =
offsetof(struct nvmf_auth_receive_command, al);
goto done;
diff --git a/drivers/nvme/target/fabrics-cmd.c b/drivers/nvme/target/fabrics-cmd.c
index 69d77d34bec1..c4b2eddd5666 100644
--- a/drivers/nvme/target/fabrics-cmd.c
+++ b/drivers/nvme/target/fabrics-cmd.c
@@ -18,7 +18,7 @@ static void nvmet_execute_prop_set(struct nvmet_req *req)
if (req->cmd->prop_set.attrib & 1) {
req->error_loc =
offsetof(struct nvmf_property_set_command, attrib);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto out;
}
@@ -29,7 +29,7 @@ static void nvmet_execute_prop_set(struct nvmet_req *req)
default:
req->error_loc =
offsetof(struct nvmf_property_set_command, offset);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
out:
nvmet_req_complete(req, status);
@@ -50,7 +50,7 @@ static void nvmet_execute_prop_get(struct nvmet_req *req)
val = ctrl->cap;
break;
default:
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
break;
}
} else {
@@ -65,7 +65,7 @@ static void nvmet_execute_prop_get(struct nvmet_req *req)
val = ctrl->csts;
break;
default:
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
break;
}
}
@@ -105,7 +105,7 @@ u16 nvmet_parse_fabrics_admin_cmd(struct nvmet_req *req)
pr_debug("received unknown capsule type 0x%x\n",
cmd->fabrics.fctype);
req->error_loc = offsetof(struct nvmf_common_command, fctype);
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
return 0;
@@ -128,7 +128,7 @@ u16 nvmet_parse_fabrics_io_cmd(struct nvmet_req *req)
pr_debug("received unknown capsule type 0x%x\n",
cmd->fabrics.fctype);
req->error_loc = offsetof(struct nvmf_common_command, fctype);
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
return 0;
@@ -147,14 +147,14 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
pr_warn("queue size zero!\n");
req->error_loc = offsetof(struct nvmf_connect_command, sqsize);
req->cqe->result.u32 = IPO_IATTR_CONNECT_SQE(sqsize);
- ret = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
+ ret = NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR;
goto err;
}
if (ctrl->sqs[qid] != NULL) {
pr_warn("qid %u has already been created\n", qid);
req->error_loc = offsetof(struct nvmf_connect_command, qid);
- return NVME_SC_CMD_SEQ_ERROR | NVME_SC_DNR;
+ return NVME_SC_CMD_SEQ_ERROR | NVME_STATUS_DNR;
}
/* for fabrics, this value applies to only the I/O Submission Queues */
@@ -163,14 +163,14 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
sqsize, mqes, ctrl->cntlid);
req->error_loc = offsetof(struct nvmf_connect_command, sqsize);
req->cqe->result.u32 = IPO_IATTR_CONNECT_SQE(sqsize);
- return NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
+ return NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR;
}
old = cmpxchg(&req->sq->ctrl, NULL, ctrl);
if (old) {
pr_warn("queue already connected!\n");
req->error_loc = offsetof(struct nvmf_connect_command, opcode);
- return NVME_SC_CONNECT_CTRL_BUSY | NVME_SC_DNR;
+ return NVME_SC_CONNECT_CTRL_BUSY | NVME_STATUS_DNR;
}
/* note: convert queue size from 0's-based value to 1's-based value */
@@ -230,14 +230,14 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
pr_warn("invalid connect version (%d).\n",
le16_to_cpu(c->recfmt));
req->error_loc = offsetof(struct nvmf_connect_command, recfmt);
- status = NVME_SC_CONNECT_FORMAT | NVME_SC_DNR;
+ status = NVME_SC_CONNECT_FORMAT | NVME_STATUS_DNR;
goto out;
}
if (unlikely(d->cntlid != cpu_to_le16(0xffff))) {
pr_warn("connect attempt for invalid controller ID %#x\n",
d->cntlid);
- status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
+ status = NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR;
req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(cntlid);
goto out;
}
@@ -257,7 +257,7 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
dhchap_status);
nvmet_ctrl_put(ctrl);
if (dhchap_status == NVME_AUTH_DHCHAP_FAILURE_FAILED)
- status = (NVME_SC_CONNECT_INVALID_HOST | NVME_SC_DNR);
+ status = (NVME_SC_CONNECT_INVALID_HOST | NVME_STATUS_DNR);
else
status = NVME_SC_INTERNAL;
goto out;
@@ -305,7 +305,7 @@ static void nvmet_execute_io_connect(struct nvmet_req *req)
if (c->recfmt != 0) {
pr_warn("invalid connect version (%d).\n",
le16_to_cpu(c->recfmt));
- status = NVME_SC_CONNECT_FORMAT | NVME_SC_DNR;
+ status = NVME_SC_CONNECT_FORMAT | NVME_STATUS_DNR;
goto out;
}
@@ -314,13 +314,13 @@ static void nvmet_execute_io_connect(struct nvmet_req *req)
ctrl = nvmet_ctrl_find_get(d->subsysnqn, d->hostnqn,
le16_to_cpu(d->cntlid), req);
if (!ctrl) {
- status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
+ status = NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR;
goto out;
}
if (unlikely(qid > ctrl->subsys->max_qid)) {
pr_warn("invalid queue id (%d)\n", qid);
- status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
+ status = NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR;
req->cqe->result.u32 = IPO_IATTR_CONNECT_SQE(qid);
goto out_ctrl_put;
}
@@ -350,13 +350,13 @@ u16 nvmet_parse_connect_cmd(struct nvmet_req *req)
pr_debug("invalid command 0x%x on unconnected queue.\n",
cmd->fabrics.opcode);
req->error_loc = offsetof(struct nvme_common_command, opcode);
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
if (cmd->fabrics.fctype != nvme_fabrics_type_connect) {
pr_debug("invalid capsule type 0x%x on unconnected queue.\n",
cmd->fabrics.fctype);
req->error_loc = offsetof(struct nvmf_common_command, fctype);
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
if (cmd->connect.qid == 0)
diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
index 381b4394731f..3ef4beacde32 100644
--- a/drivers/nvme/target/fc.c
+++ b/drivers/nvme/target/fc.c
@@ -2934,6 +2934,38 @@ nvmet_fc_discovery_chg(struct nvmet_port *port)
tgtport->ops->discovery_event(&tgtport->fc_target_port);
}
+static ssize_t
+nvmet_fc_host_traddr(struct nvmet_ctrl *ctrl,
+ char *traddr, size_t traddr_size)
+{
+ struct nvmet_sq *sq = ctrl->sqs[0];
+ struct nvmet_fc_tgt_queue *queue =
+ container_of(sq, struct nvmet_fc_tgt_queue, nvme_sq);
+ struct nvmet_fc_tgtport *tgtport = queue->assoc ? queue->assoc->tgtport : NULL;
+ struct nvmet_fc_hostport *hostport = queue->assoc ? queue->assoc->hostport : NULL;
+ u64 wwnn, wwpn;
+ ssize_t ret = 0;
+
+ if (!tgtport || !nvmet_fc_tgtport_get(tgtport))
+ return -ENODEV;
+ if (!hostport || !nvmet_fc_hostport_get(hostport)) {
+ ret = -ENODEV;
+ goto out_put;
+ }
+
+ if (tgtport->ops->host_traddr) {
+ ret = tgtport->ops->host_traddr(hostport->hosthandle, &wwnn, &wwpn);
+ if (ret)
+ goto out_put_host;
+ ret = snprintf(traddr, traddr_size, "nn-0x%llx:pn-0x%llx", wwnn, wwpn);
+ }
+out_put_host:
+ nvmet_fc_hostport_put(hostport);
+out_put:
+ nvmet_fc_tgtport_put(tgtport);
+ return ret;
+}
+
static const struct nvmet_fabrics_ops nvmet_fc_tgt_fcp_ops = {
.owner = THIS_MODULE,
.type = NVMF_TRTYPE_FC,
@@ -2943,6 +2975,7 @@ static const struct nvmet_fabrics_ops nvmet_fc_tgt_fcp_ops = {
.queue_response = nvmet_fc_fcp_nvme_cmd_done,
.delete_ctrl = nvmet_fc_delete_ctrl,
.discovery_chg = nvmet_fc_discovery_chg,
+ .host_traddr = nvmet_fc_host_traddr,
};
static int __init nvmet_fc_init_module(void)
diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c
index 913cd2ec7a6f..e1abb27927ff 100644
--- a/drivers/nvme/target/fcloop.c
+++ b/drivers/nvme/target/fcloop.c
@@ -492,6 +492,16 @@ fcloop_t2h_host_release(void *hosthandle)
/* host handle ignored for now */
}
+static int
+fcloop_t2h_host_traddr(void *hosthandle, u64 *wwnn, u64 *wwpn)
+{
+ struct fcloop_rport *rport = hosthandle;
+
+ *wwnn = rport->lport->localport->node_name;
+ *wwpn = rport->lport->localport->port_name;
+ return 0;
+}
+
/*
* Simulate reception of RSCN and converting it to a initiator transport
* call to rescan a remote port.
@@ -1074,6 +1084,7 @@ static struct nvmet_fc_target_template tgttemplate = {
.ls_req = fcloop_t2h_ls_req,
.ls_abort = fcloop_t2h_ls_abort,
.host_release = fcloop_t2h_host_release,
+ .host_traddr = fcloop_t2h_host_traddr,
.max_hw_queues = FCLOOP_HW_QUEUES,
.max_sgl_segments = FCLOOP_SGL_SEGS,
.max_dif_sgl_segments = FCLOOP_SGL_SEGS,
diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c
index 6426aac2634a..0bda83d0fc3e 100644
--- a/drivers/nvme/target/io-cmd-bdev.c
+++ b/drivers/nvme/target/io-cmd-bdev.c
@@ -61,15 +61,17 @@ static void nvmet_bdev_ns_enable_integrity(struct nvmet_ns *ns)
{
struct blk_integrity *bi = bdev_get_integrity(ns->bdev);
- if (bi) {
+ if (!bi)
+ return;
+
+ if (bi->csum_type == BLK_INTEGRITY_CSUM_CRC) {
ns->metadata_size = bi->tuple_size;
- if (bi->profile == &t10_pi_type1_crc)
+ if (bi->flags & BLK_INTEGRITY_REF_TAG)
ns->pi_type = NVME_NS_DPS_PI_TYPE1;
- else if (bi->profile == &t10_pi_type3_crc)
- ns->pi_type = NVME_NS_DPS_PI_TYPE3;
else
- /* Unsupported metadata type */
- ns->metadata_size = 0;
+ ns->pi_type = NVME_NS_DPS_PI_TYPE3;
+ } else {
+ ns->metadata_size = 0;
}
}
@@ -102,7 +104,7 @@ int nvmet_bdev_ns_enable(struct nvmet_ns *ns)
ns->pi_type = 0;
ns->metadata_size = 0;
- if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY_T10))
+ if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY))
nvmet_bdev_ns_enable_integrity(ns);
if (bdev_is_zoned(ns->bdev)) {
@@ -135,11 +137,11 @@ u16 blk_to_nvme_status(struct nvmet_req *req, blk_status_t blk_sts)
*/
switch (blk_sts) {
case BLK_STS_NOSPC:
- status = NVME_SC_CAP_EXCEEDED | NVME_SC_DNR;
+ status = NVME_SC_CAP_EXCEEDED | NVME_STATUS_DNR;
req->error_loc = offsetof(struct nvme_rw_command, length);
break;
case BLK_STS_TARGET:
- status = NVME_SC_LBA_RANGE | NVME_SC_DNR;
+ status = NVME_SC_LBA_RANGE | NVME_STATUS_DNR;
req->error_loc = offsetof(struct nvme_rw_command, slba);
break;
case BLK_STS_NOTSUPP:
@@ -147,10 +149,10 @@ u16 blk_to_nvme_status(struct nvmet_req *req, blk_status_t blk_sts)
switch (req->cmd->common.opcode) {
case nvme_cmd_dsm:
case nvme_cmd_write_zeroes:
- status = NVME_SC_ONCS_NOT_SUPPORTED | NVME_SC_DNR;
+ status = NVME_SC_ONCS_NOT_SUPPORTED | NVME_STATUS_DNR;
break;
default:
- status = NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ status = NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
break;
case BLK_STS_MEDIUM:
@@ -159,7 +161,7 @@ u16 blk_to_nvme_status(struct nvmet_req *req, blk_status_t blk_sts)
break;
case BLK_STS_IOERR:
default:
- status = NVME_SC_INTERNAL | NVME_SC_DNR;
+ status = NVME_SC_INTERNAL | NVME_STATUS_DNR;
req->error_loc = offsetof(struct nvme_common_command, opcode);
}
@@ -356,7 +358,7 @@ u16 nvmet_bdev_flush(struct nvmet_req *req)
return 0;
if (blkdev_issue_flush(req->ns->bdev))
- return NVME_SC_INTERNAL | NVME_SC_DNR;
+ return NVME_SC_INTERNAL | NVME_STATUS_DNR;
return 0;
}
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index e589915ddef8..e32790d8fc26 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -555,6 +555,10 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
goto out;
}
+ ret = nvme_add_ctrl(&ctrl->ctrl);
+ if (ret)
+ goto out_put_ctrl;
+
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
WARN_ON_ONCE(1);
@@ -611,6 +615,7 @@ out_free_queues:
kfree(ctrl->queues);
out_uninit_ctrl:
nvme_uninit_ctrl(&ctrl->ctrl);
+out_put_ctrl:
nvme_put_ctrl(&ctrl->ctrl);
out:
if (ret > 0)
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 2f22b07eab29..190f55e6d753 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -230,7 +230,9 @@ struct nvmet_ctrl {
struct device *p2p_client;
struct radix_tree_root p2p_ns_map;
-
+#ifdef CONFIG_NVME_TARGET_DEBUGFS
+ struct dentry *debugfs_dir;
+#endif
spinlock_t error_lock;
u64 err_counter;
struct nvme_error_slot slots[NVMET_ERROR_LOG_SLOTS];
@@ -262,7 +264,9 @@ struct nvmet_subsys {
struct list_head hosts;
bool allow_any_host;
-
+#ifdef CONFIG_NVME_TARGET_DEBUGFS
+ struct dentry *debugfs_dir;
+#endif
u16 max_qid;
u64 ver;
@@ -350,6 +354,8 @@ struct nvmet_fabrics_ops {
void (*delete_ctrl)(struct nvmet_ctrl *ctrl);
void (*disc_traddr)(struct nvmet_req *req,
struct nvmet_port *port, char *traddr);
+ ssize_t (*host_traddr)(struct nvmet_ctrl *ctrl,
+ char *traddr, size_t traddr_len);
u16 (*install_queue)(struct nvmet_sq *nvme_sq);
void (*discovery_chg)(struct nvmet_port *port);
u8 (*get_mdts)(const struct nvmet_ctrl *ctrl);
@@ -498,6 +504,8 @@ struct nvmet_ctrl *nvmet_ctrl_find_get(const char *subsysnqn,
struct nvmet_req *req);
void nvmet_ctrl_put(struct nvmet_ctrl *ctrl);
u16 nvmet_check_ctrl_status(struct nvmet_req *req);
+ssize_t nvmet_ctrl_host_traddr(struct nvmet_ctrl *ctrl,
+ char *traddr, size_t traddr_len);
struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
enum nvme_subsys_type type);
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index f003782d4ecf..24d0e2418d2e 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -306,7 +306,7 @@ static void nvmet_passthru_execute_cmd(struct nvmet_req *req)
ns = nvme_find_get_ns(ctrl, nsid);
if (unlikely(!ns)) {
pr_err("failed to get passthru ns nsid:%u\n", nsid);
- status = NVME_SC_INVALID_NS | NVME_SC_DNR;
+ status = NVME_SC_INVALID_NS | NVME_STATUS_DNR;
goto out;
}
@@ -426,7 +426,7 @@ u16 nvmet_parse_passthru_io_cmd(struct nvmet_req *req)
* emulated in the future if regular targets grow support for
* this feature.
*/
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
return nvmet_setup_passthru_command(req);
@@ -478,7 +478,7 @@ static u16 nvmet_passthru_get_set_features(struct nvmet_req *req)
case NVME_FEAT_RESV_PERSIST:
/* No reservations, see nvmet_parse_passthru_io_cmd() */
default:
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
}
}
@@ -546,7 +546,7 @@ u16 nvmet_parse_passthru_admin_cmd(struct nvmet_req *req)
req->p.use_workqueue = true;
return NVME_SC_SUCCESS;
}
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
case NVME_ID_CNS_NS:
req->execute = nvmet_passthru_execute_cmd;
req->p.use_workqueue = true;
@@ -558,7 +558,7 @@ u16 nvmet_parse_passthru_admin_cmd(struct nvmet_req *req)
req->p.use_workqueue = true;
return NVME_SC_SUCCESS;
}
- return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
default:
return nvmet_setup_passthru_command(req);
}
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
index 689bb5d3cfdc..1eff8ca6a5f1 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
@@ -852,12 +852,12 @@ static u16 nvmet_rdma_map_sgl_inline(struct nvmet_rdma_rsp *rsp)
if (!nvme_is_write(rsp->req.cmd)) {
rsp->req.error_loc =
offsetof(struct nvme_common_command, opcode);
- return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
if (off + len > rsp->queue->dev->inline_data_size) {
pr_err("invalid inline data offset!\n");
- return NVME_SC_SGL_INVALID_OFFSET | NVME_SC_DNR;
+ return NVME_SC_SGL_INVALID_OFFSET | NVME_STATUS_DNR;
}
/* no data command? */
@@ -919,7 +919,7 @@ static u16 nvmet_rdma_map_sgl(struct nvmet_rdma_rsp *rsp)
pr_err("invalid SGL subtype: %#x\n", sgl->type);
rsp->req.error_loc =
offsetof(struct nvme_common_command, dptr);
- return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
case NVME_KEY_SGL_FMT_DATA_DESC:
switch (sgl->type & 0xf) {
@@ -931,12 +931,12 @@ static u16 nvmet_rdma_map_sgl(struct nvmet_rdma_rsp *rsp)
pr_err("invalid SGL subtype: %#x\n", sgl->type);
rsp->req.error_loc =
offsetof(struct nvme_common_command, dptr);
- return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
default:
pr_err("invalid SGL type: %#x\n", sgl->type);
rsp->req.error_loc = offsetof(struct nvme_common_command, dptr);
- return NVME_SC_SGL_INVALID_TYPE | NVME_SC_DNR;
+ return NVME_SC_SGL_INVALID_TYPE | NVME_STATUS_DNR;
}
}
@@ -2000,6 +2000,17 @@ static void nvmet_rdma_disc_port_addr(struct nvmet_req *req,
}
}
+static ssize_t nvmet_rdma_host_port_addr(struct nvmet_ctrl *ctrl,
+ char *traddr, size_t traddr_len)
+{
+ struct nvmet_sq *nvme_sq = ctrl->sqs[0];
+ struct nvmet_rdma_queue *queue =
+ container_of(nvme_sq, struct nvmet_rdma_queue, nvme_sq);
+
+ return snprintf(traddr, traddr_len, "%pISc",
+ (struct sockaddr *)&queue->cm_id->route.addr.dst_addr);
+}
+
static u8 nvmet_rdma_get_mdts(const struct nvmet_ctrl *ctrl)
{
if (ctrl->pi_support)
@@ -2024,6 +2035,7 @@ static const struct nvmet_fabrics_ops nvmet_rdma_ops = {
.queue_response = nvmet_rdma_queue_response,
.delete_ctrl = nvmet_rdma_delete_ctrl,
.disc_traddr = nvmet_rdma_disc_port_addr,
+ .host_traddr = nvmet_rdma_host_port_addr,
.get_mdts = nvmet_rdma_get_mdts,
.get_max_queue_size = nvmet_rdma_get_max_queue_size,
};
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 380f22ee3ebb..5bff0d5464d1 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -416,10 +416,10 @@ static int nvmet_tcp_map_data(struct nvmet_tcp_cmd *cmd)
if (sgl->type == ((NVME_SGL_FMT_DATA_DESC << 4) |
NVME_SGL_FMT_OFFSET)) {
if (!nvme_is_write(cmd->req.cmd))
- return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
if (len > cmd->req.port->inline_data_size)
- return NVME_SC_SGL_INVALID_OFFSET | NVME_SC_DNR;
+ return NVME_SC_SGL_INVALID_OFFSET | NVME_STATUS_DNR;
cmd->pdu_len = len;
}
cmd->req.transfer_len += len;
@@ -2167,6 +2167,19 @@ static void nvmet_tcp_disc_port_addr(struct nvmet_req *req,
}
}
+static ssize_t nvmet_tcp_host_port_addr(struct nvmet_ctrl *ctrl,
+ char *traddr, size_t traddr_len)
+{
+ struct nvmet_sq *sq = ctrl->sqs[0];
+ struct nvmet_tcp_queue *queue =
+ container_of(sq, struct nvmet_tcp_queue, nvme_sq);
+
+ if (queue->sockaddr_peer.ss_family == AF_UNSPEC)
+ return -EINVAL;
+ return snprintf(traddr, traddr_len, "%pISc",
+ (struct sockaddr *)&queue->sockaddr_peer);
+}
+
static const struct nvmet_fabrics_ops nvmet_tcp_ops = {
.owner = THIS_MODULE,
.type = NVMF_TRTYPE_TCP,
@@ -2177,6 +2190,7 @@ static const struct nvmet_fabrics_ops nvmet_tcp_ops = {
.delete_ctrl = nvmet_tcp_delete_ctrl,
.install_queue = nvmet_tcp_install_queue,
.disc_traddr = nvmet_tcp_disc_port_addr,
+ .host_traddr = nvmet_tcp_host_port_addr,
};
static int __init nvmet_tcp_init(void)
diff --git a/drivers/nvme/target/zns.c b/drivers/nvme/target/zns.c
index 0021d06041c1..af9e13be7678 100644
--- a/drivers/nvme/target/zns.c
+++ b/drivers/nvme/target/zns.c
@@ -100,7 +100,7 @@ void nvmet_execute_identify_ns_zns(struct nvmet_req *req)
if (le32_to_cpu(req->cmd->identify.nsid) == NVME_NSID_ALL) {
req->error_loc = offsetof(struct nvme_identify, nsid);
- status = NVME_SC_INVALID_NS | NVME_SC_DNR;
+ status = NVME_SC_INVALID_NS | NVME_STATUS_DNR;
goto out;
}
@@ -121,7 +121,7 @@ void nvmet_execute_identify_ns_zns(struct nvmet_req *req)
}
if (!bdev_is_zoned(req->ns->bdev)) {
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc = offsetof(struct nvme_identify, nsid);
goto out;
}
@@ -158,17 +158,17 @@ static u16 nvmet_bdev_validate_zone_mgmt_recv(struct nvmet_req *req)
if (sect >= get_capacity(req->ns->bdev->bd_disk)) {
req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd, slba);
- return NVME_SC_LBA_RANGE | NVME_SC_DNR;
+ return NVME_SC_LBA_RANGE | NVME_STATUS_DNR;
}
if (out_bufsize < sizeof(struct nvme_zone_report)) {
req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd, numd);
- return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
if (req->cmd->zmr.zra != NVME_ZRA_ZONE_REPORT) {
req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd, zra);
- return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
switch (req->cmd->zmr.pr) {
@@ -177,7 +177,7 @@ static u16 nvmet_bdev_validate_zone_mgmt_recv(struct nvmet_req *req)
break;
default:
req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd, pr);
- return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
switch (req->cmd->zmr.zrasf) {
@@ -193,7 +193,7 @@ static u16 nvmet_bdev_validate_zone_mgmt_recv(struct nvmet_req *req)
default:
req->error_loc =
offsetof(struct nvme_zone_mgmt_recv_cmd, zrasf);
- return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
return NVME_SC_SUCCESS;
@@ -341,7 +341,7 @@ static u16 blkdev_zone_mgmt_errno_to_nvme_status(int ret)
return NVME_SC_SUCCESS;
case -EINVAL:
case -EIO:
- return NVME_SC_ZONE_INVALID_TRANSITION | NVME_SC_DNR;
+ return NVME_SC_ZONE_INVALID_TRANSITION | NVME_STATUS_DNR;
default:
return NVME_SC_INTERNAL;
}
@@ -463,7 +463,7 @@ static u16 nvmet_bdev_execute_zmgmt_send_all(struct nvmet_req *req)
default:
/* this is needed to quiet compiler warning */
req->error_loc = offsetof(struct nvme_zone_mgmt_send_cmd, zsa);
- return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
}
return NVME_SC_SUCCESS;
@@ -481,7 +481,7 @@ static void nvmet_bdev_zmgmt_send_work(struct work_struct *w)
if (op == REQ_OP_LAST) {
req->error_loc = offsetof(struct nvme_zone_mgmt_send_cmd, zsa);
- status = NVME_SC_ZONE_INVALID_TRANSITION | NVME_SC_DNR;
+ status = NVME_SC_ZONE_INVALID_TRANSITION | NVME_STATUS_DNR;
goto out;
}
@@ -493,13 +493,13 @@ static void nvmet_bdev_zmgmt_send_work(struct work_struct *w)
if (sect >= get_capacity(bdev->bd_disk)) {
req->error_loc = offsetof(struct nvme_zone_mgmt_send_cmd, slba);
- status = NVME_SC_LBA_RANGE | NVME_SC_DNR;
+ status = NVME_SC_LBA_RANGE | NVME_STATUS_DNR;
goto out;
}
if (sect & (zone_sectors - 1)) {
req->error_loc = offsetof(struct nvme_zone_mgmt_send_cmd, slba);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto out;
}
@@ -551,13 +551,13 @@ void nvmet_bdev_execute_zone_append(struct nvmet_req *req)
if (sect >= get_capacity(req->ns->bdev->bd_disk)) {
req->error_loc = offsetof(struct nvme_rw_command, slba);
- status = NVME_SC_LBA_RANGE | NVME_SC_DNR;
+ status = NVME_SC_LBA_RANGE | NVME_STATUS_DNR;
goto out;
}
if (sect & (bdev_zone_sectors(req->ns->bdev) - 1)) {
req->error_loc = offsetof(struct nvme_rw_command, slba);
- status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto out;
}
@@ -590,7 +590,7 @@ void nvmet_bdev_execute_zone_append(struct nvmet_req *req)
}
if (total_len != nvmet_rw_data_len(req)) {
- status = NVME_SC_INTERNAL | NVME_SC_DNR;
+ status = NVME_SC_INTERNAL | NVME_STATUS_DNR;
goto out_put_bio;
}
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index e1ec3b7200d7..f8dd7eb40fbe 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -396,10 +396,9 @@ static int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
if (!config->base_dev)
return -EINVAL;
- if (config->type == NVMEM_TYPE_FRAM)
- bin_attr_nvmem_eeprom_compat.attr.name = "fram";
-
nvmem->eeprom = bin_attr_nvmem_eeprom_compat;
+ if (config->type == NVMEM_TYPE_FRAM)
+ nvmem->eeprom.attr.name = "fram";
nvmem->eeprom.attr.mode = nvmem_bin_attr_get_umode(nvmem);
nvmem->eeprom.size = nvmem->size;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -463,7 +462,7 @@ static int nvmem_populate_sysfs_cells(struct nvmem_device *nvmem)
"%s@%x,%x", entry->name,
entry->offset,
entry->bit_offset);
- attrs[i].attr.mode = 0444;
+ attrs[i].attr.mode = 0444 & nvmem_bin_attr_get_umode(nvmem);
attrs[i].size = entry->bytes;
attrs[i].read = &nvmem_cell_attr_read;
attrs[i].private = entry;
diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c
index 33678d0af2c2..6c2f80e166e2 100644
--- a/drivers/nvmem/meson-efuse.c
+++ b/drivers/nvmem/meson-efuse.c
@@ -18,18 +18,24 @@ static int meson_efuse_read(void *context, unsigned int offset,
void *val, size_t bytes)
{
struct meson_sm_firmware *fw = context;
+ int ret;
- return meson_sm_call_read(fw, (u8 *)val, bytes, SM_EFUSE_READ, offset,
- bytes, 0, 0, 0);
+ ret = meson_sm_call_read(fw, (u8 *)val, bytes, SM_EFUSE_READ, offset,
+ bytes, 0, 0, 0);
+
+ return ret < 0 ? ret : 0;
}
static int meson_efuse_write(void *context, unsigned int offset,
void *val, size_t bytes)
{
struct meson_sm_firmware *fw = context;
+ int ret;
+
+ ret = meson_sm_call_write(fw, (u8 *)val, bytes, SM_EFUSE_WRITE, offset,
+ bytes, 0, 0, 0);
- return meson_sm_call_write(fw, (u8 *)val, bytes, SM_EFUSE_WRITE, offset,
- bytes, 0, 0, 0);
+ return ret < 0 ? ret : 0;
}
static const struct of_device_id meson_efuse_match[] = {
diff --git a/drivers/nvmem/rmem.c b/drivers/nvmem/rmem.c
index 752d0bf4445e..7f907c5a445e 100644
--- a/drivers/nvmem/rmem.c
+++ b/drivers/nvmem/rmem.c
@@ -46,7 +46,10 @@ static int rmem_read(void *context, unsigned int offset,
memunmap(addr);
- return count;
+ if (count < 0)
+ return count;
+
+ return count == bytes ? 0 : -EIO;
}
static int rmem_probe(struct platform_device *pdev)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 462375b293e4..c94203ce65bb 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -81,7 +81,8 @@ EXPORT_SYMBOL_GPL(of_irq_find_parent);
/*
* These interrupt controllers abuse interrupt-map for unspeakable
* reasons and rely on the core code to *ignore* it (the drivers do
- * their own parsing of the property).
+ * their own parsing of the property). The PAsemi entry covers a
+ * non-sensical interrupt-map that is better left ignored.
*
* If you think of adding to the list for something *new*, think
* again. There is a high chance that you will be sent back to the
@@ -95,6 +96,7 @@ static const char * const of_irq_imap_abusers[] = {
"fsl,ls1043a-extirq",
"fsl,ls1088a-extirq",
"renesas,rza1-irqc",
+ "pasemi,rootbus",
NULL,
};
@@ -293,20 +295,8 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
imaplen -= imap - oldimap;
pr_debug(" -> imaplen=%d\n", imaplen);
}
- if (!match) {
- if (intc) {
- /*
- * The PASEMI Nemo is a known offender, so
- * let's only warn for anyone else.
- */
- WARN(!IS_ENABLED(CONFIG_PPC_PASEMI),
- "%pOF interrupt-map failed, using interrupt-controller\n",
- ipar);
- return 0;
- }
-
+ if (!match)
goto fail;
- }
/*
* Successfully parsed an interrupt-map translation; copy new
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index d35001589d88..aa4d1833f442 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -296,5 +296,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"
endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 175302036890..8ddad57934a6 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -9,6 +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/
ifdef CONFIG_PCI
obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 826b5016a101..8765e2d2aafa 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -12,6 +12,7 @@
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
@@ -354,6 +355,14 @@ void pci_bus_add_device(struct pci_dev *dev)
pci_warn(dev, "device attach failed (%d)\n", retval);
pci_dev_assign_added(dev, true);
+
+ if (IS_ENABLED(CONFIG_OF) && pci_is_bridge(dev)) {
+ retval = of_platform_populate(dev->dev.of_node, NULL, NULL,
+ &dev->dev);
+ if (retval)
+ pci_err(dev, "failed to populate child OF nodes (%d)\n",
+ retval);
+ }
}
EXPORT_SYMBOL_GPL(pci_bus_add_device);
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 51e3dd0ea5ab..b908fe1ae951 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -6,6 +6,7 @@
*/
#define pr_fmt(fmt) "PCI: OF: " fmt
+#include <linux/cleanup.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -13,6 +14,7 @@
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
+#include <linux/platform_device.h>
#include "pci.h"
#ifdef CONFIG_PCI
@@ -25,16 +27,20 @@
*/
int pci_set_of_node(struct pci_dev *dev)
{
- struct device_node *node;
-
if (!dev->bus->dev.of_node)
return 0;
- node = of_pci_find_child_device(dev->bus->dev.of_node, dev->devfn);
+ struct device_node *node __free(device_node) =
+ of_pci_find_child_device(dev->bus->dev.of_node, dev->devfn);
if (!node)
return 0;
- device_set_node(&dev->dev, of_fwnode_handle(node));
+ struct device *pdev __free(put_device) =
+ bus_find_device_by_of_node(&platform_bus_type, node);
+ if (pdev)
+ dev->bus->dev.of_node_reused = true;
+
+ device_set_node(&dev->dev, of_fwnode_handle(no_free_ptr(node)));
return 0;
}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5fbabb4e3425..4c367f13acdc 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -3069,7 +3069,9 @@ int pci_host_probe(struct pci_host_bridge *bridge)
struct pci_bus *bus, *child;
int ret;
+ pci_lock_rescan_remove();
ret = pci_scan_root_bus_bridge(bridge);
+ pci_unlock_rescan_remove();
if (ret < 0) {
dev_err(bridge->dev.parent, "Scanning root bridge failed");
return ret;
diff --git a/drivers/pci/pwrctl/Kconfig b/drivers/pci/pwrctl/Kconfig
new file mode 100644
index 000000000000..f1b824955d4b
--- /dev/null
+++ b/drivers/pci/pwrctl/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+menu "PCI Power control drivers"
+
+config PCI_PWRCTL
+ tristate
+
+config PCI_PWRCTL_PWRSEQ
+ tristate "PCI Power Control driver using the Power Sequencing subsystem"
+ select POWER_SEQUENCING
+ select PCI_PWRCTL
+ default m if ((ATH11K_PCI || ATH12K) && ARCH_QCOM)
+ help
+ Enable support for the PCI power control driver for device
+ drivers using the Power Sequencing subsystem.
+
+endmenu
diff --git a/drivers/pci/pwrctl/Makefile b/drivers/pci/pwrctl/Makefile
new file mode 100644
index 000000000000..d308aae4800c
--- /dev/null
+++ b/drivers/pci/pwrctl/Makefile
@@ -0,0 +1,6 @@
+# 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
new file mode 100644
index 000000000000..feca26ad2f6a
--- /dev/null
+++ b/drivers/pci/pwrctl/core.c
@@ -0,0 +1,137 @@
+// 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;
+}
+
+/**
+ * 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;
+
+ pci_lock_rescan_remove();
+ pci_rescan_bus(to_pci_dev(pwrctl->dev->parent)->bus);
+ pci_unlock_rescan_remove();
+
+ 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 <[email protected]>");
+MODULE_DESCRIPTION("PCI Device Power Control core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c b/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
new file mode 100644
index 000000000000..c7a113a76c0c
--- /dev/null
+++ b/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pci-pwrctl.h>
+#include <linux/platform_device.h>
+#include <linux/pwrseq/consumer.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+struct pci_pwrctl_pwrseq_data {
+ struct pci_pwrctl ctx;
+ struct pwrseq_desc *pwrseq;
+};
+
+static void devm_pci_pwrctl_pwrseq_power_off(void *data)
+{
+ struct pwrseq_desc *pwrseq = data;
+
+ pwrseq_power_off(pwrseq);
+}
+
+static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev)
+{
+ struct pci_pwrctl_pwrseq_data *data;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->pwrseq = devm_pwrseq_get(dev, of_device_get_match_data(dev));
+ if (IS_ERR(data->pwrseq))
+ return dev_err_probe(dev, PTR_ERR(data->pwrseq),
+ "Failed to get the power sequencer\n");
+
+ ret = pwrseq_power_on(data->pwrseq);
+ if (ret)
+ 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,
+ data->pwrseq);
+ if (ret)
+ return ret;
+
+ data->ctx.dev = dev;
+
+ ret = devm_pci_pwrctl_device_set_ready(dev, &data->ctx);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register the pwrctl wrapper\n");
+
+ return 0;
+}
+
+static const struct of_device_id pci_pwrctl_pwrseq_of_match[] = {
+ {
+ /* ATH11K in QCA6390 package. */
+ .compatible = "pci17cb,1101",
+ .data = "wlan",
+ },
+ {
+ /* ATH12K in WCN7850 package. */
+ .compatible = "pci17cb,1107",
+ .data = "wlan",
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pci_pwrctl_pwrseq_of_match);
+
+static struct platform_driver pci_pwrctl_pwrseq_driver = {
+ .driver = {
+ .name = "pci-pwrctl-pwrseq",
+ .of_match_table = pci_pwrctl_pwrseq_of_match,
+ },
+ .probe = pci_pwrctl_pwrseq_probe,
+};
+module_platform_driver(pci_pwrctl_pwrseq_driver);
+
+MODULE_AUTHOR("Bartosz Golaszewski <[email protected]>");
+MODULE_DESCRIPTION("Generic PCI Power Control module for power sequenced devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index d749ea8250d6..910387e5bdbf 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/of_platform.h>
#include "pci.h"
static void pci_free_resources(struct pci_dev *dev)
@@ -18,7 +19,7 @@ static void pci_stop_dev(struct pci_dev *dev)
pci_pme_active(dev, false);
if (pci_dev_is_added(dev)) {
-
+ of_platform_depopulate(&dev->dev);
device_release_driver(&dev->dev);
pci_proc_detach_device(dev);
pci_remove_sysfs_dev_files(dev);
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 7526a9e714fa..aa9530b4064f 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -56,6 +56,18 @@ config ARM_PMU
Say y if you want to use CPU performance monitors on ARM-based
systems.
+config ARM_V6_PMU
+ depends on ARM_PMU && (CPU_V6 || CPU_V6K)
+ def_bool y
+
+config ARM_V7_PMU
+ depends on ARM_PMU && CPU_V7
+ def_bool y
+
+config ARM_XSCALE_PMU
+ depends on ARM_PMU && CPU_XSCALE
+ def_bool y
+
config RISCV_PMU
depends on RISCV
bool "RISC-V PMU framework"
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
index 29b1c28203ef..d43df81d52f7 100644
--- a/drivers/perf/Makefile
+++ b/drivers/perf/Makefile
@@ -6,6 +6,9 @@ obj-$(CONFIG_ARM_DSU_PMU) += arm_dsu_pmu.o
obj-$(CONFIG_ARM_PMU) += arm_pmu.o arm_pmu_platform.o
obj-$(CONFIG_ARM_PMU_ACPI) += arm_pmu_acpi.o
obj-$(CONFIG_ARM_PMUV3) += arm_pmuv3.o
+obj-$(CONFIG_ARM_V6_PMU) += arm_v6_pmu.o
+obj-$(CONFIG_ARM_V7_PMU) += arm_v7_pmu.o
+obj-$(CONFIG_ARM_XSCALE_PMU) += arm_xscale_pmu.o
obj-$(CONFIG_ARM_SMMU_V3_PMU) += arm_smmuv3_pmu.o
obj-$(CONFIG_FSL_IMX8_DDR_PMU) += fsl_imx8_ddr_perf.o
obj-$(CONFIG_FSL_IMX9_DDR_PMU) += fsl_imx9_ddr_perf.o
diff --git a/drivers/perf/arm-ccn.c b/drivers/perf/arm-ccn.c
index 86ef31ac7503..5c66b9278862 100644
--- a/drivers/perf/arm-ccn.c
+++ b/drivers/perf/arm-ccn.c
@@ -1561,4 +1561,5 @@ module_init(arm_ccn_init);
module_exit(arm_ccn_exit);
MODULE_AUTHOR("Pawel Moll <[email protected]>");
+MODULE_DESCRIPTION("ARM CCN (Cache Coherent Network) Performance Monitor Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index e26ad1d3ed0b..c932d9d355cf 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -174,9 +174,8 @@
#define CMN_CONFIG_WP_COMBINE GENMASK_ULL(30, 27)
#define CMN_CONFIG_WP_DEV_SEL GENMASK_ULL(50, 48)
#define CMN_CONFIG_WP_CHN_SEL GENMASK_ULL(55, 51)
-/* Note that we don't yet support the tertiary match group on newer IPs */
-#define CMN_CONFIG_WP_GRP BIT_ULL(56)
-#define CMN_CONFIG_WP_EXCLUSIVE BIT_ULL(57)
+#define CMN_CONFIG_WP_GRP GENMASK_ULL(57, 56)
+#define CMN_CONFIG_WP_EXCLUSIVE BIT_ULL(58)
#define CMN_CONFIG1_WP_VAL GENMASK_ULL(63, 0)
#define CMN_CONFIG2_WP_MASK GENMASK_ULL(63, 0)
@@ -590,6 +589,13 @@ struct arm_cmn_hw_event {
s8 dtc_idx[CMN_MAX_DTCS];
u8 num_dns;
u8 dtm_offset;
+
+ /*
+ * WP config registers are divided to UP and DOWN events. We need to
+ * keep to track only one of them.
+ */
+ DECLARE_BITMAP(wp_idx, CMN_MAX_XPS);
+
bool wide_sel;
enum cmn_filter_select filter_sel;
};
@@ -617,6 +623,17 @@ static unsigned int arm_cmn_get_index(u64 x[], unsigned int pos)
return (x[pos / 32] >> ((pos % 32) * 2)) & 3;
}
+static void arm_cmn_set_wp_idx(unsigned long *wp_idx, unsigned int pos, bool val)
+{
+ if (val)
+ set_bit(pos, wp_idx);
+}
+
+static unsigned int arm_cmn_get_wp_idx(unsigned long *wp_idx, unsigned int pos)
+{
+ return test_bit(pos, wp_idx);
+}
+
struct arm_cmn_event_attr {
struct device_attribute attr;
enum cmn_model model;
@@ -1336,12 +1353,37 @@ static const struct attribute_group *arm_cmn_attr_groups[] = {
NULL
};
-static int arm_cmn_wp_idx(struct perf_event *event)
+static int arm_cmn_find_free_wp_idx(struct arm_cmn_dtm *dtm,
+ struct perf_event *event)
+{
+ int wp_idx = CMN_EVENT_EVENTID(event);
+
+ if (dtm->wp_event[wp_idx] >= 0)
+ if (dtm->wp_event[++wp_idx] >= 0)
+ return -ENOSPC;
+
+ return wp_idx;
+}
+
+static int arm_cmn_get_assigned_wp_idx(struct perf_event *event,
+ struct arm_cmn_hw_event *hw,
+ unsigned int pos)
+{
+ return CMN_EVENT_EVENTID(event) + arm_cmn_get_wp_idx(hw->wp_idx, pos);
+}
+
+static void arm_cmn_claim_wp_idx(struct arm_cmn_dtm *dtm,
+ struct perf_event *event,
+ unsigned int dtc, int wp_idx,
+ unsigned int pos)
{
- return CMN_EVENT_EVENTID(event) + CMN_EVENT_WP_GRP(event);
+ struct arm_cmn_hw_event *hw = to_cmn_hw(event);
+
+ dtm->wp_event[wp_idx] = hw->dtc_idx[dtc];
+ arm_cmn_set_wp_idx(hw->wp_idx, pos, wp_idx - CMN_EVENT_EVENTID(event));
}
-static u32 arm_cmn_wp_config(struct perf_event *event)
+static u32 arm_cmn_wp_config(struct perf_event *event, int wp_idx)
{
u32 config;
u32 dev = CMN_EVENT_WP_DEV_SEL(event);
@@ -1351,6 +1393,10 @@ static u32 arm_cmn_wp_config(struct perf_event *event)
u32 combine = CMN_EVENT_WP_COMBINE(event);
bool is_cmn600 = to_cmn(event->pmu)->part == PART_CMN600;
+ /* CMN-600 supports only primary and secondary matching groups */
+ if (is_cmn600)
+ grp &= 1;
+
config = FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL, dev) |
FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_CHN_SEL, chn) |
FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_GRP, grp) |
@@ -1358,7 +1404,9 @@ static u32 arm_cmn_wp_config(struct perf_event *event)
if (exc)
config |= is_cmn600 ? CMN600_WPn_CONFIG_WP_EXCLUSIVE :
CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE;
- if (combine && !grp)
+
+ /* wp_combine is available only on WP0 and WP2 */
+ if (combine && !(wp_idx & 0x1))
config |= is_cmn600 ? CMN600_WPn_CONFIG_WP_COMBINE :
CMN_DTM_WPn_CONFIG_WP_COMBINE;
return config;
@@ -1520,12 +1568,12 @@ static void arm_cmn_event_start(struct perf_event *event, int flags)
writeq_relaxed(CMN_CC_INIT, cmn->dtc[i].base + CMN_DT_PMCCNTR);
cmn->dtc[i].cc_active = true;
} else if (type == CMN_TYPE_WP) {
- int wp_idx = arm_cmn_wp_idx(event);
u64 val = CMN_EVENT_WP_VAL(event);
u64 mask = CMN_EVENT_WP_MASK(event);
for_each_hw_dn(hw, dn, i) {
void __iomem *base = dn->pmu_base + CMN_DTM_OFFSET(hw->dtm_offset);
+ int wp_idx = arm_cmn_get_assigned_wp_idx(event, hw, i);
writeq_relaxed(val, base + CMN_DTM_WPn_VAL(wp_idx));
writeq_relaxed(mask, base + CMN_DTM_WPn_MASK(wp_idx));
@@ -1550,10 +1598,9 @@ static void arm_cmn_event_stop(struct perf_event *event, int flags)
i = hw->dtc_idx[0];
cmn->dtc[i].cc_active = false;
} else if (type == CMN_TYPE_WP) {
- int wp_idx = arm_cmn_wp_idx(event);
-
for_each_hw_dn(hw, dn, i) {
void __iomem *base = dn->pmu_base + CMN_DTM_OFFSET(hw->dtm_offset);
+ int wp_idx = arm_cmn_get_assigned_wp_idx(event, hw, i);
writeq_relaxed(0, base + CMN_DTM_WPn_MASK(wp_idx));
writeq_relaxed(~0ULL, base + CMN_DTM_WPn_VAL(wp_idx));
@@ -1571,10 +1618,23 @@ struct arm_cmn_val {
u8 dtm_count[CMN_MAX_DTMS];
u8 occupid[CMN_MAX_DTMS][SEL_MAX];
u8 wp[CMN_MAX_DTMS][4];
+ u8 wp_combine[CMN_MAX_DTMS][2];
int dtc_count[CMN_MAX_DTCS];
bool cycles;
};
+static int arm_cmn_val_find_free_wp_config(struct perf_event *event,
+ struct arm_cmn_val *val, int dtm)
+{
+ int wp_idx = CMN_EVENT_EVENTID(event);
+
+ if (val->wp[dtm][wp_idx])
+ if (val->wp[dtm][++wp_idx])
+ return -ENOSPC;
+
+ return wp_idx;
+}
+
static void arm_cmn_val_add_event(struct arm_cmn *cmn, struct arm_cmn_val *val,
struct perf_event *event)
{
@@ -1606,8 +1666,9 @@ static void arm_cmn_val_add_event(struct arm_cmn *cmn, struct arm_cmn_val *val,
if (type != CMN_TYPE_WP)
continue;
- wp_idx = arm_cmn_wp_idx(event);
- val->wp[dtm][wp_idx] = CMN_EVENT_WP_COMBINE(event) + 1;
+ wp_idx = arm_cmn_val_find_free_wp_config(event, val, dtm);
+ val->wp[dtm][wp_idx] = 1;
+ val->wp_combine[dtm][wp_idx >> 1] += !!CMN_EVENT_WP_COMBINE(event);
}
}
@@ -1631,6 +1692,7 @@ static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
return -ENOMEM;
arm_cmn_val_add_event(cmn, val, leader);
+
for_each_sibling_event(sibling, leader)
arm_cmn_val_add_event(cmn, val, sibling);
@@ -1645,7 +1707,7 @@ static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
goto done;
for_each_hw_dn(hw, dn, i) {
- int wp_idx, wp_cmb, dtm = dn->dtm, sel = hw->filter_sel;
+ int wp_idx, dtm = dn->dtm, sel = hw->filter_sel;
if (val->dtm_count[dtm] == CMN_DTM_NUM_COUNTERS)
goto done;
@@ -1657,12 +1719,12 @@ static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
if (type != CMN_TYPE_WP)
continue;
- wp_idx = arm_cmn_wp_idx(event);
- if (val->wp[dtm][wp_idx])
+ wp_idx = arm_cmn_val_find_free_wp_config(event, val, dtm);
+ if (wp_idx < 0)
goto done;
- wp_cmb = val->wp[dtm][wp_idx ^ 1];
- if (wp_cmb && wp_cmb != CMN_EVENT_WP_COMBINE(event) + 1)
+ if (wp_idx & 1 &&
+ val->wp_combine[dtm][wp_idx >> 1] != !!CMN_EVENT_WP_COMBINE(event))
goto done;
}
@@ -1773,8 +1835,11 @@ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
struct arm_cmn_dtm *dtm = &cmn->dtms[hw->dn[i].dtm] + hw->dtm_offset;
unsigned int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
- if (type == CMN_TYPE_WP)
- dtm->wp_event[arm_cmn_wp_idx(event)] = -1;
+ if (type == CMN_TYPE_WP) {
+ int wp_idx = arm_cmn_get_assigned_wp_idx(event, hw, i);
+
+ dtm->wp_event[wp_idx] = -1;
+ }
if (hw->filter_sel > SEL_NONE)
hw->dn[i].occupid[hw->filter_sel].count--;
@@ -1783,6 +1848,7 @@ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
writel_relaxed(dtm->pmu_config_low, dtm->base + CMN_DTM_PMU_CONFIG);
}
memset(hw->dtm_idx, 0, sizeof(hw->dtm_idx));
+ memset(hw->wp_idx, 0, sizeof(hw->wp_idx));
for_each_hw_dtc_idx(hw, j, idx)
cmn->dtc[j].counters[idx] = NULL;
@@ -1836,19 +1902,23 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
if (type == CMN_TYPE_XP) {
input_sel = CMN__PMEVCNT0_INPUT_SEL_XP + dtm_idx;
} else if (type == CMN_TYPE_WP) {
- int tmp, wp_idx = arm_cmn_wp_idx(event);
- u32 cfg = arm_cmn_wp_config(event);
+ int tmp, wp_idx;
+ u32 cfg;
- if (dtm->wp_event[wp_idx] >= 0)
+ wp_idx = arm_cmn_find_free_wp_idx(dtm, event);
+ if (wp_idx < 0)
goto free_dtms;
+ cfg = arm_cmn_wp_config(event, wp_idx);
+
tmp = dtm->wp_event[wp_idx ^ 1];
if (tmp >= 0 && CMN_EVENT_WP_COMBINE(event) !=
CMN_EVENT_WP_COMBINE(cmn->dtc[d].counters[tmp]))
goto free_dtms;
input_sel = CMN__PMEVCNT0_INPUT_SEL_WP + wp_idx;
- dtm->wp_event[wp_idx] = hw->dtc_idx[d];
+
+ arm_cmn_claim_wp_idx(dtm, event, d, wp_idx, i);
writel_relaxed(cfg, dtm->base + CMN_DTM_WPn_CONFIG(wp_idx));
} else {
struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
diff --git a/drivers/perf/arm_cspmu/ampere_cspmu.c b/drivers/perf/arm_cspmu/ampere_cspmu.c
index f146a455e838..f72f5689923c 100644
--- a/drivers/perf/arm_cspmu/ampere_cspmu.c
+++ b/drivers/perf/arm_cspmu/ampere_cspmu.c
@@ -269,4 +269,5 @@ static void __exit ampere_cspmu_exit(void)
module_init(ampere_cspmu_init);
module_exit(ampere_cspmu_exit);
+MODULE_DESCRIPTION("Ampere SoC Performance Monitor Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index c318dc909767..2158a5975c90 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -1427,4 +1427,5 @@ EXPORT_SYMBOL_GPL(arm_cspmu_impl_unregister);
module_init(arm_cspmu_init);
module_exit(arm_cspmu_exit);
+MODULE_DESCRIPTION("ARM CoreSight Architecture Performance Monitor Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c
index 5b84b701ad62..d0ef611240aa 100644
--- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
+++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
@@ -417,4 +417,5 @@ static void __exit nvidia_cspmu_exit(void)
module_init(nvidia_cspmu_init);
module_exit(nvidia_cspmu_exit);
+MODULE_DESCRIPTION("NVIDIA Coresight Architecture Performance Monitor Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
index 23fa6c5da82c..cf0430c266a6 100644
--- a/drivers/perf/arm_pmuv3.c
+++ b/drivers/perf/arm_pmuv3.c
@@ -25,8 +25,6 @@
#include <linux/smp.h>
#include <linux/nmi.h>
-#include <asm/arm_pmuv3.h>
-
/* ARMv8 Cortex-A53 specific event types. */
#define ARMV8_A53_PERFCTR_PREF_LINEFILL 0xC2
@@ -338,6 +336,11 @@ static bool armv8pmu_event_want_user_access(struct perf_event *event)
return ATTR_CFG_GET_FLD(&event->attr, rdpmc);
}
+static u32 armv8pmu_event_get_threshold(struct perf_event_attr *attr)
+{
+ return ATTR_CFG_GET_FLD(attr, threshold);
+}
+
static u8 armv8pmu_event_threshold_control(struct perf_event_attr *attr)
{
u8 th_compare = ATTR_CFG_GET_FLD(attr, threshold_compare);
@@ -941,7 +944,8 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,
unsigned long evtype = hwc->config_base & ARMV8_PMU_EVTYPE_EVENT;
/* Always prefer to place a cycle counter into the cycle counter. */
- if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) {
+ if ((evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) &&
+ !armv8pmu_event_get_threshold(&event->attr)) {
if (!test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
return ARMV8_IDX_CYCLE_COUNTER;
else if (armv8pmu_event_is_64bit(event) &&
@@ -1033,13 +1037,13 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event,
* If FEAT_PMUv3_TH isn't implemented, then THWIDTH (threshold_max) will
* be 0 and will also trigger this check, preventing it from being used.
*/
- th = ATTR_CFG_GET_FLD(attr, threshold);
+ th = armv8pmu_event_get_threshold(attr);
if (th > threshold_max(cpu_pmu)) {
pr_debug("PMU event threshold exceeds max value\n");
return -EINVAL;
}
- if (IS_ENABLED(CONFIG_ARM64) && th) {
+ if (th) {
config_base |= FIELD_PREP(ARMV8_PMU_EVTYPE_TH, th);
config_base |= FIELD_PREP(ARMV8_PMU_EVTYPE_TC,
armv8pmu_event_threshold_control(attr));
@@ -1340,14 +1344,20 @@ PMUV3_INIT_SIMPLE(armv9_cortex_a520)
PMUV3_INIT_SIMPLE(armv9_cortex_a710)
PMUV3_INIT_SIMPLE(armv9_cortex_a715)
PMUV3_INIT_SIMPLE(armv9_cortex_a720)
+PMUV3_INIT_SIMPLE(armv9_cortex_a725)
PMUV3_INIT_SIMPLE(armv8_cortex_x1)
PMUV3_INIT_SIMPLE(armv9_cortex_x2)
PMUV3_INIT_SIMPLE(armv9_cortex_x3)
PMUV3_INIT_SIMPLE(armv9_cortex_x4)
+PMUV3_INIT_SIMPLE(armv9_cortex_x925)
PMUV3_INIT_SIMPLE(armv8_neoverse_e1)
PMUV3_INIT_SIMPLE(armv8_neoverse_n1)
PMUV3_INIT_SIMPLE(armv9_neoverse_n2)
+PMUV3_INIT_SIMPLE(armv9_neoverse_n3)
PMUV3_INIT_SIMPLE(armv8_neoverse_v1)
+PMUV3_INIT_SIMPLE(armv8_neoverse_v2)
+PMUV3_INIT_SIMPLE(armv8_neoverse_v3)
+PMUV3_INIT_SIMPLE(armv8_neoverse_v3ae)
PMUV3_INIT_SIMPLE(armv8_nvidia_carmel)
PMUV3_INIT_SIMPLE(armv8_nvidia_denver)
@@ -1379,14 +1389,20 @@ static const struct of_device_id armv8_pmu_of_device_ids[] = {
{.compatible = "arm,cortex-a710-pmu", .data = armv9_cortex_a710_pmu_init},
{.compatible = "arm,cortex-a715-pmu", .data = armv9_cortex_a715_pmu_init},
{.compatible = "arm,cortex-a720-pmu", .data = armv9_cortex_a720_pmu_init},
+ {.compatible = "arm,cortex-a725-pmu", .data = armv9_cortex_a725_pmu_init},
{.compatible = "arm,cortex-x1-pmu", .data = armv8_cortex_x1_pmu_init},
{.compatible = "arm,cortex-x2-pmu", .data = armv9_cortex_x2_pmu_init},
{.compatible = "arm,cortex-x3-pmu", .data = armv9_cortex_x3_pmu_init},
{.compatible = "arm,cortex-x4-pmu", .data = armv9_cortex_x4_pmu_init},
+ {.compatible = "arm,cortex-x925-pmu", .data = armv9_cortex_x925_pmu_init},
{.compatible = "arm,neoverse-e1-pmu", .data = armv8_neoverse_e1_pmu_init},
{.compatible = "arm,neoverse-n1-pmu", .data = armv8_neoverse_n1_pmu_init},
{.compatible = "arm,neoverse-n2-pmu", .data = armv9_neoverse_n2_pmu_init},
+ {.compatible = "arm,neoverse-n3-pmu", .data = armv9_neoverse_n3_pmu_init},
{.compatible = "arm,neoverse-v1-pmu", .data = armv8_neoverse_v1_pmu_init},
+ {.compatible = "arm,neoverse-v2-pmu", .data = armv8_neoverse_v2_pmu_init},
+ {.compatible = "arm,neoverse-v3-pmu", .data = armv8_neoverse_v3_pmu_init},
+ {.compatible = "arm,neoverse-v3ae-pmu", .data = armv8_neoverse_v3ae_pmu_init},
{.compatible = "cavium,thunder-pmu", .data = armv8_cavium_thunder_pmu_init},
{.compatible = "brcm,vulcan-pmu", .data = armv8_brcm_vulcan_pmu_init},
{.compatible = "nvidia,carmel-pmu", .data = armv8_nvidia_carmel_pmu_init},
diff --git a/arch/arm/kernel/perf_event_v6.c b/drivers/perf/arm_v6_pmu.c
index d9fd53841591..0bb685b4bac5 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/drivers/perf/arm_v6_pmu.c
@@ -31,8 +31,6 @@
* enable the interrupt.
*/
-#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
-
#include <asm/cputype.h>
#include <asm/irq_regs.h>
@@ -403,13 +401,6 @@ static int armv6_1136_pmu_init(struct arm_pmu *cpu_pmu)
return 0;
}
-static int armv6_1156_pmu_init(struct arm_pmu *cpu_pmu)
-{
- armv6pmu_init(cpu_pmu);
- cpu_pmu->name = "armv6_1156";
- return 0;
-}
-
static int armv6_1176_pmu_init(struct arm_pmu *cpu_pmu)
{
armv6pmu_init(cpu_pmu);
@@ -423,17 +414,9 @@ static const struct of_device_id armv6_pmu_of_device_ids[] = {
{ /* sentinel value */ }
};
-static const struct pmu_probe_info armv6_pmu_probe_table[] = {
- ARM_PMU_PROBE(ARM_CPU_PART_ARM1136, armv6_1136_pmu_init),
- ARM_PMU_PROBE(ARM_CPU_PART_ARM1156, armv6_1156_pmu_init),
- ARM_PMU_PROBE(ARM_CPU_PART_ARM1176, armv6_1176_pmu_init),
- { /* sentinel value */ }
-};
-
static int armv6_pmu_device_probe(struct platform_device *pdev)
{
- return arm_pmu_device_probe(pdev, armv6_pmu_of_device_ids,
- armv6_pmu_probe_table);
+ return arm_pmu_device_probe(pdev, armv6_pmu_of_device_ids, NULL);
}
static struct platform_driver armv6_pmu_driver = {
@@ -445,4 +428,3 @@ static struct platform_driver armv6_pmu_driver = {
};
builtin_platform_driver(armv6_pmu_driver);
-#endif /* CONFIG_CPU_V6 || CONFIG_CPU_V6K */
diff --git a/arch/arm/kernel/perf_event_v7.c b/drivers/perf/arm_v7_pmu.c
index a3322e2b3ea4..928ac3d626ed 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/drivers/perf/arm_v7_pmu.c
@@ -17,8 +17,6 @@
* counter and all 4 performance counters together can be reset separately.
*/
-#ifdef CONFIG_CPU_V7
-
#include <asm/cp15.h>
#include <asm/cputype.h>
#include <asm/irq_regs.h>
@@ -1979,17 +1977,9 @@ static const struct of_device_id armv7_pmu_of_device_ids[] = {
{},
};
-static const struct pmu_probe_info armv7_pmu_probe_table[] = {
- ARM_PMU_PROBE(ARM_CPU_PART_CORTEX_A8, armv7_a8_pmu_init),
- ARM_PMU_PROBE(ARM_CPU_PART_CORTEX_A9, armv7_a9_pmu_init),
- { /* sentinel value */ }
-};
-
-
static int armv7_pmu_device_probe(struct platform_device *pdev)
{
- return arm_pmu_device_probe(pdev, armv7_pmu_of_device_ids,
- armv7_pmu_probe_table);
+ return arm_pmu_device_probe(pdev, armv7_pmu_of_device_ids, NULL);
}
static struct platform_driver armv7_pmu_driver = {
@@ -2002,4 +1992,3 @@ static struct platform_driver armv7_pmu_driver = {
};
builtin_platform_driver(armv7_pmu_driver);
-#endif /* CONFIG_CPU_V7 */
diff --git a/arch/arm/kernel/perf_event_xscale.c b/drivers/perf/arm_xscale_pmu.c
index 7a2ba1c689a7..3d8b72d6b37f 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/drivers/perf/arm_xscale_pmu.c
@@ -13,8 +13,6 @@
* PMU structures.
*/
-#ifdef CONFIG_CPU_XSCALE
-
#include <asm/cputype.h>
#include <asm/irq_regs.h>
@@ -745,4 +743,3 @@ static struct platform_driver xscale_pmu_driver = {
};
builtin_platform_driver(xscale_pmu_driver);
-#endif /* CONFIG_CPU_XSCALE */
diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c
index 1f93a66eff5b..43d68b69e630 100644
--- a/drivers/perf/cxl_pmu.c
+++ b/drivers/perf/cxl_pmu.c
@@ -972,6 +972,7 @@ static __exit void cxl_pmu_exit(void)
cpuhp_remove_multi_state(cxl_pmu_cpuhp_state_num);
}
+MODULE_DESCRIPTION("CXL Performance Monitor Driver");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(CXL);
module_init(cxl_pmu_init);
diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c
index 1bbdb29743c4..746b92330ca7 100644
--- a/drivers/perf/fsl_imx8_ddr_perf.c
+++ b/drivers/perf/fsl_imx8_ddr_perf.c
@@ -850,4 +850,5 @@ static struct platform_driver imx_ddr_pmu_driver = {
};
module_platform_driver(imx_ddr_pmu_driver);
+MODULE_DESCRIPTION("Freescale i.MX8 DDR Performance Monitor Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/perf/fsl_imx9_ddr_perf.c b/drivers/perf/fsl_imx9_ddr_perf.c
index 72c2d3074cde..69f920b1caf2 100644
--- a/drivers/perf/fsl_imx9_ddr_perf.c
+++ b/drivers/perf/fsl_imx9_ddr_perf.c
@@ -11,14 +11,24 @@
#include <linux/perf_event.h>
/* Performance monitor configuration */
-#define PMCFG1 0x00
-#define PMCFG1_RD_TRANS_FILT_EN BIT(31)
-#define PMCFG1_WR_TRANS_FILT_EN BIT(30)
-#define PMCFG1_RD_BT_FILT_EN BIT(29)
-#define PMCFG1_ID_MASK GENMASK(17, 0)
+#define PMCFG1 0x00
+#define MX93_PMCFG1_RD_TRANS_FILT_EN BIT(31)
+#define MX93_PMCFG1_WR_TRANS_FILT_EN BIT(30)
+#define MX93_PMCFG1_RD_BT_FILT_EN BIT(29)
+#define MX93_PMCFG1_ID_MASK GENMASK(17, 0)
-#define PMCFG2 0x04
-#define PMCFG2_ID GENMASK(17, 0)
+#define MX95_PMCFG1_WR_BEAT_FILT_EN BIT(31)
+#define MX95_PMCFG1_RD_BEAT_FILT_EN BIT(30)
+
+#define PMCFG2 0x04
+#define MX93_PMCFG2_ID GENMASK(17, 0)
+
+#define PMCFG3 0x08
+#define PMCFG4 0x0C
+#define PMCFG5 0x10
+#define PMCFG6 0x14
+#define MX95_PMCFG_ID_MASK GENMASK(9, 0)
+#define MX95_PMCFG_ID GENMASK(25, 16)
/* Global control register affects all counters and takes priority over local control registers */
#define PMGC0 0x40
@@ -41,6 +51,10 @@
#define NUM_COUNTERS 11
#define CYCLES_COUNTER 0
+#define CYCLES_EVENT_ID 0
+
+#define CONFIG_EVENT_MASK GENMASK(7, 0)
+#define CONFIG_COUNTER_MASK GENMASK(23, 16)
#define to_ddr_pmu(p) container_of(p, struct ddr_pmu, pmu)
@@ -71,8 +85,23 @@ static const struct imx_ddr_devtype_data imx93_devtype_data = {
.identifier = "imx93",
};
+static const struct imx_ddr_devtype_data imx95_devtype_data = {
+ .identifier = "imx95",
+};
+
+static inline bool is_imx93(struct ddr_pmu *pmu)
+{
+ return pmu->devtype_data == &imx93_devtype_data;
+}
+
+static inline bool is_imx95(struct ddr_pmu *pmu)
+{
+ return pmu->devtype_data == &imx95_devtype_data;
+}
+
static const struct of_device_id imx_ddr_pmu_dt_ids[] = {
- {.compatible = "fsl,imx93-ddr-pmu", .data = &imx93_devtype_data},
+ { .compatible = "fsl,imx93-ddr-pmu", .data = &imx93_devtype_data },
+ { .compatible = "fsl,imx95-ddr-pmu", .data = &imx95_devtype_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_ddr_pmu_dt_ids);
@@ -118,21 +147,40 @@ static const struct attribute_group ddr_perf_cpumask_attr_group = {
.attrs = ddr_perf_cpumask_attrs,
};
+struct imx9_pmu_events_attr {
+ struct device_attribute attr;
+ u64 id;
+ const void *devtype_data;
+};
+
static ssize_t ddr_pmu_event_show(struct device *dev,
struct device_attribute *attr, char *page)
{
- struct perf_pmu_events_attr *pmu_attr;
+ struct imx9_pmu_events_attr *pmu_attr;
- pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+ pmu_attr = container_of(attr, struct imx9_pmu_events_attr, attr);
return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
}
-#define IMX9_DDR_PMU_EVENT_ATTR(_name, _id) \
- (&((struct perf_pmu_events_attr[]) { \
+#define COUNTER_OFFSET_IN_EVENT 8
+#define ID(counter, id) ((counter << COUNTER_OFFSET_IN_EVENT) | id)
+
+#define DDR_PMU_EVENT_ATTR_COMM(_name, _id, _data) \
+ (&((struct imx9_pmu_events_attr[]) { \
{ .attr = __ATTR(_name, 0444, ddr_pmu_event_show, NULL),\
- .id = _id, } \
+ .id = _id, \
+ .devtype_data = _data, } \
})[0].attr.attr)
+#define IMX9_DDR_PMU_EVENT_ATTR(_name, _id) \
+ DDR_PMU_EVENT_ATTR_COMM(_name, _id, NULL)
+
+#define IMX93_DDR_PMU_EVENT_ATTR(_name, _id) \
+ DDR_PMU_EVENT_ATTR_COMM(_name, _id, &imx93_devtype_data)
+
+#define IMX95_DDR_PMU_EVENT_ATTR(_name, _id) \
+ DDR_PMU_EVENT_ATTR_COMM(_name, _id, &imx95_devtype_data)
+
static struct attribute *ddr_perf_events_attrs[] = {
/* counter0 cycles event */
IMX9_DDR_PMU_EVENT_ATTR(cycles, 0),
@@ -159,90 +207,114 @@ static struct attribute *ddr_perf_events_attrs[] = {
IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_29, 63),
/* counter1 specific events */
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_0, 64),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_1, 65),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_2, 66),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_3, 67),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_4, 68),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_5, 69),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_6, 70),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_7, 71),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_0, ID(1, 64)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_1, ID(1, 65)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_2, ID(1, 66)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_3, ID(1, 67)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_4, ID(1, 68)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_5, ID(1, 69)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_6, ID(1, 70)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_7, ID(1, 71)),
/* counter2 specific events */
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_0, 64),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_1, 65),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_2, 66),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_3, 67),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_4, 68),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_5, 69),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_6, 70),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_7, 71),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_empty, 72),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_trans_filt, 73),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_0, ID(2, 64)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_1, ID(2, 65)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_2, ID(2, 66)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_3, ID(2, 67)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_4, ID(2, 68)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_5, ID(2, 69)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_6, ID(2, 70)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_7, ID(2, 71)),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_empty, ID(2, 72)),
+ IMX93_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_trans_filt, ID(2, 73)), /* imx93 specific*/
+ IMX95_DDR_PMU_EVENT_ATTR(eddrtq_pm_wr_beat_filt, ID(2, 73)), /* imx95 specific*/
/* counter3 specific events */
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_0, 64),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_1, 65),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_2, 66),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_3, 67),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_4, 68),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_5, 69),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_6, 70),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_7, 71),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_full, 72),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_wr_trans_filt, 73),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_0, ID(3, 64)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_1, ID(3, 65)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_2, ID(3, 66)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_3, ID(3, 67)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_4, ID(3, 68)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_5, ID(3, 69)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_6, ID(3, 70)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_7, ID(3, 71)),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_full, ID(3, 72)),
+ IMX93_DDR_PMU_EVENT_ATTR(eddrtq_pm_wr_trans_filt, ID(3, 73)), /* imx93 specific*/
+ IMX95_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt2, ID(3, 73)), /* imx95 specific*/
/* counter4 specific events */
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_0, 64),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_1, 65),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_2, 66),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_3, 67),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_4, 68),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_5, 69),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_6, 70),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_7, 71),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq2_rmw, 72),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt, 73),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_0, ID(4, 64)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_1, ID(4, 65)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_2, ID(4, 66)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_3, ID(4, 67)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_4, ID(4, 68)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_5, ID(4, 69)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_6, ID(4, 70)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_7, ID(4, 71)),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq2_rmw, ID(4, 72)),
+ IMX93_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt, ID(4, 73)), /* imx93 specific*/
+ IMX95_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt1, ID(4, 73)), /* imx95 specific*/
/* counter5 specific events */
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_0, 64),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_1, 65),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_2, 66),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_3, 67),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_4, 68),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_5, 69),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_6, 70),
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_7, 71),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq1, 72),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_0, ID(5, 64)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_1, ID(5, 65)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_2, ID(5, 66)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_3, ID(5, 67)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_4, ID(5, 68)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_5, ID(5, 69)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_6, ID(5, 70)),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_7, ID(5, 71)),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq1, ID(5, 72)),
+ IMX95_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt0, ID(5, 73)), /* imx95 specific*/
/* counter6 specific events */
- IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_end_0, 64),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq2, 72),
+ IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_end_0, ID(6, 64)),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq2, ID(6, 72)),
/* counter7 specific events */
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_1_2_full, 64),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_wrq0, 65),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_1_2_full, ID(7, 64)),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_wrq0, ID(7, 65)),
/* counter8 specific events */
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_bias_switched, 64),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_1_4_full, 65),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_bias_switched, ID(8, 64)),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_1_4_full, ID(8, 65)),
/* counter9 specific events */
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_wrq1, 65),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_3_4_full, 66),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_wrq1, ID(9, 65)),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_3_4_full, ID(9, 66)),
/* counter10 specific events */
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_misc_mrk, 65),
- IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq0, 66),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_misc_mrk, ID(10, 65)),
+ IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq0, ID(10, 66)),
NULL,
};
+static umode_t
+ddr_perf_events_attrs_is_visible(struct kobject *kobj,
+ struct attribute *attr, int unused)
+{
+ struct pmu *pmu = dev_get_drvdata(kobj_to_dev(kobj));
+ struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu);
+ struct imx9_pmu_events_attr *eattr;
+
+ eattr = container_of(attr, typeof(*eattr), attr.attr);
+
+ if (!eattr->devtype_data)
+ return attr->mode;
+
+ if (eattr->devtype_data != ddr_pmu->devtype_data)
+ return 0;
+
+ return attr->mode;
+}
+
static const struct attribute_group ddr_perf_events_attr_group = {
.name = "events",
.attrs = ddr_perf_events_attrs,
+ .is_visible = ddr_perf_events_attrs_is_visible,
};
-PMU_FORMAT_ATTR(event, "config:0-7");
+PMU_FORMAT_ATTR(event, "config:0-7,16-23");
PMU_FORMAT_ATTR(counter, "config:8-15");
PMU_FORMAT_ATTR(axi_id, "config1:0-17");
PMU_FORMAT_ATTR(axi_mask, "config2:0-17");
@@ -339,8 +411,10 @@ static void ddr_perf_counter_local_config(struct ddr_pmu *pmu, int config,
int counter, bool enable)
{
u32 ctrl_a;
+ int event;
ctrl_a = readl_relaxed(pmu->base + PMLCA(counter));
+ event = FIELD_GET(CONFIG_EVENT_MASK, config);
if (enable) {
ctrl_a |= PMLCA_FC;
@@ -352,7 +426,7 @@ static void ddr_perf_counter_local_config(struct ddr_pmu *pmu, int config,
ctrl_a &= ~PMLCA_FC;
ctrl_a |= PMLCA_CE;
ctrl_a &= ~FIELD_PREP(PMLCA_EVENT, 0x7F);
- ctrl_a |= FIELD_PREP(PMLCA_EVENT, (config & 0x000000FF));
+ ctrl_a |= FIELD_PREP(PMLCA_EVENT, event);
writel(ctrl_a, pmu->base + PMLCA(counter));
} else {
/* Freeze counter. */
@@ -361,39 +435,79 @@ static void ddr_perf_counter_local_config(struct ddr_pmu *pmu, int config,
}
}
-static void ddr_perf_monitor_config(struct ddr_pmu *pmu, int cfg, int cfg1, int cfg2)
+static void imx93_ddr_perf_monitor_config(struct ddr_pmu *pmu, int event,
+ int counter, int axi_id, int axi_mask)
{
u32 pmcfg1, pmcfg2;
- int event, counter;
-
- event = cfg & 0x000000FF;
- counter = (cfg & 0x0000FF00) >> 8;
+ u32 mask[] = { MX93_PMCFG1_RD_TRANS_FILT_EN,
+ MX93_PMCFG1_WR_TRANS_FILT_EN,
+ MX93_PMCFG1_RD_BT_FILT_EN };
pmcfg1 = readl_relaxed(pmu->base + PMCFG1);
- if (counter == 2 && event == 73)
- pmcfg1 |= PMCFG1_RD_TRANS_FILT_EN;
- else if (counter == 2 && event != 73)
- pmcfg1 &= ~PMCFG1_RD_TRANS_FILT_EN;
+ if (counter >= 2 && counter <= 4)
+ pmcfg1 = event == 73 ? pmcfg1 | mask[counter - 2] :
+ pmcfg1 & ~mask[counter - 2];
- if (counter == 3 && event == 73)
- pmcfg1 |= PMCFG1_WR_TRANS_FILT_EN;
- else if (counter == 3 && event != 73)
- pmcfg1 &= ~PMCFG1_WR_TRANS_FILT_EN;
+ pmcfg1 &= ~FIELD_PREP(MX93_PMCFG1_ID_MASK, 0x3FFFF);
+ pmcfg1 |= FIELD_PREP(MX93_PMCFG1_ID_MASK, axi_mask);
+ writel_relaxed(pmcfg1, pmu->base + PMCFG1);
- if (counter == 4 && event == 73)
- pmcfg1 |= PMCFG1_RD_BT_FILT_EN;
- else if (counter == 4 && event != 73)
- pmcfg1 &= ~PMCFG1_RD_BT_FILT_EN;
+ pmcfg2 = readl_relaxed(pmu->base + PMCFG2);
+ pmcfg2 &= ~FIELD_PREP(MX93_PMCFG2_ID, 0x3FFFF);
+ pmcfg2 |= FIELD_PREP(MX93_PMCFG2_ID, axi_id);
+ writel_relaxed(pmcfg2, pmu->base + PMCFG2);
+}
- pmcfg1 &= ~FIELD_PREP(PMCFG1_ID_MASK, 0x3FFFF);
- pmcfg1 |= FIELD_PREP(PMCFG1_ID_MASK, cfg2);
- writel(pmcfg1, pmu->base + PMCFG1);
+static void imx95_ddr_perf_monitor_config(struct ddr_pmu *pmu, int event,
+ int counter, int axi_id, int axi_mask)
+{
+ u32 pmcfg1, pmcfg, offset = 0;
- pmcfg2 = readl_relaxed(pmu->base + PMCFG2);
- pmcfg2 &= ~FIELD_PREP(PMCFG2_ID, 0x3FFFF);
- pmcfg2 |= FIELD_PREP(PMCFG2_ID, cfg1);
- writel(pmcfg2, pmu->base + PMCFG2);
+ pmcfg1 = readl_relaxed(pmu->base + PMCFG1);
+
+ if (event == 73) {
+ switch (counter) {
+ case 2:
+ pmcfg1 |= MX95_PMCFG1_WR_BEAT_FILT_EN;
+ offset = PMCFG3;
+ break;
+ case 3:
+ pmcfg1 |= MX95_PMCFG1_RD_BEAT_FILT_EN;
+ offset = PMCFG4;
+ break;
+ case 4:
+ pmcfg1 |= MX95_PMCFG1_RD_BEAT_FILT_EN;
+ offset = PMCFG5;
+ break;
+ case 5:
+ pmcfg1 |= MX95_PMCFG1_RD_BEAT_FILT_EN;
+ offset = PMCFG6;
+ break;
+ }
+ } else {
+ switch (counter) {
+ case 2:
+ pmcfg1 &= ~MX95_PMCFG1_WR_BEAT_FILT_EN;
+ break;
+ case 3:
+ case 4:
+ case 5:
+ pmcfg1 &= ~MX95_PMCFG1_RD_BEAT_FILT_EN;
+ break;
+ }
+ }
+
+ writel_relaxed(pmcfg1, pmu->base + PMCFG1);
+
+ if (offset) {
+ pmcfg = readl_relaxed(pmu->base + offset);
+ pmcfg &= ~(FIELD_PREP(MX95_PMCFG_ID_MASK, 0x3FF) |
+ FIELD_PREP(MX95_PMCFG_ID, 0x3FF));
+ pmcfg |= (FIELD_PREP(MX95_PMCFG_ID_MASK, axi_mask) |
+ FIELD_PREP(MX95_PMCFG_ID, axi_id));
+ writel_relaxed(pmcfg, pmu->base + offset);
+ }
}
static void ddr_perf_event_update(struct perf_event *event)
@@ -460,6 +574,28 @@ static void ddr_perf_event_start(struct perf_event *event, int flags)
hwc->state = 0;
}
+static int ddr_perf_alloc_counter(struct ddr_pmu *pmu, int event, int counter)
+{
+ int i;
+
+ if (event == CYCLES_EVENT_ID) {
+ // Cycles counter is dedicated for cycle event.
+ if (pmu->events[CYCLES_COUNTER] == NULL)
+ return CYCLES_COUNTER;
+ } else if (counter != 0) {
+ // Counter specific event use specific counter.
+ if (pmu->events[counter] == NULL)
+ return counter;
+ } else {
+ // Auto allocate counter for referene event.
+ for (i = 1; i < NUM_COUNTERS; i++)
+ if (pmu->events[i] == NULL)
+ return i;
+ }
+
+ return -ENOENT;
+}
+
static int ddr_perf_event_add(struct perf_event *event, int flags)
{
struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
@@ -467,21 +603,33 @@ static int ddr_perf_event_add(struct perf_event *event, int flags)
int cfg = event->attr.config;
int cfg1 = event->attr.config1;
int cfg2 = event->attr.config2;
- int counter;
+ int event_id, counter;
- counter = (cfg & 0x0000FF00) >> 8;
+ event_id = FIELD_GET(CONFIG_EVENT_MASK, cfg);
+ counter = FIELD_GET(CONFIG_COUNTER_MASK, cfg);
+
+ counter = ddr_perf_alloc_counter(pmu, event_id, counter);
+ if (counter < 0) {
+ dev_dbg(pmu->dev, "There are not enough counters\n");
+ return -EOPNOTSUPP;
+ }
pmu->events[counter] = event;
pmu->active_events++;
hwc->idx = counter;
hwc->state |= PERF_HES_STOPPED;
+ if (is_imx93(pmu))
+ /* read trans, write trans, read beat */
+ imx93_ddr_perf_monitor_config(pmu, event_id, counter, cfg1, cfg2);
+
+ if (is_imx95(pmu))
+ /* write beat, read beat2, read beat1, read beat */
+ imx95_ddr_perf_monitor_config(pmu, event_id, counter, cfg1, cfg2);
+
if (flags & PERF_EF_START)
ddr_perf_event_start(event, flags);
- /* read trans, write trans, read beat */
- ddr_perf_monitor_config(pmu, cfg, cfg1, cfg2);
-
return 0;
}
@@ -501,9 +649,11 @@ static void ddr_perf_event_del(struct perf_event *event, int flags)
{
struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
+ int counter = hwc->idx;
ddr_perf_event_stop(event, PERF_EF_UPDATE);
+ pmu->events[counter] = NULL;
pmu->active_events--;
hwc->idx = -1;
}
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 6392cbedcd06..918cdc31de57 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -537,4 +537,5 @@ void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module)
}
EXPORT_SYMBOL_GPL(hisi_pmu_init);
+MODULE_DESCRIPTION("HiSilicon SoC uncore Performance Monitor driver framework");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/perf/marvell_cn10k_ddr_pmu.c b/drivers/perf/marvell_cn10k_ddr_pmu.c
index e2abca188dbe..94f1ebcd2a27 100644
--- a/drivers/perf/marvell_cn10k_ddr_pmu.c
+++ b/drivers/perf/marvell_cn10k_ddr_pmu.c
@@ -763,4 +763,5 @@ module_init(cn10k_ddr_pmu_init);
module_exit(cn10k_ddr_pmu_exit);
MODULE_AUTHOR("Bharat Bhushan <[email protected]>");
+MODULE_DESCRIPTION("Marvell CN10K DRAM Subsystem (DSS) Performance Monitor Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/perf/riscv_pmu.c b/drivers/perf/riscv_pmu.c
index 78c490e0505a..0a02e85a8951 100644
--- a/drivers/perf/riscv_pmu.c
+++ b/drivers/perf/riscv_pmu.c
@@ -167,7 +167,7 @@ u64 riscv_pmu_event_update(struct perf_event *event)
unsigned long cmask;
u64 oldval, delta;
- if (!rvpmu->ctr_read)
+ if (!rvpmu->ctr_read || (hwc->state & PERF_HES_UPTODATE))
return 0;
cmask = riscv_pmu_ctr_get_width_mask(event);
diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index a2e4005e1fd0..4e842dcedfba 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -20,6 +20,7 @@
#include <linux/cpu_pm.h>
#include <linux/sched/clock.h>
#include <linux/soc/andes/irq.h>
+#include <linux/workqueue.h>
#include <asm/errata_list.h>
#include <asm/sbi.h>
@@ -114,7 +115,7 @@ struct sbi_pmu_event_data {
};
};
-static const struct sbi_pmu_event_data pmu_hw_event_map[] = {
+static struct sbi_pmu_event_data pmu_hw_event_map[] = {
[PERF_COUNT_HW_CPU_CYCLES] = {.hw_gen_event = {
SBI_PMU_HW_CPU_CYCLES,
SBI_PMU_EVENT_TYPE_HW, 0}},
@@ -148,7 +149,7 @@ static const struct sbi_pmu_event_data pmu_hw_event_map[] = {
};
#define C(x) PERF_COUNT_HW_CACHE_##x
-static const struct sbi_pmu_event_data pmu_cache_event_map[PERF_COUNT_HW_CACHE_MAX]
+static struct sbi_pmu_event_data pmu_cache_event_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
[C(L1D)] = {
@@ -293,6 +294,34 @@ static const struct sbi_pmu_event_data pmu_cache_event_map[PERF_COUNT_HW_CACHE_M
},
};
+static void pmu_sbi_check_event(struct sbi_pmu_event_data *edata)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH,
+ 0, cmask, 0, edata->event_idx, 0, 0);
+ if (!ret.error) {
+ sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP,
+ ret.value, 0x1, SBI_PMU_STOP_FLAG_RESET, 0, 0, 0);
+ } else if (ret.error == SBI_ERR_NOT_SUPPORTED) {
+ /* This event cannot be monitored by any counter */
+ edata->event_idx = -EINVAL;
+ }
+}
+
+static void pmu_sbi_check_std_events(struct work_struct *work)
+{
+ for (int i = 0; i < ARRAY_SIZE(pmu_hw_event_map); i++)
+ pmu_sbi_check_event(&pmu_hw_event_map[i]);
+
+ for (int i = 0; i < ARRAY_SIZE(pmu_cache_event_map); i++)
+ for (int j = 0; j < ARRAY_SIZE(pmu_cache_event_map[i]); j++)
+ for (int k = 0; k < ARRAY_SIZE(pmu_cache_event_map[i][j]); k++)
+ pmu_sbi_check_event(&pmu_cache_event_map[i][j][k]);
+}
+
+static DECLARE_WORK(check_std_events_work, pmu_sbi_check_std_events);
+
static int pmu_sbi_ctr_get_width(int idx)
{
return pmu_ctr_list[idx].width;
@@ -478,6 +507,12 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
u64 raw_config_val;
int ret;
+ /*
+ * Ensure we are finished checking standard hardware events for
+ * validity before allowing userspace to configure any events.
+ */
+ flush_work(&check_std_events_work);
+
switch (type) {
case PERF_TYPE_HARDWARE:
if (config >= PERF_COUNT_HW_MAX)
@@ -762,7 +797,7 @@ static inline void pmu_sbi_stop_all(struct riscv_pmu *pmu)
* which may include counters that are not enabled yet.
*/
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP,
- 0, pmu->cmask, 0, 0, 0, 0);
+ 0, pmu->cmask, SBI_PMU_STOP_FLAG_RESET, 0, 0, 0);
}
static inline void pmu_sbi_stop_hw_ctrs(struct riscv_pmu *pmu)
@@ -1359,6 +1394,9 @@ static int pmu_sbi_device_probe(struct platform_device *pdev)
if (ret)
goto out_unregister;
+ /* Asynchronously check which standard events are available */
+ schedule_work(&check_std_events_work);
+
return 0;
out_unregister:
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index fbab6ac0f0d1..7594f64eb737 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -188,6 +188,9 @@ static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus);
if (ch->soc_no_adp_ctrl) {
+ if (ch->vbus)
+ regulator_hardware_enable(ch->vbus, vbus);
+
vbus_ctrl_reg = USB2_VBCTRL;
vbus_ctrl_val = USB2_VBCTRL_VBOUT;
}
@@ -718,7 +721,10 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]);
}
- channel->vbus = devm_regulator_get_optional(dev, "vbus");
+ if (channel->soc_no_adp_ctrl && channel->is_otg_channel)
+ channel->vbus = devm_regulator_get_exclusive(dev, "vbus");
+ else
+ channel->vbus = devm_regulator_get_optional(dev, "vbus");
if (IS_ERR(channel->vbus)) {
if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) {
ret = PTR_ERR(channel->vbus);
diff --git a/drivers/pinctrl/pinctrl-da9062.c b/drivers/pinctrl/pinctrl-da9062.c
index 22e3cd2cc963..6f44a13b90ce 100644
--- a/drivers/pinctrl/pinctrl-da9062.c
+++ b/drivers/pinctrl/pinctrl-da9062.c
@@ -139,7 +139,7 @@ static int da9062_gpio_direction_input(struct gpio_chip *gc,
{
struct da9062_pctl *pctl = gpiochip_get_data(gc);
struct regmap *regmap = pctl->da9062->regmap;
- struct gpio_desc *desc = gpiochip_get_desc(gc, offset);
+ struct gpio_desc *desc = gpio_device_get_desc(gc->gpiodev, offset);
unsigned int gpi_type;
int ret;
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index 81a298517df2..960fd6a82450 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -7,6 +7,8 @@ source "drivers/platform/goldfish/Kconfig"
source "drivers/platform/chrome/Kconfig"
+source "drivers/platform/cznic/Kconfig"
+
source "drivers/platform/mellanox/Kconfig"
source "drivers/platform/olpc/Kconfig"
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index fbbe4f77aa5d..bf69cc8d7429 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -10,5 +10,6 @@ obj-$(CONFIG_MIPS) += mips/
obj-$(CONFIG_OLPC_EC) += olpc/
obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
+obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/
obj-$(CONFIG_SURFACE_PLATFORMS) += surface/
obj-$(CONFIG_ARM64) += arm64/
diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c
index 47d19f7e295a..e821b3d39590 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -388,8 +388,8 @@ EXPORT_SYMBOL(cros_ec_suspend_late);
*/
int cros_ec_suspend(struct cros_ec_device *ec_dev)
{
- cros_ec_send_suspend_event(ec_dev);
- cros_ec_disable_irq(ec_dev);
+ cros_ec_suspend_prepare(ec_dev);
+ cros_ec_suspend_late(ec_dev);
return 0;
}
EXPORT_SYMBOL(cros_ec_suspend);
diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c
index e1d313246beb..4525ad1b59f4 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.c
+++ b/drivers/platform/chrome/cros_ec_debugfs.c
@@ -26,6 +26,10 @@
#define CIRC_ADD(idx, size, value) (((idx) + (value)) & ((size) - 1))
+static unsigned int log_poll_period_ms = LOG_POLL_SEC * MSEC_PER_SEC;
+module_param(log_poll_period_ms, uint, 0644);
+MODULE_PARM_DESC(log_poll_period_ms, "EC log polling period(ms)");
+
/* waitqueue for log readers */
static DECLARE_WAIT_QUEUE_HEAD(cros_ec_debugfs_log_wq);
@@ -57,7 +61,7 @@ struct cros_ec_debugfs {
/*
* We need to make sure that the EC log buffer on the UART is large enough,
- * so that it is unlikely enough to overlow within LOG_POLL_SEC.
+ * so that it is unlikely enough to overlow within log_poll_period_ms.
*/
static void cros_ec_console_log_work(struct work_struct *__work)
{
@@ -119,7 +123,7 @@ static void cros_ec_console_log_work(struct work_struct *__work)
resched:
schedule_delayed_work(&debug_info->log_poll_work,
- msecs_to_jiffies(LOG_POLL_SEC * 1000));
+ msecs_to_jiffies(log_poll_period_ms));
}
static int cros_ec_console_log_open(struct inode *inode, struct file *file)
@@ -330,6 +334,7 @@ static int ec_read_version_supported(struct cros_ec_dev *ec)
if (!msg)
return 0;
+ msg->version = 1;
msg->command = EC_CMD_GET_CMD_VERSIONS + ec->cmd_offset;
msg->outsize = sizeof(*params);
msg->insize = sizeof(*response);
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
index ddfbfec44f4c..f0470248b109 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -39,6 +39,16 @@ static bool cros_ec_lpc_acpi_device_found;
* be used as the base port for EC mapped memory.
*/
#define CROS_EC_LPC_QUIRK_REMAP_MEMORY BIT(0)
+/*
+ * Indicates that lpc_driver_data.quirk_acpi_id should be used to find
+ * the ACPI device.
+ */
+#define CROS_EC_LPC_QUIRK_ACPI_ID BIT(1)
+/*
+ * Indicates that lpc_driver_data.quirk_aml_mutex_name should be used
+ * to find an AML mutex to protect access to Microchip EC.
+ */
+#define CROS_EC_LPC_QUIRK_AML_MUTEX BIT(2)
/**
* struct lpc_driver_data - driver data attached to a DMI device ID to indicate
@@ -46,10 +56,15 @@ static bool cros_ec_lpc_acpi_device_found;
* @quirks: a bitfield composed of quirks from CROS_EC_LPC_QUIRK_*
* @quirk_mmio_memory_base: The first I/O port addressing EC mapped memory (used
* when quirk ...REMAP_MEMORY is set.)
+ * @quirk_acpi_id: An ACPI HID to be used to find the ACPI device.
+ * @quirk_aml_mutex_name: The name of an AML mutex to be used to protect access
+ * to Microchip EC.
*/
struct lpc_driver_data {
u32 quirks;
u16 quirk_mmio_memory_base;
+ const char *quirk_acpi_id;
+ const char *quirk_aml_mutex_name;
};
/**
@@ -62,14 +77,16 @@ struct cros_ec_lpc {
/**
* struct lpc_driver_ops - LPC driver operations
- * @read: Copy length bytes from EC address offset into buffer dest. Returns
- * the 8-bit checksum of all bytes read.
- * @write: Copy length bytes from buffer msg into EC address offset. Returns
- * the 8-bit checksum of all bytes written.
+ * @read: Copy length bytes from EC address offset into buffer dest.
+ * Returns a negative error code on error, or the 8-bit checksum
+ * of all bytes read.
+ * @write: Copy length bytes from buffer msg into EC address offset.
+ * Returns a negative error code on error, or the 8-bit checksum
+ * of all bytes written.
*/
struct lpc_driver_ops {
- u8 (*read)(unsigned int offset, unsigned int length, u8 *dest);
- u8 (*write)(unsigned int offset, unsigned int length, const u8 *msg);
+ int (*read)(unsigned int offset, unsigned int length, u8 *dest);
+ int (*write)(unsigned int offset, unsigned int length, const u8 *msg);
};
static struct lpc_driver_ops cros_ec_lpc_ops = { };
@@ -78,10 +95,10 @@ static struct lpc_driver_ops cros_ec_lpc_ops = { };
* A generic instance of the read function of struct lpc_driver_ops, used for
* the LPC EC.
*/
-static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
- u8 *dest)
+static int cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
+ u8 *dest)
{
- int sum = 0;
+ u8 sum = 0;
int i;
for (i = 0; i < length; ++i) {
@@ -97,10 +114,10 @@ static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
* A generic instance of the write function of struct lpc_driver_ops, used for
* the LPC EC.
*/
-static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
- const u8 *msg)
+static int cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
+ const u8 *msg)
{
- int sum = 0;
+ u8 sum = 0;
int i;
for (i = 0; i < length; ++i) {
@@ -116,13 +133,13 @@ static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
* An instance of the read function of struct lpc_driver_ops, used for the
* MEC variant of LPC EC.
*/
-static u8 cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
- u8 *dest)
+static int cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
+ u8 *dest)
{
int in_range = cros_ec_lpc_mec_in_range(offset, length);
if (in_range < 0)
- return 0;
+ return in_range;
return in_range ?
cros_ec_lpc_io_bytes_mec(MEC_IO_READ,
@@ -135,13 +152,13 @@ static u8 cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
* An instance of the write function of struct lpc_driver_ops, used for the
* MEC variant of LPC EC.
*/
-static u8 cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length,
- const u8 *msg)
+static int cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length,
+ const u8 *msg)
{
int in_range = cros_ec_lpc_mec_in_range(offset, length);
if (in_range < 0)
- return 0;
+ return in_range;
return in_range ?
cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE,
@@ -154,11 +171,14 @@ static int ec_response_timed_out(void)
{
unsigned long one_second = jiffies + HZ;
u8 data;
+ int ret;
usleep_range(200, 300);
do {
- if (!(cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data) &
- EC_LPC_STATUS_BUSY_MASK))
+ ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data);
+ if (ret < 0)
+ return ret;
+ if (!(data & EC_LPC_STATUS_BUSY_MASK))
return 0;
usleep_range(100, 200);
} while (time_before(jiffies, one_second));
@@ -179,28 +199,41 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
goto done;
/* Write buffer */
- cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
+ ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
+ if (ret < 0)
+ goto done;
/* Here we go */
sum = EC_COMMAND_PROTOCOL_3;
- cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
+ ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
+ if (ret < 0)
+ goto done;
- if (ec_response_timed_out()) {
+ ret = ec_response_timed_out();
+ if (ret < 0)
+ goto done;
+ if (ret) {
dev_warn(ec->dev, "EC response timed out\n");
ret = -EIO;
goto done;
}
/* Check result */
- msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
+ ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
+ if (ret < 0)
+ goto done;
+ msg->result = ret;
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
/* Read back response */
dout = (u8 *)&response;
- sum = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
+ ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
dout);
+ if (ret < 0)
+ goto done;
+ sum = ret;
msg->result = response.result;
@@ -213,9 +246,12 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
/* Read response and process checksum */
- sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET +
- sizeof(response), response.data_len,
- msg->data);
+ ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET +
+ sizeof(response), response.data_len,
+ msg->data);
+ if (ret < 0)
+ goto done;
+ sum += ret;
if (sum) {
dev_err(ec->dev,
@@ -255,32 +291,47 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
sum = msg->command + args.flags + args.command_version + args.data_size;
/* Copy data and update checksum */
- sum += cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
- msg->data);
+ ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
+ msg->data);
+ if (ret < 0)
+ goto done;
+ sum += ret;
/* Finalize checksum and write args */
args.checksum = sum;
- cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
- (u8 *)&args);
+ ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
+ (u8 *)&args);
+ if (ret < 0)
+ goto done;
/* Here we go */
sum = msg->command;
- cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
+ ret = cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
+ if (ret < 0)
+ goto done;
- if (ec_response_timed_out()) {
+ ret = ec_response_timed_out();
+ if (ret < 0)
+ goto done;
+ if (ret) {
dev_warn(ec->dev, "EC response timed out\n");
ret = -EIO;
goto done;
}
/* Check result */
- msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
+ ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
+ if (ret < 0)
+ goto done;
+ msg->result = ret;
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
/* Read back args */
- cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args);
+ ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args);
+ if (ret < 0)
+ goto done;
if (args.data_size > msg->insize) {
dev_err(ec->dev,
@@ -294,8 +345,11 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
sum = msg->command + args.flags + args.command_version + args.data_size;
/* Read response and update checksum */
- sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size,
- msg->data);
+ ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size,
+ msg->data);
+ if (ret < 0)
+ goto done;
+ sum += ret;
/* Verify checksum */
if (args.checksum != sum) {
@@ -320,19 +374,24 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
int i = offset;
char *s = dest;
int cnt = 0;
+ int ret;
if (offset >= EC_MEMMAP_SIZE - bytes)
return -EINVAL;
/* fixed length */
if (bytes) {
- cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + offset, bytes, s);
+ ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + offset, bytes, s);
+ if (ret < 0)
+ return ret;
return bytes;
}
/* string */
for (; i < EC_MEMMAP_SIZE; i++, s++) {
- cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + i, 1, s);
+ ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + i, 1, s);
+ if (ret < 0)
+ return ret;
cnt++;
if (!*s)
break;
@@ -374,6 +433,26 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
pm_system_wakeup();
}
+static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level,
+ void *context, void **retval)
+{
+ *(struct acpi_device **)context = acpi_fetch_acpi_dev(handle);
+ return AE_CTRL_TERMINATE;
+}
+
+static struct acpi_device *cros_ec_lpc_get_device(const char *id)
+{
+ struct acpi_device *adev = NULL;
+ acpi_status status = acpi_get_devices(id, cros_ec_lpc_parse_device,
+ &adev, NULL);
+ if (ACPI_FAILURE(status)) {
+ pr_warn(DRV_NAME ": Looking for %s failed\n", id);
+ return NULL;
+ }
+
+ return adev;
+}
+
static int cros_ec_lpc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -401,6 +480,27 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
if (quirks & CROS_EC_LPC_QUIRK_REMAP_MEMORY)
ec_lpc->mmio_memory_base = driver_data->quirk_mmio_memory_base;
+
+ if (quirks & CROS_EC_LPC_QUIRK_ACPI_ID) {
+ adev = cros_ec_lpc_get_device(driver_data->quirk_acpi_id);
+ if (!adev) {
+ dev_err(dev, "failed to get ACPI device '%s'",
+ driver_data->quirk_acpi_id);
+ return -ENODEV;
+ }
+ ACPI_COMPANION_SET(dev, adev);
+ }
+
+ if (quirks & CROS_EC_LPC_QUIRK_AML_MUTEX) {
+ const char *name
+ = driver_data->quirk_aml_mutex_name;
+ ret = cros_ec_lpc_mec_acpi_mutex(ACPI_COMPANION(dev), name);
+ if (ret) {
+ dev_err(dev, "failed to get AML mutex '%s'", name);
+ return ret;
+ }
+ dev_info(dev, "got AML mutex '%s'", name);
+ }
}
/*
@@ -425,7 +525,9 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
*/
cros_ec_lpc_ops.read = cros_ec_lpc_mec_read_bytes;
cros_ec_lpc_ops.write = cros_ec_lpc_mec_write_bytes;
- cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
+ ret = cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
+ if (ret < 0)
+ return ret;
if (buf[0] != 'E' || buf[1] != 'C') {
if (!devm_request_region(dev, ec_lpc->mmio_memory_base, EC_MEMMAP_SIZE,
dev_name(dev))) {
@@ -436,8 +538,10 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
/* Re-assign read/write operations for the non MEC variant */
cros_ec_lpc_ops.read = cros_ec_lpc_read_bytes;
cros_ec_lpc_ops.write = cros_ec_lpc_write_bytes;
- cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + EC_MEMMAP_ID, 2,
- buf);
+ ret = cros_ec_lpc_ops.read(ec_lpc->mmio_memory_base + EC_MEMMAP_ID, 2,
+ buf);
+ if (ret < 0)
+ return ret;
if (buf[0] != 'E' || buf[1] != 'C') {
dev_err(dev, "EC ID not detected\n");
return -ENODEV;
@@ -532,6 +636,12 @@ static const struct lpc_driver_data framework_laptop_amd_lpc_driver_data __initc
.quirk_mmio_memory_base = 0xE00,
};
+static const struct lpc_driver_data framework_laptop_11_lpc_driver_data __initconst = {
+ .quirks = CROS_EC_LPC_QUIRK_ACPI_ID|CROS_EC_LPC_QUIRK_AML_MUTEX,
+ .quirk_acpi_id = "PNP0C09",
+ .quirk_aml_mutex_name = "ECMT",
+};
+
static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = {
{
/*
@@ -600,6 +710,7 @@ static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
DMI_MATCH(DMI_PRODUCT_NAME, "Laptop"),
},
+ .driver_data = (void *)&framework_laptop_11_lpc_driver_data,
},
{ /* sentinel */ }
};
@@ -661,23 +772,12 @@ static struct platform_device cros_ec_lpc_device = {
.name = DRV_NAME
};
-static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level,
- void *context, void **retval)
-{
- *(bool *)context = true;
- return AE_CTRL_TERMINATE;
-}
-
static int __init cros_ec_lpc_init(void)
{
int ret;
- acpi_status status;
const struct dmi_system_id *dmi_match;
- status = acpi_get_devices(ACPI_DRV_NAME, cros_ec_lpc_parse_device,
- &cros_ec_lpc_acpi_device_found, NULL);
- if (ACPI_FAILURE(status))
- pr_warn(DRV_NAME ": Looking for %s failed\n", ACPI_DRV_NAME);
+ cros_ec_lpc_acpi_device_found = !!cros_ec_lpc_get_device(ACPI_DRV_NAME);
dmi_match = dmi_first_match(cros_ec_lpc_dmi_table);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c b/drivers/platform/chrome/cros_ec_lpc_mec.c
index 0d9c79b270ce..a56584171168 100644
--- a/drivers/platform/chrome/cros_ec_lpc_mec.c
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -10,14 +10,66 @@
#include "cros_ec_lpc_mec.h"
+#define ACPI_LOCK_DELAY_MS 500
+
/*
* This mutex must be held while accessing the EMI unit. We can't rely on the
* EC mutex because memmap data may be accessed without it being held.
*/
static DEFINE_MUTEX(io_mutex);
+/*
+ * An alternative mutex to be used when the ACPI AML code may also
+ * access memmap data. When set, this mutex is used in preference to
+ * io_mutex.
+ */
+static acpi_handle aml_mutex;
+
static u16 mec_emi_base, mec_emi_end;
/**
+ * cros_ec_lpc_mec_lock() - Acquire mutex for EMI
+ *
+ * @return: Negative error code, or zero for success
+ */
+static int cros_ec_lpc_mec_lock(void)
+{
+ bool success;
+
+ if (!aml_mutex) {
+ mutex_lock(&io_mutex);
+ return 0;
+ }
+
+ success = ACPI_SUCCESS(acpi_acquire_mutex(aml_mutex,
+ NULL, ACPI_LOCK_DELAY_MS));
+ if (!success)
+ return -EBUSY;
+
+ return 0;
+}
+
+/**
+ * cros_ec_lpc_mec_unlock() - Release mutex for EMI
+ *
+ * @return: Negative error code, or zero for success
+ */
+static int cros_ec_lpc_mec_unlock(void)
+{
+ bool success;
+
+ if (!aml_mutex) {
+ mutex_unlock(&io_mutex);
+ return 0;
+ }
+
+ success = ACPI_SUCCESS(acpi_release_mutex(aml_mutex, NULL));
+ if (!success)
+ return -EBUSY;
+
+ return 0;
+}
+
+/**
* cros_ec_lpc_mec_emi_write_address() - Initialize EMI at a given address.
*
* @addr: Starting read / write address
@@ -41,9 +93,6 @@ static void cros_ec_lpc_mec_emi_write_address(u16 addr,
*/
int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length)
{
- if (length == 0)
- return -EINVAL;
-
if (WARN_ON(mec_emi_base == 0 || mec_emi_end == 0))
return -EINVAL;
@@ -67,16 +116,21 @@ int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length)
* @length: Number of bytes to read / write
* @buf: Destination / source buffer
*
- * Return: 8-bit checksum of all bytes read / written
+ * @return: A negative error code on error, or 8-bit checksum of all
+ * bytes read / written
*/
-u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
- unsigned int offset, unsigned int length,
- u8 *buf)
+int cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
+ unsigned int offset, unsigned int length,
+ u8 *buf)
{
int i = 0;
int io_addr;
u8 sum = 0;
enum cros_ec_lpc_mec_emi_access_mode access, new_access;
+ int ret;
+
+ if (length == 0)
+ return 0;
/* Return checksum of 0 if window is not initialized */
WARN_ON(mec_emi_base == 0 || mec_emi_end == 0);
@@ -92,7 +146,9 @@ u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
else
access = ACCESS_TYPE_LONG_AUTO_INCREMENT;
- mutex_lock(&io_mutex);
+ ret = cros_ec_lpc_mec_lock();
+ if (ret)
+ return ret;
/* Initialize I/O at desired address */
cros_ec_lpc_mec_emi_write_address(offset, access);
@@ -134,7 +190,9 @@ u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
}
done:
- mutex_unlock(&io_mutex);
+ ret = cros_ec_lpc_mec_unlock();
+ if (ret)
+ return ret;
return sum;
}
@@ -146,3 +204,18 @@ void cros_ec_lpc_mec_init(unsigned int base, unsigned int end)
mec_emi_end = end;
}
EXPORT_SYMBOL(cros_ec_lpc_mec_init);
+
+int cros_ec_lpc_mec_acpi_mutex(struct acpi_device *adev, const char *pathname)
+{
+ int status;
+
+ if (!adev)
+ return -ENOENT;
+
+ status = acpi_get_handle(adev->handle, pathname, &aml_mutex);
+ if (ACPI_FAILURE(status))
+ return -ENOENT;
+
+ return 0;
+}
+EXPORT_SYMBOL(cros_ec_lpc_mec_acpi_mutex);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.h b/drivers/platform/chrome/cros_ec_lpc_mec.h
index 9d0521b23e8a..69f9d8786f61 100644
--- a/drivers/platform/chrome/cros_ec_lpc_mec.h
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.h
@@ -8,6 +8,8 @@
#ifndef __CROS_EC_LPC_MEC_H
#define __CROS_EC_LPC_MEC_H
+#include <linux/acpi.h>
+
enum cros_ec_lpc_mec_emi_access_mode {
/* 8-bit access */
ACCESS_TYPE_BYTE = 0x0,
@@ -46,6 +48,15 @@ enum cros_ec_lpc_mec_io_type {
void cros_ec_lpc_mec_init(unsigned int base, unsigned int end);
/**
+ * cros_ec_lpc_mec_acpi_mutex() - Find and set ACPI mutex for MEC
+ *
+ * @adev: Parent ACPI device
+ * @pathname: Name of AML mutex
+ * @return: Negative error code, or zero for success
+ */
+int cros_ec_lpc_mec_acpi_mutex(struct acpi_device *adev, const char *pathname);
+
+/**
* cros_ec_lpc_mec_in_range() - Determine if addresses are in MEC EMI range.
*
* @offset: Address offset
@@ -64,9 +75,10 @@ int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length);
* @length: Number of bytes to read / write
* @buf: Destination / source buffer
*
- * @return 8-bit checksum of all bytes read / written
+ * @return: A negative error code on error, or 8-bit checksum of all
+ * bytes read / written
*/
-u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
- unsigned int offset, unsigned int length, u8 *buf);
+int cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
+ unsigned int offset, unsigned int length, u8 *buf);
#endif /* __CROS_EC_LPC_MEC_H */
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
index 945b1b15a04c..f776fd42244f 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -5,6 +5,7 @@
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/limits.h>
#include <linux/module.h>
#include <linux/platform_data/cros_ec_commands.h>
#include <linux/platform_data/cros_ec_proto.h>
@@ -239,13 +240,12 @@ int cros_ec_check_result(struct cros_ec_device *ec_dev,
}
EXPORT_SYMBOL(cros_ec_check_result);
-/*
+/**
* cros_ec_get_host_event_wake_mask
*
* Get the mask of host events that cause wake from suspend.
*
* @ec_dev: EC device to call
- * @msg: message structure to use
* @mask: result when function returns 0.
*
* LOCKING:
@@ -427,13 +427,12 @@ exit:
return ret;
}
-/*
+/**
* cros_ec_get_host_command_version_mask
*
* Get the version mask of a given command.
*
* @ec_dev: EC device to call
- * @msg: message structure to use
* @cmd: command to get the version of.
* @mask: result when function returns 0.
*
@@ -686,7 +685,7 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
static int get_next_event_xfer(struct cros_ec_device *ec_dev,
struct cros_ec_command *msg,
- struct ec_response_get_next_event_v1 *event,
+ struct ec_response_get_next_event_v3 *event,
int version, uint32_t size)
{
int ret;
@@ -709,11 +708,12 @@ static int get_next_event(struct cros_ec_device *ec_dev)
{
struct {
struct cros_ec_command msg;
- struct ec_response_get_next_event_v1 event;
+ struct ec_response_get_next_event_v3 event;
} __packed buf;
struct cros_ec_command *msg = &buf.msg;
- struct ec_response_get_next_event_v1 *event = &buf.event;
- const int cmd_version = ec_dev->mkbp_event_supported - 1;
+ struct ec_response_get_next_event_v3 *event = &buf.event;
+ int cmd_version = ec_dev->mkbp_event_supported - 1;
+ u32 size;
memset(msg, 0, sizeof(*msg));
if (ec_dev->suspended) {
@@ -721,12 +721,20 @@ static int get_next_event(struct cros_ec_device *ec_dev)
return -EHOSTDOWN;
}
- if (cmd_version == 0)
- return get_next_event_xfer(ec_dev, msg, event, 0,
- sizeof(struct ec_response_get_next_event));
+ if (cmd_version == 0) {
+ size = sizeof(struct ec_response_get_next_event);
+ } else if (cmd_version < 3) {
+ size = sizeof(struct ec_response_get_next_event_v1);
+ } else {
+ /*
+ * The max version we support is v3. So, we speak v3 even if the
+ * EC says it supports v4+.
+ */
+ cmd_version = 3;
+ size = sizeof(struct ec_response_get_next_event_v3);
+ }
- return get_next_event_xfer(ec_dev, msg, event, cmd_version,
- sizeof(struct ec_response_get_next_event_v1));
+ return get_next_event_xfer(ec_dev, msg, event, cmd_version, size);
}
static int get_keyboard_state_event(struct cros_ec_device *ec_dev)
@@ -1035,3 +1043,64 @@ error:
return ret;
}
EXPORT_SYMBOL_GPL(cros_ec_cmd);
+
+/**
+ * cros_ec_cmd_readmem - Read from EC memory.
+ *
+ * @ec_dev: EC device
+ * @offset: Is within EC_LPC_ADDR_MEMMAP region.
+ * @size: Number of bytes to read.
+ * @dest: EC command output data
+ *
+ * Return: >= 0 on success, negative error number on failure.
+ */
+int cros_ec_cmd_readmem(struct cros_ec_device *ec_dev, u8 offset, u8 size, void *dest)
+{
+ struct ec_params_read_memmap params = {};
+
+ if (!size)
+ return -EINVAL;
+
+ if (ec_dev->cmd_readmem)
+ return ec_dev->cmd_readmem(ec_dev, offset, size, dest);
+
+ params.offset = offset;
+ params.size = size;
+ return cros_ec_cmd(ec_dev, 0, EC_CMD_READ_MEMMAP,
+ &params, sizeof(params), dest, size);
+}
+EXPORT_SYMBOL_GPL(cros_ec_cmd_readmem);
+
+/**
+ * cros_ec_get_cmd_versions - Get supported version mask.
+ *
+ * @ec_dev: EC device
+ * @cmd: Command to test
+ *
+ * Return: version mask on success, negative error number on failure.
+ */
+int cros_ec_get_cmd_versions(struct cros_ec_device *ec_dev, u16 cmd)
+{
+ struct ec_params_get_cmd_versions req_v0;
+ struct ec_params_get_cmd_versions_v1 req_v1;
+ struct ec_response_get_cmd_versions resp;
+ int ret;
+
+ if (cmd <= U8_MAX) {
+ req_v0.cmd = cmd;
+ ret = cros_ec_cmd(ec_dev, 0, EC_CMD_GET_CMD_VERSIONS,
+ &req_v0, sizeof(req_v0), &resp, sizeof(resp));
+ } else {
+ req_v1.cmd = cmd;
+ ret = cros_ec_cmd(ec_dev, 1, EC_CMD_GET_CMD_VERSIONS,
+ &req_v1, sizeof(req_v1), &resp, sizeof(resp));
+ }
+
+ if (ret == -EINVAL)
+ return 0; /* Command not implemented */
+ else if (ret < 0)
+ return ret;
+ else
+ return resp.version_mask;
+}
+EXPORT_SYMBOL_GPL(cros_ec_get_cmd_versions);
diff --git a/drivers/platform/chrome/cros_ec_proto_test.c b/drivers/platform/chrome/cros_ec_proto_test.c
index 41378c2ee6a0..7ca9895a0065 100644
--- a/drivers/platform/chrome/cros_ec_proto_test.c
+++ b/drivers/platform/chrome/cros_ec_proto_test.c
@@ -2060,17 +2060,17 @@ static void cros_ec_proto_test_get_next_event_no_mkbp_event(struct kunit *test)
/* For get_keyboard_state_event(). */
{
- union ec_response_get_next_data_v1 *data;
+ union ec_response_get_next_data_v3 *data;
mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
KUNIT_ASSERT_PTR_NE(test, mock, NULL);
- data = (union ec_response_get_next_data_v1 *)mock->o_data;
+ data = (union ec_response_get_next_data_v3 *)mock->o_data;
data->host_event = 0xbeef;
}
ret = cros_ec_get_next_event(ec_dev, &wake_event, &more_events);
- KUNIT_EXPECT_EQ(test, ret, sizeof(union ec_response_get_next_data_v1));
+ KUNIT_EXPECT_EQ(test, ret, sizeof(union ec_response_get_next_data_v3));
KUNIT_EXPECT_EQ(test, ec_dev->event_data.event_type, EC_MKBP_EVENT_KEY_MATRIX);
KUNIT_EXPECT_EQ(test, ec_dev->event_data.data.host_event, 0xbeef);
@@ -2085,7 +2085,7 @@ static void cros_ec_proto_test_get_next_event_no_mkbp_event(struct kunit *test)
KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_MKBP_STATE);
- KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(union ec_response_get_next_data_v1));
+ KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(union ec_response_get_next_data_v3));
KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
}
}
@@ -2740,4 +2740,5 @@ static struct kunit_suite cros_ec_proto_test_suite = {
kunit_test_suite(cros_ec_proto_test_suite);
+MODULE_DESCRIPTION("Kunit tests for ChromeOS Embedded Controller protocol");
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/chrome/wilco_ec/mailbox.c b/drivers/platform/chrome/wilco_ec/mailbox.c
index 0f98358ea824..4d8273b47cde 100644
--- a/drivers/platform/chrome/wilco_ec/mailbox.c
+++ b/drivers/platform/chrome/wilco_ec/mailbox.c
@@ -117,13 +117,17 @@ static int wilco_ec_transfer(struct wilco_ec_device *ec,
struct wilco_ec_request *rq)
{
struct wilco_ec_response *rs;
- u8 checksum;
+ int ret;
u8 flag;
/* Write request header, then data */
- cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, 0, sizeof(*rq), (u8 *)rq);
- cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, sizeof(*rq), msg->request_size,
- msg->request_data);
+ ret = cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, 0, sizeof(*rq), (u8 *)rq);
+ if (ret < 0)
+ return ret;
+ ret = cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, sizeof(*rq), msg->request_size,
+ msg->request_data);
+ if (ret < 0)
+ return ret;
/* Start the command */
outb(EC_MAILBOX_START_COMMAND, ec->io_command->start);
@@ -149,10 +153,12 @@ static int wilco_ec_transfer(struct wilco_ec_device *ec,
/* Read back response */
rs = ec->data_buffer;
- checksum = cros_ec_lpc_io_bytes_mec(MEC_IO_READ, 0,
- sizeof(*rs) + EC_MAILBOX_DATA_SIZE,
- (u8 *)rs);
- if (checksum) {
+ ret = cros_ec_lpc_io_bytes_mec(MEC_IO_READ, 0,
+ sizeof(*rs) + EC_MAILBOX_DATA_SIZE,
+ (u8 *)rs);
+ if (ret < 0)
+ return ret;
+ if (ret) {
dev_dbg(ec->dev, "bad packet checksum 0x%02x\n", rs->checksum);
return -EBADMSG;
}
diff --git a/drivers/platform/cznic/Kconfig b/drivers/platform/cznic/Kconfig
new file mode 100644
index 000000000000..cb0d4d686d8a
--- /dev/null
+++ b/drivers/platform/cznic/Kconfig
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.rst.
+#
+
+menuconfig CZNIC_PLATFORMS
+ bool "Platform support for CZ.NIC's Turris hardware"
+ help
+ Say Y here to be able to choose driver support for CZ.NIC's Turris
+ devices. This option alone does not add any kernel code.
+
+if CZNIC_PLATFORMS
+
+config TURRIS_OMNIA_MCU
+ tristate "Turris Omnia MCU driver"
+ depends on MACH_ARMADA_38X || COMPILE_TEST
+ depends on I2C
+ depends on OF
+ depends on WATCHDOG
+ depends on GPIOLIB
+ depends on HW_RANDOM
+ depends on RTC_CLASS
+ depends on WATCHDOG_CORE
+ select GPIOLIB_IRQCHIP
+ help
+ Say Y here to add support for the features implemented by the
+ microcontroller on the CZ.NIC's Turris Omnia SOHO router.
+ The features include:
+ - board poweroff into true low power mode (with voltage regulators
+ disabled) and the ability to configure wake up from this mode (via
+ rtcwake)
+ - true random number generator (if available on the MCU)
+ - MCU watchdog
+ - GPIO pins
+ - to get front button press events (the front button can be
+ configured either to generate press events to the CPU or to change
+ front LEDs panel brightness)
+ - to enable / disable USB port voltage regulators and to detect
+ USB overcurrent
+ - to detect MiniPCIe / mSATA card presence in MiniPCIe port 0
+ - to configure resets of various peripherals on board revisions 32+
+ - to enable / disable the VHV voltage regulator to the SOC in order
+ to be able to program SOC's OTP on board revisions 32+
+ - to get input from the LED output pins of the WAN ethernet PHY, LAN
+ switch and MiniPCIe ports
+ To compile this driver as a module, choose M here; the module will be
+ called turris-omnia-mcu.
+
+endif # CZNIC_PLATFORMS
diff --git a/drivers/platform/cznic/Makefile b/drivers/platform/cznic/Makefile
new file mode 100644
index 000000000000..eae4c6b341ff
--- /dev/null
+++ b/drivers/platform/cznic/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o
+turris-omnia-mcu-y := turris-omnia-mcu-base.o
+turris-omnia-mcu-y += turris-omnia-mcu-gpio.o
+turris-omnia-mcu-y += turris-omnia-mcu-sys-off-wakeup.o
+turris-omnia-mcu-y += turris-omnia-mcu-trng.o
+turris-omnia-mcu-y += turris-omnia-mcu-watchdog.o
diff --git a/drivers/platform/cznic/turris-omnia-mcu-base.c b/drivers/platform/cznic/turris-omnia-mcu-base.c
new file mode 100644
index 000000000000..c68a7a84a951
--- /dev/null
+++ b/drivers/platform/cznic/turris-omnia-mcu-base.c
@@ -0,0 +1,408 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CZ.NIC's Turris Omnia MCU driver
+ *
+ * 2024 by Marek Behún <[email protected]>
+ */
+
+#include <linux/array_size.h>
+#include <linux/bits.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/hex.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#include <linux/turris-omnia-mcu-interface.h>
+#include "turris-omnia-mcu.h"
+
+#define OMNIA_FW_VERSION_LEN 20
+#define OMNIA_FW_VERSION_HEX_LEN (2 * OMNIA_FW_VERSION_LEN + 1)
+#define OMNIA_BOARD_INFO_LEN 16
+
+int omnia_cmd_write_read(const struct i2c_client *client,
+ void *cmd, unsigned int cmd_len,
+ void *reply, unsigned int reply_len)
+{
+ struct i2c_msg msgs[2];
+ int ret, num;
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = 0;
+ msgs[0].len = cmd_len;
+ msgs[0].buf = cmd;
+ num = 1;
+
+ if (reply_len) {
+ msgs[1].addr = client->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = reply_len;
+ msgs[1].buf = reply;
+ num++;
+ }
+
+ ret = i2c_transfer(client->adapter, msgs, num);
+ if (ret < 0)
+ return ret;
+ if (ret != num)
+ return -EIO;
+
+ return 0;
+}
+
+static int omnia_get_version_hash(struct omnia_mcu *mcu, bool bootloader,
+ char version[static OMNIA_FW_VERSION_HEX_LEN])
+{
+ u8 reply[OMNIA_FW_VERSION_LEN];
+ char *p;
+ int err;
+
+ err = omnia_cmd_read(mcu->client,
+ bootloader ? OMNIA_CMD_GET_FW_VERSION_BOOT
+ : OMNIA_CMD_GET_FW_VERSION_APP,
+ reply, sizeof(reply));
+ if (err)
+ return err;
+
+ p = bin2hex(version, reply, OMNIA_FW_VERSION_LEN);
+ *p = '\0';
+
+ return 0;
+}
+
+static ssize_t fw_version_hash_show(struct device *dev, char *buf,
+ bool bootloader)
+{
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+ char version[OMNIA_FW_VERSION_HEX_LEN];
+ int err;
+
+ err = omnia_get_version_hash(mcu, bootloader, version);
+ if (err)
+ return err;
+
+ return sysfs_emit(buf, "%s\n", version);
+}
+
+static ssize_t fw_version_hash_application_show(struct device *dev,
+ struct device_attribute *a,
+ char *buf)
+{
+ return fw_version_hash_show(dev, buf, false);
+}
+static DEVICE_ATTR_RO(fw_version_hash_application);
+
+static ssize_t fw_version_hash_bootloader_show(struct device *dev,
+ struct device_attribute *a,
+ char *buf)
+{
+ return fw_version_hash_show(dev, buf, true);
+}
+static DEVICE_ATTR_RO(fw_version_hash_bootloader);
+
+static ssize_t fw_features_show(struct device *dev, struct device_attribute *a,
+ char *buf)
+{
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "0x%x\n", mcu->features);
+}
+static DEVICE_ATTR_RO(fw_features);
+
+static ssize_t mcu_type_show(struct device *dev, struct device_attribute *a,
+ char *buf)
+{
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%s\n", mcu->type);
+}
+static DEVICE_ATTR_RO(mcu_type);
+
+static ssize_t reset_selector_show(struct device *dev,
+ struct device_attribute *a, char *buf)
+{
+ u8 reply;
+ int err;
+
+ err = omnia_cmd_read_u8(to_i2c_client(dev), OMNIA_CMD_GET_RESET,
+ &reply);
+ if (err)
+ return err;
+
+ return sysfs_emit(buf, "%d\n", reply);
+}
+static DEVICE_ATTR_RO(reset_selector);
+
+static ssize_t serial_number_show(struct device *dev,
+ struct device_attribute *a, char *buf)
+{
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%016llX\n", mcu->board_serial_number);
+}
+static DEVICE_ATTR_RO(serial_number);
+
+static ssize_t first_mac_address_show(struct device *dev,
+ struct device_attribute *a, char *buf)
+{
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%pM\n", mcu->board_first_mac);
+}
+static DEVICE_ATTR_RO(first_mac_address);
+
+static ssize_t board_revision_show(struct device *dev,
+ struct device_attribute *a, char *buf)
+{
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", mcu->board_revision);
+}
+static DEVICE_ATTR_RO(board_revision);
+
+static struct attribute *omnia_mcu_base_attrs[] = {
+ &dev_attr_fw_version_hash_application.attr,
+ &dev_attr_fw_version_hash_bootloader.attr,
+ &dev_attr_fw_features.attr,
+ &dev_attr_mcu_type.attr,
+ &dev_attr_reset_selector.attr,
+ &dev_attr_serial_number.attr,
+ &dev_attr_first_mac_address.attr,
+ &dev_attr_board_revision.attr,
+ NULL
+};
+
+static umode_t omnia_mcu_base_attrs_visible(struct kobject *kobj,
+ struct attribute *a, int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+
+ if ((a == &dev_attr_serial_number.attr ||
+ a == &dev_attr_first_mac_address.attr ||
+ a == &dev_attr_board_revision.attr) &&
+ !(mcu->features & OMNIA_FEAT_BOARD_INFO))
+ return 0;
+
+ return a->mode;
+}
+
+static const struct attribute_group omnia_mcu_base_group = {
+ .attrs = omnia_mcu_base_attrs,
+ .is_visible = omnia_mcu_base_attrs_visible,
+};
+
+static const struct attribute_group *omnia_mcu_groups[] = {
+ &omnia_mcu_base_group,
+ &omnia_mcu_gpio_group,
+ &omnia_mcu_poweroff_group,
+ NULL
+};
+
+static void omnia_mcu_print_version_hash(struct omnia_mcu *mcu, bool bootloader)
+{
+ const char *type = bootloader ? "bootloader" : "application";
+ struct device *dev = &mcu->client->dev;
+ char version[OMNIA_FW_VERSION_HEX_LEN];
+ int err;
+
+ err = omnia_get_version_hash(mcu, bootloader, version);
+ if (err) {
+ dev_err(dev, "Cannot read MCU %s firmware version: %d\n",
+ type, err);
+ return;
+ }
+
+ dev_info(dev, "MCU %s firmware version hash: %s\n", type, version);
+}
+
+static const char *omnia_status_to_mcu_type(u16 status)
+{
+ switch (status & OMNIA_STS_MCU_TYPE_MASK) {
+ case OMNIA_STS_MCU_TYPE_STM32:
+ return "STM32";
+ case OMNIA_STS_MCU_TYPE_GD32:
+ return "GD32";
+ case OMNIA_STS_MCU_TYPE_MKL:
+ return "MKL";
+ default:
+ return "unknown";
+ }
+}
+
+static void omnia_info_missing_feature(struct device *dev, const char *feature)
+{
+ dev_info(dev,
+ "Your board's MCU firmware does not support the %s feature.\n",
+ feature);
+}
+
+static int omnia_mcu_read_features(struct omnia_mcu *mcu)
+{
+ static const struct {
+ u16 mask;
+ const char *name;
+ } features[] = {
+#define _DEF_FEAT(_n, _m) { OMNIA_FEAT_ ## _n, _m }
+ _DEF_FEAT(EXT_CMDS, "extended control and status"),
+ _DEF_FEAT(WDT_PING, "watchdog pinging"),
+ _DEF_FEAT(LED_STATE_EXT_MASK, "peripheral LED pins reading"),
+ _DEF_FEAT(NEW_INT_API, "new interrupt API"),
+ _DEF_FEAT(POWEROFF_WAKEUP, "poweroff and wakeup"),
+ _DEF_FEAT(TRNG, "true random number generator"),
+#undef _DEF_FEAT
+ };
+ struct i2c_client *client = mcu->client;
+ struct device *dev = &client->dev;
+ bool suggest_fw_upgrade = false;
+ u16 status;
+ int err;
+
+ /* status word holds MCU type, which we need below */
+ err = omnia_cmd_read_u16(client, OMNIA_CMD_GET_STATUS_WORD, &status);
+ if (err)
+ return err;
+
+ /*
+ * Check whether MCU firmware supports the OMNIA_CMD_GET_FEATURES
+ * command.
+ */
+ if (status & OMNIA_STS_FEATURES_SUPPORTED) {
+ /* try read 32-bit features */
+ err = omnia_cmd_read_u32(client, OMNIA_CMD_GET_FEATURES,
+ &mcu->features);
+ if (err) {
+ /* try read 16-bit features */
+ u16 features16;
+
+ err = omnia_cmd_read_u16(client, OMNIA_CMD_GET_FEATURES,
+ &features16);
+ if (err)
+ return err;
+
+ mcu->features = features16;
+ } else {
+ if (mcu->features & OMNIA_FEAT_FROM_BIT_16_INVALID)
+ mcu->features &= GENMASK(15, 0);
+ }
+ } else {
+ dev_info(dev,
+ "Your board's MCU firmware does not support feature reading.\n");
+ suggest_fw_upgrade = true;
+ }
+
+ mcu->type = omnia_status_to_mcu_type(status);
+ dev_info(dev, "MCU type %s%s\n", mcu->type,
+ (mcu->features & OMNIA_FEAT_PERIPH_MCU) ?
+ ", with peripheral resets wired" : "");
+
+ omnia_mcu_print_version_hash(mcu, true);
+
+ if (mcu->features & OMNIA_FEAT_BOOTLOADER)
+ dev_warn(dev,
+ "MCU is running bootloader firmware. Was firmware upgrade interrupted?\n");
+ else
+ omnia_mcu_print_version_hash(mcu, false);
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(features); i++) {
+ if (mcu->features & features[i].mask)
+ continue;
+
+ omnia_info_missing_feature(dev, features[i].name);
+ suggest_fw_upgrade = true;
+ }
+
+ if (suggest_fw_upgrade)
+ dev_info(dev,
+ "Consider upgrading MCU firmware with the omnia-mcutool utility.\n");
+
+ return 0;
+}
+
+static int omnia_mcu_read_board_info(struct omnia_mcu *mcu)
+{
+ u8 reply[1 + OMNIA_BOARD_INFO_LEN];
+ int err;
+
+ err = omnia_cmd_read(mcu->client, OMNIA_CMD_BOARD_INFO_GET, reply,
+ sizeof(reply));
+ if (err)
+ return err;
+
+ if (reply[0] != OMNIA_BOARD_INFO_LEN)
+ return -EIO;
+
+ mcu->board_serial_number = get_unaligned_le64(&reply[1]);
+
+ /* we can't use ether_addr_copy() because reply is not u16-aligned */
+ memcpy(mcu->board_first_mac, &reply[9], sizeof(mcu->board_first_mac));
+
+ mcu->board_revision = reply[15];
+
+ return 0;
+}
+
+static int omnia_mcu_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct omnia_mcu *mcu;
+ int err;
+
+ if (!client->irq)
+ return dev_err_probe(dev, -EINVAL, "IRQ resource not found\n");
+
+ mcu = devm_kzalloc(dev, sizeof(*mcu), GFP_KERNEL);
+ if (!mcu)
+ return -ENOMEM;
+
+ mcu->client = client;
+ i2c_set_clientdata(client, mcu);
+
+ err = omnia_mcu_read_features(mcu);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Cannot determine MCU supported features\n");
+
+ if (mcu->features & OMNIA_FEAT_BOARD_INFO) {
+ err = omnia_mcu_read_board_info(mcu);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Cannot read board info\n");
+ }
+
+ err = omnia_mcu_register_sys_off_and_wakeup(mcu);
+ if (err)
+ return err;
+
+ err = omnia_mcu_register_watchdog(mcu);
+ if (err)
+ return err;
+
+ err = omnia_mcu_register_gpiochip(mcu);
+ if (err)
+ return err;
+
+ return omnia_mcu_register_trng(mcu);
+}
+
+static const struct of_device_id of_omnia_mcu_match[] = {
+ { .compatible = "cznic,turris-omnia-mcu" },
+ {}
+};
+
+static struct i2c_driver omnia_mcu_driver = {
+ .probe = omnia_mcu_probe,
+ .driver = {
+ .name = "turris-omnia-mcu",
+ .of_match_table = of_omnia_mcu_match,
+ .dev_groups = omnia_mcu_groups,
+ },
+};
+module_i2c_driver(omnia_mcu_driver);
+
+MODULE_AUTHOR("Marek Behun <[email protected]>");
+MODULE_DESCRIPTION("CZ.NIC's Turris Omnia MCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/cznic/turris-omnia-mcu-gpio.c b/drivers/platform/cznic/turris-omnia-mcu-gpio.c
new file mode 100644
index 000000000000..91da56a704c7
--- /dev/null
+++ b/drivers/platform/cznic/turris-omnia-mcu-gpio.c
@@ -0,0 +1,1095 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CZ.NIC's Turris Omnia MCU GPIO and IRQ driver
+ *
+ * 2024 by Marek Behún <[email protected]>
+ */
+
+#include <linux/array_size.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/bug.h>
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/devm-helpers.h>
+#include <linux/errno.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+#include <asm/unaligned.h>
+
+#include <linux/turris-omnia-mcu-interface.h>
+#include "turris-omnia-mcu.h"
+
+#define OMNIA_CMD_INT_ARG_LEN 8
+#define FRONT_BUTTON_RELEASE_DELAY_MS 50
+
+static const char * const omnia_mcu_gpio_templates[64] = {
+ /* GPIOs with value read from the 16-bit wide status */
+ [4] = "MiniPCIe0 Card Detect",
+ [5] = "MiniPCIe0 mSATA Indicator",
+ [6] = "Front USB3 port over-current",
+ [7] = "Rear USB3 port over-current",
+ [8] = "Front USB3 port power",
+ [9] = "Rear USB3 port power",
+ [12] = "Front Button",
+
+ /* GPIOs with value read from the 32-bit wide extended status */
+ [16] = "SFP nDET",
+ [28] = "MiniPCIe0 LED",
+ [29] = "MiniPCIe1 LED",
+ [30] = "MiniPCIe2 LED",
+ [31] = "MiniPCIe0 PAN LED",
+ [32] = "MiniPCIe1 PAN LED",
+ [33] = "MiniPCIe2 PAN LED",
+ [34] = "WAN PHY LED0",
+ [35] = "WAN PHY LED1",
+ [36] = "LAN switch p0 LED0",
+ [37] = "LAN switch p0 LED1",
+ [38] = "LAN switch p1 LED0",
+ [39] = "LAN switch p1 LED1",
+ [40] = "LAN switch p2 LED0",
+ [41] = "LAN switch p2 LED1",
+ [42] = "LAN switch p3 LED0",
+ [43] = "LAN switch p3 LED1",
+ [44] = "LAN switch p4 LED0",
+ [45] = "LAN switch p4 LED1",
+ [46] = "LAN switch p5 LED0",
+ [47] = "LAN switch p5 LED1",
+
+ /* GPIOs with value read from the 16-bit wide extended control status */
+ [48] = "eMMC nRESET",
+ [49] = "LAN switch nRESET",
+ [50] = "WAN PHY nRESET",
+ [51] = "MiniPCIe0 nPERST",
+ [52] = "MiniPCIe1 nPERST",
+ [53] = "MiniPCIe2 nPERST",
+ [54] = "WAN PHY SFP mux",
+ [56] = "VHV power disable",
+};
+
+struct omnia_gpio {
+ u8 cmd;
+ u8 ctl_cmd;
+ u8 bit;
+ u8 ctl_bit;
+ u8 int_bit;
+ u16 feat;
+ u16 feat_mask;
+};
+
+#define OMNIA_GPIO_INVALID_INT_BIT 0xff
+
+#define _DEF_GPIO(_cmd, _ctl_cmd, _bit, _ctl_bit, _int_bit, _feat, _feat_mask) \
+ { \
+ .cmd = _cmd, \
+ .ctl_cmd = _ctl_cmd, \
+ .bit = _bit, \
+ .ctl_bit = _ctl_bit, \
+ .int_bit = (_int_bit) < 0 ? OMNIA_GPIO_INVALID_INT_BIT \
+ : (_int_bit), \
+ .feat = _feat, \
+ .feat_mask = _feat_mask, \
+ }
+
+#define _DEF_GPIO_STS(_name) \
+ _DEF_GPIO(OMNIA_CMD_GET_STATUS_WORD, 0, __bf_shf(OMNIA_STS_ ## _name), \
+ 0, __bf_shf(OMNIA_INT_ ## _name), 0, 0)
+
+#define _DEF_GPIO_CTL(_name) \
+ _DEF_GPIO(OMNIA_CMD_GET_STATUS_WORD, OMNIA_CMD_GENERAL_CONTROL, \
+ __bf_shf(OMNIA_STS_ ## _name), __bf_shf(OMNIA_CTL_ ## _name), \
+ -1, 0, 0)
+
+#define _DEF_GPIO_EXT_STS(_name, _feat) \
+ _DEF_GPIO(OMNIA_CMD_GET_EXT_STATUS_DWORD, 0, \
+ __bf_shf(OMNIA_EXT_STS_ ## _name), 0, \
+ __bf_shf(OMNIA_INT_ ## _name), \
+ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS, \
+ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS)
+
+#define _DEF_GPIO_EXT_STS_LED(_name, _ledext) \
+ _DEF_GPIO(OMNIA_CMD_GET_EXT_STATUS_DWORD, 0, \
+ __bf_shf(OMNIA_EXT_STS_ ## _name), 0, \
+ __bf_shf(OMNIA_INT_ ## _name), \
+ OMNIA_FEAT_LED_STATE_ ## _ledext, \
+ OMNIA_FEAT_LED_STATE_EXT_MASK)
+
+#define _DEF_GPIO_EXT_STS_LEDALL(_name) \
+ _DEF_GPIO(OMNIA_CMD_GET_EXT_STATUS_DWORD, 0, \
+ __bf_shf(OMNIA_EXT_STS_ ## _name), 0, \
+ __bf_shf(OMNIA_INT_ ## _name), \
+ OMNIA_FEAT_LED_STATE_EXT_MASK, 0)
+
+#define _DEF_GPIO_EXT_CTL(_name, _feat) \
+ _DEF_GPIO(OMNIA_CMD_GET_EXT_CONTROL_STATUS, OMNIA_CMD_EXT_CONTROL, \
+ __bf_shf(OMNIA_EXT_CTL_ ## _name), \
+ __bf_shf(OMNIA_EXT_CTL_ ## _name), -1, \
+ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS, \
+ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS)
+
+#define _DEF_INT(_name) \
+ _DEF_GPIO(0, 0, 0, 0, __bf_shf(OMNIA_INT_ ## _name), 0, 0)
+
+static inline bool is_int_bit_valid(const struct omnia_gpio *gpio)
+{
+ return gpio->int_bit != OMNIA_GPIO_INVALID_INT_BIT;
+}
+
+static const struct omnia_gpio omnia_gpios[64] = {
+ /* GPIOs with value read from the 16-bit wide status */
+ [4] = _DEF_GPIO_STS(CARD_DET),
+ [5] = _DEF_GPIO_STS(MSATA_IND),
+ [6] = _DEF_GPIO_STS(USB30_OVC),
+ [7] = _DEF_GPIO_STS(USB31_OVC),
+ [8] = _DEF_GPIO_CTL(USB30_PWRON),
+ [9] = _DEF_GPIO_CTL(USB31_PWRON),
+
+ /* brightness changed interrupt, no GPIO */
+ [11] = _DEF_INT(BRIGHTNESS_CHANGED),
+
+ [12] = _DEF_GPIO_STS(BUTTON_PRESSED),
+
+ /* TRNG interrupt, no GPIO */
+ [13] = _DEF_INT(TRNG),
+
+ /* MESSAGE_SIGNED interrupt, no GPIO */
+ [14] = _DEF_INT(MESSAGE_SIGNED),
+
+ /* GPIOs with value read from the 32-bit wide extended status */
+ [16] = _DEF_GPIO_EXT_STS(SFP_nDET, PERIPH_MCU),
+ [28] = _DEF_GPIO_EXT_STS_LEDALL(WLAN0_MSATA_LED),
+ [29] = _DEF_GPIO_EXT_STS_LEDALL(WLAN1_LED),
+ [30] = _DEF_GPIO_EXT_STS_LEDALL(WLAN2_LED),
+ [31] = _DEF_GPIO_EXT_STS_LED(WPAN0_LED, EXT),
+ [32] = _DEF_GPIO_EXT_STS_LED(WPAN1_LED, EXT),
+ [33] = _DEF_GPIO_EXT_STS_LED(WPAN2_LED, EXT),
+ [34] = _DEF_GPIO_EXT_STS_LEDALL(WAN_LED0),
+ [35] = _DEF_GPIO_EXT_STS_LED(WAN_LED1, EXT_V32),
+ [36] = _DEF_GPIO_EXT_STS_LEDALL(LAN0_LED0),
+ [37] = _DEF_GPIO_EXT_STS_LEDALL(LAN0_LED1),
+ [38] = _DEF_GPIO_EXT_STS_LEDALL(LAN1_LED0),
+ [39] = _DEF_GPIO_EXT_STS_LEDALL(LAN1_LED1),
+ [40] = _DEF_GPIO_EXT_STS_LEDALL(LAN2_LED0),
+ [41] = _DEF_GPIO_EXT_STS_LEDALL(LAN2_LED1),
+ [42] = _DEF_GPIO_EXT_STS_LEDALL(LAN3_LED0),
+ [43] = _DEF_GPIO_EXT_STS_LEDALL(LAN3_LED1),
+ [44] = _DEF_GPIO_EXT_STS_LEDALL(LAN4_LED0),
+ [45] = _DEF_GPIO_EXT_STS_LEDALL(LAN4_LED1),
+ [46] = _DEF_GPIO_EXT_STS_LEDALL(LAN5_LED0),
+ [47] = _DEF_GPIO_EXT_STS_LEDALL(LAN5_LED1),
+
+ /* GPIOs with value read from the 16-bit wide extended control status */
+ [48] = _DEF_GPIO_EXT_CTL(nRES_MMC, PERIPH_MCU),
+ [49] = _DEF_GPIO_EXT_CTL(nRES_LAN, PERIPH_MCU),
+ [50] = _DEF_GPIO_EXT_CTL(nRES_PHY, PERIPH_MCU),
+ [51] = _DEF_GPIO_EXT_CTL(nPERST0, PERIPH_MCU),
+ [52] = _DEF_GPIO_EXT_CTL(nPERST1, PERIPH_MCU),
+ [53] = _DEF_GPIO_EXT_CTL(nPERST2, PERIPH_MCU),
+ [54] = _DEF_GPIO_EXT_CTL(PHY_SFP, PERIPH_MCU),
+ [56] = _DEF_GPIO_EXT_CTL(nVHV_CTRL, PERIPH_MCU),
+};
+
+/* mapping from interrupts to indexes of GPIOs in the omnia_gpios array */
+const u8 omnia_int_to_gpio_idx[32] = {
+ [__bf_shf(OMNIA_INT_CARD_DET)] = 4,
+ [__bf_shf(OMNIA_INT_MSATA_IND)] = 5,
+ [__bf_shf(OMNIA_INT_USB30_OVC)] = 6,
+ [__bf_shf(OMNIA_INT_USB31_OVC)] = 7,
+ [__bf_shf(OMNIA_INT_BUTTON_PRESSED)] = 12,
+ [__bf_shf(OMNIA_INT_TRNG)] = 13,
+ [__bf_shf(OMNIA_INT_MESSAGE_SIGNED)] = 14,
+ [__bf_shf(OMNIA_INT_SFP_nDET)] = 16,
+ [__bf_shf(OMNIA_INT_BRIGHTNESS_CHANGED)] = 11,
+ [__bf_shf(OMNIA_INT_WLAN0_MSATA_LED)] = 28,
+ [__bf_shf(OMNIA_INT_WLAN1_LED)] = 29,
+ [__bf_shf(OMNIA_INT_WLAN2_LED)] = 30,
+ [__bf_shf(OMNIA_INT_WPAN0_LED)] = 31,
+ [__bf_shf(OMNIA_INT_WPAN1_LED)] = 32,
+ [__bf_shf(OMNIA_INT_WPAN2_LED)] = 33,
+ [__bf_shf(OMNIA_INT_WAN_LED0)] = 34,
+ [__bf_shf(OMNIA_INT_WAN_LED1)] = 35,
+ [__bf_shf(OMNIA_INT_LAN0_LED0)] = 36,
+ [__bf_shf(OMNIA_INT_LAN0_LED1)] = 37,
+ [__bf_shf(OMNIA_INT_LAN1_LED0)] = 38,
+ [__bf_shf(OMNIA_INT_LAN1_LED1)] = 39,
+ [__bf_shf(OMNIA_INT_LAN2_LED0)] = 40,
+ [__bf_shf(OMNIA_INT_LAN2_LED1)] = 41,
+ [__bf_shf(OMNIA_INT_LAN3_LED0)] = 42,
+ [__bf_shf(OMNIA_INT_LAN3_LED1)] = 43,
+ [__bf_shf(OMNIA_INT_LAN4_LED0)] = 44,
+ [__bf_shf(OMNIA_INT_LAN4_LED1)] = 45,
+ [__bf_shf(OMNIA_INT_LAN5_LED0)] = 46,
+ [__bf_shf(OMNIA_INT_LAN5_LED1)] = 47,
+};
+
+/* index of PHY_SFP GPIO in the omnia_gpios array */
+#define OMNIA_GPIO_PHY_SFP_OFFSET 54
+
+static int omnia_ctl_cmd_locked(struct omnia_mcu *mcu, u8 cmd, u16 val, u16 mask)
+{
+ unsigned int len;
+ u8 buf[5];
+
+ buf[0] = cmd;
+
+ switch (cmd) {
+ case OMNIA_CMD_GENERAL_CONTROL:
+ buf[1] = val;
+ buf[2] = mask;
+ len = 3;
+ break;
+
+ case OMNIA_CMD_EXT_CONTROL:
+ put_unaligned_le16(val, &buf[1]);
+ put_unaligned_le16(mask, &buf[3]);
+ len = 5;
+ break;
+
+ default:
+ BUG();
+ }
+
+ return omnia_cmd_write(mcu->client, buf, len);
+}
+
+static int omnia_ctl_cmd(struct omnia_mcu *mcu, u8 cmd, u16 val, u16 mask)
+{
+ guard(mutex)(&mcu->lock);
+
+ return omnia_ctl_cmd_locked(mcu, cmd, val, mask);
+}
+
+static int omnia_gpio_request(struct gpio_chip *gc, unsigned int offset)
+{
+ if (!omnia_gpios[offset].cmd)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int omnia_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+
+ if (offset == OMNIA_GPIO_PHY_SFP_OFFSET) {
+ int val;
+
+ scoped_guard(mutex, &mcu->lock) {
+ val = omnia_cmd_read_bit(mcu->client,
+ OMNIA_CMD_GET_EXT_CONTROL_STATUS,
+ OMNIA_EXT_CTL_PHY_SFP_AUTO);
+ if (val < 0)
+ return val;
+ }
+
+ if (val)
+ return GPIO_LINE_DIRECTION_IN;
+
+ return GPIO_LINE_DIRECTION_OUT;
+ }
+
+ if (omnia_gpios[offset].ctl_cmd)
+ return GPIO_LINE_DIRECTION_OUT;
+
+ return GPIO_LINE_DIRECTION_IN;
+}
+
+static int omnia_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
+{
+ const struct omnia_gpio *gpio = &omnia_gpios[offset];
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+
+ if (offset == OMNIA_GPIO_PHY_SFP_OFFSET)
+ return omnia_ctl_cmd(mcu, OMNIA_CMD_EXT_CONTROL,
+ OMNIA_EXT_CTL_PHY_SFP_AUTO,
+ OMNIA_EXT_CTL_PHY_SFP_AUTO);
+
+ if (gpio->ctl_cmd)
+ return -ENOTSUPP;
+
+ return 0;
+}
+
+static int omnia_gpio_direction_output(struct gpio_chip *gc,
+ unsigned int offset, int value)
+{
+ const struct omnia_gpio *gpio = &omnia_gpios[offset];
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+ u16 val, mask;
+
+ if (!gpio->ctl_cmd)
+ return -ENOTSUPP;
+
+ mask = BIT(gpio->ctl_bit);
+ val = value ? mask : 0;
+
+ if (offset == OMNIA_GPIO_PHY_SFP_OFFSET)
+ mask |= OMNIA_EXT_CTL_PHY_SFP_AUTO;
+
+ return omnia_ctl_cmd(mcu, gpio->ctl_cmd, val, mask);
+}
+
+static int omnia_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+ const struct omnia_gpio *gpio = &omnia_gpios[offset];
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+
+ /*
+ * If firmware does not support the new interrupt API, we are informed
+ * of every change of the status word by an interrupt from MCU and save
+ * its value in the interrupt service routine. Simply return the saved
+ * value.
+ */
+ if (gpio->cmd == OMNIA_CMD_GET_STATUS_WORD &&
+ !(mcu->features & OMNIA_FEAT_NEW_INT_API))
+ return test_bit(gpio->bit, &mcu->last_status);
+
+ guard(mutex)(&mcu->lock);
+
+ /*
+ * If firmware does support the new interrupt API, we may have cached
+ * the value of a GPIO in the interrupt service routine. If not, read
+ * the relevant bit now.
+ */
+ if (is_int_bit_valid(gpio) && test_bit(gpio->int_bit, &mcu->is_cached))
+ return test_bit(gpio->int_bit, &mcu->cached);
+
+ return omnia_cmd_read_bit(mcu->client, gpio->cmd, BIT(gpio->bit));
+}
+
+static unsigned long *
+_relevant_field_for_sts_cmd(u8 cmd, unsigned long *sts, unsigned long *ext_sts,
+ unsigned long *ext_ctl)
+{
+ switch (cmd) {
+ case OMNIA_CMD_GET_STATUS_WORD:
+ return sts;
+ case OMNIA_CMD_GET_EXT_STATUS_DWORD:
+ return ext_sts;
+ case OMNIA_CMD_GET_EXT_CONTROL_STATUS:
+ return ext_ctl;
+ default:
+ return NULL;
+ }
+}
+
+static int omnia_gpio_get_multiple(struct gpio_chip *gc, unsigned long *mask,
+ unsigned long *bits)
+{
+ unsigned long sts = 0, ext_sts = 0, ext_ctl = 0, *field;
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+ struct i2c_client *client = mcu->client;
+ unsigned int i;
+ int err;
+
+ /* determine which bits to read from the 3 possible commands */
+ for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) {
+ field = _relevant_field_for_sts_cmd(omnia_gpios[i].cmd,
+ &sts, &ext_sts, &ext_ctl);
+ if (!field)
+ continue;
+
+ __set_bit(omnia_gpios[i].bit, field);
+ }
+
+ guard(mutex)(&mcu->lock);
+
+ if (mcu->features & OMNIA_FEAT_NEW_INT_API) {
+ /* read relevant bits from status */
+ err = omnia_cmd_read_bits(client, OMNIA_CMD_GET_STATUS_WORD,
+ sts, &sts);
+ if (err)
+ return err;
+ } else {
+ /*
+ * Use status word value cached in the interrupt service routine
+ * if firmware does not support the new interrupt API.
+ */
+ sts = mcu->last_status;
+ }
+
+ /* read relevant bits from extended status */
+ err = omnia_cmd_read_bits(client, OMNIA_CMD_GET_EXT_STATUS_DWORD,
+ ext_sts, &ext_sts);
+ if (err)
+ return err;
+
+ /* read relevant bits from extended control */
+ err = omnia_cmd_read_bits(client, OMNIA_CMD_GET_EXT_CONTROL_STATUS,
+ ext_ctl, &ext_ctl);
+ if (err)
+ return err;
+
+ /* assign relevant bits in result */
+ for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) {
+ field = _relevant_field_for_sts_cmd(omnia_gpios[i].cmd,
+ &sts, &ext_sts, &ext_ctl);
+ if (!field)
+ continue;
+
+ __assign_bit(i, bits, test_bit(omnia_gpios[i].bit, field));
+ }
+
+ return 0;
+}
+
+static void omnia_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
+{
+ const struct omnia_gpio *gpio = &omnia_gpios[offset];
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+ u16 val, mask;
+
+ if (!gpio->ctl_cmd)
+ return;
+
+ mask = BIT(gpio->ctl_bit);
+ val = value ? mask : 0;
+
+ omnia_ctl_cmd(mcu, gpio->ctl_cmd, val, mask);
+}
+
+static void omnia_gpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
+ unsigned long *bits)
+{
+ unsigned long ctl = 0, ctl_mask = 0, ext_ctl = 0, ext_ctl_mask = 0;
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+ unsigned int i;
+
+ for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) {
+ unsigned long *field, *field_mask;
+ u8 bit = omnia_gpios[i].ctl_bit;
+
+ switch (omnia_gpios[i].ctl_cmd) {
+ case OMNIA_CMD_GENERAL_CONTROL:
+ field = &ctl;
+ field_mask = &ctl_mask;
+ break;
+ case OMNIA_CMD_EXT_CONTROL:
+ field = &ext_ctl;
+ field_mask = &ext_ctl_mask;
+ break;
+ default:
+ field = field_mask = NULL;
+ break;
+ }
+
+ if (!field)
+ continue;
+
+ __set_bit(bit, field_mask);
+ __assign_bit(bit, field, test_bit(i, bits));
+ }
+
+ guard(mutex)(&mcu->lock);
+
+ if (ctl_mask)
+ omnia_ctl_cmd_locked(mcu, OMNIA_CMD_GENERAL_CONTROL,
+ ctl, ctl_mask);
+
+ if (ext_ctl_mask)
+ omnia_ctl_cmd_locked(mcu, OMNIA_CMD_EXT_CONTROL,
+ ext_ctl, ext_ctl_mask);
+}
+
+static bool omnia_gpio_available(struct omnia_mcu *mcu,
+ const struct omnia_gpio *gpio)
+{
+ if (gpio->feat_mask)
+ return (mcu->features & gpio->feat_mask) == gpio->feat;
+
+ if (gpio->feat)
+ return mcu->features & gpio->feat;
+
+ return true;
+}
+
+static int omnia_gpio_init_valid_mask(struct gpio_chip *gc,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+
+ for (unsigned int i = 0; i < ngpios; i++) {
+ const struct omnia_gpio *gpio = &omnia_gpios[i];
+
+ if (gpio->cmd || is_int_bit_valid(gpio))
+ __assign_bit(i, valid_mask,
+ omnia_gpio_available(mcu, gpio));
+ else
+ __clear_bit(i, valid_mask);
+ }
+
+ return 0;
+}
+
+static int omnia_gpio_of_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec,
+ u32 *flags)
+{
+ u32 bank, gpio;
+
+ if (WARN_ON(gpiospec->args_count != 3))
+ return -EINVAL;
+
+ if (flags)
+ *flags = gpiospec->args[2];
+
+ bank = gpiospec->args[0];
+ gpio = gpiospec->args[1];
+
+ switch (bank) {
+ case 0:
+ return gpio < 16 ? gpio : -EINVAL;
+ case 1:
+ return gpio < 32 ? 16 + gpio : -EINVAL;
+ case 2:
+ return gpio < 16 ? 48 + gpio : -EINVAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static void omnia_irq_shutdown(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u8 bit = omnia_gpios[hwirq].int_bit;
+
+ __clear_bit(bit, &mcu->rising);
+ __clear_bit(bit, &mcu->falling);
+}
+
+static void omnia_irq_mask(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u8 bit = omnia_gpios[hwirq].int_bit;
+
+ if (!omnia_gpios[hwirq].cmd)
+ __clear_bit(bit, &mcu->rising);
+ __clear_bit(bit, &mcu->mask);
+ gpiochip_disable_irq(gc, hwirq);
+}
+
+static void omnia_irq_unmask(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u8 bit = omnia_gpios[hwirq].int_bit;
+
+ gpiochip_enable_irq(gc, hwirq);
+ __set_bit(bit, &mcu->mask);
+ if (!omnia_gpios[hwirq].cmd)
+ __set_bit(bit, &mcu->rising);
+}
+
+static int omnia_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ struct device *dev = &mcu->client->dev;
+ u8 bit = omnia_gpios[hwirq].int_bit;
+
+ if (!(type & IRQ_TYPE_EDGE_BOTH)) {
+ dev_err(dev, "irq %u: unsupported type %u\n", d->irq, type);
+ return -EINVAL;
+ }
+
+ __assign_bit(bit, &mcu->rising, type & IRQ_TYPE_EDGE_RISING);
+ __assign_bit(bit, &mcu->falling, type & IRQ_TYPE_EDGE_FALLING);
+
+ return 0;
+}
+
+static void omnia_irq_bus_lock(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+
+ /* nothing to do if MCU firmware does not support new interrupt API */
+ if (!(mcu->features & OMNIA_FEAT_NEW_INT_API))
+ return;
+
+ mutex_lock(&mcu->lock);
+}
+
+/**
+ * omnia_mask_interleave - Interleaves the bytes from @rising and @falling
+ * @dst: the destination u8 array of interleaved bytes
+ * @rising: rising mask
+ * @falling: falling mask
+ *
+ * Interleaves the little-endian bytes from @rising and @falling words.
+ *
+ * If @rising = (r0, r1, r2, r3) and @falling = (f0, f1, f2, f3), the result is
+ * @dst = (r0, f0, r1, f1, r2, f2, r3, f3).
+ *
+ * The MCU receives an interrupt mask and reports a pending interrupt bitmap in
+ * this interleaved format. The rationale behind this is that the low-indexed
+ * bits are more important - in many cases, the user will be interested only in
+ * interrupts with indexes 0 to 7, and so the system can stop reading after
+ * first 2 bytes (r0, f0), to save time on the slow I2C bus.
+ *
+ * Feel free to remove this function and its inverse, omnia_mask_deinterleave,
+ * and use an appropriate bitmap_*() function once such a function exists.
+ */
+static void
+omnia_mask_interleave(u8 *dst, unsigned long rising, unsigned long falling)
+{
+ for (unsigned int i = 0; i < sizeof(u32); i++) {
+ dst[2 * i] = rising >> (8 * i);
+ dst[2 * i + 1] = falling >> (8 * i);
+ }
+}
+
+/**
+ * omnia_mask_deinterleave - Deinterleaves the bytes into @rising and @falling
+ * @src: the source u8 array containing the interleaved bytes
+ * @rising: pointer where to store the rising mask gathered from @src
+ * @falling: pointer where to store the falling mask gathered from @src
+ *
+ * This is the inverse function to omnia_mask_interleave.
+ */
+static void omnia_mask_deinterleave(const u8 *src, unsigned long *rising,
+ unsigned long *falling)
+{
+ *rising = *falling = 0;
+
+ for (unsigned int i = 0; i < sizeof(u32); i++) {
+ *rising |= src[2 * i] << (8 * i);
+ *falling |= src[2 * i + 1] << (8 * i);
+ }
+}
+
+static void omnia_irq_bus_sync_unlock(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+ struct device *dev = &mcu->client->dev;
+ u8 cmd[1 + OMNIA_CMD_INT_ARG_LEN];
+ unsigned long rising, falling;
+ int err;
+
+ /* nothing to do if MCU firmware does not support new interrupt API */
+ if (!(mcu->features & OMNIA_FEAT_NEW_INT_API))
+ return;
+
+ cmd[0] = OMNIA_CMD_SET_INT_MASK;
+
+ rising = mcu->rising & mcu->mask;
+ falling = mcu->falling & mcu->mask;
+
+ /* interleave the rising and falling bytes into the command arguments */
+ omnia_mask_interleave(&cmd[1], rising, falling);
+
+ dev_dbg(dev, "set int mask %8ph\n", &cmd[1]);
+
+ err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd));
+ if (err) {
+ dev_err(dev, "Cannot set mask: %d\n", err);
+ goto unlock;
+ }
+
+ /*
+ * Remember which GPIOs have both rising and falling interrupts enabled.
+ * For those we will cache their value so that .get() method is faster.
+ * We also need to forget cached values of GPIOs that aren't cached
+ * anymore.
+ */
+ mcu->both = rising & falling;
+ mcu->is_cached &= mcu->both;
+
+unlock:
+ mutex_unlock(&mcu->lock);
+}
+
+static const struct irq_chip omnia_mcu_irq_chip = {
+ .name = "Turris Omnia MCU interrupts",
+ .irq_shutdown = omnia_irq_shutdown,
+ .irq_mask = omnia_irq_mask,
+ .irq_unmask = omnia_irq_unmask,
+ .irq_set_type = omnia_irq_set_type,
+ .irq_bus_lock = omnia_irq_bus_lock,
+ .irq_bus_sync_unlock = omnia_irq_bus_sync_unlock,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static void omnia_irq_init_valid_mask(struct gpio_chip *gc,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+
+ for (unsigned int i = 0; i < ngpios; i++) {
+ const struct omnia_gpio *gpio = &omnia_gpios[i];
+
+ if (is_int_bit_valid(gpio))
+ __assign_bit(i, valid_mask,
+ omnia_gpio_available(mcu, gpio));
+ else
+ __clear_bit(i, valid_mask);
+ }
+}
+
+static int omnia_irq_init_hw(struct gpio_chip *gc)
+{
+ struct omnia_mcu *mcu = gpiochip_get_data(gc);
+ u8 cmd[1 + OMNIA_CMD_INT_ARG_LEN] = {};
+
+ cmd[0] = OMNIA_CMD_SET_INT_MASK;
+
+ return omnia_cmd_write(mcu->client, cmd, sizeof(cmd));
+}
+
+/*
+ * Determine how many bytes we need to read from the reply to the
+ * OMNIA_CMD_GET_INT_AND_CLEAR command in order to retrieve all unmasked
+ * interrupts.
+ */
+static unsigned int
+omnia_irq_compute_pending_length(unsigned long rising, unsigned long falling)
+{
+ return max(omnia_compute_reply_length(rising, true, 0),
+ omnia_compute_reply_length(falling, true, 1));
+}
+
+static bool omnia_irq_read_pending_new(struct omnia_mcu *mcu,
+ unsigned long *pending)
+{
+ struct device *dev = &mcu->client->dev;
+ u8 reply[OMNIA_CMD_INT_ARG_LEN] = {};
+ unsigned long rising, falling;
+ unsigned int len;
+ int err;
+
+ len = omnia_irq_compute_pending_length(mcu->rising & mcu->mask,
+ mcu->falling & mcu->mask);
+ if (!len)
+ return false;
+
+ guard(mutex)(&mcu->lock);
+
+ err = omnia_cmd_read(mcu->client, OMNIA_CMD_GET_INT_AND_CLEAR, reply,
+ len);
+ if (err) {
+ dev_err(dev, "Cannot read pending IRQs: %d\n", err);
+ return false;
+ }
+
+ /* deinterleave the reply bytes into rising and falling */
+ omnia_mask_deinterleave(reply, &rising, &falling);
+
+ rising &= mcu->mask;
+ falling &= mcu->mask;
+ *pending = rising | falling;
+
+ /* cache values for GPIOs that have both edges enabled */
+ mcu->is_cached &= ~(rising & falling);
+ mcu->is_cached |= mcu->both & (rising ^ falling);
+ mcu->cached = (mcu->cached | rising) & ~falling;
+
+ return true;
+}
+
+static int omnia_read_status_word_old_fw(struct omnia_mcu *mcu,
+ unsigned long *status)
+{
+ u16 raw_status;
+ int err;
+
+ err = omnia_cmd_read_u16(mcu->client, OMNIA_CMD_GET_STATUS_WORD,
+ &raw_status);
+ if (err)
+ return err;
+
+ /*
+ * Old firmware has a bug wherein it never resets the USB port
+ * overcurrent bits back to zero. Ignore them.
+ */
+ *status = raw_status & ~(OMNIA_STS_USB30_OVC | OMNIA_STS_USB31_OVC);
+
+ return 0;
+}
+
+static void button_release_emul_fn(struct work_struct *work)
+{
+ struct omnia_mcu *mcu = container_of(to_delayed_work(work),
+ struct omnia_mcu,
+ button_release_emul_work);
+
+ mcu->button_pressed_emul = false;
+ generic_handle_irq_safe(mcu->client->irq);
+}
+
+static void
+fill_int_from_sts(unsigned long *rising, unsigned long *falling,
+ unsigned long rising_sts, unsigned long falling_sts,
+ unsigned long sts_bit, unsigned long int_bit)
+{
+ if (rising_sts & sts_bit)
+ *rising |= int_bit;
+ if (falling_sts & sts_bit)
+ *falling |= int_bit;
+}
+
+static bool omnia_irq_read_pending_old(struct omnia_mcu *mcu,
+ unsigned long *pending)
+{
+ unsigned long status, rising_sts, falling_sts, rising, falling;
+ struct device *dev = &mcu->client->dev;
+ int err;
+
+ guard(mutex)(&mcu->lock);
+
+ err = omnia_read_status_word_old_fw(mcu, &status);
+ if (err) {
+ dev_err(dev, "Cannot read pending IRQs: %d\n", err);
+ return false;
+ }
+
+ /*
+ * The old firmware triggers an interrupt whenever status word changes,
+ * but does not inform about which bits rose or fell. We need to compute
+ * this here by comparing with the last status word value.
+ *
+ * The OMNIA_STS_BUTTON_PRESSED bit needs special handling, because the
+ * old firmware clears the OMNIA_STS_BUTTON_PRESSED bit on successful
+ * completion of the OMNIA_CMD_GET_STATUS_WORD command, resulting in
+ * another interrupt:
+ * - first we get an interrupt, we read the status word where
+ * OMNIA_STS_BUTTON_PRESSED is present,
+ * - MCU clears the OMNIA_STS_BUTTON_PRESSED bit because we read the
+ * status word,
+ * - we get another interrupt because the status word changed again
+ * (the OMNIA_STS_BUTTON_PRESSED bit was cleared).
+ *
+ * The gpiolib-cdev, gpiolib-sysfs and gpio-keys input driver all call
+ * the gpiochip's .get() method after an edge event on a requested GPIO
+ * occurs.
+ *
+ * We ensure that the .get() method reads 1 for the button GPIO for some
+ * time.
+ */
+
+ if (status & OMNIA_STS_BUTTON_PRESSED) {
+ mcu->button_pressed_emul = true;
+ mod_delayed_work(system_wq, &mcu->button_release_emul_work,
+ msecs_to_jiffies(FRONT_BUTTON_RELEASE_DELAY_MS));
+ } else if (mcu->button_pressed_emul) {
+ status |= OMNIA_STS_BUTTON_PRESSED;
+ }
+
+ rising_sts = ~mcu->last_status & status;
+ falling_sts = mcu->last_status & ~status;
+
+ mcu->last_status = status;
+
+ /*
+ * Fill in the relevant interrupt bits from status bits for CARD_DET,
+ * MSATA_IND and BUTTON_PRESSED.
+ */
+ rising = 0;
+ falling = 0;
+ fill_int_from_sts(&rising, &falling, rising_sts, falling_sts,
+ OMNIA_STS_CARD_DET, OMNIA_INT_CARD_DET);
+ fill_int_from_sts(&rising, &falling, rising_sts, falling_sts,
+ OMNIA_STS_MSATA_IND, OMNIA_INT_MSATA_IND);
+ fill_int_from_sts(&rising, &falling, rising_sts, falling_sts,
+ OMNIA_STS_BUTTON_PRESSED, OMNIA_INT_BUTTON_PRESSED);
+
+ /* Use only bits that are enabled */
+ rising &= mcu->rising & mcu->mask;
+ falling &= mcu->falling & mcu->mask;
+ *pending = rising | falling;
+
+ return true;
+}
+
+static bool omnia_irq_read_pending(struct omnia_mcu *mcu,
+ unsigned long *pending)
+{
+ if (mcu->features & OMNIA_FEAT_NEW_INT_API)
+ return omnia_irq_read_pending_new(mcu, pending);
+ else
+ return omnia_irq_read_pending_old(mcu, pending);
+}
+
+static irqreturn_t omnia_irq_thread_handler(int irq, void *dev_id)
+{
+ struct omnia_mcu *mcu = dev_id;
+ struct irq_domain *domain;
+ unsigned long pending;
+ unsigned int i;
+
+ if (!omnia_irq_read_pending(mcu, &pending))
+ return IRQ_NONE;
+
+ domain = mcu->gc.irq.domain;
+
+ for_each_set_bit(i, &pending, 32) {
+ unsigned int nested_irq;
+
+ nested_irq = irq_find_mapping(domain, omnia_int_to_gpio_idx[i]);
+
+ handle_nested_irq(nested_irq);
+ }
+
+ return IRQ_RETVAL(pending);
+}
+
+static const char * const front_button_modes[] = { "mcu", "cpu" };
+
+static ssize_t front_button_mode_show(struct device *dev,
+ struct device_attribute *a, char *buf)
+{
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+ int val;
+
+ if (mcu->features & OMNIA_FEAT_NEW_INT_API) {
+ val = omnia_cmd_read_bit(mcu->client, OMNIA_CMD_GET_STATUS_WORD,
+ OMNIA_STS_BUTTON_MODE);
+ if (val < 0)
+ return val;
+ } else {
+ val = !!(mcu->last_status & OMNIA_STS_BUTTON_MODE);
+ }
+
+ return sysfs_emit(buf, "%s\n", front_button_modes[val]);
+}
+
+static ssize_t front_button_mode_store(struct device *dev,
+ struct device_attribute *a,
+ const char *buf, size_t count)
+{
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+ int err, i;
+
+ i = sysfs_match_string(front_button_modes, buf);
+ if (i < 0)
+ return i;
+
+ err = omnia_ctl_cmd_locked(mcu, OMNIA_CMD_GENERAL_CONTROL,
+ i ? OMNIA_CTL_BUTTON_MODE : 0,
+ OMNIA_CTL_BUTTON_MODE);
+ if (err)
+ return err;
+
+ return count;
+}
+static DEVICE_ATTR_RW(front_button_mode);
+
+static struct attribute *omnia_mcu_gpio_attrs[] = {
+ &dev_attr_front_button_mode.attr,
+ NULL
+};
+
+const struct attribute_group omnia_mcu_gpio_group = {
+ .attrs = omnia_mcu_gpio_attrs,
+};
+
+int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu)
+{
+ bool new_api = mcu->features & OMNIA_FEAT_NEW_INT_API;
+ struct device *dev = &mcu->client->dev;
+ unsigned long irqflags;
+ int err;
+
+ err = devm_mutex_init(dev, &mcu->lock);
+ if (err)
+ return err;
+
+ mcu->gc.request = omnia_gpio_request;
+ mcu->gc.get_direction = omnia_gpio_get_direction;
+ mcu->gc.direction_input = omnia_gpio_direction_input;
+ mcu->gc.direction_output = omnia_gpio_direction_output;
+ mcu->gc.get = omnia_gpio_get;
+ mcu->gc.get_multiple = omnia_gpio_get_multiple;
+ mcu->gc.set = omnia_gpio_set;
+ 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.base = -1;
+ mcu->gc.ngpio = ARRAY_SIZE(omnia_gpios);
+ mcu->gc.label = "Turris Omnia MCU GPIOs";
+ mcu->gc.parent = dev;
+ mcu->gc.owner = THIS_MODULE;
+ mcu->gc.of_gpio_n_cells = 3;
+ mcu->gc.of_xlate = omnia_gpio_of_xlate;
+
+ gpio_irq_chip_set_chip(&mcu->gc.irq, &omnia_mcu_irq_chip);
+ /* This will let us handle the parent IRQ in the driver */
+ mcu->gc.irq.parent_handler = NULL;
+ mcu->gc.irq.num_parents = 0;
+ mcu->gc.irq.parents = NULL;
+ mcu->gc.irq.default_type = IRQ_TYPE_NONE;
+ mcu->gc.irq.handler = handle_bad_irq;
+ mcu->gc.irq.threaded = true;
+ if (new_api)
+ mcu->gc.irq.init_hw = omnia_irq_init_hw;
+ mcu->gc.irq.init_valid_mask = omnia_irq_init_valid_mask;
+
+ err = devm_gpiochip_add_data(dev, &mcu->gc, mcu);
+ if (err)
+ return dev_err_probe(dev, err, "Cannot add GPIO chip\n");
+
+ /*
+ * Before requesting the interrupt, if firmware does not support the new
+ * interrupt API, we need to cache the value of the status word, so that
+ * when it changes, we may compare the new value with the cached one in
+ * the interrupt handler.
+ */
+ if (!new_api) {
+ err = omnia_read_status_word_old_fw(mcu, &mcu->last_status);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Cannot read status word\n");
+
+ INIT_DELAYED_WORK(&mcu->button_release_emul_work,
+ button_release_emul_fn);
+ }
+
+ irqflags = IRQF_ONESHOT;
+ if (new_api)
+ irqflags |= IRQF_TRIGGER_LOW;
+ else
+ irqflags |= IRQF_TRIGGER_FALLING;
+
+ err = devm_request_threaded_irq(dev, mcu->client->irq, NULL,
+ omnia_irq_thread_handler, irqflags,
+ "turris-omnia-mcu", mcu);
+ if (err)
+ return dev_err_probe(dev, err, "Cannot request IRQ\n");
+
+ if (!new_api) {
+ /*
+ * The button_release_emul_work has to be initialized before the
+ * thread is requested, and on driver remove it needs to be
+ * canceled before the thread is freed. Therefore we can't use
+ * devm_delayed_work_autocancel() directly, because the order
+ * devm_delayed_work_autocancel();
+ * devm_request_threaded_irq();
+ * would cause improper release order:
+ * free_irq();
+ * cancel_delayed_work_sync();
+ * Instead we first initialize the work above, and only now
+ * after IRQ is requested we add the work devm action.
+ */
+ err = devm_add_action(dev, devm_delayed_work_drop,
+ &mcu->button_release_emul_work);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
diff --git a/drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c b/drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c
new file mode 100644
index 000000000000..0e8ab15b6037
--- /dev/null
+++ b/drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CZ.NIC's Turris Omnia MCU system off and RTC wakeup driver
+ *
+ * This is not a true RTC driver (in the sense that it does not provide a
+ * real-time clock), rather the MCU implements a wakeup from powered off state
+ * at a specified time relative to MCU boot, and we expose this feature via RTC
+ * alarm, so that it can be used via the rtcwake command, which is the standard
+ * Linux command for this.
+ *
+ * 2024 by Marek Behún <[email protected]>
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/kstrtox.h>
+#include <linux/reboot.h>
+#include <linux/rtc.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#include <linux/turris-omnia-mcu-interface.h>
+#include "turris-omnia-mcu.h"
+
+static int omnia_get_uptime_wakeup(const struct i2c_client *client, u32 *uptime,
+ u32 *wakeup)
+{
+ __le32 reply[2];
+ int err;
+
+ err = omnia_cmd_read(client, OMNIA_CMD_GET_UPTIME_AND_WAKEUP, reply,
+ sizeof(reply));
+ if (err)
+ return err;
+
+ if (uptime)
+ *uptime = le32_to_cpu(reply[0]);
+
+ if (wakeup)
+ *wakeup = le32_to_cpu(reply[1]);
+
+ return 0;
+}
+
+static int omnia_read_time(struct device *dev, struct rtc_time *tm)
+{
+ u32 uptime;
+ int err;
+
+ err = omnia_get_uptime_wakeup(to_i2c_client(dev), &uptime, NULL);
+ if (err)
+ return err;
+
+ rtc_time64_to_tm(uptime, tm);
+
+ return 0;
+}
+
+static int omnia_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct omnia_mcu *mcu = i2c_get_clientdata(client);
+ u32 wakeup;
+ int err;
+
+ err = omnia_get_uptime_wakeup(client, NULL, &wakeup);
+ if (err)
+ return err;
+
+ alrm->enabled = !!wakeup;
+ rtc_time64_to_tm(wakeup ?: mcu->rtc_alarm, &alrm->time);
+
+ return 0;
+}
+
+static int omnia_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct omnia_mcu *mcu = i2c_get_clientdata(client);
+
+ mcu->rtc_alarm = rtc_tm_to_time64(&alrm->time);
+
+ if (alrm->enabled)
+ return omnia_cmd_write_u32(client, OMNIA_CMD_SET_WAKEUP,
+ mcu->rtc_alarm);
+
+ return 0;
+}
+
+static int omnia_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct omnia_mcu *mcu = i2c_get_clientdata(client);
+
+ return omnia_cmd_write_u32(client, OMNIA_CMD_SET_WAKEUP,
+ enabled ? mcu->rtc_alarm : 0);
+}
+
+static const struct rtc_class_ops omnia_rtc_ops = {
+ .read_time = omnia_read_time,
+ .read_alarm = omnia_read_alarm,
+ .set_alarm = omnia_set_alarm,
+ .alarm_irq_enable = omnia_alarm_irq_enable,
+};
+
+static int omnia_power_off(struct sys_off_data *data)
+{
+ struct omnia_mcu *mcu = data->cb_data;
+ __be32 tmp;
+ u8 cmd[9];
+ u16 arg;
+ int err;
+
+ if (mcu->front_button_poweron)
+ arg = OMNIA_CMD_POWER_OFF_POWERON_BUTTON;
+ else
+ arg = 0;
+
+ cmd[0] = OMNIA_CMD_POWER_OFF;
+ put_unaligned_le16(OMNIA_CMD_POWER_OFF_MAGIC, &cmd[1]);
+ put_unaligned_le16(arg, &cmd[3]);
+
+ /*
+ * Although all values from and to MCU are passed in little-endian, the
+ * MCU's CRC unit uses big-endian CRC32 polynomial (0x04c11db7), so we
+ * need to use crc32_be() here.
+ */
+ tmp = cpu_to_be32(get_unaligned_le32(&cmd[1]));
+ put_unaligned_le32(crc32_be(~0, (void *)&tmp, sizeof(tmp)), &cmd[5]);
+
+ err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd));
+ if (err)
+ dev_err(&mcu->client->dev,
+ "Unable to send the poweroff command: %d\n", err);
+
+ return NOTIFY_DONE;
+}
+
+static int omnia_restart(struct sys_off_data *data)
+{
+ struct omnia_mcu *mcu = data->cb_data;
+ u8 cmd[3];
+ int err;
+
+ cmd[0] = OMNIA_CMD_GENERAL_CONTROL;
+
+ if (reboot_mode == REBOOT_HARD)
+ cmd[1] = cmd[2] = OMNIA_CTL_HARD_RST;
+ else
+ cmd[1] = cmd[2] = OMNIA_CTL_LIGHT_RST;
+
+ err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd));
+ if (err)
+ dev_err(&mcu->client->dev,
+ "Unable to send the restart command: %d\n", err);
+
+ /*
+ * MCU needs a little bit to process the I2C command, otherwise it will
+ * do a light reset based on SOC SYSRES_OUT pin.
+ */
+ mdelay(1);
+
+ return NOTIFY_DONE;
+}
+
+static ssize_t front_button_poweron_show(struct device *dev,
+ struct device_attribute *a, char *buf)
+{
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%d\n", mcu->front_button_poweron);
+}
+
+static ssize_t front_button_poweron_store(struct device *dev,
+ struct device_attribute *a,
+ const char *buf, size_t count)
+{
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+ bool val;
+ int err;
+
+ err = kstrtobool(buf, &val);
+ if (err)
+ return err;
+
+ mcu->front_button_poweron = val;
+
+ return count;
+}
+static DEVICE_ATTR_RW(front_button_poweron);
+
+static struct attribute *omnia_mcu_poweroff_attrs[] = {
+ &dev_attr_front_button_poweron.attr,
+ NULL
+};
+
+static umode_t poweroff_attrs_visible(struct kobject *kobj, struct attribute *a,
+ int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct omnia_mcu *mcu = dev_get_drvdata(dev);
+
+ if (mcu->features & OMNIA_FEAT_POWEROFF_WAKEUP)
+ return a->mode;
+
+ return 0;
+}
+
+const struct attribute_group omnia_mcu_poweroff_group = {
+ .attrs = omnia_mcu_poweroff_attrs,
+ .is_visible = poweroff_attrs_visible,
+};
+
+int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu)
+{
+ struct device *dev = &mcu->client->dev;
+ int err;
+
+ /* MCU restart is always available */
+ err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART,
+ SYS_OFF_PRIO_FIRMWARE,
+ omnia_restart, mcu);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Cannot register system restart handler\n");
+
+ /*
+ * Poweroff and wakeup are available only if POWEROFF_WAKEUP feature is
+ * present.
+ */
+ if (!(mcu->features & OMNIA_FEAT_POWEROFF_WAKEUP))
+ return 0;
+
+ err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_FIRMWARE,
+ omnia_power_off, mcu);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Cannot register system power off handler\n");
+
+ mcu->rtcdev = devm_rtc_allocate_device(dev);
+ if (IS_ERR(mcu->rtcdev))
+ return dev_err_probe(dev, PTR_ERR(mcu->rtcdev),
+ "Cannot allocate RTC device\n");
+
+ mcu->rtcdev->ops = &omnia_rtc_ops;
+ mcu->rtcdev->range_max = U32_MAX;
+ set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, mcu->rtcdev->features);
+
+ err = devm_rtc_register_device(mcu->rtcdev);
+ if (err)
+ return dev_err_probe(dev, err, "Cannot register RTC device\n");
+
+ mcu->front_button_poweron = true;
+
+ return 0;
+}
diff --git a/drivers/platform/cznic/turris-omnia-mcu-trng.c b/drivers/platform/cznic/turris-omnia-mcu-trng.c
new file mode 100644
index 000000000000..ad953fb3c37a
--- /dev/null
+++ b/drivers/platform/cznic/turris-omnia-mcu-trng.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CZ.NIC's Turris Omnia MCU TRNG driver
+ *
+ * 2024 by Marek Behún <[email protected]>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/completion.h>
+#include <linux/container_of.h>
+#include <linux/errno.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/hw_random.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/minmax.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <linux/turris-omnia-mcu-interface.h>
+#include "turris-omnia-mcu.h"
+
+#define OMNIA_CMD_TRNG_MAX_ENTROPY_LEN 64
+
+static irqreturn_t omnia_trng_irq_handler(int irq, void *dev_id)
+{
+ struct omnia_mcu *mcu = dev_id;
+
+ complete(&mcu->trng_entropy_ready);
+
+ return IRQ_HANDLED;
+}
+
+static int omnia_trng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+ struct omnia_mcu *mcu = container_of(rng, struct omnia_mcu, trng);
+ u8 reply[1 + OMNIA_CMD_TRNG_MAX_ENTROPY_LEN];
+ int err, bytes;
+
+ if (!wait && !completion_done(&mcu->trng_entropy_ready))
+ return 0;
+
+ do {
+ if (wait_for_completion_interruptible(&mcu->trng_entropy_ready))
+ return -ERESTARTSYS;
+
+ err = omnia_cmd_read(mcu->client,
+ OMNIA_CMD_TRNG_COLLECT_ENTROPY,
+ reply, sizeof(reply));
+ if (err)
+ return err;
+
+ bytes = min3(reply[0], max, OMNIA_CMD_TRNG_MAX_ENTROPY_LEN);
+ } while (wait && !bytes);
+
+ memcpy(data, &reply[1], bytes);
+
+ return bytes;
+}
+
+int omnia_mcu_register_trng(struct omnia_mcu *mcu)
+{
+ struct device *dev = &mcu->client->dev;
+ u8 irq_idx, dummy;
+ int irq, err;
+
+ if (!(mcu->features & OMNIA_FEAT_TRNG))
+ return 0;
+
+ irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+ irq = gpiod_to_irq(gpio_device_get_desc(mcu->gc.gpiodev, irq_idx));
+ if (!irq)
+ return dev_err_probe(dev, -ENXIO, "Cannot get TRNG IRQ\n");
+
+ /*
+ * If someone else cleared the TRNG interrupt but did not read the
+ * entropy, a new interrupt won't be generated, and entropy collection
+ * will be stuck. Ensure an interrupt will be generated by executing
+ * the collect entropy command (and discarding the result).
+ */
+ err = omnia_cmd_read(mcu->client, OMNIA_CMD_TRNG_COLLECT_ENTROPY,
+ &dummy, 1);
+ if (err)
+ return err;
+
+ init_completion(&mcu->trng_entropy_ready);
+
+ err = devm_request_threaded_irq(dev, irq, NULL, omnia_trng_irq_handler,
+ IRQF_ONESHOT, "turris-omnia-mcu-trng",
+ mcu);
+ if (err)
+ return dev_err_probe(dev, err, "Cannot request TRNG IRQ\n");
+
+ mcu->trng.name = "turris-omnia-mcu-trng";
+ mcu->trng.read = omnia_trng_read;
+
+ err = devm_hwrng_register(dev, &mcu->trng);
+ if (err)
+ return dev_err_probe(dev, err, "Cannot register TRNG\n");
+
+ return 0;
+}
diff --git a/drivers/platform/cznic/turris-omnia-mcu-watchdog.c b/drivers/platform/cznic/turris-omnia-mcu-watchdog.c
new file mode 100644
index 000000000000..3ad146ec1d80
--- /dev/null
+++ b/drivers/platform/cznic/turris-omnia-mcu-watchdog.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CZ.NIC's Turris Omnia MCU watchdog driver
+ *
+ * 2024 by Marek Behún <[email protected]>
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/units.h>
+#include <linux/watchdog.h>
+
+#include <linux/turris-omnia-mcu-interface.h>
+#include "turris-omnia-mcu.h"
+
+#define WATCHDOG_TIMEOUT 120
+
+static unsigned int timeout;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int omnia_wdt_start(struct watchdog_device *wdt)
+{
+ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
+
+ return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 1);
+}
+
+static int omnia_wdt_stop(struct watchdog_device *wdt)
+{
+ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
+
+ return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 0);
+}
+
+static int omnia_wdt_ping(struct watchdog_device *wdt)
+{
+ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
+
+ return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 1);
+}
+
+static int omnia_wdt_set_timeout(struct watchdog_device *wdt,
+ unsigned int timeout)
+{
+ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
+
+ return omnia_cmd_write_u16(mcu->client, OMNIA_CMD_SET_WDT_TIMEOUT,
+ timeout * DECI);
+}
+
+static unsigned int omnia_wdt_get_timeleft(struct watchdog_device *wdt)
+{
+ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
+ u16 timeleft;
+ int err;
+
+ err = omnia_cmd_read_u16(mcu->client, OMNIA_CMD_GET_WDT_TIMELEFT,
+ &timeleft);
+ if (err) {
+ dev_err(&mcu->client->dev, "Cannot get watchdog timeleft: %d\n",
+ err);
+ return 0;
+ }
+
+ return timeleft / DECI;
+}
+
+static const struct watchdog_info omnia_wdt_info = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+ .identity = "Turris Omnia MCU Watchdog",
+};
+
+static const struct watchdog_ops omnia_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = omnia_wdt_start,
+ .stop = omnia_wdt_stop,
+ .ping = omnia_wdt_ping,
+ .set_timeout = omnia_wdt_set_timeout,
+ .get_timeleft = omnia_wdt_get_timeleft,
+};
+
+int omnia_mcu_register_watchdog(struct omnia_mcu *mcu)
+{
+ struct device *dev = &mcu->client->dev;
+ u8 state;
+ int err;
+
+ if (!(mcu->features & OMNIA_FEAT_WDT_PING))
+ return 0;
+
+ mcu->wdt.info = &omnia_wdt_info;
+ mcu->wdt.ops = &omnia_wdt_ops;
+ mcu->wdt.parent = dev;
+ mcu->wdt.min_timeout = 1;
+ mcu->wdt.max_timeout = 65535 / DECI;
+
+ mcu->wdt.timeout = WATCHDOG_TIMEOUT;
+ watchdog_init_timeout(&mcu->wdt, timeout, dev);
+
+ watchdog_set_drvdata(&mcu->wdt, mcu);
+
+ omnia_wdt_set_timeout(&mcu->wdt, mcu->wdt.timeout);
+
+ err = omnia_cmd_read_u8(mcu->client, OMNIA_CMD_GET_WATCHDOG_STATE,
+ &state);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Cannot get MCU watchdog state\n");
+
+ if (state)
+ set_bit(WDOG_HW_RUNNING, &mcu->wdt.status);
+
+ watchdog_set_nowayout(&mcu->wdt, nowayout);
+ watchdog_stop_on_reboot(&mcu->wdt);
+ err = devm_watchdog_register_device(dev, &mcu->wdt);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Cannot register MCU watchdog\n");
+
+ return 0;
+}
diff --git a/drivers/platform/cznic/turris-omnia-mcu.h b/drivers/platform/cznic/turris-omnia-mcu.h
new file mode 100644
index 000000000000..2ca56ae13aa9
--- /dev/null
+++ b/drivers/platform/cznic/turris-omnia-mcu.h
@@ -0,0 +1,194 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * CZ.NIC's Turris Omnia MCU driver
+ *
+ * 2024 by Marek Behún <[email protected]>
+ */
+
+#ifndef __TURRIS_OMNIA_MCU_H
+#define __TURRIS_OMNIA_MCU_H
+
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/gpio/driver.h>
+#include <linux/hw_random.h>
+#include <linux/if_ether.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <linux/workqueue.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+
+struct i2c_client;
+struct rtc_device;
+
+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;
+
+ /* 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;
+
+ /* RTC device for configuring wake-up */
+ struct rtc_device *rtcdev;
+ u32 rtc_alarm;
+ bool front_button_poweron;
+
+ /* MCU watchdog */
+ struct watchdog_device wdt;
+
+ /* true random number generator */
+ struct hwrng trng;
+ struct completion trng_entropy_ready;
+};
+
+int omnia_cmd_write_read(const struct i2c_client *client,
+ void *cmd, unsigned int cmd_len,
+ void *reply, unsigned int reply_len);
+
+static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
+ unsigned int len)
+{
+ return omnia_cmd_write_read(client, cmd, len, NULL, 0);
+}
+
+static inline int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd,
+ u8 val)
+{
+ u8 buf[2] = { cmd, val };
+
+ return omnia_cmd_write(client, buf, sizeof(buf));
+}
+
+static inline int omnia_cmd_write_u16(const struct i2c_client *client, u8 cmd,
+ u16 val)
+{
+ u8 buf[3];
+
+ buf[0] = cmd;
+ put_unaligned_le16(val, &buf[1]);
+
+ return omnia_cmd_write(client, buf, sizeof(buf));
+}
+
+static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd,
+ u32 val)
+{
+ u8 buf[5];
+
+ buf[0] = cmd;
+ put_unaligned_le32(val, &buf[1]);
+
+ return omnia_cmd_write(client, buf, sizeof(buf));
+}
+
+static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,
+ void *reply, unsigned int len)
+{
+ return omnia_cmd_write_read(client, &cmd, 1, reply, len);
+}
+
+static inline unsigned int
+omnia_compute_reply_length(unsigned long mask, bool interleaved,
+ unsigned int offset)
+{
+ if (!mask)
+ return 0;
+
+ return ((__fls(mask) >> 3) << interleaved) + 1 + offset;
+}
+
+/* Returns 0 on success */
+static inline int omnia_cmd_read_bits(const struct i2c_client *client, u8 cmd,
+ unsigned long bits, unsigned long *dst)
+{
+ __le32 reply;
+ int err;
+
+ if (!bits) {
+ *dst = 0;
+ return 0;
+ }
+
+ err = omnia_cmd_read(client, cmd, &reply,
+ omnia_compute_reply_length(bits, false, 0));
+ if (err)
+ return err;
+
+ *dst = le32_to_cpu(reply) & bits;
+
+ return 0;
+}
+
+static inline int omnia_cmd_read_bit(const struct i2c_client *client, u8 cmd,
+ unsigned long bit)
+{
+ unsigned long reply;
+ int err;
+
+ err = omnia_cmd_read_bits(client, cmd, bit, &reply);
+ if (err)
+ return err;
+
+ return !!reply;
+}
+
+static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd,
+ u32 *dst)
+{
+ __le32 reply;
+ int err;
+
+ err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
+ if (err)
+ return err;
+
+ *dst = le32_to_cpu(reply);
+
+ return 0;
+}
+
+static inline int omnia_cmd_read_u16(const struct i2c_client *client, u8 cmd,
+ u16 *dst)
+{
+ __le16 reply;
+ int err;
+
+ err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
+ if (err)
+ return err;
+
+ *dst = le16_to_cpu(reply);
+
+ return 0;
+}
+
+static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd,
+ u8 *reply)
+{
+ return omnia_cmd_read(client, cmd, reply, sizeof(*reply));
+}
+
+extern const u8 omnia_int_to_gpio_idx[32];
+extern const struct attribute_group omnia_mcu_gpio_group;
+extern const struct attribute_group omnia_mcu_poweroff_group;
+
+int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu);
+int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu);
+int omnia_mcu_register_trng(struct omnia_mcu *mcu);
+int omnia_mcu_register_watchdog(struct omnia_mcu *mcu);
+
+#endif /* __TURRIS_OMNIA_MCU_H */
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 3a8d8df89186..78a5aac2dcfd 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -3271,7 +3271,7 @@ static const char *find_hci_method(acpi_handle handle)
*/
#define QUIRK_HCI_HOTKEY_QUICKSTART BIT(1)
-static const struct dmi_system_id toshiba_dmi_quirks[] = {
+static const struct dmi_system_id toshiba_dmi_quirks[] __initconst = {
{
/* Toshiba Portégé R700 */
/* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
@@ -3299,6 +3299,7 @@ static const struct dmi_system_id toshiba_dmi_quirks[] = {
},
.driver_data = (void *)(QUIRK_TURN_ON_PANEL_ON_RESUME | QUIRK_HCI_HOTKEY_QUICKSTART),
},
+ { }
};
static int toshiba_acpi_add(struct acpi_device *acpi_dev)
@@ -3306,8 +3307,6 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
struct toshiba_acpi_dev *dev;
const char *hci_method;
u32 dummy;
- const struct dmi_system_id *dmi_id;
- long quirks = 0;
int ret = 0;
if (toshiba_acpi)
@@ -3460,16 +3459,6 @@ iio_error:
}
#endif
- dmi_id = dmi_first_match(toshiba_dmi_quirks);
- if (dmi_id)
- quirks = (long)dmi_id->driver_data;
-
- if (turn_on_panel_on_resume == -1)
- turn_on_panel_on_resume = !!(quirks & QUIRK_TURN_ON_PANEL_ON_RESUME);
-
- if (hci_hotkey_quickstart == -1)
- hci_hotkey_quickstart = !!(quirks & QUIRK_HCI_HOTKEY_QUICKSTART);
-
toshiba_wwan_available(dev);
if (dev->wwan_supported)
toshiba_acpi_setup_wwan_rfkill(dev);
@@ -3618,10 +3607,27 @@ static struct acpi_driver toshiba_acpi_driver = {
.drv.pm = &toshiba_acpi_pm,
};
+static void __init toshiba_dmi_init(void)
+{
+ const struct dmi_system_id *dmi_id;
+ long quirks = 0;
+
+ dmi_id = dmi_first_match(toshiba_dmi_quirks);
+ if (dmi_id)
+ quirks = (long)dmi_id->driver_data;
+
+ if (turn_on_panel_on_resume == -1)
+ turn_on_panel_on_resume = !!(quirks & QUIRK_TURN_ON_PANEL_ON_RESUME);
+
+ if (hci_hotkey_quickstart == -1)
+ hci_hotkey_quickstart = !!(quirks & QUIRK_HCI_HOTKEY_QUICKSTART);
+}
+
static int __init toshiba_acpi_init(void)
{
int ret;
+ toshiba_dmi_init();
toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
if (!toshiba_proc_dir) {
pr_err("Unable to create proc dir " PROC_TOSHIBA "\n");
diff --git a/drivers/pmdomain/amlogic/meson-ee-pwrc.c b/drivers/pmdomain/amlogic/meson-ee-pwrc.c
index fcec6eb610e4..fbb2b4103930 100644
--- a/drivers/pmdomain/amlogic/meson-ee-pwrc.c
+++ b/drivers/pmdomain/amlogic/meson-ee-pwrc.c
@@ -648,4 +648,5 @@ static struct platform_driver meson_ee_pwrc_driver = {
},
};
module_platform_driver(meson_ee_pwrc_driver);
+MODULE_DESCRIPTION("Amlogic Meson Everything-Else Power Domains driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/pmdomain/amlogic/meson-gx-pwrc-vpu.c b/drivers/pmdomain/amlogic/meson-gx-pwrc-vpu.c
index 33df520eab95..6028e91664a4 100644
--- a/drivers/pmdomain/amlogic/meson-gx-pwrc-vpu.c
+++ b/drivers/pmdomain/amlogic/meson-gx-pwrc-vpu.c
@@ -376,4 +376,5 @@ static struct platform_driver meson_gx_pwrc_vpu_driver = {
},
};
module_platform_driver(meson_gx_pwrc_vpu_driver);
+MODULE_DESCRIPTION("Amlogic Meson GX Power Domains driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/pmdomain/amlogic/meson-secure-pwrc.c b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
index 4d5bda0d60fc..42ce41a2fe3a 100644
--- a/drivers/pmdomain/amlogic/meson-secure-pwrc.c
+++ b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
@@ -14,6 +14,8 @@
#include <dt-bindings/power/amlogic,c3-pwrc.h>
#include <dt-bindings/power/meson-s4-power.h>
#include <dt-bindings/power/amlogic,t7-pwrc.h>
+#include <dt-bindings/power/amlogic,a4-pwrc.h>
+#include <dt-bindings/power/amlogic,a5-pwrc.h>
#include <linux/arm-smccc.h>
#include <linux/firmware/meson/meson_sm.h>
#include <linux/module.h>
@@ -45,7 +47,7 @@ struct meson_secure_pwrc_domain_desc {
struct meson_secure_pwrc_domain_data {
unsigned int count;
- struct meson_secure_pwrc_domain_desc *domains;
+ const struct meson_secure_pwrc_domain_desc *domains;
};
static bool pwrc_secure_is_off(struct meson_secure_pwrc_domain *pwrc_domain)
@@ -109,7 +111,7 @@ static int meson_secure_pwrc_on(struct generic_pm_domain *domain)
.parent = __parent, \
}
-static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = {
+static const struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = {
SEC_PD(DSPA, 0),
SEC_PD(DSPB, 0),
/* UART should keep working in ATF after suspend and before resume */
@@ -136,7 +138,41 @@ static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = {
SEC_PD(RSA, 0),
};
-static struct meson_secure_pwrc_domain_desc c3_pwrc_domains[] = {
+static const struct meson_secure_pwrc_domain_desc a4_pwrc_domains[] = {
+ SEC_PD(A4_AUDIO, 0),
+ SEC_PD(A4_SDIOA, 0),
+ SEC_PD(A4_EMMC, 0),
+ SEC_PD(A4_USB_COMB, 0),
+ SEC_PD(A4_ETH, 0),
+ SEC_PD(A4_VOUT, 0),
+ SEC_PD(A4_AUDIO_PDM, 0),
+ /* DMC is for DDR PHY ana/dig and DMC, and should be always on */
+ SEC_PD(A4_DMC, GENPD_FLAG_ALWAYS_ON),
+ /* WRAP is secure_top, a lot of modules are included, and should be always on */
+ SEC_PD(A4_SYS_WRAP, GENPD_FLAG_ALWAYS_ON),
+ SEC_PD(A4_AO_I2C_S, 0),
+ SEC_PD(A4_AO_UART, 0),
+ /* IR is wake up trigger source, and should be always on */
+ SEC_PD(A4_AO_IR, GENPD_FLAG_ALWAYS_ON),
+};
+
+static const struct meson_secure_pwrc_domain_desc a5_pwrc_domains[] = {
+ SEC_PD(A5_NNA, 0),
+ SEC_PD(A5_AUDIO, 0),
+ SEC_PD(A5_SDIOA, 0),
+ SEC_PD(A5_EMMC, 0),
+ SEC_PD(A5_USB_COMB, 0),
+ SEC_PD(A5_ETH, 0),
+ SEC_PD(A5_RSA, 0),
+ SEC_PD(A5_AUDIO_PDM, 0),
+ /* DMC is for DDR PHY ana/dig and DMC, and should be always on */
+ SEC_PD(A5_DMC, GENPD_FLAG_ALWAYS_ON),
+ /* WRAP is secure_top, a lot of modules are included, and should be always on */
+ SEC_PD(A5_SYS_WRAP, GENPD_FLAG_ALWAYS_ON),
+ SEC_PD(A5_DSPA, 0),
+};
+
+static const struct meson_secure_pwrc_domain_desc c3_pwrc_domains[] = {
SEC_PD(C3_NNA, 0),
SEC_PD(C3_AUDIO, 0),
SEC_PD(C3_SDIOA, 0),
@@ -153,7 +189,7 @@ static struct meson_secure_pwrc_domain_desc c3_pwrc_domains[] = {
SEC_PD(C3_VCODEC, 0),
};
-static struct meson_secure_pwrc_domain_desc s4_pwrc_domains[] = {
+static const struct meson_secure_pwrc_domain_desc s4_pwrc_domains[] = {
SEC_PD(S4_DOS_HEVC, 0),
SEC_PD(S4_DOS_VDEC, 0),
SEC_PD(S4_VPU_HDMI, 0),
@@ -165,7 +201,7 @@ static struct meson_secure_pwrc_domain_desc s4_pwrc_domains[] = {
SEC_PD(S4_AUDIO, 0),
};
-static struct meson_secure_pwrc_domain_desc t7_pwrc_domains[] = {
+static const struct meson_secure_pwrc_domain_desc t7_pwrc_domains[] = {
SEC_PD(T7_DSPA, 0),
SEC_PD(T7_DSPB, 0),
TOP_PD(T7_DOS_HCODEC, 0, PWRC_T7_NIC3_ID),
@@ -311,6 +347,16 @@ static struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = {
.count = ARRAY_SIZE(a1_pwrc_domains),
};
+static struct meson_secure_pwrc_domain_data amlogic_secure_a4_pwrc_data = {
+ .domains = a4_pwrc_domains,
+ .count = ARRAY_SIZE(a4_pwrc_domains),
+};
+
+static struct meson_secure_pwrc_domain_data amlogic_secure_a5_pwrc_data = {
+ .domains = a5_pwrc_domains,
+ .count = ARRAY_SIZE(a5_pwrc_domains),
+};
+
static struct meson_secure_pwrc_domain_data amlogic_secure_c3_pwrc_data = {
.domains = c3_pwrc_domains,
.count = ARRAY_SIZE(c3_pwrc_domains),
@@ -332,6 +378,14 @@ static const struct of_device_id meson_secure_pwrc_match_table[] = {
.data = &meson_secure_a1_pwrc_data,
},
{
+ .compatible = "amlogic,a4-pwrc",
+ .data = &amlogic_secure_a4_pwrc_data,
+ },
+ {
+ .compatible = "amlogic,a5-pwrc",
+ .data = &amlogic_secure_a5_pwrc_data,
+ },
+ {
.compatible = "amlogic,c3-pwrc",
.data = &amlogic_secure_c3_pwrc_data,
},
@@ -355,4 +409,5 @@ static struct platform_driver meson_secure_pwrc_driver = {
},
};
module_platform_driver(meson_secure_pwrc_driver);
+MODULE_DESCRIPTION("Amlogic Meson Secure Power Domains driver");
MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/pmdomain/arm/scmi_pm_domain.c b/drivers/pmdomain/arm/scmi_pm_domain.c
index 0e05a79de82d..a7784a8bb5db 100644
--- a/drivers/pmdomain/arm/scmi_pm_domain.c
+++ b/drivers/pmdomain/arm/scmi_pm_domain.c
@@ -102,6 +102,7 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
scmi_pd->genpd.name = scmi_pd->name;
scmi_pd->genpd.power_off = scmi_pd_power_off;
scmi_pd->genpd.power_on = scmi_pd_power_on;
+ scmi_pd->genpd.flags = GENPD_FLAG_ACTIVE_WAKEUP;
pm_genpd_init(&scmi_pd->genpd, NULL,
state == SCMI_POWER_STATE_GENERIC_OFF);
diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
index 623d15b68707..7a61aa88c061 100644
--- a/drivers/pmdomain/core.c
+++ b/drivers/pmdomain/core.c
@@ -588,6 +588,68 @@ void dev_pm_genpd_synced_poweroff(struct device *dev)
}
EXPORT_SYMBOL_GPL(dev_pm_genpd_synced_poweroff);
+/**
+ * dev_pm_genpd_set_hwmode() - Set the HW mode for the device and its PM domain.
+ *
+ * @dev: Device for which the HW-mode should be changed.
+ * @enable: Value to set or unset the HW-mode.
+ *
+ * Some PM domains can rely on HW signals to control the power for a device. To
+ * allow a consumer driver to switch the behaviour for its device in runtime,
+ * which may be beneficial from a latency or energy point of view, this function
+ * may be called.
+ *
+ * It is assumed that the users guarantee that the genpd wouldn't be detached
+ * while this routine is getting called.
+ *
+ * Return: Returns 0 on success and negative error values on failures.
+ */
+int dev_pm_genpd_set_hwmode(struct device *dev, bool enable)
+{
+ struct generic_pm_domain *genpd;
+ int ret = 0;
+
+ genpd = dev_to_genpd_safe(dev);
+ if (!genpd)
+ return -ENODEV;
+
+ if (!genpd->set_hwmode_dev)
+ return -EOPNOTSUPP;
+
+ genpd_lock(genpd);
+
+ if (dev_gpd_data(dev)->hw_mode == enable)
+ goto out;
+
+ ret = genpd->set_hwmode_dev(genpd, dev, enable);
+ if (!ret)
+ dev_gpd_data(dev)->hw_mode = enable;
+
+out:
+ genpd_unlock(genpd);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_genpd_set_hwmode);
+
+/**
+ * dev_pm_genpd_get_hwmode() - Get the HW mode setting for the device.
+ *
+ * @dev: Device for which the current HW-mode setting should be fetched.
+ *
+ * This helper function allows consumer drivers to fetch the current HW mode
+ * setting of its the device.
+ *
+ * It is assumed that the users guarantee that the genpd wouldn't be detached
+ * while this routine is getting called.
+ *
+ * Return: Returns the HW mode setting of device from SW cached hw_mode.
+ */
+bool dev_pm_genpd_get_hwmode(struct device *dev)
+{
+ return dev_gpd_data(dev)->hw_mode;
+}
+EXPORT_SYMBOL_GPL(dev_pm_genpd_get_hwmode);
+
static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
{
unsigned int state_idx = genpd->state_idx;
@@ -1687,6 +1749,8 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
gpd_data->cpu = genpd_get_cpu(genpd, base_dev);
+ gpd_data->hw_mode = genpd->get_hwmode_dev ? genpd->get_hwmode_dev(genpd, dev) : false;
+
ret = genpd->attach_dev ? genpd->attach_dev(genpd, dev) : 0;
if (ret)
goto out;
@@ -2079,7 +2143,7 @@ static void genpd_free_data(struct generic_pm_domain *genpd)
static void genpd_lock_init(struct generic_pm_domain *genpd)
{
- if (genpd->flags & GENPD_FLAG_IRQ_SAFE) {
+ if (genpd_is_irq_safe(genpd)) {
spin_lock_init(&genpd->slock);
genpd->lock_ops = &genpd_spin_ops;
} else {
@@ -3120,6 +3184,15 @@ static void rtpm_status_str(struct seq_file *s, struct device *dev)
seq_printf(s, "%-25s ", p);
}
+static void mode_status_str(struct seq_file *s, struct device *dev)
+{
+ struct generic_pm_domain_data *gpd_data;
+
+ gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
+
+ seq_printf(s, "%20s", gpd_data->hw_mode ? "HW" : "SW");
+}
+
static void perf_status_str(struct seq_file *s, struct device *dev)
{
struct generic_pm_domain_data *gpd_data;
@@ -3178,6 +3251,7 @@ static int genpd_summary_one(struct seq_file *s,
seq_printf(s, "\n %-50s ", kobj_path);
rtpm_status_str(s, pm_data->dev);
perf_status_str(s, pm_data->dev);
+ mode_status_str(s, pm_data->dev);
kfree(kobj_path);
}
@@ -3194,8 +3268,8 @@ static int summary_show(struct seq_file *s, void *data)
int ret = 0;
seq_puts(s, "domain status children performance\n");
- seq_puts(s, " /device runtime status\n");
- seq_puts(s, "----------------------------------------------------------------------------------------------\n");
+ seq_puts(s, " /device runtime status managed by\n");
+ seq_puts(s, "------------------------------------------------------------------------------------------------------------\n");
ret = mutex_lock_interruptible(&gpd_list_lock);
if (ret)
diff --git a/drivers/pmdomain/qcom/rpmhpd.c b/drivers/pmdomain/qcom/rpmhpd.c
index de9121ef4216..d2cb4271a1ca 100644
--- a/drivers/pmdomain/qcom/rpmhpd.c
+++ b/drivers/pmdomain/qcom/rpmhpd.c
@@ -40,6 +40,7 @@
* @addr: Resource address as looped up using resource name from
* cmd-db
* @state_synced: Indicator that sync_state has been invoked for the rpmhpd resource
+ * @skip_retention_level: Indicate that retention level should not be used for the power domain
*/
struct rpmhpd {
struct device *dev;
@@ -56,6 +57,7 @@ struct rpmhpd {
const char *res_name;
u32 addr;
bool state_synced;
+ bool skip_retention_level;
};
struct rpmhpd_desc {
@@ -173,6 +175,7 @@ static struct rpmhpd mxc = {
.pd = { .name = "mxc", },
.peer = &mxc_ao,
.res_name = "mxc.lvl",
+ .skip_retention_level = true,
};
static struct rpmhpd mxc_ao = {
@@ -180,6 +183,7 @@ static struct rpmhpd mxc_ao = {
.active_only = true,
.peer = &mxc,
.res_name = "mxc.lvl",
+ .skip_retention_level = true,
};
static struct rpmhpd nsp = {
@@ -819,6 +823,9 @@ static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
return -EINVAL;
for (i = 0; i < rpmhpd->level_count; i++) {
+ if (rpmhpd->skip_retention_level && buf[i] == RPMH_REGULATOR_LEVEL_RETENTION)
+ continue;
+
rpmhpd->level[i] = buf[i];
/* Remember the first corner with non-zero level */
diff --git a/drivers/pmdomain/renesas/rmobile-sysc.c b/drivers/pmdomain/renesas/rmobile-sysc.c
index 0b77f37787d5..5848e79aa438 100644
--- a/drivers/pmdomain/renesas/rmobile-sysc.c
+++ b/drivers/pmdomain/renesas/rmobile-sysc.c
@@ -268,9 +268,7 @@ static int __init rmobile_add_pm_domains(void __iomem *base,
struct device_node *parent,
struct generic_pm_domain *genpd_parent)
{
- struct device_node *np;
-
- for_each_child_of_node(parent, np) {
+ for_each_child_of_node_scoped(parent, np) {
struct rmobile_pm_domain *pd;
u32 idx = ~0;
@@ -279,10 +277,8 @@ static int __init rmobile_add_pm_domains(void __iomem *base,
}
pd = kzalloc(sizeof(*pd), GFP_KERNEL);
- if (!pd) {
- of_node_put(np);
+ if (!pd)
return -ENOMEM;
- }
pd->genpd.name = np->name;
pd->base = base;
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 696bf77a7042..9a8e44ca9ae4 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
source "drivers/power/reset/Kconfig"
+source "drivers/power/sequencing/Kconfig"
source "drivers/power/supply/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index effbf0377f32..962a2cd30a51 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_POWER_RESET) += reset/
+obj-$(CONFIG_POWER_SEQUENCING) += sequencing/
obj-$(CONFIG_POWER_SUPPLY) += supply/
diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
new file mode 100644
index 000000000000..c9f1cdb66524
--- /dev/null
+++ b/drivers/power/sequencing/Kconfig
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+menuconfig POWER_SEQUENCING
+ tristate "Power Sequencing support"
+ help
+ Say Y here to enable the Power Sequencing subsystem.
+
+ This subsystem is designed to control power to devices that share
+ complex resources and/or require specific power sequences to be run
+ during power-up.
+
+ If unsure, say no.
+
+if POWER_SEQUENCING
+
+config POWER_SEQUENCING_QCOM_WCN
+ tristate "Qualcomm WCN family PMU driver"
+ default m if ARCH_QCOM
+ help
+ Say Y here to enable the power sequencing driver for Qualcomm
+ WCN Bluetooth/WLAN chipsets.
+
+ Typically, a package from the Qualcomm WCN family contains the BT
+ and WLAN modules whose power is controlled by the PMU module. As the
+ former two share the power-up sequence which is executed by the PMU,
+ this driver is needed for correct power control or else we'd risk not
+ respecting the required delays between enabling Bluetooth and WLAN.
+
+endif
diff --git a/drivers/power/sequencing/Makefile b/drivers/power/sequencing/Makefile
new file mode 100644
index 000000000000..2eec2df7912d
--- /dev/null
+++ b/drivers/power/sequencing/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_POWER_SEQUENCING) += pwrseq-core.o
+pwrseq-core-y := core.o
+
+obj-$(CONFIG_POWER_SEQUENCING_QCOM_WCN) += pwrseq-qcom-wcn.o
diff --git a/drivers/power/sequencing/core.c b/drivers/power/sequencing/core.c
new file mode 100644
index 000000000000..9c32b07a55e7
--- /dev/null
+++ b/drivers/power/sequencing/core.c
@@ -0,0 +1,1105 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#include <linux/bug.h>
+#include <linux/cleanup.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/idr.h>
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/lockdep.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/property.h>
+#include <linux/pwrseq/consumer.h>
+#include <linux/pwrseq/provider.h>
+#include <linux/radix-tree.h>
+#include <linux/rwsem.h>
+#include <linux/slab.h>
+
+/*
+ * Power-sequencing framework for linux.
+ *
+ * This subsystem allows power sequence providers to register a set of targets
+ * that consumers may request and power-up/down.
+ *
+ * Glossary:
+ *
+ * Unit - a unit is a discreet 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.
+ *
+ * Target - a target is a set of units (composed of the "final" unit and its
+ * dependencies) that a consumer selects by its name when requesting a handle
+ * to the power sequencer. Via the dependency system, multiple targets may
+ * share the same parts of a power sequence but ignore parts that are
+ * irrelevant.
+ *
+ * Descriptor - a handle passed by the pwrseq core to every consumer that
+ * serves as the entry point to the provider layer. It ensures coherence
+ * between different users and keeps reference counting consistent.
+ *
+ * Each provider must define a .match() callback whose role is to determine
+ * whether a potential consumer is in fact associated with this sequencer.
+ * This allows creating abstraction layers on top of regular device-tree
+ * resources like regulators, clocks and other nodes connected to the consumer
+ * via phandle.
+ */
+
+static DEFINE_IDA(pwrseq_ida);
+
+/*
+ * Protects the device list on the pwrseq bus from concurrent modifications
+ * but allows simultaneous read-only access.
+ */
+static DECLARE_RWSEM(pwrseq_sem);
+
+/**
+ * struct pwrseq_unit - Private power-sequence unit data.
+ * @ref: Reference count for this object. When it goes to 0, the object is
+ * destroyed.
+ * @name: Name of this target.
+ * @list: Link to siblings on the list of all units of a single sequencer.
+ * @deps: List of units on which this unit depends.
+ * @enable: Callback running the part of the power-on sequence provided by
+ * this unit.
+ * @disable: Callback running the part of the power-off sequence provided
+ * by this unit.
+ * @enable_count: Current number of users that enabled this unit. May be the
+ * consumer of the power sequencer or other units that depend
+ * on this one.
+ */
+struct pwrseq_unit {
+ struct kref ref;
+ const char *name;
+ struct list_head list;
+ struct list_head deps;
+ pwrseq_power_state_func enable;
+ pwrseq_power_state_func disable;
+ unsigned int enable_count;
+};
+
+static struct pwrseq_unit *pwrseq_unit_new(const struct pwrseq_unit_data *data)
+{
+ struct pwrseq_unit *unit;
+
+ unit = kzalloc(sizeof(*unit), GFP_KERNEL);
+ if (!unit)
+ return NULL;
+
+ unit->name = kstrdup_const(data->name, GFP_KERNEL);
+ if (!unit->name) {
+ kfree(unit);
+ return NULL;
+ }
+
+ kref_init(&unit->ref);
+ INIT_LIST_HEAD(&unit->deps);
+ unit->enable = data->enable;
+ unit->disable = data->disable;
+
+ return unit;
+}
+
+static struct pwrseq_unit *pwrseq_unit_get(struct pwrseq_unit *unit)
+{
+ kref_get(&unit->ref);
+
+ return unit;
+}
+
+static void pwrseq_unit_release(struct kref *ref);
+
+static void pwrseq_unit_put(struct pwrseq_unit *unit)
+{
+ kref_put(&unit->ref, pwrseq_unit_release);
+}
+
+/**
+ * struct pwrseq_unit_dep - Wrapper around a reference to the unit structure
+ * allowing to keep it on multiple dependency lists
+ * in different units.
+ * @list: Siblings on the list.
+ * @unit: Address of the referenced unit.
+ */
+struct pwrseq_unit_dep {
+ struct list_head list;
+ struct pwrseq_unit *unit;
+};
+
+static struct pwrseq_unit_dep *pwrseq_unit_dep_new(struct pwrseq_unit *unit)
+{
+ struct pwrseq_unit_dep *dep;
+
+ dep = kzalloc(sizeof(*dep), GFP_KERNEL);
+ if (!dep)
+ return NULL;
+
+ dep->unit = unit;
+
+ return dep;
+}
+
+static void pwrseq_unit_dep_free(struct pwrseq_unit_dep *ref)
+{
+ pwrseq_unit_put(ref->unit);
+ kfree(ref);
+}
+
+static void pwrseq_unit_free_deps(struct list_head *list)
+{
+ struct pwrseq_unit_dep *dep, *next;
+
+ list_for_each_entry_safe(dep, next, list, list) {
+ list_del(&dep->list);
+ pwrseq_unit_dep_free(dep);
+ }
+}
+
+static void pwrseq_unit_release(struct kref *ref)
+{
+ struct pwrseq_unit *unit = container_of(ref, struct pwrseq_unit, ref);
+
+ pwrseq_unit_free_deps(&unit->deps);
+ list_del(&unit->list);
+ kfree_const(unit->name);
+ kfree(unit);
+}
+
+/**
+ * struct pwrseq_target - Private power-sequence target data.
+ * @list: Siblings on the list of all targets exposed by a power sequencer.
+ * @name: Name of the target.
+ * @unit: Final unit for this target.
+ * @post_enable: Callback run after the target unit has been enabled, *after*
+ * the state lock has been released. It's useful for implementing
+ * boot-up delays without blocking other users from powering up
+ * using the same power sequencer.
+ */
+struct pwrseq_target {
+ struct list_head list;
+ const char *name;
+ struct pwrseq_unit *unit;
+ pwrseq_power_state_func post_enable;
+};
+
+static struct pwrseq_target *
+pwrseq_target_new(const struct pwrseq_target_data *data)
+{
+ struct pwrseq_target *target;
+
+ target = kzalloc(sizeof(*target), GFP_KERNEL);
+ if (!target)
+ return NULL;
+
+ target->name = kstrdup_const(data->name, GFP_KERNEL);
+ if (!target->name) {
+ kfree(target);
+ return NULL;
+ }
+
+ target->post_enable = data->post_enable;
+
+ return target;
+}
+
+static void pwrseq_target_free(struct pwrseq_target *target)
+{
+ pwrseq_unit_put(target->unit);
+ kfree_const(target->name);
+ kfree(target);
+}
+
+/**
+ * struct pwrseq_device - Private power sequencing data.
+ * @dev: Device struct associated with this sequencer.
+ * @id: Device ID.
+ * @owner: Prevents removal of active power sequencing providers.
+ * @rw_lock: Protects the device from being unregistered while in use.
+ * @state_lock: Prevents multiple users running the power sequence at the same
+ * time.
+ * @match: Power sequencer matching callback.
+ * @targets: List of targets exposed by this sequencer.
+ * @units: List of all units supported by this sequencer.
+ */
+struct pwrseq_device {
+ struct device dev;
+ int id;
+ struct module *owner;
+ struct rw_semaphore rw_lock;
+ struct mutex state_lock;
+ pwrseq_match_func match;
+ struct list_head targets;
+ struct list_head units;
+};
+
+static struct pwrseq_device *to_pwrseq_device(struct device *dev)
+{
+ return container_of(dev, struct pwrseq_device, dev);
+}
+
+static struct pwrseq_device *pwrseq_device_get(struct pwrseq_device *pwrseq)
+{
+ get_device(&pwrseq->dev);
+
+ return pwrseq;
+}
+
+static void pwrseq_device_put(struct pwrseq_device *pwrseq)
+{
+ put_device(&pwrseq->dev);
+}
+
+/**
+ * struct pwrseq_desc - Wraps access to the pwrseq_device and ensures that one
+ * user cannot break the reference counting for others.
+ * @pwrseq: Reference to the power sequencing device.
+ * @target: Reference to the target this descriptor allows to control.
+ * @powered_on: Power state set by the holder of the descriptor (not necessarily
+ * corresponding to the actual power state of the device).
+ */
+struct pwrseq_desc {
+ struct pwrseq_device *pwrseq;
+ struct pwrseq_target *target;
+ bool powered_on;
+};
+
+static const struct bus_type pwrseq_bus = {
+ .name = "pwrseq",
+};
+
+static void pwrseq_release(struct device *dev)
+{
+ struct pwrseq_device *pwrseq = to_pwrseq_device(dev);
+ struct pwrseq_target *target, *pos;
+
+ list_for_each_entry_safe(target, pos, &pwrseq->targets, list) {
+ list_del(&target->list);
+ pwrseq_target_free(target);
+ }
+
+ mutex_destroy(&pwrseq->state_lock);
+ ida_free(&pwrseq_ida, pwrseq->id);
+ kfree(pwrseq);
+}
+
+static const struct device_type pwrseq_device_type = {
+ .name = "power_sequencer",
+ .release = pwrseq_release,
+};
+
+static int pwrseq_check_unit_deps(const struct pwrseq_unit_data *data,
+ struct radix_tree_root *visited_units)
+{
+ const struct pwrseq_unit_data *tmp, **cur;
+ int ret;
+
+ ret = radix_tree_insert(visited_units, (unsigned long)data,
+ (void *)data);
+ if (ret)
+ return ret;
+
+ for (cur = data->deps; cur && *cur; cur++) {
+ tmp = radix_tree_lookup(visited_units, (unsigned long)*cur);
+ if (tmp) {
+ WARN(1, "Circular dependency in power sequencing flow detected!\n");
+ return -EINVAL;
+ }
+
+ ret = pwrseq_check_unit_deps(*cur, visited_units);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pwrseq_check_target_deps(const struct pwrseq_target_data *data)
+{
+ struct radix_tree_root visited_units;
+ struct radix_tree_iter iter;
+ void __rcu **slot;
+ int ret;
+
+ if (!data->unit)
+ return -EINVAL;
+
+ INIT_RADIX_TREE(&visited_units, GFP_KERNEL);
+ ret = pwrseq_check_unit_deps(data->unit, &visited_units);
+ radix_tree_for_each_slot(slot, &visited_units, &iter, 0)
+ radix_tree_delete(&visited_units, iter.index);
+
+ return ret;
+}
+
+static int pwrseq_unit_setup_deps(const struct pwrseq_unit_data **data,
+ struct list_head *dep_list,
+ struct list_head *unit_list,
+ struct radix_tree_root *processed_units);
+
+static struct pwrseq_unit *
+pwrseq_unit_setup(const struct pwrseq_unit_data *data,
+ struct list_head *unit_list,
+ struct radix_tree_root *processed_units)
+{
+ struct pwrseq_unit *unit;
+ int ret;
+
+ unit = radix_tree_lookup(processed_units, (unsigned long)data);
+ if (unit)
+ return pwrseq_unit_get(unit);
+
+ unit = pwrseq_unit_new(data);
+ if (!unit)
+ return ERR_PTR(-ENOMEM);
+
+ if (data->deps) {
+ ret = pwrseq_unit_setup_deps(data->deps, &unit->deps,
+ unit_list, processed_units);
+ if (ret) {
+ pwrseq_unit_put(unit);
+ return ERR_PTR(ret);
+ }
+ }
+
+ ret = radix_tree_insert(processed_units, (unsigned long)data, unit);
+ if (ret) {
+ pwrseq_unit_put(unit);
+ return ERR_PTR(ret);
+ }
+
+ list_add_tail(&unit->list, unit_list);
+
+ return unit;
+}
+
+static int pwrseq_unit_setup_deps(const struct pwrseq_unit_data **data,
+ struct list_head *dep_list,
+ struct list_head *unit_list,
+ struct radix_tree_root *processed_units)
+{
+ const struct pwrseq_unit_data *pos;
+ struct pwrseq_unit_dep *dep;
+ struct pwrseq_unit *unit;
+ int i;
+
+ for (i = 0; data[i]; i++) {
+ pos = data[i];
+
+ unit = pwrseq_unit_setup(pos, unit_list, processed_units);
+ if (IS_ERR(unit))
+ return PTR_ERR(unit);
+
+ dep = pwrseq_unit_dep_new(unit);
+ if (!dep) {
+ pwrseq_unit_put(unit);
+ return -ENOMEM;
+ }
+
+ list_add_tail(&dep->list, dep_list);
+ }
+
+ return 0;
+}
+
+static int pwrseq_do_setup_targets(const struct pwrseq_target_data **data,
+ struct pwrseq_device *pwrseq,
+ struct radix_tree_root *processed_units)
+{
+ const struct pwrseq_target_data *pos;
+ struct pwrseq_target *target;
+ int ret, i;
+
+ for (i = 0; data[i]; i++) {
+ pos = data[i];
+
+ ret = pwrseq_check_target_deps(pos);
+ if (ret)
+ return ret;
+
+ target = pwrseq_target_new(pos);
+ if (!target)
+ return -ENOMEM;
+
+ target->unit = pwrseq_unit_setup(pos->unit, &pwrseq->units,
+ processed_units);
+ if (IS_ERR(target->unit)) {
+ ret = PTR_ERR(target->unit);
+ pwrseq_target_free(target);
+ return ret;
+ }
+
+ list_add_tail(&target->list, &pwrseq->targets);
+ }
+
+ return 0;
+}
+
+static int pwrseq_setup_targets(const struct pwrseq_target_data **targets,
+ struct pwrseq_device *pwrseq)
+{
+ struct radix_tree_root processed_units;
+ struct radix_tree_iter iter;
+ void __rcu **slot;
+ int ret;
+
+ INIT_RADIX_TREE(&processed_units, GFP_KERNEL);
+ ret = pwrseq_do_setup_targets(targets, pwrseq, &processed_units);
+ radix_tree_for_each_slot(slot, &processed_units, &iter, 0)
+ radix_tree_delete(&processed_units, iter.index);
+
+ return ret;
+}
+
+/**
+ * pwrseq_device_register() - Register a new power sequencer.
+ * @config: Configuration of the new power sequencing device.
+ *
+ * The config structure is only used during the call and can be freed after
+ * the function returns. The config structure *must* have the parent device
+ * as well as the match() callback and at least one target set.
+ *
+ * Returns:
+ * Returns the address of the new pwrseq device or ERR_PTR() on failure.
+ */
+struct pwrseq_device *
+pwrseq_device_register(const struct pwrseq_config *config)
+{
+ struct pwrseq_device *pwrseq;
+ int ret, id;
+
+ if (!config->parent || !config->match || !config->targets ||
+ !config->targets[0])
+ return ERR_PTR(-EINVAL);
+
+ pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL);
+ if (!pwrseq)
+ return ERR_PTR(-ENOMEM);
+
+ pwrseq->dev.type = &pwrseq_device_type;
+ pwrseq->dev.bus = &pwrseq_bus;
+ pwrseq->dev.parent = config->parent;
+ device_set_node(&pwrseq->dev, dev_fwnode(config->parent));
+ dev_set_drvdata(&pwrseq->dev, config->drvdata);
+
+ id = ida_alloc(&pwrseq_ida, GFP_KERNEL);
+ if (id < 0) {
+ kfree(pwrseq);
+ return ERR_PTR(id);
+ }
+
+ pwrseq->id = id;
+
+ /*
+ * From this point onwards the device's release() callback is
+ * responsible for freeing resources.
+ */
+ device_initialize(&pwrseq->dev);
+
+ ret = dev_set_name(&pwrseq->dev, "pwrseq.%d", pwrseq->id);
+ if (ret)
+ goto err_put_pwrseq;
+
+ pwrseq->owner = config->owner ?: THIS_MODULE;
+ pwrseq->match = config->match;
+
+ init_rwsem(&pwrseq->rw_lock);
+ mutex_init(&pwrseq->state_lock);
+ INIT_LIST_HEAD(&pwrseq->targets);
+ INIT_LIST_HEAD(&pwrseq->units);
+
+ ret = pwrseq_setup_targets(config->targets, pwrseq);
+ if (ret)
+ goto err_put_pwrseq;
+
+ scoped_guard(rwsem_write, &pwrseq_sem) {
+ ret = device_add(&pwrseq->dev);
+ if (ret)
+ goto err_put_pwrseq;
+ }
+
+ return pwrseq;
+
+err_put_pwrseq:
+ pwrseq_device_put(pwrseq);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(pwrseq_device_register);
+
+/**
+ * pwrseq_device_unregister() - Unregister the power sequencer.
+ * @pwrseq: Power sequencer to unregister.
+ */
+void pwrseq_device_unregister(struct pwrseq_device *pwrseq)
+{
+ struct device *dev = &pwrseq->dev;
+ struct pwrseq_target *target;
+
+ scoped_guard(mutex, &pwrseq->state_lock) {
+ guard(rwsem_write)(&pwrseq->rw_lock);
+
+ list_for_each_entry(target, &pwrseq->targets, list)
+ WARN(target->unit->enable_count,
+ "REMOVING POWER SEQUENCER WITH ACTIVE USERS\n");
+
+ guard(rwsem_write)(&pwrseq_sem);
+
+ device_del(dev);
+ }
+
+ pwrseq_device_put(pwrseq);
+}
+EXPORT_SYMBOL_GPL(pwrseq_device_unregister);
+
+static void devm_pwrseq_device_unregister(void *data)
+{
+ struct pwrseq_device *pwrseq = data;
+
+ pwrseq_device_unregister(pwrseq);
+}
+
+/**
+ * devm_pwrseq_device_register() - Managed variant of pwrseq_device_register().
+ * @dev: Managing device.
+ * @config: Configuration of the new power sequencing device.
+ *
+ * Returns:
+ * Returns the address of the new pwrseq device or ERR_PTR() on failure.
+ */
+struct pwrseq_device *
+devm_pwrseq_device_register(struct device *dev,
+ const struct pwrseq_config *config)
+{
+ struct pwrseq_device *pwrseq;
+ int ret;
+
+ pwrseq = pwrseq_device_register(config);
+ if (IS_ERR(pwrseq))
+ return pwrseq;
+
+ ret = devm_add_action_or_reset(dev, devm_pwrseq_device_unregister,
+ pwrseq);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return pwrseq;
+}
+EXPORT_SYMBOL_GPL(devm_pwrseq_device_register);
+
+/**
+ * pwrseq_device_get_drvdata() - Get the driver private data associated with
+ * this sequencer.
+ * @pwrseq: Power sequencer object.
+ *
+ * Returns:
+ * Address of the private driver data.
+ */
+void *pwrseq_device_get_drvdata(struct pwrseq_device *pwrseq)
+{
+ return dev_get_drvdata(&pwrseq->dev);
+}
+EXPORT_SYMBOL_GPL(pwrseq_device_get_drvdata);
+
+struct pwrseq_match_data {
+ struct pwrseq_desc *desc;
+ struct device *dev;
+ const char *target;
+};
+
+static int pwrseq_match_device(struct device *pwrseq_dev, void *data)
+{
+ struct pwrseq_device *pwrseq = to_pwrseq_device(pwrseq_dev);
+ struct pwrseq_match_data *match_data = data;
+ struct pwrseq_target *target;
+ int ret;
+
+ lockdep_assert_held_read(&pwrseq_sem);
+
+ guard(rwsem_read)(&pwrseq->rw_lock);
+ if (!device_is_registered(&pwrseq->dev))
+ return 0;
+
+ ret = pwrseq->match(pwrseq, match_data->dev);
+ if (ret <= 0)
+ return ret;
+
+ /* We got the matching device, let's find the right target. */
+ list_for_each_entry(target, &pwrseq->targets, list) {
+ if (strcmp(target->name, match_data->target))
+ continue;
+
+ match_data->desc->target = target;
+ }
+
+ /*
+ * This device does not have this target. No point in deferring as it
+ * will not get a new target dynamically later.
+ */
+ if (!match_data->desc->target)
+ return -ENOENT;
+
+ if (!try_module_get(pwrseq->owner))
+ return -EPROBE_DEFER;
+
+ match_data->desc->pwrseq = pwrseq_device_get(pwrseq);
+
+ return 1;
+}
+
+/**
+ * pwrseq_get() - Get the power sequencer associated with this device.
+ * @dev: Device for which to get the sequencer.
+ * @target: Name of the target exposed by the sequencer this device wants to
+ * reach.
+ *
+ * Returns:
+ * New power sequencer descriptor for use by the consumer driver or ERR_PTR()
+ * on failure.
+ */
+struct pwrseq_desc *pwrseq_get(struct device *dev, const char *target)
+{
+ struct pwrseq_match_data match_data;
+ int ret;
+
+ struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc),
+ GFP_KERNEL);
+ if (!desc)
+ return ERR_PTR(-ENOMEM);
+
+ match_data.desc = desc;
+ match_data.dev = dev;
+ match_data.target = target;
+
+ guard(rwsem_read)(&pwrseq_sem);
+
+ ret = bus_for_each_dev(&pwrseq_bus, NULL, &match_data,
+ pwrseq_match_device);
+ if (ret < 0)
+ return ERR_PTR(ret);
+ if (ret == 0)
+ /* No device matched. */
+ return ERR_PTR(-EPROBE_DEFER);
+
+ return_ptr(desc);
+}
+EXPORT_SYMBOL_GPL(pwrseq_get);
+
+/**
+ * pwrseq_put() - Release the power sequencer descriptor.
+ * @desc: Descriptor to release.
+ */
+void pwrseq_put(struct pwrseq_desc *desc)
+{
+ struct pwrseq_device *pwrseq;
+
+ if (!desc)
+ return;
+
+ pwrseq = desc->pwrseq;
+
+ if (desc->powered_on)
+ pwrseq_power_off(desc);
+
+ kfree(desc);
+ module_put(pwrseq->owner);
+ pwrseq_device_put(pwrseq);
+}
+EXPORT_SYMBOL_GPL(pwrseq_put);
+
+static void devm_pwrseq_put(void *data)
+{
+ struct pwrseq_desc *desc = data;
+
+ pwrseq_put(desc);
+}
+
+/**
+ * devm_pwrseq_get() - Managed variant of pwrseq_get().
+ * @dev: Device for which to get the sequencer and which also manages its
+ * lifetime.
+ * @target: Name of the target exposed by the sequencer this device wants to
+ * reach.
+ *
+ * Returns:
+ * New power sequencer descriptor for use by the consumer driver or ERR_PTR()
+ * on failure.
+ */
+struct pwrseq_desc *devm_pwrseq_get(struct device *dev, const char *target)
+{
+ struct pwrseq_desc *desc;
+ int ret;
+
+ desc = pwrseq_get(dev, target);
+ if (IS_ERR(desc))
+ return desc;
+
+ ret = devm_add_action_or_reset(dev, devm_pwrseq_put, desc);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return desc;
+}
+EXPORT_SYMBOL_GPL(devm_pwrseq_get);
+
+static int pwrseq_unit_enable(struct pwrseq_device *pwrseq,
+ struct pwrseq_unit *target);
+static int pwrseq_unit_disable(struct pwrseq_device *pwrseq,
+ struct pwrseq_unit *target);
+
+static int pwrseq_unit_enable_deps(struct pwrseq_device *pwrseq,
+ struct list_head *list)
+{
+ struct pwrseq_unit_dep *pos;
+ int ret = 0;
+
+ list_for_each_entry(pos, list, list) {
+ ret = pwrseq_unit_enable(pwrseq, pos->unit);
+ if (ret) {
+ list_for_each_entry_continue_reverse(pos, list, list)
+ pwrseq_unit_disable(pwrseq, pos->unit);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int pwrseq_unit_disable_deps(struct pwrseq_device *pwrseq,
+ struct list_head *list)
+{
+ struct pwrseq_unit_dep *pos;
+ int ret = 0;
+
+ list_for_each_entry_reverse(pos, list, list) {
+ ret = pwrseq_unit_disable(pwrseq, pos->unit);
+ if (ret) {
+ list_for_each_entry_continue(pos, list, list)
+ pwrseq_unit_enable(pwrseq, pos->unit);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int pwrseq_unit_enable(struct pwrseq_device *pwrseq,
+ struct pwrseq_unit *unit)
+{
+ int ret;
+
+ lockdep_assert_held_read(&pwrseq->rw_lock);
+ lockdep_assert_held(&pwrseq->state_lock);
+
+ if (unit->enable_count != 0) {
+ unit->enable_count++;
+ return 0;
+ }
+
+ ret = pwrseq_unit_enable_deps(pwrseq, &unit->deps);
+ if (ret) {
+ dev_err(&pwrseq->dev,
+ "Failed to enable dependencies before power-on for target '%s': %d\n",
+ unit->name, ret);
+ return ret;
+ }
+
+ if (unit->enable) {
+ ret = unit->enable(pwrseq);
+ if (ret) {
+ dev_err(&pwrseq->dev,
+ "Failed to enable target '%s': %d\n",
+ unit->name, ret);
+ pwrseq_unit_disable_deps(pwrseq, &unit->deps);
+ return ret;
+ }
+ }
+
+ unit->enable_count++;
+
+ return 0;
+}
+
+static int pwrseq_unit_disable(struct pwrseq_device *pwrseq,
+ struct pwrseq_unit *unit)
+{
+ int ret;
+
+ lockdep_assert_held_read(&pwrseq->rw_lock);
+ lockdep_assert_held(&pwrseq->state_lock);
+
+ if (unit->enable_count == 0) {
+ WARN(1, "Unmatched power-off for target '%s'\n",
+ unit->name);
+ return -EBUSY;
+ }
+
+ if (unit->enable_count != 1) {
+ unit->enable_count--;
+ return 0;
+ }
+
+ if (unit->disable) {
+ ret = unit->disable(pwrseq);
+ if (ret) {
+ dev_err(&pwrseq->dev,
+ "Failed to disable target '%s': %d\n",
+ unit->name, ret);
+ return ret;
+ }
+ }
+
+ ret = pwrseq_unit_disable_deps(pwrseq, &unit->deps);
+ if (ret) {
+ dev_err(&pwrseq->dev,
+ "Failed to disable dependencies after power-off for target '%s': %d\n",
+ unit->name, ret);
+ if (unit->enable)
+ unit->enable(pwrseq);
+ return ret;
+ }
+
+ unit->enable_count--;
+
+ return 0;
+}
+
+/**
+ * pwrseq_power_on() - Issue a power-on request on behalf of the consumer
+ * device.
+ * @desc: Descriptor referencing the power sequencer.
+ *
+ * This function tells the power sequencer that the consumer wants to be
+ * powered-up. The sequencer may already have powered-up the device in which
+ * case the function returns 0. If the power-up sequence is already in
+ * progress, the function will block until it's done and return 0. If this is
+ * the first request, the device will be powered up.
+ *
+ * Returns:
+ * 0 on success, negative error number on failure.
+ */
+int pwrseq_power_on(struct pwrseq_desc *desc)
+{
+ struct pwrseq_device *pwrseq;
+ struct pwrseq_target *target;
+ struct pwrseq_unit *unit;
+ int ret;
+
+ might_sleep();
+
+ if (!desc || desc->powered_on)
+ return 0;
+
+ pwrseq = desc->pwrseq;
+ target = desc->target;
+ unit = target->unit;
+
+ guard(rwsem_read)(&pwrseq->rw_lock);
+ if (!device_is_registered(&pwrseq->dev))
+ return -ENODEV;
+
+ scoped_guard(mutex, &pwrseq->state_lock) {
+ ret = pwrseq_unit_enable(pwrseq, unit);
+ if (!ret)
+ desc->powered_on = true;
+ }
+
+ if (target->post_enable) {
+ ret = target->post_enable(pwrseq);
+ if (ret) {
+ pwrseq_unit_disable(pwrseq, unit);
+ desc->powered_on = false;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pwrseq_power_on);
+
+/**
+ * pwrseq_power_off() - Issue a power-off request on behalf of the consumer
+ * device.
+ * @desc: Descriptor referencing the power sequencer.
+ *
+ * This undoes the effects of pwrseq_power_on(). It issues a power-off request
+ * on behalf of the consumer and when the last remaining user does so, the
+ * power-down sequence will be started. If one is in progress, the function
+ * will block until it's complete and then return.
+ *
+ * Returns:
+ * 0 on success, negative error number on failure.
+ */
+int pwrseq_power_off(struct pwrseq_desc *desc)
+{
+ struct pwrseq_device *pwrseq;
+ struct pwrseq_unit *unit;
+ int ret;
+
+ might_sleep();
+
+ if (!desc || !desc->powered_on)
+ return 0;
+
+ pwrseq = desc->pwrseq;
+ unit = desc->target->unit;
+
+ guard(rwsem_read)(&pwrseq->rw_lock);
+ if (!device_is_registered(&pwrseq->dev))
+ return -ENODEV;
+
+ guard(mutex)(&pwrseq->state_lock);
+
+ ret = pwrseq_unit_disable(pwrseq, unit);
+ if (!ret)
+ desc->powered_on = false;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pwrseq_power_off);
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+
+struct pwrseq_debugfs_count_ctx {
+ struct device *dev;
+ loff_t index;
+};
+
+static int pwrseq_debugfs_seq_count(struct device *dev, void *data)
+{
+ struct pwrseq_debugfs_count_ctx *ctx = data;
+
+ ctx->dev = dev;
+
+ return ctx->index-- ? 0 : 1;
+}
+
+static void *pwrseq_debugfs_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ struct pwrseq_debugfs_count_ctx ctx;
+
+ ctx.dev = NULL;
+ ctx.index = *pos;
+
+ /*
+ * We're holding the lock for the entire printout so no need to fiddle
+ * with device reference count.
+ */
+ down_read(&pwrseq_sem);
+
+ bus_for_each_dev(&pwrseq_bus, NULL, &ctx, pwrseq_debugfs_seq_count);
+ if (!ctx.index)
+ return NULL;
+
+ return ctx.dev;
+}
+
+static void *pwrseq_debugfs_seq_next(struct seq_file *seq, void *data,
+ loff_t *pos)
+{
+ struct device *curr = data;
+
+ ++*pos;
+
+ struct device *next __free(put_device) =
+ bus_find_next_device(&pwrseq_bus, curr);
+ return next;
+}
+
+static void pwrseq_debugfs_seq_show_target(struct seq_file *seq,
+ struct pwrseq_target *target)
+{
+ seq_printf(seq, " target: [%s] (target unit: [%s])\n",
+ target->name, target->unit->name);
+}
+
+static void pwrseq_debugfs_seq_show_unit(struct seq_file *seq,
+ struct pwrseq_unit *unit)
+{
+ struct pwrseq_unit_dep *ref;
+
+ seq_printf(seq, " unit: [%s] - enable count: %u\n",
+ unit->name, unit->enable_count);
+
+ if (list_empty(&unit->deps))
+ return;
+
+ seq_puts(seq, " dependencies:\n");
+ list_for_each_entry(ref, &unit->deps, list)
+ seq_printf(seq, " [%s]\n", ref->unit->name);
+}
+
+static int pwrseq_debugfs_seq_show(struct seq_file *seq, void *data)
+{
+ struct device *dev = data;
+ struct pwrseq_device *pwrseq = to_pwrseq_device(dev);
+ struct pwrseq_target *target;
+ struct pwrseq_unit *unit;
+
+ seq_printf(seq, "%s:\n", dev_name(dev));
+
+ seq_puts(seq, " targets:\n");
+ list_for_each_entry(target, &pwrseq->targets, list)
+ pwrseq_debugfs_seq_show_target(seq, target);
+
+ seq_puts(seq, " units:\n");
+ list_for_each_entry(unit, &pwrseq->units, list)
+ pwrseq_debugfs_seq_show_unit(seq, unit);
+
+ return 0;
+}
+
+static void pwrseq_debugfs_seq_stop(struct seq_file *seq, void *data)
+{
+ up_read(&pwrseq_sem);
+}
+
+static const struct seq_operations pwrseq_debugfs_sops = {
+ .start = pwrseq_debugfs_seq_start,
+ .next = pwrseq_debugfs_seq_next,
+ .show = pwrseq_debugfs_seq_show,
+ .stop = pwrseq_debugfs_seq_stop,
+};
+DEFINE_SEQ_ATTRIBUTE(pwrseq_debugfs);
+
+static struct dentry *pwrseq_debugfs_dentry;
+
+#endif /* CONFIG_DEBUG_FS */
+
+static int __init pwrseq_init(void)
+{
+ int ret;
+
+ ret = bus_register(&pwrseq_bus);
+ if (ret) {
+ pr_err("Failed to register the power sequencer bus\n");
+ return ret;
+ }
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+ pwrseq_debugfs_dentry = debugfs_create_file("pwrseq", 0444, NULL, NULL,
+ &pwrseq_debugfs_fops);
+#endif /* CONFIG_DEBUG_FS */
+
+ return 0;
+}
+subsys_initcall(pwrseq_init);
+
+static void __exit pwrseq_exit(void)
+{
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+ debugfs_remove_recursive(pwrseq_debugfs_dentry);
+#endif /* CONFIG_DEBUG_FS */
+
+ bus_unregister(&pwrseq_bus);
+}
+module_exit(pwrseq_exit);
+
+MODULE_AUTHOR("Bartosz Golaszewski <[email protected]>");
+MODULE_DESCRIPTION("Power Sequencing subsystem core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c
new file mode 100644
index 000000000000..42dacfda745e
--- /dev/null
+++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/jiffies.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pwrseq/provider.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+struct pwrseq_qcom_wcn_pdata {
+ const char *const *vregs;
+ size_t num_vregs;
+ unsigned int pwup_delay_ms;
+ unsigned int gpio_enable_delay_ms;
+};
+
+struct pwrseq_qcom_wcn_ctx {
+ struct pwrseq_device *pwrseq;
+ struct device_node *of_node;
+ const struct pwrseq_qcom_wcn_pdata *pdata;
+ struct regulator_bulk_data *regs;
+ struct gpio_desc *bt_gpio;
+ struct gpio_desc *wlan_gpio;
+ struct clk *clk;
+ unsigned long last_gpio_enable_jf;
+};
+
+static void pwrseq_qcom_wcn_ensure_gpio_delay(struct pwrseq_qcom_wcn_ctx *ctx)
+{
+ unsigned long diff_jiffies;
+ unsigned int diff_msecs;
+
+ if (!ctx->pdata->gpio_enable_delay_ms)
+ return;
+
+ diff_jiffies = jiffies - ctx->last_gpio_enable_jf;
+ diff_msecs = jiffies_to_msecs(diff_jiffies);
+
+ if (diff_msecs < ctx->pdata->gpio_enable_delay_ms)
+ msleep(ctx->pdata->gpio_enable_delay_ms - diff_msecs);
+}
+
+static int pwrseq_qcom_wcn_vregs_enable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ return regulator_bulk_enable(ctx->pdata->num_vregs, ctx->regs);
+}
+
+static int pwrseq_qcom_wcn_vregs_disable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ return regulator_bulk_disable(ctx->pdata->num_vregs, ctx->regs);
+}
+
+static const struct pwrseq_unit_data pwrseq_qcom_wcn_vregs_unit_data = {
+ .name = "regulators-enable",
+ .enable = pwrseq_qcom_wcn_vregs_enable,
+ .disable = pwrseq_qcom_wcn_vregs_disable,
+};
+
+static int pwrseq_qcom_wcn_clk_enable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ return clk_prepare_enable(ctx->clk);
+}
+
+static int pwrseq_qcom_wcn_clk_disable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ clk_disable_unprepare(ctx->clk);
+
+ return 0;
+}
+
+static const struct pwrseq_unit_data pwrseq_qcom_wcn_clk_unit_data = {
+ .name = "clock-enable",
+ .enable = pwrseq_qcom_wcn_clk_enable,
+ .disable = pwrseq_qcom_wcn_clk_disable,
+};
+
+static const struct pwrseq_unit_data *pwrseq_qcom_wcn_unit_deps[] = {
+ &pwrseq_qcom_wcn_vregs_unit_data,
+ &pwrseq_qcom_wcn_clk_unit_data,
+ NULL
+};
+
+static int pwrseq_qcom_wcn_bt_enable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ pwrseq_qcom_wcn_ensure_gpio_delay(ctx);
+ gpiod_set_value_cansleep(ctx->bt_gpio, 1);
+ ctx->last_gpio_enable_jf = jiffies;
+
+ return 0;
+}
+
+static int pwrseq_qcom_wcn_bt_disable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ gpiod_set_value_cansleep(ctx->bt_gpio, 0);
+
+ return 0;
+}
+
+static const struct pwrseq_unit_data pwrseq_qcom_wcn_bt_unit_data = {
+ .name = "bluetooth-enable",
+ .deps = pwrseq_qcom_wcn_unit_deps,
+ .enable = pwrseq_qcom_wcn_bt_enable,
+ .disable = pwrseq_qcom_wcn_bt_disable,
+};
+
+static int pwrseq_qcom_wcn_wlan_enable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ pwrseq_qcom_wcn_ensure_gpio_delay(ctx);
+ gpiod_set_value_cansleep(ctx->wlan_gpio, 1);
+ ctx->last_gpio_enable_jf = jiffies;
+
+ return 0;
+}
+
+static int pwrseq_qcom_wcn_wlan_disable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ gpiod_set_value_cansleep(ctx->wlan_gpio, 0);
+
+ return 0;
+}
+
+static const struct pwrseq_unit_data pwrseq_qcom_wcn_wlan_unit_data = {
+ .name = "wlan-enable",
+ .deps = pwrseq_qcom_wcn_unit_deps,
+ .enable = pwrseq_qcom_wcn_wlan_enable,
+ .disable = pwrseq_qcom_wcn_wlan_disable,
+};
+
+static int pwrseq_qcom_wcn_pwup_delay(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ if (ctx->pdata->pwup_delay_ms)
+ msleep(ctx->pdata->pwup_delay_ms);
+
+ return 0;
+}
+
+static const struct pwrseq_target_data pwrseq_qcom_wcn_bt_target_data = {
+ .name = "bluetooth",
+ .unit = &pwrseq_qcom_wcn_bt_unit_data,
+ .post_enable = pwrseq_qcom_wcn_pwup_delay,
+};
+
+static const struct pwrseq_target_data pwrseq_qcom_wcn_wlan_target_data = {
+ .name = "wlan",
+ .unit = &pwrseq_qcom_wcn_wlan_unit_data,
+ .post_enable = pwrseq_qcom_wcn_pwup_delay,
+};
+
+static const struct pwrseq_target_data *pwrseq_qcom_wcn_targets[] = {
+ &pwrseq_qcom_wcn_bt_target_data,
+ &pwrseq_qcom_wcn_wlan_target_data,
+ NULL
+};
+
+static const char *const pwrseq_qca6390_vregs[] = {
+ "vddio",
+ "vddaon",
+ "vddpmu",
+ "vddrfa0p95",
+ "vddrfa1p3",
+ "vddrfa1p9",
+ "vddpcie1p3",
+ "vddpcie1p9",
+};
+
+static const struct pwrseq_qcom_wcn_pdata pwrseq_qca6390_of_data = {
+ .vregs = pwrseq_qca6390_vregs,
+ .num_vregs = ARRAY_SIZE(pwrseq_qca6390_vregs),
+ .pwup_delay_ms = 60,
+ .gpio_enable_delay_ms = 100,
+};
+
+static const char *const pwrseq_wcn7850_vregs[] = {
+ "vdd",
+ "vddio",
+ "vddio1p2",
+ "vddaon",
+ "vdddig",
+ "vddrfa1p2",
+ "vddrfa1p8",
+};
+
+static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn7850_of_data = {
+ .vregs = pwrseq_wcn7850_vregs,
+ .num_vregs = ARRAY_SIZE(pwrseq_wcn7850_vregs),
+ .pwup_delay_ms = 50,
+};
+
+static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq,
+ struct device *dev)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+ struct device_node *dev_node = dev->of_node;
+
+ /*
+ * The PMU supplies power to the Bluetooth and WLAN modules. both
+ * consume the PMU AON output so check the presence of the
+ * 'vddaon-supply' property and whether it leads us to the right
+ * device.
+ */
+ if (!of_property_present(dev_node, "vddaon-supply"))
+ return 0;
+
+ struct device_node *reg_node __free(device_node) =
+ of_parse_phandle(dev_node, "vddaon-supply", 0);
+ if (!reg_node)
+ return 0;
+
+ /*
+ * `reg_node` is the PMU AON regulator, its parent is the `regulators`
+ * node and finally its grandparent is the PMU device node that we're
+ * looking for.
+ */
+ if (!reg_node->parent || !reg_node->parent->parent ||
+ reg_node->parent->parent != ctx->of_node)
+ return 0;
+
+ return 1;
+}
+
+static int pwrseq_qcom_wcn_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pwrseq_qcom_wcn_ctx *ctx;
+ struct pwrseq_config config;
+ int i, ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->of_node = dev->of_node;
+
+ ctx->pdata = of_device_get_match_data(dev);
+ if (!ctx->pdata)
+ return dev_err_probe(dev, -ENODEV,
+ "Failed to obtain platform data\n");
+
+ ctx->regs = devm_kcalloc(dev, ctx->pdata->num_vregs,
+ sizeof(*ctx->regs), GFP_KERNEL);
+ if (!ctx->regs)
+ return -ENOMEM;
+
+ for (i = 0; i < ctx->pdata->num_vregs; i++)
+ ctx->regs[i].supply = ctx->pdata->vregs[i];
+
+ ret = devm_regulator_bulk_get(dev, ctx->pdata->num_vregs, ctx->regs);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "Failed to get all regulators\n");
+
+ ctx->bt_gpio = devm_gpiod_get_optional(dev, "bt-enable", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->bt_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->bt_gpio),
+ "Failed to get the Bluetooth enable GPIO\n");
+
+ ctx->wlan_gpio = devm_gpiod_get_optional(dev, "wlan-enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->wlan_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->wlan_gpio),
+ "Failed to get the WLAN enable GPIO\n");
+
+ ctx->clk = devm_clk_get_optional(dev, NULL);
+ if (IS_ERR(ctx->clk))
+ return dev_err_probe(dev, PTR_ERR(ctx->clk),
+ "Failed to get the reference clock\n");
+
+ memset(&config, 0, sizeof(config));
+
+ config.parent = dev;
+ config.owner = THIS_MODULE;
+ config.drvdata = ctx;
+ config.match = pwrseq_qcom_wcn_match;
+ config.targets = pwrseq_qcom_wcn_targets;
+
+ ctx->pwrseq = devm_pwrseq_device_register(dev, &config);
+ if (IS_ERR(ctx->pwrseq))
+ return dev_err_probe(dev, PTR_ERR(ctx->pwrseq),
+ "Failed to register the power sequencer\n");
+
+ return 0;
+}
+
+static const struct of_device_id pwrseq_qcom_wcn_of_match[] = {
+ {
+ .compatible = "qcom,qca6390-pmu",
+ .data = &pwrseq_qca6390_of_data,
+ },
+ {
+ .compatible = "qcom,wcn7850-pmu",
+ .data = &pwrseq_wcn7850_of_data,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pwrseq_qcom_wcn_of_match);
+
+static struct platform_driver pwrseq_qcom_wcn_driver = {
+ .driver = {
+ .name = "pwrseq-qcom_wcn",
+ .of_match_table = pwrseq_qcom_wcn_of_match,
+ },
+ .probe = pwrseq_qcom_wcn_probe,
+};
+module_platform_driver(pwrseq_qcom_wcn_driver);
+
+MODULE_AUTHOR("Bartosz Golaszewski <[email protected]>");
+MODULE_DESCRIPTION("Qualcomm WCN PMU power sequencing driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 3e31375491d5..f6321a42aa53 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -860,6 +860,18 @@ config CHARGER_CROS_PCHG
the peripheral charge ports from the EC and converts that into
power_supply properties.
+config CHARGER_CROS_CONTROL
+ tristate "ChromeOS EC based charge control"
+ depends on MFD_CROS_EC_DEV
+ depends on ACPI_BATTERY
+ default MFD_CROS_EC_DEV
+ help
+ Say Y here to enable ChromeOS EC based battery charge control.
+ This driver can manage charge thresholds and behaviour.
+
+ This driver can also be built as a module. If so, the module will be
+ called cros_charge-control.
+
config CHARGER_SC2731
tristate "Spreadtrum SC2731 charger driver"
depends on MFD_SC27XX_PMIC || COMPILE_TEST
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 58b567278034..31ca6653a564 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -100,6 +100,7 @@ obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o
obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_CONTROL) += cros_charge-control.o
obj-$(CONFIG_CHARGER_CROS_USBPD) += cros_usbpd-charger.o
obj-$(CONFIG_CHARGER_CROS_PCHG) += cros_peripheral_charger.o
obj-$(CONFIG_CHARGER_SC2731) += sc2731_charger.o
diff --git a/drivers/power/supply/cros_charge-control.c b/drivers/power/supply/cros_charge-control.c
new file mode 100644
index 000000000000..17c53591ce19
--- /dev/null
+++ b/drivers/power/supply/cros_charge-control.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * ChromeOS EC driver for charge control
+ *
+ * Copyright (C) 2024 Thomas Weißschuh <[email protected]>
+ */
+#include <acpi/battery.h>
+#include <linux/container_of.h>
+#include <linux/dmi.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_data/cros_ec_commands.h>
+#include <linux/platform_data/cros_ec_proto.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#define EC_CHARGE_CONTROL_BEHAVIOURS (BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) | \
+ BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE) | \
+ BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE))
+
+enum CROS_CHCTL_ATTR {
+ CROS_CHCTL_ATTR_START_THRESHOLD,
+ CROS_CHCTL_ATTR_END_THRESHOLD,
+ CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR,
+ _CROS_CHCTL_ATTR_COUNT
+};
+
+/*
+ * Semantics of data *returned* from the EC API and Linux sysfs differ
+ * slightly, also the v1 API can not return any data.
+ * To match the expected sysfs API, data is never read back from the EC but
+ * cached in the driver.
+ *
+ * Changes to the EC bypassing the driver will not be reflected in sysfs.
+ * Any change to "charge_behaviour" will synchronize the EC with the driver state.
+ */
+
+struct cros_chctl_priv {
+ struct cros_ec_device *cros_ec;
+ struct acpi_battery_hook battery_hook;
+ struct power_supply *hooked_battery;
+ u8 cmd_version;
+
+ /* The callbacks need to access this priv structure.
+ * As neither the struct device nor power_supply are under the drivers
+ * control, embed the attributes within priv to use with container_of().
+ */
+ struct device_attribute device_attrs[_CROS_CHCTL_ATTR_COUNT];
+ struct attribute *attributes[_CROS_CHCTL_ATTR_COUNT];
+ struct attribute_group group;
+
+ enum power_supply_charge_behaviour current_behaviour;
+ u8 current_start_threshold, current_end_threshold;
+};
+
+static int cros_chctl_send_charge_control_cmd(struct cros_ec_device *cros_ec,
+ u8 cmd_version, struct ec_params_charge_control *req)
+{
+ static const u8 outsizes[] = {
+ [1] = offsetof(struct ec_params_charge_control, cmd),
+ [2] = sizeof(struct ec_params_charge_control),
+ [3] = sizeof(struct ec_params_charge_control),
+ };
+
+ struct {
+ struct cros_ec_command msg;
+ union {
+ struct ec_params_charge_control req;
+ struct ec_response_charge_control resp;
+ } __packed data;
+ } __packed buf = {
+ .msg = {
+ .command = EC_CMD_CHARGE_CONTROL,
+ .version = cmd_version,
+ .insize = 0,
+ .outsize = outsizes[cmd_version],
+ },
+ .data.req = *req,
+ };
+
+ return cros_ec_cmd_xfer_status(cros_ec, &buf.msg);
+}
+
+static int cros_chctl_configure_ec(struct cros_chctl_priv *priv)
+{
+ struct ec_params_charge_control req = {};
+
+ req.cmd = EC_CHARGE_CONTROL_CMD_SET;
+
+ switch (priv->current_behaviour) {
+ case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO:
+ req.mode = CHARGE_CONTROL_NORMAL;
+ break;
+ case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE:
+ req.mode = CHARGE_CONTROL_IDLE;
+ break;
+ case POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE:
+ req.mode = CHARGE_CONTROL_DISCHARGE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (priv->current_behaviour == POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO &&
+ !(priv->current_start_threshold == 0 && priv->current_end_threshold == 100)) {
+ req.sustain_soc.lower = priv->current_start_threshold;
+ req.sustain_soc.upper = priv->current_end_threshold;
+ } else {
+ /* Disable charging limits */
+ req.sustain_soc.lower = -1;
+ req.sustain_soc.upper = -1;
+ }
+
+ return cros_chctl_send_charge_control_cmd(priv->cros_ec, priv->cmd_version, &req);
+}
+
+static struct cros_chctl_priv *cros_chctl_attr_to_priv(struct attribute *attr,
+ enum CROS_CHCTL_ATTR idx)
+{
+ struct device_attribute *dev_attr = container_of(attr, struct device_attribute, attr);
+
+ return container_of(dev_attr, struct cros_chctl_priv, device_attrs[idx]);
+}
+
+static ssize_t cros_chctl_store_threshold(struct device *dev, struct cros_chctl_priv *priv,
+ int is_end_threshold, const char *buf, size_t count)
+{
+ int ret, val;
+
+ ret = kstrtoint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+ if (val < 0 || val > 100)
+ return -EINVAL;
+
+ if (is_end_threshold) {
+ if (val <= priv->current_start_threshold)
+ return -EINVAL;
+ priv->current_end_threshold = val;
+ } else {
+ if (val >= priv->current_end_threshold)
+ return -EINVAL;
+ priv->current_start_threshold = val;
+ }
+
+ if (priv->current_behaviour == POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) {
+ ret = cros_chctl_configure_ec(priv);
+ if (ret < 0)
+ return ret;
+ }
+
+ return count;
+}
+
+static ssize_t charge_control_start_threshold_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
+ CROS_CHCTL_ATTR_START_THRESHOLD);
+
+ return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_start_threshold);
+}
+
+static ssize_t charge_control_start_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
+ CROS_CHCTL_ATTR_START_THRESHOLD);
+
+ return cros_chctl_store_threshold(dev, priv, 0, buf, count);
+}
+
+static ssize_t charge_control_end_threshold_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
+ CROS_CHCTL_ATTR_END_THRESHOLD);
+
+ return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_end_threshold);
+}
+
+static ssize_t charge_control_end_threshold_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
+ CROS_CHCTL_ATTR_END_THRESHOLD);
+
+ return cros_chctl_store_threshold(dev, priv, 1, buf, count);
+}
+
+static ssize_t charge_behaviour_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
+ CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR);
+
+ return power_supply_charge_behaviour_show(dev, EC_CHARGE_CONTROL_BEHAVIOURS,
+ priv->current_behaviour, buf);
+}
+
+static ssize_t charge_behaviour_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
+ CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR);
+ int ret;
+
+ ret = power_supply_charge_behaviour_parse(EC_CHARGE_CONTROL_BEHAVIOURS, buf);
+ if (ret < 0)
+ return ret;
+
+ priv->current_behaviour = ret;
+
+ ret = cros_chctl_configure_ec(priv);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static umode_t cros_chtl_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
+{
+ struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(attr, n);
+
+ if (priv->cmd_version < 2) {
+ if (n == CROS_CHCTL_ATTR_START_THRESHOLD)
+ return 0;
+ if (n == CROS_CHCTL_ATTR_END_THRESHOLD)
+ return 0;
+ }
+
+ return attr->mode;
+}
+
+static int cros_chctl_add_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
+{
+ struct cros_chctl_priv *priv = container_of(hook, struct cros_chctl_priv, battery_hook);
+
+ if (priv->hooked_battery)
+ return 0;
+
+ priv->hooked_battery = battery;
+ return device_add_group(&battery->dev, &priv->group);
+}
+
+static int cros_chctl_remove_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
+{
+ struct cros_chctl_priv *priv = container_of(hook, struct cros_chctl_priv, battery_hook);
+
+ if (priv->hooked_battery == battery) {
+ device_remove_group(&battery->dev, &priv->group);
+ priv->hooked_battery = NULL;
+ }
+
+ return 0;
+}
+
+static bool probe_with_fwk_charge_control;
+module_param(probe_with_fwk_charge_control, bool, 0644);
+MODULE_PARM_DESC(probe_with_fwk_charge_control,
+ "Probe the driver in the presence of the custom Framework EC charge control");
+
+static int cros_chctl_fwk_charge_control_versions(struct cros_ec_device *cros_ec)
+{
+ if (!dmi_match(DMI_SYS_VENDOR, "Framework"))
+ return 0;
+
+ return cros_ec_get_cmd_versions(cros_ec, 0x3E03 /* FW_EC_CMD_CHARGE_LIMIT */);
+}
+
+static int cros_chctl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
+ struct cros_ec_device *cros_ec = ec_dev->ec_dev;
+ struct cros_chctl_priv *priv;
+ size_t i;
+ int ret;
+
+ ret = cros_chctl_fwk_charge_control_versions(cros_ec);
+ if (ret < 0)
+ return ret;
+ if (ret > 0 && !probe_with_fwk_charge_control) {
+ dev_info(dev, "Framework charge control detected, preventing load\n");
+ return -ENODEV;
+ }
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ ret = cros_ec_get_cmd_versions(cros_ec, EC_CMD_CHARGE_CONTROL);
+ if (ret < 0)
+ return ret;
+ else if (ret & EC_VER_MASK(3))
+ priv->cmd_version = 3;
+ else if (ret & EC_VER_MASK(2))
+ priv->cmd_version = 2;
+ else if (ret & EC_VER_MASK(1))
+ priv->cmd_version = 1;
+ else
+ return -ENODEV;
+
+ dev_dbg(dev, "Command version: %u\n", (unsigned int)priv->cmd_version);
+
+ priv->cros_ec = cros_ec;
+ priv->device_attrs[CROS_CHCTL_ATTR_START_THRESHOLD] =
+ (struct device_attribute)__ATTR_RW(charge_control_start_threshold);
+ priv->device_attrs[CROS_CHCTL_ATTR_END_THRESHOLD] =
+ (struct device_attribute)__ATTR_RW(charge_control_end_threshold);
+ priv->device_attrs[CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR] =
+ (struct device_attribute)__ATTR_RW(charge_behaviour);
+ for (i = 0; i < _CROS_CHCTL_ATTR_COUNT; i++) {
+ sysfs_attr_init(&priv->device_attrs[i].attr);
+ priv->attributes[i] = &priv->device_attrs[i].attr;
+ }
+ priv->group.is_visible = cros_chtl_attr_is_visible;
+ priv->group.attrs = priv->attributes;
+
+ priv->battery_hook.name = dev_name(dev);
+ priv->battery_hook.add_battery = cros_chctl_add_battery;
+ priv->battery_hook.remove_battery = cros_chctl_remove_battery;
+
+ priv->current_behaviour = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
+ priv->current_start_threshold = 0;
+ priv->current_end_threshold = 100;
+
+ /* Bring EC into well-known state */
+ ret = cros_chctl_configure_ec(priv);
+ if (ret < 0)
+ return ret;
+
+ return devm_battery_hook_register(dev, &priv->battery_hook);
+}
+
+static const struct platform_device_id cros_chctl_id[] = {
+ { "cros-charge-control", 0 },
+ {}
+};
+
+static struct platform_driver cros_chctl_driver = {
+ .driver.name = "cros-charge-control",
+ .probe = cros_chctl_probe,
+ .id_table = cros_chctl_id,
+};
+module_platform_driver(cros_chctl_driver);
+
+MODULE_DEVICE_TABLE(platform, cros_chctl_id);
+MODULE_DESCRIPTION("ChromeOS EC charge control");
+MODULE_AUTHOR("Thomas Weißschuh <[email protected]>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ptp/ptp_vmw.c b/drivers/ptp/ptp_vmw.c
index 7ec90359428a..20ab05c4daa8 100644
--- a/drivers/ptp/ptp_vmw.c
+++ b/drivers/ptp/ptp_vmw.c
@@ -14,7 +14,6 @@
#include <asm/hypervisor.h>
#include <asm/vmware.h>
-#define VMWARE_MAGIC 0x564D5868
#define VMWARE_CMD_PCLK(nr) ((nr << 16) | 97)
#define VMWARE_CMD_PCLK_GETTIME VMWARE_CMD_PCLK(0)
@@ -24,15 +23,10 @@ static struct ptp_clock *ptp_vmw_clock;
static int ptp_vmw_pclk_read(u64 *ns)
{
- u32 ret, nsec_hi, nsec_lo, unused1, unused2, unused3;
-
- asm volatile (VMWARE_HYPERCALL :
- "=a"(ret), "=b"(nsec_hi), "=c"(nsec_lo), "=d"(unused1),
- "=S"(unused2), "=D"(unused3) :
- "a"(VMWARE_MAGIC), "b"(0),
- "c"(VMWARE_CMD_PCLK_GETTIME), "d"(0) :
- "memory");
+ u32 ret, nsec_hi, nsec_lo;
+ ret = vmware_hypercall3(VMWARE_CMD_PCLK_GETTIME, 0,
+ &nsec_hi, &nsec_lo);
if (ret == 0)
*ns = ((u64)nsec_hi << 32) | nsec_lo;
return ret;
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 1dd7921194f5..3e53838990f5 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -94,6 +94,19 @@ config PWM_ATMEL_TCB
To compile this driver as a module, choose M here: the module
will be called pwm-atmel-tcb.
+config PWM_AXI_PWMGEN
+ tristate "Analog Devices AXI PWM generator"
+ depends on MICROBLAZE || NIOS2 || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_INTEL_SOCFPGA || COMPILE_TEST
+ select REGMAP_MMIO
+ help
+ This enables support for the Analog Devices AXI PWM generator.
+
+ This is a configurable PWM generator with variable pulse width and
+ period.
+
+ To compile this driver as a module, choose M here: the module will be
+ called pwm-axi-pwmgen.
+
config PWM_BCM_IPROC
tristate "iProc PWM support"
depends on ARCH_BCM_IPROC || COMPILE_TEST
@@ -223,6 +236,17 @@ config PWM_FSL_FTM
To compile this driver as a module, choose M here: the module
will be called pwm-fsl-ftm.
+config PWM_GPIO
+ tristate "GPIO PWM support"
+ depends on GPIOLIB
+ depends on HIGH_RES_TIMERS
+ help
+ Generic PWM framework driver for software PWM toggling a GPIO pin
+ from kernel high-resolution timers.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-gpio.
+
config PWM_HIBVT
tristate "HiSilicon BVT PWM support"
depends on ARCH_HISI || COMPILE_TEST
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 90913519f11a..0be4f3e6dd43 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_PWM_APPLE) += pwm-apple.o
obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o
obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o
+obj-$(CONFIG_PWM_AXI_PWMGEN) += pwm-axi-pwmgen.o
obj-$(CONFIG_PWM_BCM_IPROC) += pwm-bcm-iproc.o
obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o
obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o
@@ -18,6 +19,7 @@ obj-$(CONFIG_PWM_DWC_CORE) += pwm-dwc-core.o
obj-$(CONFIG_PWM_DWC) += pwm-dwc.o
obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o
+obj-$(CONFIG_PWM_GPIO) += pwm-gpio.o
obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o
obj-$(CONFIG_PWM_IMG) += pwm-img.o
obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 18574857641e..8acbcf5b6673 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -6,6 +6,8 @@
* Copyright (C) 2011-2012 Avionic Design GmbH
*/
+#define DEFAULT_SYMBOL_NAMESPACE PWM
+
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/idr.h>
@@ -135,6 +137,25 @@ static void pwm_apply_debug(struct pwm_device *pwm,
}
}
+static bool pwm_state_valid(const struct pwm_state *state)
+{
+ /*
+ * For a disabled state all other state description is irrelevant and
+ * and supposed to be ignored. So also ignore any strange values and
+ * consider the state ok.
+ */
+ if (state->enabled)
+ return true;
+
+ if (!state->period)
+ return false;
+
+ if (state->duty_cycle > state->period)
+ return false;
+
+ return true;
+}
+
/**
* __pwm_apply() - atomically apply a new state to a PWM device
* @pwm: PWM device
@@ -145,9 +166,25 @@ static int __pwm_apply(struct pwm_device *pwm, const struct pwm_state *state)
struct pwm_chip *chip;
int err;
- if (!pwm || !state || !state->period ||
- state->duty_cycle > state->period)
+ if (!pwm || !state)
+ return -EINVAL;
+
+ if (!pwm_state_valid(state)) {
+ /*
+ * Allow to transition from one invalid state to another.
+ * This ensures that you can e.g. change the polarity while
+ * the period is zero. (This happens on stm32 when the hardware
+ * is in its poweron default state.) This greatly simplifies
+ * working with the sysfs API where you can only change one
+ * parameter at a time.
+ */
+ if (!pwm_state_valid(&pwm->state)) {
+ pwm->state = *state;
+ return 0;
+ }
+
return -EINVAL;
+ }
chip = pwm->chip;
@@ -291,19 +328,15 @@ EXPORT_SYMBOL_GPL(pwm_adjust_config);
int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
unsigned long timeout)
{
- int err;
-
if (!pwm || !pwm->chip->ops)
return -EINVAL;
if (!pwm->chip->ops->capture)
return -ENOSYS;
- mutex_lock(&pwm_lock);
- err = pwm->chip->ops->capture(pwm->chip, pwm, result, timeout);
- mutex_unlock(&pwm_lock);
+ guard(mutex)(&pwm_lock);
- return err;
+ return pwm->chip->ops->capture(pwm->chip, pwm, result, timeout);
}
EXPORT_SYMBOL_GPL(pwm_capture);
@@ -315,19 +348,15 @@ static struct pwm_chip *pwmchip_find_by_name(const char *name)
if (!name)
return NULL;
- mutex_lock(&pwm_lock);
+ guard(mutex)(&pwm_lock);
idr_for_each_entry_ul(&pwm_chips, chip, tmp, id) {
const char *chip_name = dev_name(pwmchip_parent(chip));
- if (chip_name && strcmp(chip_name, name) == 0) {
- mutex_unlock(&pwm_lock);
+ if (chip_name && strcmp(chip_name, name) == 0)
return chip;
- }
}
- mutex_unlock(&pwm_lock);
-
return NULL;
}
@@ -394,9 +423,9 @@ err_get_device:
* chip. A negative error code is returned if the index is not valid for the
* specified PWM chip or if the PWM device cannot be requested.
*/
-struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
- unsigned int index,
- const char *label)
+static struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
+ unsigned int index,
+ const char *label)
{
struct pwm_device *pwm;
int err;
@@ -404,18 +433,16 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
if (!chip || index >= chip->npwm)
return ERR_PTR(-EINVAL);
- mutex_lock(&pwm_lock);
+ guard(mutex)(&pwm_lock);
+
pwm = &chip->pwms[index];
err = pwm_device_request(pwm, label);
if (err < 0)
- pwm = ERR_PTR(err);
+ return ERR_PTR(err);
- mutex_unlock(&pwm_lock);
return pwm;
}
-EXPORT_SYMBOL_GPL(pwm_request_from_chip);
-
struct pwm_device *
of_pwm_xlate_with_flags(struct pwm_chip *chip, const struct of_phandle_args *args)
@@ -511,11 +538,11 @@ static ssize_t period_store(struct device *pwm_dev,
if (ret)
return ret;
- mutex_lock(&export->lock);
+ guard(mutex)(&export->lock);
+
pwm_get_state(pwm, &state);
state.period = val;
ret = pwm_apply_might_sleep(pwm, &state);
- mutex_unlock(&export->lock);
return ret ? : size;
}
@@ -546,11 +573,11 @@ static ssize_t duty_cycle_store(struct device *pwm_dev,
if (ret)
return ret;
- mutex_lock(&export->lock);
+ guard(mutex)(&export->lock);
+
pwm_get_state(pwm, &state);
state.duty_cycle = val;
ret = pwm_apply_might_sleep(pwm, &state);
- mutex_unlock(&export->lock);
return ret ? : size;
}
@@ -580,7 +607,7 @@ static ssize_t enable_store(struct device *pwm_dev,
if (ret)
return ret;
- mutex_lock(&export->lock);
+ guard(mutex)(&export->lock);
pwm_get_state(pwm, &state);
@@ -592,14 +619,11 @@ static ssize_t enable_store(struct device *pwm_dev,
state.enabled = true;
break;
default:
- ret = -EINVAL;
- goto unlock;
+ return -EINVAL;
}
ret = pwm_apply_might_sleep(pwm, &state);
-unlock:
- mutex_unlock(&export->lock);
return ret ? : size;
}
@@ -643,11 +667,11 @@ static ssize_t polarity_store(struct device *pwm_dev,
else
return -EINVAL;
- mutex_lock(&export->lock);
+ guard(mutex)(&export->lock);
+
pwm_get_state(pwm, &state);
state.polarity = polarity;
ret = pwm_apply_might_sleep(pwm, &state);
- mutex_unlock(&export->lock);
return ret ? : size;
}
@@ -1102,11 +1126,11 @@ int __pwmchip_add(struct pwm_chip *chip, struct module *owner)
chip->owner = owner;
- mutex_lock(&pwm_lock);
+ guard(mutex)(&pwm_lock);
ret = idr_alloc(&pwm_chips, chip, 0, 0, GFP_KERNEL);
if (ret < 0)
- goto err_idr_alloc;
+ return ret;
chip->id = ret;
@@ -1119,8 +1143,6 @@ int __pwmchip_add(struct pwm_chip *chip, struct module *owner)
if (ret)
goto err_device_add;
- mutex_unlock(&pwm_lock);
-
return 0;
err_device_add:
@@ -1128,9 +1150,6 @@ err_device_add:
of_pwmchip_remove(chip);
idr_remove(&pwm_chips, chip->id);
-err_idr_alloc:
-
- mutex_unlock(&pwm_lock);
return ret;
}
@@ -1149,11 +1168,8 @@ void pwmchip_remove(struct pwm_chip *chip)
if (IS_ENABLED(CONFIG_OF))
of_pwmchip_remove(chip);
- mutex_lock(&pwm_lock);
-
- idr_remove(&pwm_chips, chip->id);
-
- mutex_unlock(&pwm_lock);
+ scoped_guard(mutex, &pwm_lock)
+ idr_remove(&pwm_chips, chip->id);
device_del(&chip->dev);
}
@@ -1209,15 +1225,11 @@ static struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode)
struct pwm_chip *chip;
unsigned long id, tmp;
- mutex_lock(&pwm_lock);
+ guard(mutex)(&pwm_lock);
idr_for_each_entry_ul(&pwm_chips, chip, tmp, id)
- if (pwmchip_parent(chip) && device_match_fwnode(pwmchip_parent(chip), fwnode)) {
- mutex_unlock(&pwm_lock);
+ if (pwmchip_parent(chip) && device_match_fwnode(pwmchip_parent(chip), fwnode))
return chip;
- }
-
- mutex_unlock(&pwm_lock);
return ERR_PTR(-EPROBE_DEFER);
}
@@ -1366,14 +1378,12 @@ static LIST_HEAD(pwm_lookup_list);
*/
void pwm_add_table(struct pwm_lookup *table, size_t num)
{
- mutex_lock(&pwm_lookup_lock);
+ guard(mutex)(&pwm_lookup_lock);
while (num--) {
list_add_tail(&table->list, &pwm_lookup_list);
table++;
}
-
- mutex_unlock(&pwm_lookup_lock);
}
/**
@@ -1383,14 +1393,12 @@ void pwm_add_table(struct pwm_lookup *table, size_t num)
*/
void pwm_remove_table(struct pwm_lookup *table, size_t num)
{
- mutex_lock(&pwm_lookup_lock);
+ guard(mutex)(&pwm_lookup_lock);
while (num--) {
list_del(&table->list);
table++;
}
-
- mutex_unlock(&pwm_lookup_lock);
}
/**
@@ -1451,36 +1459,33 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
* Then we take the most specific entry - with the following order
* of precedence: dev+con > dev only > con only.
*/
- mutex_lock(&pwm_lookup_lock);
-
- list_for_each_entry(p, &pwm_lookup_list, list) {
- match = 0;
+ scoped_guard(mutex, &pwm_lookup_lock)
+ list_for_each_entry(p, &pwm_lookup_list, list) {
+ match = 0;
- if (p->dev_id) {
- if (!dev_id || strcmp(p->dev_id, dev_id))
- continue;
+ if (p->dev_id) {
+ if (!dev_id || strcmp(p->dev_id, dev_id))
+ continue;
- match += 2;
- }
+ match += 2;
+ }
- if (p->con_id) {
- if (!con_id || strcmp(p->con_id, con_id))
- continue;
+ if (p->con_id) {
+ if (!con_id || strcmp(p->con_id, con_id))
+ continue;
- match += 1;
- }
+ match += 1;
+ }
- if (match > best) {
- chosen = p;
+ if (match > best) {
+ chosen = p;
- if (match != 3)
- best = match;
- else
- break;
+ if (match != 3)
+ best = match;
+ else
+ break;
+ }
}
- }
-
- mutex_unlock(&pwm_lookup_lock);
if (!chosen)
return ERR_PTR(-ENODEV);
@@ -1532,11 +1537,11 @@ void pwm_put(struct pwm_device *pwm)
chip = pwm->chip;
- mutex_lock(&pwm_lock);
+ guard(mutex)(&pwm_lock);
if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) {
pr_warn("PWM device already freed\n");
- goto out;
+ return;
}
if (chip->ops->free)
@@ -1547,8 +1552,6 @@ void pwm_put(struct pwm_device *pwm)
put_device(&chip->dev);
module_put(chip->owner);
-out:
- mutex_unlock(&pwm_lock);
}
EXPORT_SYMBOL_GPL(pwm_put);
@@ -1705,9 +1708,17 @@ DEFINE_SEQ_ATTRIBUTE(pwm_debugfs);
static int __init pwm_init(void)
{
+ int ret;
+
+ ret = class_register(&pwm_class);
+ if (ret) {
+ pr_err("Failed to initialize PWM class (%pe)\n", ERR_PTR(ret));
+ return ret;
+ }
+
if (IS_ENABLED(CONFIG_DEBUG_FS))
debugfs_create_file("pwm", 0444, NULL, NULL, &pwm_debugfs_fops);
- return class_register(&pwm_class);
+ return 0;
}
subsys_initcall(pwm_init);
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
index 528e54c5999d..f9a9c12cbcdd 100644
--- a/drivers/pwm/pwm-atmel-tcb.c
+++ b/drivers/pwm/pwm-atmel-tcb.c
@@ -81,7 +81,8 @@ static int atmel_tcb_pwm_request(struct pwm_chip *chip,
tcbpwm->period = 0;
tcbpwm->div = 0;
- spin_lock(&tcbpwmc->lock);
+ guard(spinlock)(&tcbpwmc->lock);
+
regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr);
/*
* Get init config from Timer Counter registers if
@@ -107,7 +108,6 @@ static int atmel_tcb_pwm_request(struct pwm_chip *chip,
cmr |= ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO | ATMEL_TC_EEVT_XC0;
regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), cmr);
- spin_unlock(&tcbpwmc->lock);
return 0;
}
@@ -137,7 +137,6 @@ static void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm,
if (tcbpwm->duty == 0)
polarity = !polarity;
- spin_lock(&tcbpwmc->lock);
regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr);
/* flush old setting and set the new one */
@@ -172,8 +171,6 @@ static void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm,
ATMEL_TC_SWTRG);
tcbpwmc->bkup.enabled = 0;
}
-
- spin_unlock(&tcbpwmc->lock);
}
static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -194,7 +191,6 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm,
if (tcbpwm->duty == 0)
polarity = !polarity;
- spin_lock(&tcbpwmc->lock);
regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr);
/* flush old setting and set the new one */
@@ -256,7 +252,6 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm,
regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CCR),
ATMEL_TC_SWTRG | ATMEL_TC_CLKEN);
tcbpwmc->bkup.enabled = 1;
- spin_unlock(&tcbpwmc->lock);
return 0;
}
@@ -265,7 +260,8 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
{
struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
struct atmel_tcb_pwm_device *tcbpwm = &tcbpwmc->pwms[pwm->hwpwm];
- struct atmel_tcb_pwm_device *atcbpwm = NULL;
+ /* companion PWM sharing register values period and div */
+ struct atmel_tcb_pwm_device *atcbpwm = &tcbpwmc->pwms[pwm->hwpwm ^ 1];
int i = 0;
int slowclk = 0;
unsigned period;
@@ -310,11 +306,6 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
duty = div_u64(duty_ns, min);
period = div_u64(period_ns, min);
- if (pwm->hwpwm == 0)
- atcbpwm = &tcbpwmc->pwms[1];
- else
- atcbpwm = &tcbpwmc->pwms[0];
-
/*
* PWM devices provided by the TCB driver are grouped by 2.
* PWM devices in a given group must be configured with the
@@ -323,8 +314,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
* We're checking the period value of the second PWM device
* in this group before applying the new config.
*/
- if ((atcbpwm && atcbpwm->duty > 0 &&
- atcbpwm->duty != atcbpwm->period) &&
+ if ((atcbpwm->duty > 0 && atcbpwm->duty != atcbpwm->period) &&
(atcbpwm->div != i || atcbpwm->period != period)) {
dev_err(pwmchip_parent(chip),
"failed to configure period_ns: PWM group already configured with a different value\n");
@@ -341,9 +331,12 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
static int atmel_tcb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
+ struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
int duty_cycle, period;
int ret;
+ guard(spinlock)(&tcbpwmc->lock);
+
if (!state->enabled) {
atmel_tcb_pwm_disable(chip, pwm, state->polarity);
return 0;
@@ -389,17 +382,17 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
{
struct pwm_chip *chip;
const struct of_device_id *match;
- struct atmel_tcb_pwm_chip *tcbpwm;
+ struct atmel_tcb_pwm_chip *tcbpwmc;
const struct atmel_tcb_config *config;
struct device_node *np = pdev->dev.of_node;
char clk_name[] = "t0_clk";
int err;
int channel;
- chip = devm_pwmchip_alloc(&pdev->dev, NPWM, sizeof(*tcbpwm));
+ chip = devm_pwmchip_alloc(&pdev->dev, NPWM, sizeof(*tcbpwmc));
if (IS_ERR(chip))
return PTR_ERR(chip);
- tcbpwm = to_tcb_chip(chip);
+ tcbpwmc = to_tcb_chip(chip);
err = of_property_read_u32(np, "reg", &channel);
if (err < 0) {
@@ -409,20 +402,20 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
return err;
}
- tcbpwm->regmap = syscon_node_to_regmap(np->parent);
- if (IS_ERR(tcbpwm->regmap))
- return PTR_ERR(tcbpwm->regmap);
+ tcbpwmc->regmap = syscon_node_to_regmap(np->parent);
+ if (IS_ERR(tcbpwmc->regmap))
+ return PTR_ERR(tcbpwmc->regmap);
- tcbpwm->slow_clk = of_clk_get_by_name(np->parent, "slow_clk");
- if (IS_ERR(tcbpwm->slow_clk))
- return PTR_ERR(tcbpwm->slow_clk);
+ tcbpwmc->slow_clk = of_clk_get_by_name(np->parent, "slow_clk");
+ if (IS_ERR(tcbpwmc->slow_clk))
+ return PTR_ERR(tcbpwmc->slow_clk);
clk_name[1] += channel;
- tcbpwm->clk = of_clk_get_by_name(np->parent, clk_name);
- if (IS_ERR(tcbpwm->clk))
- tcbpwm->clk = of_clk_get_by_name(np->parent, "t0_clk");
- if (IS_ERR(tcbpwm->clk)) {
- err = PTR_ERR(tcbpwm->clk);
+ tcbpwmc->clk = of_clk_get_by_name(np->parent, clk_name);
+ if (IS_ERR(tcbpwmc->clk))
+ tcbpwmc->clk = of_clk_get_by_name(np->parent, "t0_clk");
+ if (IS_ERR(tcbpwmc->clk)) {
+ err = PTR_ERR(tcbpwmc->clk);
goto err_slow_clk;
}
@@ -430,22 +423,22 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
config = match->data;
if (config->has_gclk) {
- tcbpwm->gclk = of_clk_get_by_name(np->parent, "gclk");
- if (IS_ERR(tcbpwm->gclk)) {
- err = PTR_ERR(tcbpwm->gclk);
+ tcbpwmc->gclk = of_clk_get_by_name(np->parent, "gclk");
+ if (IS_ERR(tcbpwmc->gclk)) {
+ err = PTR_ERR(tcbpwmc->gclk);
goto err_clk;
}
}
chip->ops = &atmel_tcb_pwm_ops;
- tcbpwm->channel = channel;
- tcbpwm->width = config->counter_width;
+ tcbpwmc->channel = channel;
+ tcbpwmc->width = config->counter_width;
- err = clk_prepare_enable(tcbpwm->slow_clk);
+ err = clk_prepare_enable(tcbpwmc->slow_clk);
if (err)
goto err_gclk;
- spin_lock_init(&tcbpwm->lock);
+ spin_lock_init(&tcbpwmc->lock);
err = pwmchip_add(chip);
if (err < 0)
@@ -456,16 +449,16 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
return 0;
err_disable_clk:
- clk_disable_unprepare(tcbpwm->slow_clk);
+ clk_disable_unprepare(tcbpwmc->slow_clk);
err_gclk:
- clk_put(tcbpwm->gclk);
+ clk_put(tcbpwmc->gclk);
err_clk:
- clk_put(tcbpwm->clk);
+ clk_put(tcbpwmc->clk);
err_slow_clk:
- clk_put(tcbpwm->slow_clk);
+ clk_put(tcbpwmc->slow_clk);
return err;
}
@@ -473,14 +466,14 @@ err_slow_clk:
static void atmel_tcb_pwm_remove(struct platform_device *pdev)
{
struct pwm_chip *chip = platform_get_drvdata(pdev);
- struct atmel_tcb_pwm_chip *tcbpwm = to_tcb_chip(chip);
+ struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
pwmchip_remove(chip);
- clk_disable_unprepare(tcbpwm->slow_clk);
- clk_put(tcbpwm->gclk);
- clk_put(tcbpwm->clk);
- clk_put(tcbpwm->slow_clk);
+ clk_disable_unprepare(tcbpwmc->slow_clk);
+ clk_put(tcbpwmc->gclk);
+ clk_put(tcbpwmc->clk);
+ clk_put(tcbpwmc->slow_clk);
}
static const struct of_device_id atmel_tcb_pwm_dt_ids[] = {
@@ -492,14 +485,14 @@ MODULE_DEVICE_TABLE(of, atmel_tcb_pwm_dt_ids);
static int atmel_tcb_pwm_suspend(struct device *dev)
{
struct pwm_chip *chip = dev_get_drvdata(dev);
- struct atmel_tcb_pwm_chip *tcbpwm = to_tcb_chip(chip);
- struct atmel_tcb_channel *chan = &tcbpwm->bkup;
- unsigned int channel = tcbpwm->channel;
+ struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
+ struct atmel_tcb_channel *chan = &tcbpwmc->bkup;
+ unsigned int channel = tcbpwmc->channel;
- regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, CMR), &chan->cmr);
- regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, RA), &chan->ra);
- regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, RB), &chan->rb);
- regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, RC), &chan->rc);
+ regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(channel, CMR), &chan->cmr);
+ regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(channel, RA), &chan->ra);
+ regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(channel, RB), &chan->rb);
+ regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(channel, RC), &chan->rc);
return 0;
}
@@ -507,17 +500,17 @@ static int atmel_tcb_pwm_suspend(struct device *dev)
static int atmel_tcb_pwm_resume(struct device *dev)
{
struct pwm_chip *chip = dev_get_drvdata(dev);
- struct atmel_tcb_pwm_chip *tcbpwm = to_tcb_chip(chip);
- struct atmel_tcb_channel *chan = &tcbpwm->bkup;
- unsigned int channel = tcbpwm->channel;
+ struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
+ struct atmel_tcb_channel *chan = &tcbpwmc->bkup;
+ unsigned int channel = tcbpwmc->channel;
- regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, CMR), chan->cmr);
- regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, RA), chan->ra);
- regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, RB), chan->rb);
- regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, RC), chan->rc);
+ regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(channel, CMR), chan->cmr);
+ regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(channel, RA), chan->ra);
+ regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(channel, RB), chan->rb);
+ regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(channel, RC), chan->rc);
if (chan->enabled)
- regmap_write(tcbpwm->regmap,
+ regmap_write(tcbpwmc->regmap,
ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
ATMEL_TC_REG(channel, CCR));
diff --git a/drivers/pwm/pwm-axi-pwmgen.c b/drivers/pwm/pwm-axi-pwmgen.c
new file mode 100644
index 000000000000..3ad60edf20a5
--- /dev/null
+++ b/drivers/pwm/pwm-axi-pwmgen.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Analog Devices AXI PWM generator
+ *
+ * Copyright 2024 Analog Devices Inc.
+ * Copyright 2024 Baylibre SAS
+ *
+ * Device docs: https://analogdevicesinc.github.io/hdl/library/axi_pwm_gen/index.html
+ *
+ * Limitations:
+ * - The writes to registers for period and duty are shadowed until
+ * LOAD_CONFIG is written to AXI_PWMGEN_REG_CONFIG, at which point
+ * they take effect.
+ * - Writing LOAD_CONFIG also has the effect of re-synchronizing all
+ * enabled channels, which could cause glitching on other channels. It
+ * is therefore expected that channels are assigned harmonic periods
+ * and all have a single user coordinating this.
+ * - Supports normal polarity. Does not support changing polarity.
+ * - On disable, the PWM output becomes low (inactive).
+ */
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/fpga/adi-axi-common.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define AXI_PWMGEN_REG_CORE_VERSION 0x00
+#define AXI_PWMGEN_REG_ID 0x04
+#define AXI_PWMGEN_REG_SCRATCHPAD 0x08
+#define AXI_PWMGEN_REG_CORE_MAGIC 0x0C
+#define AXI_PWMGEN_REG_CONFIG 0x10
+#define AXI_PWMGEN_REG_NPWM 0x14
+#define AXI_PWMGEN_CHX_PERIOD(ch) (0x40 + (4 * (ch)))
+#define AXI_PWMGEN_CHX_DUTY(ch) (0x80 + (4 * (ch)))
+#define AXI_PWMGEN_CHX_OFFSET(ch) (0xC0 + (4 * (ch)))
+#define AXI_PWMGEN_REG_CORE_MAGIC_VAL 0x601A3471 /* Identification number to test during setup */
+#define AXI_PWMGEN_LOAD_CONFIG BIT(1)
+#define AXI_PWMGEN_REG_CONFIG_RESET BIT(0)
+
+struct axi_pwmgen_ddata {
+ struct regmap *regmap;
+ unsigned long clk_rate_hz;
+};
+
+static const struct regmap_config axi_pwmgen_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xFC,
+};
+
+static int axi_pwmgen_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct axi_pwmgen_ddata *ddata = pwmchip_get_drvdata(chip);
+ unsigned int ch = pwm->hwpwm;
+ struct regmap *regmap = ddata->regmap;
+ u64 period_cnt, duty_cnt;
+ int ret;
+
+ if (state->polarity != PWM_POLARITY_NORMAL)
+ return -EINVAL;
+
+ if (state->enabled) {
+ period_cnt = mul_u64_u64_div_u64(state->period, ddata->clk_rate_hz, NSEC_PER_SEC);
+ if (period_cnt > UINT_MAX)
+ period_cnt = UINT_MAX;
+
+ if (period_cnt == 0)
+ return -EINVAL;
+
+ ret = regmap_write(regmap, AXI_PWMGEN_CHX_PERIOD(ch), period_cnt);
+ if (ret)
+ return ret;
+
+ duty_cnt = mul_u64_u64_div_u64(state->duty_cycle, ddata->clk_rate_hz, NSEC_PER_SEC);
+ if (duty_cnt > UINT_MAX)
+ duty_cnt = UINT_MAX;
+
+ ret = regmap_write(regmap, AXI_PWMGEN_CHX_DUTY(ch), duty_cnt);
+ if (ret)
+ return ret;
+ } else {
+ ret = regmap_write(regmap, AXI_PWMGEN_CHX_PERIOD(ch), 0);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(regmap, AXI_PWMGEN_CHX_DUTY(ch), 0);
+ if (ret)
+ return ret;
+ }
+
+ return regmap_write(regmap, AXI_PWMGEN_REG_CONFIG, AXI_PWMGEN_LOAD_CONFIG);
+}
+
+static int axi_pwmgen_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct axi_pwmgen_ddata *ddata = pwmchip_get_drvdata(chip);
+ struct regmap *regmap = ddata->regmap;
+ unsigned int ch = pwm->hwpwm;
+ u32 cnt;
+ int ret;
+
+ ret = regmap_read(regmap, AXI_PWMGEN_CHX_PERIOD(ch), &cnt);
+ if (ret)
+ return ret;
+
+ state->enabled = cnt != 0;
+
+ state->period = DIV_ROUND_UP_ULL((u64)cnt * NSEC_PER_SEC, ddata->clk_rate_hz);
+
+ ret = regmap_read(regmap, AXI_PWMGEN_CHX_DUTY(ch), &cnt);
+ if (ret)
+ return ret;
+
+ state->duty_cycle = DIV_ROUND_UP_ULL((u64)cnt * NSEC_PER_SEC, ddata->clk_rate_hz);
+
+ state->polarity = PWM_POLARITY_NORMAL;
+
+ return 0;
+}
+
+static const struct pwm_ops axi_pwmgen_pwm_ops = {
+ .apply = axi_pwmgen_apply,
+ .get_state = axi_pwmgen_get_state,
+};
+
+static int axi_pwmgen_setup(struct regmap *regmap, struct device *dev)
+{
+ int ret;
+ u32 val;
+
+ ret = regmap_read(regmap, AXI_PWMGEN_REG_CORE_MAGIC, &val);
+ if (ret)
+ return ret;
+
+ if (val != AXI_PWMGEN_REG_CORE_MAGIC_VAL)
+ return dev_err_probe(dev, -ENODEV,
+ "failed to read expected value from register: got %08x, expected %08x\n",
+ val, AXI_PWMGEN_REG_CORE_MAGIC_VAL);
+
+ ret = regmap_read(regmap, AXI_PWMGEN_REG_CORE_VERSION, &val);
+ if (ret)
+ return ret;
+
+ if (ADI_AXI_PCORE_VER_MAJOR(val) != 2) {
+ return dev_err_probe(dev, -ENODEV, "Unsupported peripheral version %u.%u.%u\n",
+ ADI_AXI_PCORE_VER_MAJOR(val),
+ ADI_AXI_PCORE_VER_MINOR(val),
+ ADI_AXI_PCORE_VER_PATCH(val));
+ }
+
+ /* Enable the core */
+ ret = regmap_clear_bits(regmap, AXI_PWMGEN_REG_CONFIG, AXI_PWMGEN_REG_CONFIG_RESET);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(regmap, AXI_PWMGEN_REG_NPWM, &val);
+ if (ret)
+ return ret;
+
+ /* Return the number of PWMs */
+ return val;
+}
+
+static int axi_pwmgen_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+ struct pwm_chip *chip;
+ struct axi_pwmgen_ddata *ddata;
+ struct clk *clk;
+ void __iomem *io_base;
+ int ret;
+
+ io_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(io_base))
+ return PTR_ERR(io_base);
+
+ regmap = devm_regmap_init_mmio(dev, io_base, &axi_pwmgen_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "failed to init register map\n");
+
+ ret = axi_pwmgen_setup(regmap, dev);
+ if (ret < 0)
+ return ret;
+
+ chip = devm_pwmchip_alloc(dev, ret, sizeof(*ddata));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ ddata = pwmchip_get_drvdata(chip);
+ ddata->regmap = regmap;
+
+ clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk), "failed to get clock\n");
+
+ ret = devm_clk_rate_exclusive_get(dev, clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get exclusive rate\n");
+
+ ddata->clk_rate_hz = clk_get_rate(clk);
+ if (!ddata->clk_rate_hz || ddata->clk_rate_hz > NSEC_PER_SEC)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid clock rate: %lu\n", ddata->clk_rate_hz);
+
+ chip->ops = &axi_pwmgen_pwm_ops;
+ chip->atomic = true;
+
+ ret = devm_pwmchip_add(dev, chip);
+ if (ret)
+ return dev_err_probe(dev, ret, "could not add PWM chip\n");
+
+ return 0;
+}
+
+static const struct of_device_id axi_pwmgen_ids[] = {
+ { .compatible = "adi,axi-pwmgen-2.00.a" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, axi_pwmgen_ids);
+
+static struct platform_driver axi_pwmgen_driver = {
+ .driver = {
+ .name = "axi-pwmgen",
+ .of_match_table = axi_pwmgen_ids,
+ },
+ .probe = axi_pwmgen_probe,
+};
+module_platform_driver(axi_pwmgen_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergiu Cuciurean <[email protected]>");
+MODULE_AUTHOR("Trevor Gamblin <[email protected]>");
+MODULE_DESCRIPTION("Driver for the Analog Devices AXI PWM generator");
diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c
index 606ccfdaf4cc..189301dc395e 100644
--- a/drivers/pwm/pwm-cros-ec.c
+++ b/drivers/pwm/pwm-cros-ec.c
@@ -20,20 +20,10 @@
*
* @ec: Pointer to EC device
* @use_pwm_type: Use PWM types instead of generic channels
- * @channel: array with per-channel data
*/
struct cros_ec_pwm_device {
struct cros_ec_device *ec;
bool use_pwm_type;
- struct cros_ec_pwm *channel;
-};
-
-/**
- * struct cros_ec_pwm - per-PWM driver data
- * @duty_cycle: cached duty cycle
- */
-struct cros_ec_pwm {
- u16 duty_cycle;
};
static inline struct cros_ec_pwm_device *pwm_to_cros_ec_pwm(struct pwm_chip *chip)
@@ -135,7 +125,6 @@ static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
- struct cros_ec_pwm *channel = &ec_pwm->channel[pwm->hwpwm];
u16 duty_cycle;
int ret;
@@ -156,8 +145,6 @@ static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (ret < 0)
return ret;
- channel->duty_cycle = state->duty_cycle;
-
return 0;
}
@@ -165,7 +152,6 @@ static int cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
- struct cros_ec_pwm *channel = &ec_pwm->channel[pwm->hwpwm];
int ret;
ret = cros_ec_pwm_get_duty(ec_pwm->ec, ec_pwm->use_pwm_type, pwm->hwpwm);
@@ -175,44 +161,13 @@ static int cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
}
state->enabled = (ret > 0);
+ state->duty_cycle = ret;
state->period = EC_PWM_MAX_DUTY;
state->polarity = PWM_POLARITY_NORMAL;
- /*
- * Note that "disabled" and "duty cycle == 0" are treated the same. If
- * the cached duty cycle is not zero, used the cached duty cycle. This
- * ensures that the configured duty cycle is kept across a disable and
- * enable operation and avoids potentially confusing consumers.
- *
- * For the case of the initial hardware readout, channel->duty_cycle
- * will be 0 and the actual duty cycle read from the EC is used.
- */
- if (ret == 0 && channel->duty_cycle > 0)
- state->duty_cycle = channel->duty_cycle;
- else
- state->duty_cycle = ret;
-
return 0;
}
-static struct pwm_device *
-cros_ec_pwm_xlate(struct pwm_chip *chip, const struct of_phandle_args *args)
-{
- struct pwm_device *pwm;
-
- if (args->args[0] >= chip->npwm)
- return ERR_PTR(-EINVAL);
-
- pwm = pwm_request_from_chip(chip, args->args[0], NULL);
- if (IS_ERR(pwm))
- return pwm;
-
- /* The EC won't let us change the period */
- pwm->args.period = EC_PWM_MAX_DUTY;
-
- return pwm;
-}
-
static const struct pwm_ops cros_ec_pwm_ops = {
.get_state = cros_ec_pwm_get_state,
.apply = cros_ec_pwm_apply,
@@ -263,7 +218,7 @@ static int cros_ec_pwm_probe(struct platform_device *pdev)
struct cros_ec_pwm_device *ec_pwm;
struct pwm_chip *chip;
bool use_pwm_type = false;
- unsigned int npwm;
+ unsigned int i, npwm;
int ret;
if (!ec)
@@ -289,12 +244,17 @@ static int cros_ec_pwm_probe(struct platform_device *pdev)
/* PWM chip */
chip->ops = &cros_ec_pwm_ops;
- chip->of_xlate = cros_ec_pwm_xlate;
- ec_pwm->channel = devm_kcalloc(dev, chip->npwm, sizeof(*ec_pwm->channel),
- GFP_KERNEL);
- if (!ec_pwm->channel)
- return -ENOMEM;
+ /*
+ * The device tree binding for this device is special as it only uses a
+ * single cell (for the hwid) and so doesn't provide a default period.
+ * This isn't a big problem though as the hardware only supports a
+ * single period length, it's just a bit ugly to make this fit into the
+ * pwm core abstractions. So initialize the period here, as
+ * of_pwm_xlate_with_flags() won't do that for us.
+ */
+ for (i = 0; i < npwm; ++i)
+ chip->pwms[i].args.period = EC_PWM_MAX_DUTY;
dev_dbg(dev, "Probed %u PWMs\n", chip->npwm);
diff --git a/drivers/pwm/pwm-gpio.c b/drivers/pwm/pwm-gpio.c
new file mode 100644
index 000000000000..9f8884ac7504
--- /dev/null
+++ b/drivers/pwm/pwm-gpio.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Generic software PWM for modulating GPIOs
+ *
+ * Copyright (C) 2020 Axis Communications AB
+ * Copyright (C) 2020 Nicola Di Lieto
+ * Copyright (C) 2024 Stefan Wahren
+ * Copyright (C) 2024 Linus Walleij
+ */
+
+#include <linux/cleanup.h>
+#include <linux/container_of.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/hrtimer.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/pwm.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+struct pwm_gpio {
+ struct hrtimer gpio_timer;
+ struct gpio_desc *gpio;
+ struct pwm_state state;
+ struct pwm_state next_state;
+
+ /* Protect internal state between pwm_ops and hrtimer */
+ spinlock_t lock;
+
+ bool changing;
+ bool running;
+ bool level;
+};
+
+static void pwm_gpio_round(struct pwm_state *dest, const struct pwm_state *src)
+{
+ u64 dividend;
+ u32 remainder;
+
+ *dest = *src;
+
+ /* Round down to hrtimer resolution */
+ dividend = dest->period;
+ remainder = do_div(dividend, hrtimer_resolution);
+ dest->period -= remainder;
+
+ dividend = dest->duty_cycle;
+ remainder = do_div(dividend, hrtimer_resolution);
+ dest->duty_cycle -= remainder;
+}
+
+static u64 pwm_gpio_toggle(struct pwm_gpio *gpwm, bool level)
+{
+ const struct pwm_state *state = &gpwm->state;
+ bool invert = state->polarity == PWM_POLARITY_INVERSED;
+
+ gpwm->level = level;
+ gpiod_set_value(gpwm->gpio, gpwm->level ^ invert);
+
+ if (!state->duty_cycle || state->duty_cycle == state->period) {
+ gpwm->running = false;
+ return 0;
+ }
+
+ gpwm->running = true;
+ return level ? state->duty_cycle : state->period - state->duty_cycle;
+}
+
+static enum hrtimer_restart pwm_gpio_timer(struct hrtimer *gpio_timer)
+{
+ struct pwm_gpio *gpwm = container_of(gpio_timer, struct pwm_gpio,
+ gpio_timer);
+ u64 next_toggle;
+ bool new_level;
+
+ guard(spinlock_irqsave)(&gpwm->lock);
+
+ /* Apply new state at end of current period */
+ if (!gpwm->level && gpwm->changing) {
+ gpwm->changing = false;
+ gpwm->state = gpwm->next_state;
+ new_level = !!gpwm->state.duty_cycle;
+ } else {
+ new_level = !gpwm->level;
+ }
+
+ next_toggle = pwm_gpio_toggle(gpwm, new_level);
+ if (next_toggle)
+ hrtimer_forward(gpio_timer, hrtimer_get_expires(gpio_timer),
+ ns_to_ktime(next_toggle));
+
+ return next_toggle ? HRTIMER_RESTART : HRTIMER_NORESTART;
+}
+
+static int pwm_gpio_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct pwm_gpio *gpwm = pwmchip_get_drvdata(chip);
+ bool invert = state->polarity == PWM_POLARITY_INVERSED;
+
+ if (state->duty_cycle && state->duty_cycle < hrtimer_resolution)
+ return -EINVAL;
+
+ if (state->duty_cycle != state->period &&
+ (state->period - state->duty_cycle < hrtimer_resolution))
+ return -EINVAL;
+
+ if (!state->enabled) {
+ hrtimer_cancel(&gpwm->gpio_timer);
+ } else if (!gpwm->running) {
+ int ret;
+
+ /*
+ * This just enables the output, but pwm_gpio_toggle()
+ * really starts the duty cycle.
+ */
+ ret = gpiod_direction_output(gpwm->gpio, invert);
+ if (ret)
+ return ret;
+ }
+
+ guard(spinlock_irqsave)(&gpwm->lock);
+
+ if (!state->enabled) {
+ pwm_gpio_round(&gpwm->state, state);
+ gpwm->running = false;
+ gpwm->changing = false;
+
+ gpiod_set_value(gpwm->gpio, invert);
+ } else if (gpwm->running) {
+ pwm_gpio_round(&gpwm->next_state, state);
+ gpwm->changing = true;
+ } else {
+ unsigned long next_toggle;
+
+ pwm_gpio_round(&gpwm->state, state);
+ gpwm->changing = false;
+
+ next_toggle = pwm_gpio_toggle(gpwm, !!state->duty_cycle);
+ if (next_toggle)
+ hrtimer_start(&gpwm->gpio_timer, next_toggle,
+ HRTIMER_MODE_REL);
+ }
+
+ return 0;
+}
+
+static int pwm_gpio_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct pwm_gpio *gpwm = pwmchip_get_drvdata(chip);
+
+ guard(spinlock_irqsave)(&gpwm->lock);
+
+ if (gpwm->changing)
+ *state = gpwm->next_state;
+ else
+ *state = gpwm->state;
+
+ return 0;
+}
+
+static const struct pwm_ops pwm_gpio_ops = {
+ .apply = pwm_gpio_apply,
+ .get_state = pwm_gpio_get_state,
+};
+
+static void pwm_gpio_disable_hrtimer(void *data)
+{
+ struct pwm_gpio *gpwm = data;
+
+ hrtimer_cancel(&gpwm->gpio_timer);
+}
+
+static int pwm_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pwm_chip *chip;
+ struct pwm_gpio *gpwm;
+ int ret;
+
+ chip = devm_pwmchip_alloc(dev, 1, sizeof(*gpwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+
+ gpwm = pwmchip_get_drvdata(chip);
+
+ spin_lock_init(&gpwm->lock);
+
+ gpwm->gpio = devm_gpiod_get(dev, NULL, GPIOD_ASIS);
+ if (IS_ERR(gpwm->gpio))
+ return dev_err_probe(dev, PTR_ERR(gpwm->gpio),
+ "%pfw: could not get gpio\n",
+ dev_fwnode(dev));
+
+ if (gpiod_cansleep(gpwm->gpio))
+ return dev_err_probe(dev, -EINVAL,
+ "%pfw: sleeping GPIO not supported\n",
+ dev_fwnode(dev));
+
+ chip->ops = &pwm_gpio_ops;
+ chip->atomic = true;
+
+ hrtimer_init(&gpwm->gpio_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ret = devm_add_action_or_reset(dev, pwm_gpio_disable_hrtimer, gpwm);
+ if (ret)
+ return ret;
+
+ gpwm->gpio_timer.function = pwm_gpio_timer;
+
+ ret = pwmchip_add(chip);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "could not add pwmchip\n");
+
+ return 0;
+}
+
+static const struct of_device_id pwm_gpio_dt_ids[] = {
+ { .compatible = "pwm-gpio" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pwm_gpio_dt_ids);
+
+static struct platform_driver pwm_gpio_driver = {
+ .driver = {
+ .name = "pwm-gpio",
+ .of_match_table = pwm_gpio_dt_ids,
+ },
+ .probe = pwm_gpio_probe,
+};
+module_platform_driver(pwm_gpio_driver);
+
+MODULE_DESCRIPTION("PWM GPIO driver");
+MODULE_AUTHOR("Vincent Whitchurch");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c
index c50ddbac43c8..96ea343856f0 100644
--- a/drivers/pwm/pwm-imx-tpm.c
+++ b/drivers/pwm/pwm-imx-tpm.c
@@ -20,6 +20,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/slab.h>
@@ -380,6 +381,7 @@ static int pwm_imx_tpm_probe(struct platform_device *pdev)
static int pwm_imx_tpm_suspend(struct device *dev)
{
struct imx_tpm_pwm_chip *tpm = dev_get_drvdata(dev);
+ int ret;
if (tpm->enable_count > 0)
return -EBUSY;
@@ -393,7 +395,11 @@ static int pwm_imx_tpm_suspend(struct device *dev)
clk_disable_unprepare(tpm->clk);
- return 0;
+ ret = pinctrl_pm_select_sleep_state(dev);
+ if (ret)
+ clk_prepare_enable(tpm->clk);
+
+ return ret;
}
static int pwm_imx_tpm_resume(struct device *dev)
@@ -401,9 +407,15 @@ static int pwm_imx_tpm_resume(struct device *dev)
struct imx_tpm_pwm_chip *tpm = dev_get_drvdata(dev);
int ret = 0;
- ret = clk_prepare_enable(tpm->clk);
+ ret = pinctrl_pm_select_default_state(dev);
if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(tpm->clk);
+ if (ret) {
dev_err(dev, "failed to prepare or enable clock: %d\n", ret);
+ pinctrl_pm_select_sleep_state(dev);
+ }
return ret;
}
diff --git a/drivers/pwm/pwm-imx1.c b/drivers/pwm/pwm-imx1.c
index 1d2aae2d278f..d5535d208005 100644
--- a/drivers/pwm/pwm-imx1.c
+++ b/drivers/pwm/pwm-imx1.c
@@ -194,5 +194,6 @@ static struct platform_driver pwm_imx1_driver = {
};
module_platform_driver(pwm_imx1_driver);
+MODULE_DESCRIPTION("i.MX1 and i.MX21 Pulse Width Modulator driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Sascha Hauer <[email protected]>");
diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
index e1412116ef65..9e2bbf5b4a8c 100644
--- a/drivers/pwm/pwm-imx27.c
+++ b/drivers/pwm/pwm-imx27.c
@@ -352,5 +352,6 @@ static struct platform_driver imx_pwm_driver = {
};
module_platform_driver(imx_pwm_driver);
+MODULE_DESCRIPTION("i.MX27 and later i.MX SoCs Pulse Width Modulator driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Sascha Hauer <[email protected]>");
diff --git a/drivers/pwm/pwm-intel-lgm.c b/drivers/pwm/pwm-intel-lgm.c
index f9cc7c17c8f0..084c71a0a11b 100644
--- a/drivers/pwm/pwm-intel-lgm.c
+++ b/drivers/pwm/pwm-intel-lgm.c
@@ -230,4 +230,5 @@ static struct platform_driver lgm_pwm_driver = {
};
module_platform_driver(lgm_pwm_driver);
+MODULE_DESCRIPTION("Intel LGM Pulse Width Modulator driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index da4bf543d357..6bdb01619380 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -201,12 +201,11 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
* state instead of its inactive state.
*/
if ((state->polarity == PWM_POLARITY_NORMAL) ^ state->enabled)
- regmap_update_bits(jz->map, TCU_REG_TCSRc(pwm->hwpwm),
- TCU_TCSR_PWM_INITL_HIGH, 0);
+ regmap_clear_bits(jz->map, TCU_REG_TCSRc(pwm->hwpwm),
+ TCU_TCSR_PWM_INITL_HIGH);
else
- regmap_update_bits(jz->map, TCU_REG_TCSRc(pwm->hwpwm),
- TCU_TCSR_PWM_INITL_HIGH,
- TCU_TCSR_PWM_INITL_HIGH);
+ regmap_set_bits(jz->map, TCU_REG_TCSRc(pwm->hwpwm),
+ TCU_TCSR_PWM_INITL_HIGH);
if (state->enabled)
jz4740_pwm_enable(chip, pwm);
diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c
index 25045c229520..f7ece2809e6b 100644
--- a/drivers/pwm/pwm-lpss-pci.c
+++ b/drivers/pwm/pwm-lpss-pci.c
@@ -46,25 +46,6 @@ static void pwm_lpss_remove_pci(struct pci_dev *pdev)
pm_runtime_get_sync(&pdev->dev);
}
-static int pwm_lpss_runtime_suspend_pci(struct device *dev)
-{
- /*
- * The PCI core will handle transition to D3 automatically. We only
- * need to provide runtime PM hooks for that to happen.
- */
- return 0;
-}
-
-static int pwm_lpss_runtime_resume_pci(struct device *dev)
-{
- return 0;
-}
-
-static DEFINE_RUNTIME_DEV_PM_OPS(pwm_lpss_pci_pm,
- pwm_lpss_runtime_suspend_pci,
- pwm_lpss_runtime_resume_pci,
- NULL);
-
static const struct pci_device_id pwm_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x0ac8), (unsigned long)&pwm_lpss_bxt_info},
{ PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&pwm_lpss_byt_info},
@@ -84,9 +65,6 @@ static struct pci_driver pwm_lpss_driver_pci = {
.id_table = pwm_lpss_pci_ids,
.probe = pwm_lpss_probe_pci,
.remove = pwm_lpss_remove_pci,
- .driver = {
- .pm = pm_ptr(&pwm_lpss_pci_pm),
- },
};
module_pci_driver(pwm_lpss_driver_pci);
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
index dbc9f5b17bdc..5130238a4567 100644
--- a/drivers/pwm/pwm-lpss-platform.c
+++ b/drivers/pwm/pwm-lpss-platform.c
@@ -55,14 +55,7 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev)
DPM_FLAG_SMART_SUSPEND);
pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
-
- return 0;
-}
-
-static void pwm_lpss_remove_platform(struct platform_device *pdev)
-{
- pm_runtime_disable(&pdev->dev);
+ return devm_pm_runtime_enable(&pdev->dev);
}
static const struct acpi_device_id pwm_lpss_acpi_match[] = {
@@ -80,7 +73,6 @@ static struct platform_driver pwm_lpss_driver_platform = {
.acpi_match_table = pwm_lpss_acpi_match,
},
.probe = pwm_lpss_probe_platform,
- .remove_new = pwm_lpss_remove_platform,
};
module_platform_driver(pwm_lpss_driver_platform);
diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
index 19a87873ad60..01dfa0fab80a 100644
--- a/drivers/pwm/pwm-mediatek.c
+++ b/drivers/pwm/pwm-mediatek.c
@@ -395,4 +395,5 @@ static struct platform_driver pwm_mediatek_driver = {
module_platform_driver(pwm_mediatek_driver);
MODULE_AUTHOR("John Crispin <[email protected]>");
+MODULE_DESCRIPTION("MediaTek general purpose Pulse Width Modulator driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
index b2f97dfb01bb..98e6c1533312 100644
--- a/drivers/pwm/pwm-meson.c
+++ b/drivers/pwm/pwm-meson.c
@@ -460,6 +460,37 @@ static int meson_pwm_init_channels_meson8b_v2(struct pwm_chip *chip)
return meson_pwm_init_clocks_meson8b(chip, mux_parent_data);
}
+static void meson_pwm_s4_put_clk(void *data)
+{
+ struct clk *clk = data;
+
+ clk_put(clk);
+}
+
+static int meson_pwm_init_channels_s4(struct pwm_chip *chip)
+{
+ struct device *dev = pwmchip_parent(chip);
+ struct device_node *np = dev->of_node;
+ struct meson_pwm *meson = to_meson_pwm(chip);
+ int i, ret;
+
+ for (i = 0; i < MESON_NUM_PWMS; i++) {
+ meson->channels[i].clk = of_clk_get(np, i);
+ if (IS_ERR(meson->channels[i].clk))
+ return dev_err_probe(dev,
+ PTR_ERR(meson->channels[i].clk),
+ "Failed to get clk\n");
+
+ ret = devm_add_action_or_reset(dev, meson_pwm_s4_put_clk,
+ meson->channels[i].clk);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to add clk_put action\n");
+ }
+
+ return 0;
+}
+
static const struct meson_pwm_data pwm_meson8b_data = {
.parent_names = { "xtal", NULL, "fclk_div4", "fclk_div3" },
.channels_init = meson_pwm_init_channels_meson8b_legacy,
@@ -498,6 +529,10 @@ static const struct meson_pwm_data pwm_meson8_v2_data = {
.channels_init = meson_pwm_init_channels_meson8b_v2,
};
+static const struct meson_pwm_data pwm_s4_data = {
+ .channels_init = meson_pwm_init_channels_s4,
+};
+
static const struct of_device_id meson_pwm_matches[] = {
{
.compatible = "amlogic,meson8-pwm-v2",
@@ -536,6 +571,10 @@ static const struct of_device_id meson_pwm_matches[] = {
.compatible = "amlogic,meson-g12a-ao-pwm-cd",
.data = &pwm_g12a_ao_cd_data
},
+ {
+ .compatible = "amlogic,meson-s4-pwm",
+ .data = &pwm_s4_data
+ },
{},
};
MODULE_DEVICE_TABLE(of, meson_pwm_matches);
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index bb7bb48b2e6d..430bd6a709e9 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -208,4 +208,5 @@ static struct platform_driver pwm_driver = {
module_platform_driver(pwm_driver);
+MODULE_DESCRIPTION("PXA Pulse Width Modulator driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index efb60c9f0cb3..7adf4f2b1049 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -644,6 +644,7 @@ static struct platform_driver pwm_samsung_driver = {
};
module_platform_driver(pwm_samsung_driver);
+MODULE_DESCRIPTION("Samsung Pulse Width Modulator driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tomasz Figa <[email protected]>");
MODULE_ALIAS("platform:samsung-pwm");
diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c
index 6c6f3b38c835..4f372279f313 100644
--- a/drivers/pwm/pwm-spear.c
+++ b/drivers/pwm/pwm-spear.c
@@ -255,6 +255,7 @@ static struct platform_driver spear_pwm_driver = {
module_platform_driver(spear_pwm_driver);
+MODULE_DESCRIPTION("ST Microelectronics SPEAr Pulse Width Modulator driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Shiraz Hashim <[email protected]>");
MODULE_AUTHOR("Viresh Kumar <[email protected]>");
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index 8bae3fd2b330..fd754a99cf2e 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -368,7 +368,7 @@ static int stm32_pwm_config(struct stm32_pwm *priv, unsigned int ch,
dty = mul_u64_u64_div_u64(duty_ns, clk_get_rate(priv->clk),
(u64)NSEC_PER_SEC * (prescaler + 1));
- regmap_write(priv->regmap, TIM_CCR1 + 4 * ch, dty);
+ regmap_write(priv->regmap, TIM_CCRx(ch + 1), dty);
/* Configure output mode */
shift = (ch & 0x1) * CCMR_CHANNEL_SHIFT;
@@ -390,9 +390,9 @@ static int stm32_pwm_set_polarity(struct stm32_pwm *priv, unsigned int ch,
{
u32 mask;
- mask = TIM_CCER_CC1P << (ch * 4);
+ mask = TIM_CCER_CCxP(ch + 1);
if (priv->have_complementary_output)
- mask |= TIM_CCER_CC1NP << (ch * 4);
+ mask |= TIM_CCER_CCxNP(ch + 1);
regmap_update_bits(priv->regmap, TIM_CCER, mask,
polarity == PWM_POLARITY_NORMAL ? 0 : mask);
@@ -410,9 +410,9 @@ static int stm32_pwm_enable(struct stm32_pwm *priv, unsigned int ch)
return ret;
/* Enable channel */
- mask = TIM_CCER_CC1E << (ch * 4);
+ mask = TIM_CCER_CCxE(ch + 1);
if (priv->have_complementary_output)
- mask |= TIM_CCER_CC1NE << (ch * 4);
+ mask |= TIM_CCER_CCxNE(ch);
regmap_set_bits(priv->regmap, TIM_CCER, mask);
@@ -430,9 +430,9 @@ static void stm32_pwm_disable(struct stm32_pwm *priv, unsigned int ch)
u32 mask;
/* Disable channel */
- mask = TIM_CCER_CC1E << (ch * 4);
+ mask = TIM_CCER_CCxE(ch + 1);
if (priv->have_complementary_output)
- mask |= TIM_CCER_CC1NE << (ch * 4);
+ mask |= TIM_CCER_CCxNE(ch + 1);
regmap_clear_bits(priv->regmap, TIM_CCER, mask);
@@ -452,8 +452,9 @@ static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
enabled = pwm->state.enabled;
- if (enabled && !state->enabled) {
- stm32_pwm_disable(priv, pwm->hwpwm);
+ if (!state->enabled) {
+ if (enabled)
+ stm32_pwm_disable(priv, pwm->hwpwm);
return 0;
}
@@ -501,8 +502,8 @@ static int stm32_pwm_get_state(struct pwm_chip *chip,
if (ret)
goto out;
- state->enabled = ccer & (TIM_CCER_CC1E << (ch * 4));
- state->polarity = (ccer & (TIM_CCER_CC1P << (ch * 4))) ?
+ state->enabled = ccer & TIM_CCER_CCxE(ch + 1);
+ state->polarity = (ccer & TIM_CCER_CCxP(ch + 1)) ?
PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
ret = regmap_read(priv->regmap, TIM_PSC, &psc);
if (ret)
@@ -510,7 +511,7 @@ static int stm32_pwm_get_state(struct pwm_chip *chip,
ret = regmap_read(priv->regmap, TIM_ARR, &arr);
if (ret)
goto out;
- ret = regmap_read(priv->regmap, TIM_CCR1 + 4 * ch, &ccr);
+ ret = regmap_read(priv->regmap, TIM_CCRx(ch + 1), &ccr);
if (ret)
goto out;
@@ -711,7 +712,7 @@ static int stm32_pwm_suspend(struct device *dev)
ccer = active_channels(priv);
for (i = 0; i < chip->npwm; i++) {
- mask = TIM_CCER_CC1E << (i * 4);
+ mask = TIM_CCER_CCxE(i + 1);
if (ccer & mask) {
dev_err(dev, "PWM %u still in use by consumer %s\n",
i, chip->pwms[i].label);
diff --git a/drivers/pwm/pwm-visconti.c b/drivers/pwm/pwm-visconti.c
index 9e55380957be..28fae4979e3f 100644
--- a/drivers/pwm/pwm-visconti.c
+++ b/drivers/pwm/pwm-visconti.c
@@ -170,6 +170,7 @@ static struct platform_driver visconti_pwm_driver = {
};
module_platform_driver(visconti_pwm_driver);
+MODULE_DESCRIPTION("Toshiba Visconti Pulse Width Modulator driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Nobuhiro Iwamatsu <[email protected]>");
MODULE_ALIAS("platform:pwm-visconti");
diff --git a/drivers/pwm/pwm-xilinx.c b/drivers/pwm/pwm-xilinx.c
index 3a7deebb0d0c..52c241982807 100644
--- a/drivers/pwm/pwm-xilinx.c
+++ b/drivers/pwm/pwm-xilinx.c
@@ -224,7 +224,6 @@ static int xilinx_pwm_probe(struct platform_device *pdev)
if (IS_ERR(chip))
return PTR_ERR(chip);
priv = xilinx_pwm_chip_to_priv(chip);
- platform_set_drvdata(pdev, chip);
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
@@ -263,37 +262,24 @@ static int xilinx_pwm_probe(struct platform_device *pdev)
* alas, such properties are not allowed to be used.
*/
- priv->clk = devm_clk_get(dev, "s_axi_aclk");
+ priv->clk = devm_clk_get_enabled(dev, "s_axi_aclk");
if (IS_ERR(priv->clk))
return dev_err_probe(dev, PTR_ERR(priv->clk),
"Could not get clock\n");
- ret = clk_prepare_enable(priv->clk);
+ ret = devm_clk_rate_exclusive_get(dev, priv->clk);
if (ret)
- return dev_err_probe(dev, ret, "Clock enable failed\n");
- clk_rate_exclusive_get(priv->clk);
+ return dev_err_probe(dev, ret,
+ "Failed to lock clock rate\n");
chip->ops = &xilinx_pwm_ops;
- ret = pwmchip_add(chip);
- if (ret) {
- clk_rate_exclusive_put(priv->clk);
- clk_disable_unprepare(priv->clk);
+ ret = devm_pwmchip_add(dev, chip);
+ if (ret)
return dev_err_probe(dev, ret, "Could not register PWM chip\n");
- }
return 0;
}
-static void xilinx_pwm_remove(struct platform_device *pdev)
-{
- struct pwm_chip *chip = platform_get_drvdata(pdev);
- struct xilinx_timer_priv *priv = xilinx_pwm_chip_to_priv(chip);
-
- pwmchip_remove(chip);
- clk_rate_exclusive_put(priv->clk);
- clk_disable_unprepare(priv->clk);
-}
-
static const struct of_device_id xilinx_pwm_of_match[] = {
{ .compatible = "xlnx,xps-timer-1.00.a", },
{},
@@ -302,7 +288,6 @@ MODULE_DEVICE_TABLE(of, xilinx_pwm_of_match);
static struct platform_driver xilinx_pwm_driver = {
.probe = xilinx_pwm_probe,
- .remove_new = xilinx_pwm_remove,
.driver = {
.name = "xilinx-pwm",
.of_match_table = of_match_ptr(xilinx_pwm_of_match),
diff --git a/drivers/ras/amd/atl/core.c b/drivers/ras/amd/atl/core.c
index 6dc4e06305f7..4197e10993ac 100644
--- a/drivers/ras/amd/atl/core.c
+++ b/drivers/ras/amd/atl/core.c
@@ -49,26 +49,26 @@ static bool legacy_hole_en(struct addr_ctx *ctx)
return FIELD_GET(DF_LEGACY_MMIO_HOLE_EN, reg);
}
-static int add_legacy_hole(struct addr_ctx *ctx)
+static u64 add_legacy_hole(struct addr_ctx *ctx, u64 addr)
{
- u32 dram_hole_base;
- u8 func = 0;
-
if (!legacy_hole_en(ctx))
- return 0;
+ return addr;
- if (df_cfg.rev >= DF4)
- func = 7;
+ if (addr >= df_cfg.dram_hole_base)
+ addr += (BIT_ULL(32) - df_cfg.dram_hole_base);
- if (df_indirect_read_broadcast(ctx->node_id, func, 0x104, &dram_hole_base))
- return -EINVAL;
+ return addr;
+}
- dram_hole_base &= DF_DRAM_HOLE_BASE_MASK;
+static u64 remove_legacy_hole(struct addr_ctx *ctx, u64 addr)
+{
+ if (!legacy_hole_en(ctx))
+ return addr;
- if (ctx->ret_addr >= dram_hole_base)
- ctx->ret_addr += (BIT_ULL(32) - dram_hole_base);
+ if (addr >= df_cfg.dram_hole_base)
+ addr -= (BIT_ULL(32) - df_cfg.dram_hole_base);
- return 0;
+ return addr;
}
static u64 get_base_addr(struct addr_ctx *ctx)
@@ -83,14 +83,14 @@ static u64 get_base_addr(struct addr_ctx *ctx)
return base_addr << DF_DRAM_BASE_LIMIT_LSB;
}
-static int add_base_and_hole(struct addr_ctx *ctx)
+u64 add_base_and_hole(struct addr_ctx *ctx, u64 addr)
{
- ctx->ret_addr += get_base_addr(ctx);
-
- if (add_legacy_hole(ctx))
- return -EINVAL;
+ return add_legacy_hole(ctx, addr + get_base_addr(ctx));
+}
- return 0;
+u64 remove_base_and_hole(struct addr_ctx *ctx, u64 addr)
+{
+ return remove_legacy_hole(ctx, addr) - get_base_addr(ctx);
}
static bool late_hole_remove(struct addr_ctx *ctx)
@@ -125,6 +125,9 @@ unsigned long norm_to_sys_addr(u8 socket_id, u8 die_id, u8 coh_st_inst_id, unsig
ctx.inputs.die_id = die_id;
ctx.inputs.coh_st_inst_id = coh_st_inst_id;
+ if (legacy_hole_en(&ctx) && !df_cfg.dram_hole_base)
+ return -EINVAL;
+
if (determine_node_id(&ctx, socket_id, die_id))
return -EINVAL;
@@ -134,14 +137,14 @@ unsigned long norm_to_sys_addr(u8 socket_id, u8 die_id, u8 coh_st_inst_id, unsig
if (denormalize_address(&ctx))
return -EINVAL;
- if (!late_hole_remove(&ctx) && add_base_and_hole(&ctx))
- return -EINVAL;
+ if (!late_hole_remove(&ctx))
+ ctx.ret_addr = add_base_and_hole(&ctx, ctx.ret_addr);
if (dehash_address(&ctx))
return -EINVAL;
- if (late_hole_remove(&ctx) && add_base_and_hole(&ctx))
- return -EINVAL;
+ if (late_hole_remove(&ctx))
+ ctx.ret_addr = add_base_and_hole(&ctx, ctx.ret_addr);
if (addr_over_limit(&ctx))
return -EINVAL;
@@ -206,7 +209,7 @@ static int __init amd_atl_init(void)
__module_get(THIS_MODULE);
amd_atl_register_decoder(convert_umc_mca_addr_to_sys_addr);
- pr_info("AMD Address Translation Library initialized");
+ pr_info("AMD Address Translation Library initialized\n");
return 0;
}
@@ -222,4 +225,5 @@ static void __exit amd_atl_exit(void)
module_init(amd_atl_init);
module_exit(amd_atl_exit);
+MODULE_DESCRIPTION("AMD Address Translation Library");
MODULE_LICENSE("GPL");
diff --git a/drivers/ras/amd/atl/dehash.c b/drivers/ras/amd/atl/dehash.c
index 4ea46262c4f5..d4ee7ecabaee 100644
--- a/drivers/ras/amd/atl/dehash.c
+++ b/drivers/ras/amd/atl/dehash.c
@@ -12,41 +12,10 @@
#include "internal.h"
-/*
- * Verify the interleave bits are correct in the different interleaving
- * settings.
- *
- * If @num_intlv_dies and/or @num_intlv_sockets are 1, it means the
- * respective interleaving is disabled.
- */
-static inline bool map_bits_valid(struct addr_ctx *ctx, u8 bit1, u8 bit2,
- u8 num_intlv_dies, u8 num_intlv_sockets)
-{
- if (!(ctx->map.intlv_bit_pos == bit1 || ctx->map.intlv_bit_pos == bit2)) {
- pr_debug("Invalid interleave bit: %u", ctx->map.intlv_bit_pos);
- return false;
- }
-
- if (ctx->map.num_intlv_dies > num_intlv_dies) {
- pr_debug("Invalid number of interleave dies: %u", ctx->map.num_intlv_dies);
- return false;
- }
-
- if (ctx->map.num_intlv_sockets > num_intlv_sockets) {
- pr_debug("Invalid number of interleave sockets: %u", ctx->map.num_intlv_sockets);
- return false;
- }
-
- return true;
-}
-
static int df2_dehash_addr(struct addr_ctx *ctx)
{
u8 hashed_bit, intlv_bit, intlv_bit_pos;
- if (!map_bits_valid(ctx, 8, 9, 1, 1))
- return -EINVAL;
-
intlv_bit_pos = ctx->map.intlv_bit_pos;
intlv_bit = !!(BIT_ULL(intlv_bit_pos) & ctx->ret_addr);
@@ -67,9 +36,6 @@ static int df3_dehash_addr(struct addr_ctx *ctx)
bool hash_ctl_64k, hash_ctl_2M, hash_ctl_1G;
u8 hashed_bit, intlv_bit, intlv_bit_pos;
- if (!map_bits_valid(ctx, 8, 9, 1, 1))
- return -EINVAL;
-
hash_ctl_64k = FIELD_GET(DF3_HASH_CTL_64K, ctx->map.ctl);
hash_ctl_2M = FIELD_GET(DF3_HASH_CTL_2M, ctx->map.ctl);
hash_ctl_1G = FIELD_GET(DF3_HASH_CTL_1G, ctx->map.ctl);
@@ -171,9 +137,6 @@ static int df4_dehash_addr(struct addr_ctx *ctx)
bool hash_ctl_64k, hash_ctl_2M, hash_ctl_1G;
u8 hashed_bit, intlv_bit;
- if (!map_bits_valid(ctx, 8, 8, 1, 2))
- return -EINVAL;
-
hash_ctl_64k = FIELD_GET(DF4_HASH_CTL_64K, ctx->map.ctl);
hash_ctl_2M = FIELD_GET(DF4_HASH_CTL_2M, ctx->map.ctl);
hash_ctl_1G = FIELD_GET(DF4_HASH_CTL_1G, ctx->map.ctl);
@@ -247,9 +210,6 @@ static int df4p5_dehash_addr(struct addr_ctx *ctx)
u8 hashed_bit, intlv_bit;
u64 rehash_vector;
- if (!map_bits_valid(ctx, 8, 8, 1, 2))
- return -EINVAL;
-
hash_ctl_64k = FIELD_GET(DF4_HASH_CTL_64K, ctx->map.ctl);
hash_ctl_2M = FIELD_GET(DF4_HASH_CTL_2M, ctx->map.ctl);
hash_ctl_1G = FIELD_GET(DF4_HASH_CTL_1G, ctx->map.ctl);
@@ -360,9 +320,6 @@ static int mi300_dehash_addr(struct addr_ctx *ctx)
bool hashed_bit, intlv_bit, test_bit;
u8 num_intlv_bits, base_bit, i;
- if (!map_bits_valid(ctx, 8, 8, 4, 1))
- return -EINVAL;
-
hash_ctl_4k = FIELD_GET(DF4p5_HASH_CTL_4K, ctx->map.ctl);
hash_ctl_64k = FIELD_GET(DF4_HASH_CTL_64K, ctx->map.ctl);
hash_ctl_2M = FIELD_GET(DF4_HASH_CTL_2M, ctx->map.ctl);
diff --git a/drivers/ras/amd/atl/denormalize.c b/drivers/ras/amd/atl/denormalize.c
index e279224288d6..1a525cfa983c 100644
--- a/drivers/ras/amd/atl/denormalize.c
+++ b/drivers/ras/amd/atl/denormalize.c
@@ -448,6 +448,118 @@ static u16 get_logical_coh_st_fabric_id(struct addr_ctx *ctx)
return (phys_fabric_id & df_cfg.node_id_mask) | log_fabric_id;
}
+static u16 get_logical_coh_st_fabric_id_for_current_spa(struct addr_ctx *ctx,
+ struct df4p5_denorm_ctx *denorm_ctx)
+{
+ bool hash_ctl_64k, hash_ctl_2M, hash_ctl_1G, hash_ctl_1T;
+ bool hash_pa8, hash_pa9, hash_pa12, hash_pa13;
+ u64 cs_id = 0;
+
+ hash_ctl_64k = FIELD_GET(DF4_HASH_CTL_64K, ctx->map.ctl);
+ hash_ctl_2M = FIELD_GET(DF4_HASH_CTL_2M, ctx->map.ctl);
+ hash_ctl_1G = FIELD_GET(DF4_HASH_CTL_1G, ctx->map.ctl);
+ hash_ctl_1T = FIELD_GET(DF4p5_HASH_CTL_1T, ctx->map.ctl);
+
+ hash_pa8 = FIELD_GET(BIT_ULL(8), denorm_ctx->current_spa);
+ hash_pa8 ^= FIELD_GET(BIT_ULL(14), denorm_ctx->current_spa);
+ hash_pa8 ^= FIELD_GET(BIT_ULL(16), denorm_ctx->current_spa) & hash_ctl_64k;
+ hash_pa8 ^= FIELD_GET(BIT_ULL(21), denorm_ctx->current_spa) & hash_ctl_2M;
+ hash_pa8 ^= FIELD_GET(BIT_ULL(30), denorm_ctx->current_spa) & hash_ctl_1G;
+ hash_pa8 ^= FIELD_GET(BIT_ULL(40), denorm_ctx->current_spa) & hash_ctl_1T;
+
+ hash_pa9 = FIELD_GET(BIT_ULL(9), denorm_ctx->current_spa);
+ hash_pa9 ^= FIELD_GET(BIT_ULL(17), denorm_ctx->current_spa) & hash_ctl_64k;
+ hash_pa9 ^= FIELD_GET(BIT_ULL(22), denorm_ctx->current_spa) & hash_ctl_2M;
+ hash_pa9 ^= FIELD_GET(BIT_ULL(31), denorm_ctx->current_spa) & hash_ctl_1G;
+ hash_pa9 ^= FIELD_GET(BIT_ULL(41), denorm_ctx->current_spa) & hash_ctl_1T;
+
+ hash_pa12 = FIELD_GET(BIT_ULL(12), denorm_ctx->current_spa);
+ hash_pa12 ^= FIELD_GET(BIT_ULL(18), denorm_ctx->current_spa) & hash_ctl_64k;
+ hash_pa12 ^= FIELD_GET(BIT_ULL(23), denorm_ctx->current_spa) & hash_ctl_2M;
+ hash_pa12 ^= FIELD_GET(BIT_ULL(32), denorm_ctx->current_spa) & hash_ctl_1G;
+ hash_pa12 ^= FIELD_GET(BIT_ULL(42), denorm_ctx->current_spa) & hash_ctl_1T;
+
+ hash_pa13 = FIELD_GET(BIT_ULL(13), denorm_ctx->current_spa);
+ hash_pa13 ^= FIELD_GET(BIT_ULL(19), denorm_ctx->current_spa) & hash_ctl_64k;
+ hash_pa13 ^= FIELD_GET(BIT_ULL(24), denorm_ctx->current_spa) & hash_ctl_2M;
+ hash_pa13 ^= FIELD_GET(BIT_ULL(33), denorm_ctx->current_spa) & hash_ctl_1G;
+ hash_pa13 ^= FIELD_GET(BIT_ULL(43), denorm_ctx->current_spa) & hash_ctl_1T;
+
+ switch (ctx->map.intlv_mode) {
+ case DF4p5_NPS0_24CHAN_1K_HASH:
+ cs_id = FIELD_GET(GENMASK_ULL(63, 13), denorm_ctx->current_spa) << 3;
+ cs_id %= denorm_ctx->mod_value;
+ cs_id <<= 2;
+ cs_id |= (hash_pa9 | (hash_pa12 << 1));
+ cs_id |= hash_pa8 << df_cfg.socket_id_shift;
+ break;
+
+ case DF4p5_NPS0_24CHAN_2K_HASH:
+ cs_id = FIELD_GET(GENMASK_ULL(63, 14), denorm_ctx->current_spa) << 4;
+ cs_id %= denorm_ctx->mod_value;
+ cs_id <<= 2;
+ cs_id |= (hash_pa12 | (hash_pa13 << 1));
+ cs_id |= hash_pa8 << df_cfg.socket_id_shift;
+ break;
+
+ case DF4p5_NPS1_12CHAN_1K_HASH:
+ cs_id = FIELD_GET(GENMASK_ULL(63, 12), denorm_ctx->current_spa) << 2;
+ cs_id %= denorm_ctx->mod_value;
+ cs_id <<= 2;
+ cs_id |= (hash_pa8 | (hash_pa9 << 1));
+ break;
+
+ case DF4p5_NPS1_12CHAN_2K_HASH:
+ cs_id = FIELD_GET(GENMASK_ULL(63, 13), denorm_ctx->current_spa) << 3;
+ cs_id %= denorm_ctx->mod_value;
+ cs_id <<= 2;
+ cs_id |= (hash_pa8 | (hash_pa12 << 1));
+ break;
+
+ case DF4p5_NPS2_6CHAN_1K_HASH:
+ case DF4p5_NPS1_10CHAN_1K_HASH:
+ cs_id = FIELD_GET(GENMASK_ULL(63, 12), denorm_ctx->current_spa) << 2;
+ cs_id |= (FIELD_GET(BIT_ULL(9), denorm_ctx->current_spa) << 1);
+ cs_id %= denorm_ctx->mod_value;
+ cs_id <<= 1;
+ cs_id |= hash_pa8;
+ break;
+
+ case DF4p5_NPS2_6CHAN_2K_HASH:
+ case DF4p5_NPS1_10CHAN_2K_HASH:
+ cs_id = FIELD_GET(GENMASK_ULL(63, 12), denorm_ctx->current_spa) << 2;
+ cs_id %= denorm_ctx->mod_value;
+ cs_id <<= 1;
+ cs_id |= hash_pa8;
+ break;
+
+ case DF4p5_NPS4_3CHAN_1K_HASH:
+ case DF4p5_NPS2_5CHAN_1K_HASH:
+ cs_id = FIELD_GET(GENMASK_ULL(63, 12), denorm_ctx->current_spa) << 2;
+ cs_id |= FIELD_GET(GENMASK_ULL(9, 8), denorm_ctx->current_spa);
+ cs_id %= denorm_ctx->mod_value;
+ break;
+
+ case DF4p5_NPS4_3CHAN_2K_HASH:
+ case DF4p5_NPS2_5CHAN_2K_HASH:
+ cs_id = FIELD_GET(GENMASK_ULL(63, 12), denorm_ctx->current_spa) << 2;
+ cs_id |= FIELD_GET(BIT_ULL(8), denorm_ctx->current_spa) << 1;
+ cs_id %= denorm_ctx->mod_value;
+ break;
+
+ default:
+ atl_debug_on_bad_intlv_mode(ctx);
+ return 0;
+ }
+
+ if (cs_id > 0xffff) {
+ atl_debug(ctx, "Translation error: Resulting cs_id larger than u16\n");
+ return 0;
+ }
+
+ return cs_id;
+}
+
static int denorm_addr_common(struct addr_ctx *ctx)
{
u64 denorm_addr;
@@ -699,6 +811,442 @@ static int denorm_addr_df4_np2(struct addr_ctx *ctx)
return 0;
}
+static u64 normalize_addr_df4p5_np2(struct addr_ctx *ctx, struct df4p5_denorm_ctx *denorm_ctx,
+ u64 addr)
+{
+ u64 temp_addr_a = 0, temp_addr_b = 0;
+
+ switch (ctx->map.intlv_mode) {
+ case DF4p5_NPS0_24CHAN_1K_HASH:
+ case DF4p5_NPS1_12CHAN_1K_HASH:
+ case DF4p5_NPS2_6CHAN_1K_HASH:
+ case DF4p5_NPS4_3CHAN_1K_HASH:
+ case DF4p5_NPS1_10CHAN_1K_HASH:
+ case DF4p5_NPS2_5CHAN_1K_HASH:
+ temp_addr_a = FIELD_GET(GENMASK_ULL(11, 10), addr) << 8;
+ break;
+
+ case DF4p5_NPS0_24CHAN_2K_HASH:
+ case DF4p5_NPS1_12CHAN_2K_HASH:
+ case DF4p5_NPS2_6CHAN_2K_HASH:
+ case DF4p5_NPS4_3CHAN_2K_HASH:
+ case DF4p5_NPS1_10CHAN_2K_HASH:
+ case DF4p5_NPS2_5CHAN_2K_HASH:
+ temp_addr_a = FIELD_GET(GENMASK_ULL(11, 9), addr) << 8;
+ break;
+
+ default:
+ atl_debug_on_bad_intlv_mode(ctx);
+ return 0;
+ }
+
+ switch (ctx->map.intlv_mode) {
+ case DF4p5_NPS0_24CHAN_1K_HASH:
+ temp_addr_b = FIELD_GET(GENMASK_ULL(63, 13), addr) / denorm_ctx->mod_value;
+ temp_addr_b <<= 10;
+ break;
+
+ case DF4p5_NPS0_24CHAN_2K_HASH:
+ temp_addr_b = FIELD_GET(GENMASK_ULL(63, 14), addr) / denorm_ctx->mod_value;
+ temp_addr_b <<= 11;
+ break;
+
+ case DF4p5_NPS1_12CHAN_1K_HASH:
+ temp_addr_b = FIELD_GET(GENMASK_ULL(63, 12), addr) / denorm_ctx->mod_value;
+ temp_addr_b <<= 10;
+ break;
+
+ case DF4p5_NPS1_12CHAN_2K_HASH:
+ temp_addr_b = FIELD_GET(GENMASK_ULL(63, 13), addr) / denorm_ctx->mod_value;
+ temp_addr_b <<= 11;
+ break;
+
+ case DF4p5_NPS2_6CHAN_1K_HASH:
+ case DF4p5_NPS1_10CHAN_1K_HASH:
+ temp_addr_b = FIELD_GET(GENMASK_ULL(63, 12), addr) << 1;
+ temp_addr_b |= FIELD_GET(BIT_ULL(9), addr);
+ temp_addr_b /= denorm_ctx->mod_value;
+ temp_addr_b <<= 10;
+ break;
+
+ case DF4p5_NPS2_6CHAN_2K_HASH:
+ case DF4p5_NPS1_10CHAN_2K_HASH:
+ temp_addr_b = FIELD_GET(GENMASK_ULL(63, 12), addr) / denorm_ctx->mod_value;
+ temp_addr_b <<= 11;
+ break;
+
+ case DF4p5_NPS4_3CHAN_1K_HASH:
+ case DF4p5_NPS2_5CHAN_1K_HASH:
+ temp_addr_b = FIELD_GET(GENMASK_ULL(63, 12), addr) << 2;
+ temp_addr_b |= FIELD_GET(GENMASK_ULL(9, 8), addr);
+ temp_addr_b /= denorm_ctx->mod_value;
+ temp_addr_b <<= 10;
+ break;
+
+ case DF4p5_NPS4_3CHAN_2K_HASH:
+ case DF4p5_NPS2_5CHAN_2K_HASH:
+ temp_addr_b = FIELD_GET(GENMASK_ULL(63, 12), addr) << 1;
+ temp_addr_b |= FIELD_GET(BIT_ULL(8), addr);
+ temp_addr_b /= denorm_ctx->mod_value;
+ temp_addr_b <<= 11;
+ break;
+
+ default:
+ atl_debug_on_bad_intlv_mode(ctx);
+ return 0;
+ }
+
+ return denorm_ctx->base_denorm_addr | temp_addr_a | temp_addr_b;
+}
+
+static void recalculate_hashed_bits_df4p5_np2(struct addr_ctx *ctx,
+ struct df4p5_denorm_ctx *denorm_ctx)
+{
+ bool hash_ctl_64k, hash_ctl_2M, hash_ctl_1G, hash_ctl_1T, hashed_bit;
+
+ if (!denorm_ctx->rehash_vector)
+ return;
+
+ hash_ctl_64k = FIELD_GET(DF4_HASH_CTL_64K, ctx->map.ctl);
+ hash_ctl_2M = FIELD_GET(DF4_HASH_CTL_2M, ctx->map.ctl);
+ hash_ctl_1G = FIELD_GET(DF4_HASH_CTL_1G, ctx->map.ctl);
+ hash_ctl_1T = FIELD_GET(DF4p5_HASH_CTL_1T, ctx->map.ctl);
+
+ if (denorm_ctx->rehash_vector & BIT_ULL(8)) {
+ hashed_bit = FIELD_GET(BIT_ULL(8), denorm_ctx->current_spa);
+ hashed_bit ^= FIELD_GET(BIT_ULL(14), denorm_ctx->current_spa);
+ hashed_bit ^= FIELD_GET(BIT_ULL(16), denorm_ctx->current_spa) & hash_ctl_64k;
+ hashed_bit ^= FIELD_GET(BIT_ULL(21), denorm_ctx->current_spa) & hash_ctl_2M;
+ hashed_bit ^= FIELD_GET(BIT_ULL(30), denorm_ctx->current_spa) & hash_ctl_1G;
+ hashed_bit ^= FIELD_GET(BIT_ULL(40), denorm_ctx->current_spa) & hash_ctl_1T;
+
+ if (FIELD_GET(BIT_ULL(8), denorm_ctx->current_spa) != hashed_bit)
+ denorm_ctx->current_spa ^= BIT_ULL(8);
+ }
+
+ if (denorm_ctx->rehash_vector & BIT_ULL(9)) {
+ hashed_bit = FIELD_GET(BIT_ULL(9), denorm_ctx->current_spa);
+ hashed_bit ^= FIELD_GET(BIT_ULL(17), denorm_ctx->current_spa) & hash_ctl_64k;
+ hashed_bit ^= FIELD_GET(BIT_ULL(22), denorm_ctx->current_spa) & hash_ctl_2M;
+ hashed_bit ^= FIELD_GET(BIT_ULL(31), denorm_ctx->current_spa) & hash_ctl_1G;
+ hashed_bit ^= FIELD_GET(BIT_ULL(41), denorm_ctx->current_spa) & hash_ctl_1T;
+
+ if (FIELD_GET(BIT_ULL(9), denorm_ctx->current_spa) != hashed_bit)
+ denorm_ctx->current_spa ^= BIT_ULL(9);
+ }
+
+ if (denorm_ctx->rehash_vector & BIT_ULL(12)) {
+ hashed_bit = FIELD_GET(BIT_ULL(12), denorm_ctx->current_spa);
+ hashed_bit ^= FIELD_GET(BIT_ULL(18), denorm_ctx->current_spa) & hash_ctl_64k;
+ hashed_bit ^= FIELD_GET(BIT_ULL(23), denorm_ctx->current_spa) & hash_ctl_2M;
+ hashed_bit ^= FIELD_GET(BIT_ULL(32), denorm_ctx->current_spa) & hash_ctl_1G;
+ hashed_bit ^= FIELD_GET(BIT_ULL(42), denorm_ctx->current_spa) & hash_ctl_1T;
+
+ if (FIELD_GET(BIT_ULL(12), denorm_ctx->current_spa) != hashed_bit)
+ denorm_ctx->current_spa ^= BIT_ULL(12);
+ }
+
+ if (denorm_ctx->rehash_vector & BIT_ULL(13)) {
+ hashed_bit = FIELD_GET(BIT_ULL(13), denorm_ctx->current_spa);
+ hashed_bit ^= FIELD_GET(BIT_ULL(19), denorm_ctx->current_spa) & hash_ctl_64k;
+ hashed_bit ^= FIELD_GET(BIT_ULL(24), denorm_ctx->current_spa) & hash_ctl_2M;
+ hashed_bit ^= FIELD_GET(BIT_ULL(33), denorm_ctx->current_spa) & hash_ctl_1G;
+ hashed_bit ^= FIELD_GET(BIT_ULL(43), denorm_ctx->current_spa) & hash_ctl_1T;
+
+ if (FIELD_GET(BIT_ULL(13), denorm_ctx->current_spa) != hashed_bit)
+ denorm_ctx->current_spa ^= BIT_ULL(13);
+ }
+}
+
+static bool match_logical_coh_st_fabric_id(struct addr_ctx *ctx,
+ struct df4p5_denorm_ctx *denorm_ctx)
+{
+ /*
+ * The logical CS fabric ID of the permutation must be calculated from the
+ * current SPA with the base and with the MMIO hole.
+ */
+ u16 id = get_logical_coh_st_fabric_id_for_current_spa(ctx, denorm_ctx);
+
+ atl_debug(ctx, "Checking calculated logical coherent station fabric id:\n");
+ atl_debug(ctx, " calculated fabric id = 0x%x\n", id);
+ atl_debug(ctx, " expected fabric id = 0x%x\n", denorm_ctx->coh_st_fabric_id);
+
+ return denorm_ctx->coh_st_fabric_id == id;
+}
+
+static bool match_norm_addr(struct addr_ctx *ctx, struct df4p5_denorm_ctx *denorm_ctx)
+{
+ u64 addr = remove_base_and_hole(ctx, denorm_ctx->current_spa);
+
+ /*
+ * The normalized address must be calculated with the current SPA without
+ * the base and without the MMIO hole.
+ */
+ addr = normalize_addr_df4p5_np2(ctx, denorm_ctx, addr);
+
+ atl_debug(ctx, "Checking calculated normalized address:\n");
+ atl_debug(ctx, " calculated normalized addr = 0x%016llx\n", addr);
+ atl_debug(ctx, " expected normalized addr = 0x%016llx\n", ctx->ret_addr);
+
+ return addr == ctx->ret_addr;
+}
+
+static int check_permutations(struct addr_ctx *ctx, struct df4p5_denorm_ctx *denorm_ctx)
+{
+ u64 test_perm, temp_addr, denorm_addr, num_perms;
+ unsigned int dropped_remainder;
+
+ denorm_ctx->div_addr *= denorm_ctx->mod_value;
+
+ /*
+ * The high order bits of num_permutations represent the permutations
+ * of the dropped remainder. This will be either 0-3 or 0-5 depending
+ * on the interleave mode. The low order bits represent the
+ * permutations of other "lost" bits which will be any combination of
+ * 1, 2, or 3 bits depending on the interleave mode.
+ */
+ num_perms = denorm_ctx->mod_value << denorm_ctx->perm_shift;
+
+ for (test_perm = 0; test_perm < num_perms; test_perm++) {
+ denorm_addr = denorm_ctx->base_denorm_addr;
+ dropped_remainder = test_perm >> denorm_ctx->perm_shift;
+ temp_addr = denorm_ctx->div_addr + dropped_remainder;
+
+ switch (ctx->map.intlv_mode) {
+ case DF4p5_NPS0_24CHAN_2K_HASH:
+ denorm_addr |= temp_addr << 14;
+ break;
+
+ case DF4p5_NPS0_24CHAN_1K_HASH:
+ case DF4p5_NPS1_12CHAN_2K_HASH:
+ denorm_addr |= temp_addr << 13;
+ break;
+
+ case DF4p5_NPS1_12CHAN_1K_HASH:
+ case DF4p5_NPS2_6CHAN_2K_HASH:
+ case DF4p5_NPS1_10CHAN_2K_HASH:
+ denorm_addr |= temp_addr << 12;
+ break;
+
+ case DF4p5_NPS2_6CHAN_1K_HASH:
+ case DF4p5_NPS1_10CHAN_1K_HASH:
+ denorm_addr |= FIELD_GET(BIT_ULL(0), temp_addr) << 9;
+ denorm_addr |= FIELD_GET(GENMASK_ULL(63, 1), temp_addr) << 12;
+ break;
+
+ case DF4p5_NPS4_3CHAN_1K_HASH:
+ case DF4p5_NPS2_5CHAN_1K_HASH:
+ denorm_addr |= FIELD_GET(GENMASK_ULL(1, 0), temp_addr) << 8;
+ denorm_addr |= FIELD_GET(GENMASK_ULL(63, 2), (temp_addr)) << 12;
+ break;
+
+ case DF4p5_NPS4_3CHAN_2K_HASH:
+ case DF4p5_NPS2_5CHAN_2K_HASH:
+ denorm_addr |= FIELD_GET(BIT_ULL(0), temp_addr) << 8;
+ denorm_addr |= FIELD_GET(GENMASK_ULL(63, 1), temp_addr) << 12;
+ break;
+
+ default:
+ atl_debug_on_bad_intlv_mode(ctx);
+ return -EINVAL;
+ }
+
+ switch (ctx->map.intlv_mode) {
+ case DF4p5_NPS0_24CHAN_1K_HASH:
+ denorm_addr |= FIELD_GET(BIT_ULL(0), test_perm) << 8;
+ denorm_addr |= FIELD_GET(BIT_ULL(1), test_perm) << 9;
+ denorm_addr |= FIELD_GET(BIT_ULL(2), test_perm) << 12;
+ break;
+
+ case DF4p5_NPS0_24CHAN_2K_HASH:
+ denorm_addr |= FIELD_GET(BIT_ULL(0), test_perm) << 8;
+ denorm_addr |= FIELD_GET(BIT_ULL(1), test_perm) << 12;
+ denorm_addr |= FIELD_GET(BIT_ULL(2), test_perm) << 13;
+ break;
+
+ case DF4p5_NPS1_12CHAN_2K_HASH:
+ denorm_addr |= FIELD_GET(BIT_ULL(0), test_perm) << 8;
+ denorm_addr |= FIELD_GET(BIT_ULL(1), test_perm) << 12;
+ break;
+
+ case DF4p5_NPS1_12CHAN_1K_HASH:
+ case DF4p5_NPS4_3CHAN_1K_HASH:
+ case DF4p5_NPS2_5CHAN_1K_HASH:
+ denorm_addr |= FIELD_GET(BIT_ULL(0), test_perm) << 8;
+ denorm_addr |= FIELD_GET(BIT_ULL(1), test_perm) << 9;
+ break;
+
+ case DF4p5_NPS2_6CHAN_1K_HASH:
+ case DF4p5_NPS2_6CHAN_2K_HASH:
+ case DF4p5_NPS4_3CHAN_2K_HASH:
+ case DF4p5_NPS1_10CHAN_1K_HASH:
+ case DF4p5_NPS1_10CHAN_2K_HASH:
+ case DF4p5_NPS2_5CHAN_2K_HASH:
+ denorm_addr |= FIELD_GET(BIT_ULL(0), test_perm) << 8;
+ break;
+
+ default:
+ atl_debug_on_bad_intlv_mode(ctx);
+ return -EINVAL;
+ }
+
+ denorm_ctx->current_spa = add_base_and_hole(ctx, denorm_addr);
+ recalculate_hashed_bits_df4p5_np2(ctx, denorm_ctx);
+
+ atl_debug(ctx, "Checking potential system physical address 0x%016llx\n",
+ denorm_ctx->current_spa);
+
+ if (!match_logical_coh_st_fabric_id(ctx, denorm_ctx))
+ continue;
+
+ if (!match_norm_addr(ctx, denorm_ctx))
+ continue;
+
+ if (denorm_ctx->resolved_spa == INVALID_SPA ||
+ denorm_ctx->current_spa > denorm_ctx->resolved_spa)
+ denorm_ctx->resolved_spa = denorm_ctx->current_spa;
+ }
+
+ if (denorm_ctx->resolved_spa == INVALID_SPA) {
+ atl_debug(ctx, "Failed to find valid SPA for normalized address 0x%016llx\n",
+ ctx->ret_addr);
+ return -EINVAL;
+ }
+
+ /* Return the resolved SPA without the base, without the MMIO hole */
+ ctx->ret_addr = remove_base_and_hole(ctx, denorm_ctx->resolved_spa);
+
+ return 0;
+}
+
+static int init_df4p5_denorm_ctx(struct addr_ctx *ctx, struct df4p5_denorm_ctx *denorm_ctx)
+{
+ denorm_ctx->current_spa = INVALID_SPA;
+ denorm_ctx->resolved_spa = INVALID_SPA;
+
+ switch (ctx->map.intlv_mode) {
+ case DF4p5_NPS0_24CHAN_1K_HASH:
+ denorm_ctx->perm_shift = 3;
+ denorm_ctx->rehash_vector = BIT(8) | BIT(9) | BIT(12);
+ break;
+
+ case DF4p5_NPS0_24CHAN_2K_HASH:
+ denorm_ctx->perm_shift = 3;
+ denorm_ctx->rehash_vector = BIT(8) | BIT(12) | BIT(13);
+ break;
+
+ case DF4p5_NPS1_12CHAN_1K_HASH:
+ denorm_ctx->perm_shift = 2;
+ denorm_ctx->rehash_vector = BIT(8);
+ break;
+
+ case DF4p5_NPS1_12CHAN_2K_HASH:
+ denorm_ctx->perm_shift = 2;
+ denorm_ctx->rehash_vector = BIT(8) | BIT(12);
+ break;
+
+ case DF4p5_NPS2_6CHAN_1K_HASH:
+ case DF4p5_NPS2_6CHAN_2K_HASH:
+ case DF4p5_NPS1_10CHAN_1K_HASH:
+ case DF4p5_NPS1_10CHAN_2K_HASH:
+ denorm_ctx->perm_shift = 1;
+ denorm_ctx->rehash_vector = BIT(8);
+ break;
+
+ case DF4p5_NPS4_3CHAN_1K_HASH:
+ case DF4p5_NPS2_5CHAN_1K_HASH:
+ denorm_ctx->perm_shift = 2;
+ denorm_ctx->rehash_vector = 0;
+ break;
+
+ case DF4p5_NPS4_3CHAN_2K_HASH:
+ case DF4p5_NPS2_5CHAN_2K_HASH:
+ denorm_ctx->perm_shift = 1;
+ denorm_ctx->rehash_vector = 0;
+ break;
+
+ default:
+ atl_debug_on_bad_intlv_mode(ctx);
+ return -EINVAL;
+ }
+
+ denorm_ctx->base_denorm_addr = FIELD_GET(GENMASK_ULL(7, 0), ctx->ret_addr);
+
+ switch (ctx->map.intlv_mode) {
+ case DF4p5_NPS0_24CHAN_1K_HASH:
+ case DF4p5_NPS1_12CHAN_1K_HASH:
+ case DF4p5_NPS2_6CHAN_1K_HASH:
+ case DF4p5_NPS4_3CHAN_1K_HASH:
+ case DF4p5_NPS1_10CHAN_1K_HASH:
+ case DF4p5_NPS2_5CHAN_1K_HASH:
+ denorm_ctx->base_denorm_addr |= FIELD_GET(GENMASK_ULL(9, 8), ctx->ret_addr) << 10;
+ denorm_ctx->div_addr = FIELD_GET(GENMASK_ULL(63, 10), ctx->ret_addr);
+ break;
+
+ case DF4p5_NPS0_24CHAN_2K_HASH:
+ case DF4p5_NPS1_12CHAN_2K_HASH:
+ case DF4p5_NPS2_6CHAN_2K_HASH:
+ case DF4p5_NPS4_3CHAN_2K_HASH:
+ case DF4p5_NPS1_10CHAN_2K_HASH:
+ case DF4p5_NPS2_5CHAN_2K_HASH:
+ denorm_ctx->base_denorm_addr |= FIELD_GET(GENMASK_ULL(10, 8), ctx->ret_addr) << 9;
+ denorm_ctx->div_addr = FIELD_GET(GENMASK_ULL(63, 11), ctx->ret_addr);
+ break;
+
+ default:
+ atl_debug_on_bad_intlv_mode(ctx);
+ return -EINVAL;
+ }
+
+ if (ctx->map.num_intlv_chan % 3 == 0)
+ denorm_ctx->mod_value = 3;
+ else
+ denorm_ctx->mod_value = 5;
+
+ denorm_ctx->coh_st_fabric_id = get_logical_coh_st_fabric_id(ctx) - get_dst_fabric_id(ctx);
+
+ atl_debug(ctx, "Initialized df4p5_denorm_ctx:");
+ atl_debug(ctx, " mod_value = %d", denorm_ctx->mod_value);
+ atl_debug(ctx, " perm_shift = %d", denorm_ctx->perm_shift);
+ atl_debug(ctx, " rehash_vector = 0x%x", denorm_ctx->rehash_vector);
+ atl_debug(ctx, " base_denorm_addr = 0x%016llx", denorm_ctx->base_denorm_addr);
+ atl_debug(ctx, " div_addr = 0x%016llx", denorm_ctx->div_addr);
+ atl_debug(ctx, " coh_st_fabric_id = 0x%x", denorm_ctx->coh_st_fabric_id);
+
+ return 0;
+}
+
+/*
+ * For DF 4.5, parts of the physical address can be directly pulled from the
+ * normalized address. The exact bits will differ between interleave modes, but
+ * using NPS0_24CHAN_1K_HASH as an example, the normalized address consists of
+ * bits [63:13] (divided by 3), bits [11:10], and bits [7:0] of the system
+ * physical address.
+ *
+ * In this case, there is no way to reconstruct the missing bits (bits 8, 9,
+ * and 12) from the normalized address. Additionally, when bits [63:13] are
+ * divided by 3, the remainder is dropped. Determine the proper combination of
+ * "lost" bits and dropped remainder by iterating through each possible
+ * permutation of these bits and then normalizing the generated system physical
+ * addresses. If the normalized address matches the address we are trying to
+ * translate, then we have found the correct permutation of bits.
+ */
+static int denorm_addr_df4p5_np2(struct addr_ctx *ctx)
+{
+ struct df4p5_denorm_ctx denorm_ctx;
+ int ret = 0;
+
+ memset(&denorm_ctx, 0, sizeof(denorm_ctx));
+
+ atl_debug(ctx, "Denormalizing DF 4.5 normalized address 0x%016llx", ctx->ret_addr);
+
+ ret = init_df4p5_denorm_ctx(ctx, &denorm_ctx);
+ if (ret)
+ return ret;
+
+ return check_permutations(ctx, &denorm_ctx);
+}
+
int denormalize_address(struct addr_ctx *ctx)
{
switch (ctx->map.intlv_mode) {
@@ -710,6 +1258,19 @@ int denormalize_address(struct addr_ctx *ctx)
case DF4_NPS2_5CHAN_HASH:
case DF4_NPS1_10CHAN_HASH:
return denorm_addr_df4_np2(ctx);
+ case DF4p5_NPS0_24CHAN_1K_HASH:
+ case DF4p5_NPS4_3CHAN_1K_HASH:
+ case DF4p5_NPS2_6CHAN_1K_HASH:
+ case DF4p5_NPS1_12CHAN_1K_HASH:
+ case DF4p5_NPS2_5CHAN_1K_HASH:
+ case DF4p5_NPS1_10CHAN_1K_HASH:
+ case DF4p5_NPS4_3CHAN_2K_HASH:
+ case DF4p5_NPS2_6CHAN_2K_HASH:
+ case DF4p5_NPS1_12CHAN_2K_HASH:
+ case DF4p5_NPS0_24CHAN_2K_HASH:
+ case DF4p5_NPS2_5CHAN_2K_HASH:
+ case DF4p5_NPS1_10CHAN_2K_HASH:
+ return denorm_addr_df4p5_np2(ctx);
case DF3_6CHAN:
return denorm_addr_df3_6chan(ctx);
default:
diff --git a/drivers/ras/amd/atl/internal.h b/drivers/ras/amd/atl/internal.h
index 196c1c8b578c..9de5d53d0568 100644
--- a/drivers/ras/amd/atl/internal.h
+++ b/drivers/ras/amd/atl/internal.h
@@ -21,6 +21,9 @@
#include "reg_fields.h"
+#undef pr_fmt
+#define pr_fmt(fmt) "amd_atl: " fmt
+
/* Maximum possible number of Coherent Stations within a single Data Fabric. */
#define MAX_COH_ST_CHANNELS 32
@@ -34,6 +37,8 @@
#define DF_DRAM_BASE_LIMIT_LSB 28
#define MI300_DRAM_LIMIT_LSB 20
+#define INVALID_SPA ~0ULL
+
enum df_revisions {
UNKNOWN,
DF2,
@@ -90,6 +95,44 @@ enum intlv_modes {
DF4p5_NPS1_10CHAN_2K_HASH = 0x49,
};
+struct df4p5_denorm_ctx {
+ /* Indicates the number of "lost" bits. This will be 1, 2, or 3. */
+ u8 perm_shift;
+
+ /* A mask indicating the bits that need to be rehashed. */
+ u16 rehash_vector;
+
+ /*
+ * Represents the value that the high bits of the normalized address
+ * are divided by during normalization. This value will be 3 for
+ * interleave modes with a number of channels divisible by 3 or the
+ * value will be 5 for interleave modes with a number of channels
+ * divisible by 5. Power-of-two interleave modes are handled
+ * separately.
+ */
+ u8 mod_value;
+
+ /*
+ * Represents the bits that can be directly pulled from the normalized
+ * address. In each case, pass through bits [7:0] of the normalized
+ * address. The other bits depend on the interleave bit position which
+ * will be bit 10 for 1K interleave stripe cases and bit 11 for 2K
+ * interleave stripe cases.
+ */
+ u64 base_denorm_addr;
+
+ /*
+ * Represents the high bits of the physical address that have been
+ * divided by the mod_value.
+ */
+ u64 div_addr;
+
+ u64 current_spa;
+ u64 resolved_spa;
+
+ u16 coh_st_fabric_id;
+};
+
struct df_flags {
__u8 legacy_ficaa : 1,
socket_id_shift_quirk : 1,
@@ -132,6 +175,8 @@ struct df_config {
/* Number of DRAM Address maps visible in a Coherent Station. */
u8 num_coh_st_maps;
+ u32 dram_hole_base;
+
/* Global flags to handle special cases. */
struct df_flags flags;
};
@@ -234,6 +279,9 @@ int dehash_address(struct addr_ctx *ctx);
unsigned long norm_to_sys_addr(u8 socket_id, u8 die_id, u8 coh_st_inst_id, unsigned long addr);
unsigned long convert_umc_mca_addr_to_sys_addr(struct atl_err *err);
+u64 add_base_and_hole(struct addr_ctx *ctx, u64 addr);
+u64 remove_base_and_hole(struct addr_ctx *ctx, u64 addr);
+
/*
* Make a gap in @data that is @num_bits long starting at @bit_num.
* e.g. data = 11111111'b
diff --git a/drivers/ras/amd/atl/map.c b/drivers/ras/amd/atl/map.c
index 8b908e8d7495..24a05af747d5 100644
--- a/drivers/ras/amd/atl/map.c
+++ b/drivers/ras/amd/atl/map.c
@@ -642,6 +642,99 @@ static int get_global_map_data(struct addr_ctx *ctx)
return 0;
}
+/*
+ * Verify the interleave bits are correct in the different interleaving
+ * settings.
+ *
+ * If @num_intlv_dies and/or @num_intlv_sockets are 1, it means the
+ * respective interleaving is disabled.
+ */
+static inline bool map_bits_valid(struct addr_ctx *ctx, u8 bit1, u8 bit2,
+ u8 num_intlv_dies, u8 num_intlv_sockets)
+{
+ if (!(ctx->map.intlv_bit_pos == bit1 || ctx->map.intlv_bit_pos == bit2)) {
+ pr_debug("Invalid interleave bit: %u", ctx->map.intlv_bit_pos);
+ return false;
+ }
+
+ if (ctx->map.num_intlv_dies > num_intlv_dies) {
+ pr_debug("Invalid number of interleave dies: %u", ctx->map.num_intlv_dies);
+ return false;
+ }
+
+ if (ctx->map.num_intlv_sockets > num_intlv_sockets) {
+ pr_debug("Invalid number of interleave sockets: %u", ctx->map.num_intlv_sockets);
+ return false;
+ }
+
+ return true;
+}
+
+static int validate_address_map(struct addr_ctx *ctx)
+{
+ switch (ctx->map.intlv_mode) {
+ case DF2_2CHAN_HASH:
+ case DF3_COD4_2CHAN_HASH:
+ case DF3_COD2_4CHAN_HASH:
+ case DF3_COD1_8CHAN_HASH:
+ if (!map_bits_valid(ctx, 8, 9, 1, 1))
+ goto err;
+ break;
+
+ case DF4_NPS4_2CHAN_HASH:
+ case DF4_NPS2_4CHAN_HASH:
+ case DF4_NPS1_8CHAN_HASH:
+ case DF4p5_NPS4_2CHAN_1K_HASH:
+ case DF4p5_NPS4_2CHAN_2K_HASH:
+ case DF4p5_NPS2_4CHAN_1K_HASH:
+ case DF4p5_NPS2_4CHAN_2K_HASH:
+ case DF4p5_NPS1_8CHAN_1K_HASH:
+ case DF4p5_NPS1_8CHAN_2K_HASH:
+ case DF4p5_NPS1_16CHAN_1K_HASH:
+ case DF4p5_NPS1_16CHAN_2K_HASH:
+ if (!map_bits_valid(ctx, 8, 8, 1, 2))
+ goto err;
+ break;
+
+ case DF4p5_NPS4_3CHAN_1K_HASH:
+ case DF4p5_NPS4_3CHAN_2K_HASH:
+ case DF4p5_NPS2_5CHAN_1K_HASH:
+ case DF4p5_NPS2_5CHAN_2K_HASH:
+ case DF4p5_NPS2_6CHAN_1K_HASH:
+ case DF4p5_NPS2_6CHAN_2K_HASH:
+ case DF4p5_NPS1_10CHAN_1K_HASH:
+ case DF4p5_NPS1_10CHAN_2K_HASH:
+ case DF4p5_NPS1_12CHAN_1K_HASH:
+ case DF4p5_NPS1_12CHAN_2K_HASH:
+ if (ctx->map.num_intlv_sockets != 1 || !map_bits_valid(ctx, 8, 0, 1, 1))
+ goto err;
+ break;
+
+ case DF4p5_NPS0_24CHAN_1K_HASH:
+ case DF4p5_NPS0_24CHAN_2K_HASH:
+ if (ctx->map.num_intlv_sockets < 2 || !map_bits_valid(ctx, 8, 0, 1, 2))
+ goto err;
+ break;
+
+ case MI3_HASH_8CHAN:
+ case MI3_HASH_16CHAN:
+ case MI3_HASH_32CHAN:
+ if (!map_bits_valid(ctx, 8, 8, 4, 1))
+ goto err;
+ break;
+
+ /* Nothing to do for modes that don't need special validation checks. */
+ default:
+ break;
+ }
+
+ return 0;
+
+err:
+ atl_debug(ctx, "Inconsistent address map");
+ return -EINVAL;
+}
+
static void dump_address_map(struct dram_addr_map *map)
{
u8 i;
@@ -678,5 +771,9 @@ int get_address_map(struct addr_ctx *ctx)
dump_address_map(&ctx->map);
+ ret = validate_address_map(ctx);
+ if (ret)
+ return ret;
+
return ret;
}
diff --git a/drivers/ras/amd/atl/system.c b/drivers/ras/amd/atl/system.c
index 6979fa3d4fe2..e18d916d5e8b 100644
--- a/drivers/ras/amd/atl/system.c
+++ b/drivers/ras/amd/atl/system.c
@@ -223,6 +223,21 @@ static int determine_df_rev(void)
return -EINVAL;
}
+static int get_dram_hole_base(void)
+{
+ u8 func = 0;
+
+ if (df_cfg.rev >= DF4)
+ func = 7;
+
+ if (df_indirect_read_broadcast(0, func, 0x104, &df_cfg.dram_hole_base))
+ return -EINVAL;
+
+ df_cfg.dram_hole_base &= DF_DRAM_HOLE_BASE_MASK;
+
+ return 0;
+}
+
static void get_num_maps(void)
{
switch (df_cfg.rev) {
@@ -266,6 +281,7 @@ static void dump_df_cfg(void)
pr_debug("num_coh_st_maps=%u", df_cfg.num_coh_st_maps);
+ pr_debug("dram_hole_base=0x%x", df_cfg.dram_hole_base);
pr_debug("flags.legacy_ficaa=%u", df_cfg.flags.legacy_ficaa);
pr_debug("flags.socket_id_shift_quirk=%u", df_cfg.flags.socket_id_shift_quirk);
}
@@ -273,7 +289,7 @@ static void dump_df_cfg(void)
int get_df_system_info(void)
{
if (determine_df_rev()) {
- pr_warn("amd_atl: Failed to determine DF Revision");
+ pr_warn("Failed to determine DF Revision");
df_cfg.rev = UNKNOWN;
return -EINVAL;
}
@@ -282,6 +298,9 @@ int get_df_system_info(void)
get_num_maps();
+ if (get_dram_hole_base())
+ pr_warn("Failed to read DRAM hole base");
+
dump_df_cfg();
return 0;
diff --git a/drivers/ras/amd/fmpm.c b/drivers/ras/amd/fmpm.c
index 271dfad05d68..90de737fbc90 100644
--- a/drivers/ras/amd/fmpm.c
+++ b/drivers/ras/amd/fmpm.c
@@ -56,6 +56,8 @@
#include "../debugfs.h"
+#include "atl/internal.h"
+
#define INVALID_CPU UINT_MAX
/* Validation Bits */
@@ -116,8 +118,6 @@ static struct fru_rec **fru_records;
/* system physical addresses array */
static u64 *spa_entries;
-#define INVALID_SPA ~0ULL
-
static struct dentry *fmpm_dfs_dir;
static struct dentry *fmpm_dfs_entries;
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index d333be2bea3b..0281a9a6f4ce 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1634,6 +1634,15 @@ config REGULATOR_UNIPHIER
help
Support for regulators implemented on Socionext UniPhier SoCs.
+config REGULATOR_RZG2L_VBCTRL
+ tristate "Renesas RZ/G2L USB VBUS regulator driver"
+ depends on ARCH_RZG2L || COMPILE_TEST
+ depends on OF
+ select REGMAP_MMIO
+ default ARCH_RZG2L
+ help
+ Support for VBUS regulators implemented on Renesas RZ/G2L SoCs.
+
config REGULATOR_VCTRL
tristate "Voltage controlled regulators"
depends on OF
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index ba15fa5f30ad..6127ffb4b011 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -189,6 +189,7 @@ obj-$(CONFIG_REGULATOR_TPS65132) += tps65132-regulator.o
obj-$(CONFIG_REGULATOR_TPS68470) += tps68470-regulator.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o
obj-$(CONFIG_REGULATOR_UNIPHIER) += uniphier-regulator.o
+obj-$(CONFIG_REGULATOR_RZG2L_VBCTRL) += renesas-usb-vbus-regulator.o
obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o
obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
obj-$(CONFIG_REGULATOR_VQMMC_IPQ4019) += vqmmc-ipq4019-regulator.o
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 844e9587a880..7674b7f2df14 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3409,6 +3409,34 @@ int regulator_list_hardware_vsel(struct regulator *regulator,
EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
/**
+ * regulator_hardware_enable - access the HW for enable/disable regulator
+ * @regulator: regulator source
+ * @enable: true for enable, false for disable
+ *
+ * Request that the regulator be enabled/disabled with the regulator output at
+ * the predefined voltage or current value.
+ *
+ * On success 0 is returned, otherwise a negative errno is returned.
+ */
+int regulator_hardware_enable(struct regulator *regulator, bool enable)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+ const struct regulator_ops *ops = rdev->desc->ops;
+ int ret = -EOPNOTSUPP;
+
+ if (!rdev->exclusive || !ops || !ops->enable || !ops->disable)
+ return ret;
+
+ if (enable)
+ ret = ops->enable(rdev);
+ else
+ ret = ops->disable(rdev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_hardware_enable);
+
+/**
* regulator_get_linear_step - return the voltage step size between VSEL values
* @regulator: regulator source
*
diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c
index 96257551bb12..d97162f73793 100644
--- a/drivers/regulator/da9121-regulator.c
+++ b/drivers/regulator/da9121-regulator.c
@@ -865,7 +865,7 @@ static const struct regmap_access_table da9121_volatile_table = {
};
/* DA9121 regmap config for 1 channel variants */
-static struct regmap_config da9121_1ch_regmap_config = {
+static const struct regmap_config da9121_1ch_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = DA9121_REG_OTP_CONFIG_ID,
@@ -876,7 +876,7 @@ static struct regmap_config da9121_1ch_regmap_config = {
};
/* DA9121 regmap config for 2 channel variants */
-static struct regmap_config da9121_2ch_regmap_config = {
+static const struct regmap_config da9121_2ch_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = DA9121_REG_OTP_CONFIG_ID,
@@ -993,7 +993,7 @@ error:
static int da9121_assign_chip_model(struct i2c_client *i2c,
struct da9121 *chip)
{
- struct regmap_config *regmap;
+ const struct regmap_config *regmap;
int ret = 0;
chip->dev = &i2c->dev;
@@ -1192,4 +1192,5 @@ static struct i2c_driver da9121_regulator_driver = {
module_i2c_driver(da9121_regulator_driver);
+MODULE_DESCRIPTION("Dialog Semiconductor DA9121/DA9122/DA9220/DA9217/DA9130/DA9131/DA9132 regulator driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index 02b85ca4a6fc..39ade0dba40f 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -202,8 +202,8 @@ static int da9210_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id da9210_i2c_id[] = {
- {"da9210", 0},
- {},
+ { "da9210" },
+ {}
};
MODULE_DEVICE_TABLE(i2c, da9210_i2c_id);
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index e1b5c45f97f4..d4dab86fe385 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -439,7 +439,7 @@ static int lp3971_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id lp3971_i2c_id[] = {
- { "lp3971", 0 },
+ { "lp3971" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index 7bd6f05edd8d..1b918fb72134 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -537,7 +537,7 @@ static int lp3972_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id lp3972_i2c_id[] = {
- { "lp3972", 0 },
+ { "lp3972" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp3972_i2c_id);
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c
index 8d01e18046f3..5509bee49bda 100644
--- a/drivers/regulator/lp8755.c
+++ b/drivers/regulator/lp8755.c
@@ -430,7 +430,7 @@ static void lp8755_remove(struct i2c_client *client)
}
static const struct i2c_device_id lp8755_id[] = {
- {LP8755_NAME, 0},
+ { LP8755_NAME },
{}
};
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 0f133129252e..4242fbb7b147 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -276,7 +276,7 @@ static int max1586_pmic_probe(struct i2c_client *client)
}
static const struct i2c_device_id max1586_id[] = {
- { "max1586", 0 },
+ { "max1586" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max1586_id);
diff --git a/drivers/regulator/max20411-regulator.c b/drivers/regulator/max20411-regulator.c
index 8c09dc71b16d..02d7009ea0e6 100644
--- a/drivers/regulator/max20411-regulator.c
+++ b/drivers/regulator/max20411-regulator.c
@@ -145,8 +145,8 @@ static const struct of_device_id of_max20411_match_tbl[] = {
MODULE_DEVICE_TABLE(of, of_max20411_match_tbl);
static const struct i2c_device_id max20411_id[] = {
- { "max20411", 0 },
- { },
+ { "max20411" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, max20411_id);
@@ -161,4 +161,5 @@ static struct i2c_driver max20411_i2c_driver = {
};
module_i2c_driver(max20411_i2c_driver);
+MODULE_DESCRIPTION("Maxim MAX20411 High-Efficiency Single Step-Down Converter driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/max77503-regulator.c b/drivers/regulator/max77503-regulator.c
index 4a6ba4dd2acd..c7c94e868fc1 100644
--- a/drivers/regulator/max77503-regulator.c
+++ b/drivers/regulator/max77503-regulator.c
@@ -25,14 +25,6 @@
#define MAX77503_AD_ENABLED 0x1
#define MAX77503_AD_DISABLED 0x0
-struct max77503_dev {
- struct device *dev;
- struct device_node *of_node;
- struct regulator_desc desc;
- struct regulator_dev *rdev;
- struct regmap *regmap;
-};
-
static const struct regmap_config max77503_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
diff --git a/drivers/regulator/max77857-regulator.c b/drivers/regulator/max77857-regulator.c
index 145ad0281857..bc28dc8503a8 100644
--- a/drivers/regulator/max77857-regulator.c
+++ b/drivers/regulator/max77857-regulator.c
@@ -67,7 +67,7 @@ static bool max77857_volatile_reg(struct device *dev, unsigned int reg)
}
}
-static struct regmap_config max77857_regmap_config = {
+static const struct regmap_config max77857_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.cache_type = REGCACHE_MAPLE,
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 24e1dfba78c8..f57c588bcf28 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -240,7 +240,7 @@ static int max8649_regulator_probe(struct i2c_client *client)
}
static const struct i2c_device_id max8649_id[] = {
- { "max8649", 0 },
+ { "max8649" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max8649_id);
diff --git a/drivers/regulator/max8893.c b/drivers/regulator/max8893.c
index 30592425e193..5a90633d8536 100644
--- a/drivers/regulator/max8893.c
+++ b/drivers/regulator/max8893.c
@@ -162,8 +162,8 @@ MODULE_DEVICE_TABLE(of, max8893_dt_match);
#endif
static const struct i2c_device_id max8893_ids[] = {
- { "max8893", 0 },
- { },
+ { "max8893" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, max8893_ids);
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 0b0b841d214a..1f94315bfb02 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -307,8 +307,8 @@ static int max8952_pmic_probe(struct i2c_client *client)
}
static const struct i2c_device_id max8952_ids[] = {
- { "max8952", 0 },
- { },
+ { "max8952" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, max8952_ids);
diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c
index 0c15a19fe83a..5de9d4fa5113 100644
--- a/drivers/regulator/mcp16502.c
+++ b/drivers/regulator/mcp16502.c
@@ -577,7 +577,7 @@ static const struct dev_pm_ops mcp16502_pm_ops = {
};
#endif
static const struct i2c_device_id mcp16502_i2c_id[] = {
- { "mcp16502", 0 },
+ { "mcp16502" },
{ }
};
MODULE_DEVICE_TABLE(i2c, mcp16502_i2c_id);
diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c
index c00638cd2d1e..2ebc1c0b5e6f 100644
--- a/drivers/regulator/mt6311-regulator.c
+++ b/drivers/regulator/mt6311-regulator.c
@@ -133,8 +133,8 @@ static int mt6311_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id mt6311_i2c_id[] = {
- {"mt6311", 0},
- {},
+ { "mt6311" },
+ {}
};
MODULE_DEVICE_TABLE(i2c, mt6311_i2c_id);
diff --git a/drivers/regulator/mtk-dvfsrc-regulator.c b/drivers/regulator/mtk-dvfsrc-regulator.c
index f1280d45265d..9bf4163221f1 100644
--- a/drivers/regulator/mtk-dvfsrc-regulator.c
+++ b/drivers/regulator/mtk-dvfsrc-regulator.c
@@ -1,99 +1,94 @@
// SPDX-License-Identifier: GPL-2.0
-//
-// Copyright (c) 2020 MediaTek Inc.
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ * Copyright (c) 2024 Collabora Ltd.
+ * AngeloGioacchino Del Regno <[email protected]>
+ */
-#include <linux/err.h>
-#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/of_.h>
+#include <linux/of.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
-#include <linux/soc/mediatek/mtk_dvfsrc.h>
-
-#define DVFSRC_ID_VCORE 0
-#define DVFSRC_ID_VSCP 1
-
-#define MT_DVFSRC_REGULAR(match, _name, _volt_table) \
-[DVFSRC_ID_##_name] = { \
- .desc = { \
- .name = match, \
- .of_match = of_match_ptr(match), \
- .ops = &dvfsrc_vcore_ops, \
- .type = REGULATOR_VOLTAGE, \
- .id = DVFSRC_ID_##_name, \
- .owner = THIS_MODULE, \
- .n_voltages = ARRAY_SIZE(_volt_table), \
- .volt_table = _volt_table, \
- }, \
-}
-
-/*
- * DVFSRC regulators' information
- *
- * @desc: standard fields of regulator description.
- * @voltage_selector: Selector used for get_voltage_sel() and
- * set_voltage_sel() callbacks
- */
+#include <linux/soc/mediatek/dvfsrc.h>
-struct dvfsrc_regulator {
- struct regulator_desc desc;
+enum dvfsrc_regulator_id {
+ DVFSRC_ID_VCORE,
+ DVFSRC_ID_VSCP,
+ DVFSRC_ID_MAX
};
-/*
- * MTK DVFSRC regulators' init data
- *
- * @size: num of regulators
- * @regulator_info: regulator info.
- */
-struct dvfsrc_regulator_init_data {
+struct dvfsrc_regulator_pdata {
+ struct regulator_desc *descs;
u32 size;
- struct dvfsrc_regulator *regulator_info;
};
-static inline struct device *to_dvfsrc_dev(struct regulator_dev *rdev)
+#define MTK_DVFSRC_VREG(match, _name, _volt_table) \
+{ \
+ .name = match, \
+ .of_match = match, \
+ .ops = &dvfsrc_vcore_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = DVFSRC_ID_##_name, \
+ .owner = THIS_MODULE, \
+ .n_voltages = ARRAY_SIZE(_volt_table), \
+ .volt_table = _volt_table, \
+}
+
+static inline struct device *to_dvfs_regulator_dev(struct regulator_dev *rdev)
{
return rdev_get_dev(rdev)->parent;
}
+static inline struct device *to_dvfsrc_dev(struct regulator_dev *rdev)
+{
+ return to_dvfs_regulator_dev(rdev)->parent;
+}
+
+static int dvfsrc_get_cmd(int rdev_id, enum mtk_dvfsrc_cmd *cmd)
+{
+ switch (rdev_id) {
+ case DVFSRC_ID_VCORE:
+ *cmd = MTK_DVFSRC_CMD_VCORE_LEVEL;
+ break;
+ case DVFSRC_ID_VSCP:
+ *cmd = MTK_DVFSRC_CMD_VSCP_LEVEL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int dvfsrc_set_voltage_sel(struct regulator_dev *rdev,
unsigned int selector)
{
struct device *dvfsrc_dev = to_dvfsrc_dev(rdev);
+ enum mtk_dvfsrc_cmd req_cmd;
int id = rdev_get_id(rdev);
+ int ret;
- if (id == DVFSRC_ID_VCORE)
- mtk_dvfsrc_send_request(dvfsrc_dev,
- MTK_DVFSRC_CMD_VCORE_REQUEST,
- selector);
- else if (id == DVFSRC_ID_VSCP)
- mtk_dvfsrc_send_request(dvfsrc_dev,
- MTK_DVFSRC_CMD_VSCP_REQUEST,
- selector);
- else
- return -EINVAL;
+ ret = dvfsrc_get_cmd(id, &req_cmd);
+ if (ret)
+ return ret;
- return 0;
+ return mtk_dvfsrc_send_request(dvfsrc_dev, req_cmd, selector);
}
static int dvfsrc_get_voltage_sel(struct regulator_dev *rdev)
{
struct device *dvfsrc_dev = to_dvfsrc_dev(rdev);
+ enum mtk_dvfsrc_cmd query_cmd;
int id = rdev_get_id(rdev);
int val, ret;
- if (id == DVFSRC_ID_VCORE)
- ret = mtk_dvfsrc_query_info(dvfsrc_dev,
- MTK_DVFSRC_CMD_VCORE_LEVEL_QUERY,
- &val);
- else if (id == DVFSRC_ID_VSCP)
- ret = mtk_dvfsrc_query_info(dvfsrc_dev,
- MTK_DVFSRC_CMD_VSCP_LEVEL_QUERY,
- &val);
- else
- return -EINVAL;
+ ret = dvfsrc_get_cmd(id, &query_cmd);
+ if (ret)
+ return ret;
- if (ret != 0)
+ ret = mtk_dvfsrc_query_info(dvfsrc_dev, query_cmd, &val);
+ if (ret)
return ret;
return val;
@@ -105,110 +100,97 @@ static const struct regulator_ops dvfsrc_vcore_ops = {
.set_voltage_sel = dvfsrc_set_voltage_sel,
};
+static const unsigned int mt6873_voltages[] = {
+ 575000,
+ 600000,
+ 650000,
+ 725000,
+};
+
+static struct regulator_desc mt6873_regulators[] = {
+ MTK_DVFSRC_VREG("dvfsrc-vcore", VCORE, mt6873_voltages),
+ MTK_DVFSRC_VREG("dvfsrc-vscp", VSCP, mt6873_voltages),
+};
+
+static const struct dvfsrc_regulator_pdata mt6873_data = {
+ .descs = mt6873_regulators,
+ .size = ARRAY_SIZE(mt6873_regulators),
+};
+
static const unsigned int mt8183_voltages[] = {
725000,
800000,
};
-static struct dvfsrc_regulator mt8183_regulators[] = {
- MT_DVFSRC_REGULAR("dvfsrc-vcore", VCORE,
- mt8183_voltages),
+static struct regulator_desc mt8183_regulators[] = {
+ MTK_DVFSRC_VREG("dvfsrc-vcore", VCORE, mt8183_voltages),
};
-static const struct dvfsrc_regulator_init_data regulator_mt8183_data = {
+static const struct dvfsrc_regulator_pdata mt8183_data = {
+ .descs = mt8183_regulators,
.size = ARRAY_SIZE(mt8183_regulators),
- .regulator_info = &mt8183_regulators[0],
};
-static const unsigned int mt6873_voltages[] = {
- 575000,
+static const unsigned int mt8195_voltages[] = {
+ 550000,
600000,
650000,
- 725000,
+ 750000,
};
-static struct dvfsrc_regulator mt6873_regulators[] = {
- MT_DVFSRC_REGULAR("dvfsrc-vcore", VCORE,
- mt6873_voltages),
- MT_DVFSRC_REGULAR("dvfsrc-vscp", VSCP,
- mt6873_voltages),
-};
-
-static const struct dvfsrc_regulator_init_data regulator_mt6873_data = {
- .size = ARRAY_SIZE(mt6873_regulators),
- .regulator_info = &mt6873_regulators[0],
+static struct regulator_desc mt8195_regulators[] = {
+ MTK_DVFSRC_VREG("dvfsrc-vcore", VCORE, mt8195_voltages),
+ MTK_DVFSRC_VREG("dvfsrc-vscp", VSCP, mt8195_voltages),
};
-static const struct of_device_id mtk_dvfsrc_regulator_match[] = {
- {
- .compatible = "mediatek,mt8183-dvfsrc",
- .data = &regulator_mt8183_data,
- }, {
- .compatible = "mediatek,mt8192-dvfsrc",
- .data = &regulator_mt6873_data,
- }, {
- .compatible = "mediatek,mt6873-dvfsrc",
- .data = &regulator_mt6873_data,
- }, {
- /* sentinel */
- },
+static const struct dvfsrc_regulator_pdata mt8195_data = {
+ .descs = mt8195_regulators,
+ .size = ARRAY_SIZE(mt8195_regulators),
};
-MODULE_DEVICE_TABLE(of, mtk_dvfsrc_regulator_match);
static int dvfsrc_vcore_regulator_probe(struct platform_device *pdev)
{
- const struct of_device_id *match;
- struct device *dev = &pdev->dev;
- struct regulator_config config = { };
- struct regulator_dev *rdev;
- const struct dvfsrc_regulator_init_data *regulator_init_data;
- struct dvfsrc_regulator *mt_regulators;
+ struct regulator_config config = { .dev = &pdev->dev };
+ const struct dvfsrc_regulator_pdata *pdata;
int i;
- match = of_match_node(mtk_dvfsrc_regulator_match, dev->parent->of_node);
+ pdata = device_get_match_data(&pdev->dev);
+ if (!pdata)
+ return -EINVAL;
- if (!match) {
- dev_err(dev, "invalid compatible string\n");
- return -ENODEV;
- }
+ for (i = 0; i < pdata->size; i++) {
+ struct regulator_desc *vrdesc = &pdata->descs[i];
+ struct regulator_dev *rdev;
- regulator_init_data = match->data;
-
- mt_regulators = regulator_init_data->regulator_info;
- for (i = 0; i < regulator_init_data->size; i++) {
- config.dev = dev->parent;
- config.driver_data = (mt_regulators + i);
- rdev = devm_regulator_register(dev, &(mt_regulators + i)->desc,
- &config);
- if (IS_ERR(rdev)) {
- dev_err(dev, "failed to register %s\n",
- (mt_regulators + i)->desc.name);
- return PTR_ERR(rdev);
- }
+ rdev = devm_regulator_register(&pdev->dev, vrdesc, &config);
+ if (IS_ERR(rdev))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rdev),
+ "failed to register %s\n", vrdesc->name);
}
return 0;
}
+static const struct of_device_id mtk_dvfsrc_regulator_match[] = {
+ { .compatible = "mediatek,mt6873-dvfsrc-regulator", .data = &mt6873_data },
+ { .compatible = "mediatek,mt8183-dvfsrc-regulator", .data = &mt8183_data },
+ { .compatible = "mediatek,mt8192-dvfsrc-regulator", .data = &mt6873_data },
+ { .compatible = "mediatek,mt8195-dvfsrc-regulator", .data = &mt8195_data },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mtk_dvfsrc_regulator_match);
+
static struct platform_driver mtk_dvfsrc_regulator_driver = {
.driver = {
.name = "mtk-dvfsrc-regulator",
+ .of_match_table = mtk_dvfsrc_regulator_match,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = dvfsrc_vcore_regulator_probe,
};
+module_platform_driver(mtk_dvfsrc_regulator_driver);
-static int __init mtk_dvfsrc_regulator_init(void)
-{
- return platform_driver_register(&mtk_dvfsrc_regulator_driver);
-}
-subsys_initcall(mtk_dvfsrc_regulator_init);
-
-static void __exit mtk_dvfsrc_regulator_exit(void)
-{
- platform_driver_unregister(&mtk_dvfsrc_regulator_driver);
-}
-module_exit(mtk_dvfsrc_regulator_exit);
-
+MODULE_AUTHOR("AngeloGioacchino Del Regno <[email protected]>");
MODULE_AUTHOR("Arvin wang <[email protected]>");
-MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MediaTek DVFS Resource Collector Regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c
index be488c5dff14..9714afe347dc 100644
--- a/drivers/regulator/pca9450-regulator.c
+++ b/drivers/regulator/pca9450-regulator.c
@@ -891,11 +891,6 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
unsigned int reset_ctrl;
int ret;
- if (!i2c->irq) {
- dev_err(&i2c->dev, "No IRQ configured?\n");
- return -EINVAL;
- }
-
pca9450 = devm_kzalloc(&i2c->dev, sizeof(struct pca9450), GFP_KERNEL);
if (!pca9450)
return -ENOMEM;
@@ -967,23 +962,25 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
}
}
- ret = devm_request_threaded_irq(pca9450->dev, pca9450->irq, NULL,
- pca9450_irq_handler,
- (IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
- "pca9450-irq", pca9450);
- if (ret != 0) {
- dev_err(pca9450->dev, "Failed to request IRQ: %d\n",
- pca9450->irq);
- return ret;
- }
- /* Unmask all interrupt except PWRON/WDOG/RSVD */
- ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_INT1_MSK,
- IRQ_VR_FLT1 | IRQ_VR_FLT2 | IRQ_LOWVSYS |
- IRQ_THERM_105 | IRQ_THERM_125,
- IRQ_PWRON | IRQ_WDOGB | IRQ_RSVD);
- if (ret) {
- dev_err(&i2c->dev, "Unmask irq error\n");
- return ret;
+ if (pca9450->irq) {
+ ret = devm_request_threaded_irq(pca9450->dev, pca9450->irq, NULL,
+ pca9450_irq_handler,
+ (IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
+ "pca9450-irq", pca9450);
+ if (ret != 0) {
+ dev_err(pca9450->dev, "Failed to request IRQ: %d\n",
+ pca9450->irq);
+ return ret;
+ }
+ /* Unmask all interrupt except PWRON/WDOG/RSVD */
+ ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_INT1_MSK,
+ IRQ_VR_FLT1 | IRQ_VR_FLT2 | IRQ_LOWVSYS |
+ IRQ_THERM_105 | IRQ_THERM_125,
+ IRQ_PWRON | IRQ_WDOGB | IRQ_RSVD);
+ if (ret) {
+ dev_err(&i2c->dev, "Unmask irq error\n");
+ return ret;
+ }
}
/* Clear PRESET_EN bit in BUCK123_DVS to use DVS registers */
diff --git a/drivers/regulator/pf8x00-regulator.c b/drivers/regulator/pf8x00-regulator.c
index 9fd8e0949b32..ea3611de42b4 100644
--- a/drivers/regulator/pf8x00-regulator.c
+++ b/drivers/regulator/pf8x00-regulator.c
@@ -596,10 +596,10 @@ static const struct of_device_id pf8x00_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pf8x00_dt_ids);
static const struct i2c_device_id pf8x00_i2c_id[] = {
- { "pf8100", 0 },
- { "pf8121a", 0 },
- { "pf8200", 0 },
- {},
+ { "pf8100" },
+ { "pf8121a" },
+ { "pf8200" },
+ {}
};
MODULE_DEVICE_TABLE(i2c, pf8x00_i2c_id);
diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c
index aa90360fa046..ae1c4b9daaa1 100644
--- a/drivers/regulator/pv88060-regulator.c
+++ b/drivers/regulator/pv88060-regulator.c
@@ -360,8 +360,8 @@ static int pv88060_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id pv88060_i2c_id[] = {
- {"pv88060", 0},
- {},
+ { "pv88060" },
+ {}
};
MODULE_DEVICE_TABLE(i2c, pv88060_i2c_id);
diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c
index f4acde4d56c8..3c48757bbbda 100644
--- a/drivers/regulator/pv88090-regulator.c
+++ b/drivers/regulator/pv88090-regulator.c
@@ -381,8 +381,8 @@ static int pv88090_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id pv88090_i2c_id[] = {
- {"pv88090", 0},
- {},
+ { "pv88090" },
+ {}
};
MODULE_DEVICE_TABLE(i2c, pv88090_i2c_id);
diff --git a/drivers/regulator/renesas-usb-vbus-regulator.c b/drivers/regulator/renesas-usb-vbus-regulator.c
new file mode 100644
index 000000000000..4eceb6b54497
--- /dev/null
+++ b/drivers/regulator/renesas-usb-vbus-regulator.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Renesas USB VBUS output regulator driver
+//
+// Copyright (C) 2024 Renesas Electronics Corporation
+//
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+static const struct regulator_ops rzg2l_usb_vbus_reg_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static const struct regulator_desc rzg2l_usb_vbus_rdesc = {
+ .name = "vbus",
+ .of_match = of_match_ptr("regulator-vbus"),
+ .ops = &rzg2l_usb_vbus_reg_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .enable_reg = 0,
+ .enable_mask = BIT(0),
+ .enable_is_inverted = true,
+ .fixed_uV = 5000000,
+ .n_voltages = 1,
+};
+
+static int rzg2l_usb_vbus_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_config config = { };
+ struct device *dev = &pdev->dev;
+ struct regulator_dev *rdev;
+
+ config.regmap = dev_get_regmap(dev->parent, NULL);
+ if (!config.regmap)
+ return dev_err_probe(dev, -ENOENT, "Failed to get regmap\n");
+
+ config.dev = dev;
+ config.of_node = of_get_child_by_name(dev->parent->of_node, "regulator-vbus");
+ if (!config.of_node)
+ return dev_err_probe(dev, -ENODEV, "regulator node not found\n");
+
+ rdev = devm_regulator_register(dev, &rzg2l_usb_vbus_rdesc, &config);
+ if (IS_ERR(rdev)) {
+ of_node_put(config.of_node);
+ return dev_err_probe(dev, PTR_ERR(rdev),
+ "not able to register vbus regulator\n");
+ }
+
+ of_node_put(config.of_node);
+
+ return 0;
+}
+
+static struct platform_driver rzg2l_usb_vbus_regulator_driver = {
+ .probe = rzg2l_usb_vbus_regulator_probe,
+ .driver = {
+ .name = "rzg2l-usb-vbus-regulator",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+};
+module_platform_driver(rzg2l_usb_vbus_regulator_driver);
+
+MODULE_AUTHOR("Biju Das <[email protected]>");
+MODULE_DESCRIPTION("Renesas RZ/G2L USB Vbus Regulator Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/rt4831-regulator.c b/drivers/regulator/rt4831-regulator.c
index 97e6f7e2a0ba..dfc868a24056 100644
--- a/drivers/regulator/rt4831-regulator.c
+++ b/drivers/regulator/rt4831-regulator.c
@@ -202,4 +202,5 @@ static struct platform_driver rt4831_regulator_driver = {
module_platform_driver(rt4831_regulator_driver);
MODULE_AUTHOR("ChiYuan Huang <[email protected]>");
+MODULE_DESCRIPTION("Richtek RT4831 DSV Regulators driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/rtq2208-regulator.c b/drivers/regulator/rtq2208-regulator.c
index c31b6dc3229c..a5c126afc648 100644
--- a/drivers/regulator/rtq2208-regulator.c
+++ b/drivers/regulator/rtq2208-regulator.c
@@ -219,7 +219,7 @@ static const struct regulator_ops rtq2208_regulator_buck_ops = {
.set_suspend_mode = rtq2208_set_suspend_mode,
};
-static const struct regulator_ops rtq2208_regulator_ldo_ops = {
+static const struct regulator_ops rtq2208_regulator_ldo_fix_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -228,6 +228,23 @@ static const struct regulator_ops rtq2208_regulator_ldo_ops = {
.set_suspend_disable = rtq2208_set_suspend_disable,
};
+static const struct regulator_ops rtq2208_regulator_ldo_adj_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_table,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+ .set_suspend_enable = rtq2208_set_suspend_enable,
+ .set_suspend_disable = rtq2208_set_suspend_disable,
+};
+
+static const unsigned int rtq2208_ldo_volt_table[] = {
+ 1800000,
+ 3300000,
+};
+
static struct of_regulator_match rtq2208_ldo_match[] = {
{.name = "ldo2", },
{.name = "ldo1", },
@@ -331,8 +348,9 @@ static int rtq2208_of_get_ldo_dvs_ability(struct device *dev)
{
struct device_node *np;
struct of_regulator_match *match;
- struct rtq2208_regulator_desc *rdesc;
+ struct regulator_desc *desc;
struct regulator_init_data *init_data;
+ u32 fixed_uV;
int ret, i;
if (!dev->of_node)
@@ -352,13 +370,27 @@ static int rtq2208_of_get_ldo_dvs_ability(struct device *dev)
for (i = 0; i < ARRAY_SIZE(rtq2208_ldo_match); i++) {
match = rtq2208_ldo_match + i;
init_data = match->init_data;
- rdesc = (struct rtq2208_regulator_desc *)match->driver_data;
+ desc = (struct regulator_desc *)match->desc;
- if (!init_data || !rdesc)
+ if (!init_data || !desc)
continue;
- if (init_data->constraints.min_uV == init_data->constraints.max_uV)
- rdesc->desc.fixed_uV = init_data->constraints.min_uV;
+ /* specify working fixed voltage if the propery exists */
+ ret = of_property_read_u32(match->of_node, "richtek,fixed-microvolt", &fixed_uV);
+
+ if (!ret) {
+ if (fixed_uV != init_data->constraints.min_uV ||
+ fixed_uV != init_data->constraints.max_uV)
+ return -EINVAL;
+ desc->n_voltages = 1;
+ desc->fixed_uV = fixed_uV;
+ desc->fixed_uV = init_data->constraints.min_uV;
+ desc->ops = &rtq2208_regulator_ldo_fix_ops;
+ } else {
+ desc->n_voltages = ARRAY_SIZE(rtq2208_ldo_volt_table);
+ desc->volt_table = rtq2208_ldo_volt_table;
+ desc->ops = &rtq2208_regulator_ldo_adj_ops;
+ }
}
return 0;
diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c
index 59aa16825d8a..3bbd4a29e6d3 100644
--- a/drivers/regulator/slg51000-regulator.c
+++ b/drivers/regulator/slg51000-regulator.c
@@ -497,8 +497,8 @@ static int slg51000_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id slg51000_i2c_id[] = {
- {"slg51000", 0},
- {},
+ { "slg51000" },
+ {}
};
MODULE_DEVICE_TABLE(i2c, slg51000_i2c_id);
diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c
index 85b0102fb9b1..b7aeef6e09e7 100644
--- a/drivers/regulator/stm32-pwr.c
+++ b/drivers/regulator/stm32-pwr.c
@@ -166,6 +166,7 @@ static int stm32_pwr_regulator_probe(struct platform_device *pdev)
static const struct of_device_id __maybe_unused stm32_pwr_of_match[] = {
{ .compatible = "st,stm32mp1,pwr-reg", },
+ { .compatible = "st,stm32mp13-pwr-reg", },
{},
};
MODULE_DEVICE_TABLE(of, stm32_pwr_of_match);
diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c
index 1bcfdd6dcfc1..d79a4cc25a0d 100644
--- a/drivers/regulator/sy8106a-regulator.c
+++ b/drivers/regulator/sy8106a-regulator.c
@@ -130,8 +130,8 @@ static const struct of_device_id sy8106a_i2c_of_match[] = {
MODULE_DEVICE_TABLE(of, sy8106a_i2c_of_match);
static const struct i2c_device_id sy8106a_i2c_id[] = {
- { "sy8106a", 0 },
- { },
+ { "sy8106a" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, sy8106a_i2c_id);
diff --git a/drivers/regulator/tps6286x-regulator.c b/drivers/regulator/tps6286x-regulator.c
index 758c70269653..75f441f36de7 100644
--- a/drivers/regulator/tps6286x-regulator.c
+++ b/drivers/regulator/tps6286x-regulator.c
@@ -136,11 +136,11 @@ static int tps6286x_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id tps6286x_i2c_id[] = {
- { "tps62864", 0 },
- { "tps62866", 0 },
- { "tps62868", 0 },
- { "tps62869", 0 },
- {},
+ { "tps62864" },
+ { "tps62866" },
+ { "tps62868" },
+ { "tps62869" },
+ {}
};
MODULE_DEVICE_TABLE(i2c, tps6286x_i2c_id);
@@ -156,4 +156,5 @@ static struct i2c_driver tps6286x_regulator_driver = {
module_i2c_driver(tps6286x_regulator_driver);
+MODULE_DESCRIPTION("TI TPS6286x Power Regulator driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps6287x-regulator.c b/drivers/regulator/tps6287x-regulator.c
index 3c9d79e003e4..7a0551f0c8c0 100644
--- a/drivers/regulator/tps6287x-regulator.c
+++ b/drivers/regulator/tps6287x-regulator.c
@@ -165,11 +165,11 @@ static const struct of_device_id tps6287x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, tps6287x_dt_ids);
static const struct i2c_device_id tps6287x_i2c_id[] = {
- { "tps62870", 0 },
- { "tps62871", 0 },
- { "tps62872", 0 },
- { "tps62873", 0 },
- {},
+ { "tps62870" },
+ { "tps62871" },
+ { "tps62872" },
+ { "tps62873" },
+ {}
};
MODULE_DEVICE_TABLE(i2c, tps6287x_i2c_id);
diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c
index 86a626a4f610..6153d0295b6d 100644
--- a/drivers/regulator/userspace-consumer.c
+++ b/drivers/regulator/userspace-consumer.c
@@ -158,10 +158,8 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev)
ret = devm_regulator_bulk_get_exclusive(&pdev->dev, drvdata->num_supplies,
drvdata->supplies);
- if (ret) {
- dev_err(&pdev->dev, "Failed to get supplies: %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Failed to get supplies\n");
platform_set_drvdata(pdev, drvdata);
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 7112f5932609..67bce340a87e 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -68,6 +68,7 @@ config RESET_BRCMSTB_RESCAL
config RESET_GPIO
tristate "GPIO reset controller"
+ depends on GPIOLIB
help
This enables a generic reset controller for resets attached via
GPIOs. Typically for OF platforms this driver expects "reset-gpios"
@@ -91,6 +92,14 @@ config RESET_IMX7
help
This enables the reset controller driver for i.MX7 SoCs.
+config RESET_IMX8MP_AUDIOMIX
+ tristate "i.MX8MP AudioMix Reset Driver"
+ depends on ARCH_MXC || COMPILE_TEST
+ select AUXILIARY_BUS
+ default CLK_IMX8MP
+ help
+ This enables the reset controller driver for i.MX8MP AudioMix
+
config RESET_INTEL_GW
bool "Intel Reset Controller Driver"
depends on X86 || COMPILE_TEST
@@ -328,6 +337,12 @@ config RESET_ZYNQ
help
This enables the reset controller driver for Xilinx Zynq SoCs.
+config RESET_ZYNQMP
+ bool "ZYNQMP Reset Driver" if COMPILE_TEST
+ default ARCH_ZYNQMP
+ help
+ This enables the reset controller driver for Xilinx ZynqMP SoCs.
+
source "drivers/reset/starfive/Kconfig"
source "drivers/reset/sti/Kconfig"
source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index fd8b49fa46fc..27b0bbdfcc04 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -2,8 +2,8 @@
obj-y += core.o
obj-y += hisilicon/
obj-y += starfive/
-obj-$(CONFIG_ARCH_STI) += sti/
-obj-$(CONFIG_ARCH_TEGRA) += tegra/
+obj-y += sti/
+obj-y += tegra/
obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o
@@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
obj-$(CONFIG_RESET_GPIO) += reset-gpio.o
obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
+obj-$(CONFIG_RESET_IMX8MP_AUDIOMIX) += reset-imx8mp-audiomix.o
obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o
obj-$(CONFIG_RESET_K210) += reset-k210.o
obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
@@ -41,4 +42,4 @@ obj-$(CONFIG_RESET_TN48M_CPLD) += reset-tn48m.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
-obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
+obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
diff --git a/drivers/reset/hisilicon/hi6220_reset.c b/drivers/reset/hisilicon/hi6220_reset.c
index 5c3267acd2b1..65aa5ff5ed82 100644
--- a/drivers/reset/hisilicon/hi6220_reset.c
+++ b/drivers/reset/hisilicon/hi6220_reset.c
@@ -219,4 +219,5 @@ static int __init hi6220_reset_init(void)
postcore_initcall(hi6220_reset_init);
+MODULE_DESCRIPTION("Hisilicon Hi6220 reset controller driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
new file mode 100644
index 000000000000..6e3f3069f727
--- /dev/null
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2024 NXP
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/reset-controller.h>
+
+#define EARC 0x200
+#define EARC_RESET_MASK 0x3
+
+struct imx8mp_audiomix_reset {
+ struct reset_controller_dev rcdev;
+ spinlock_t lock; /* protect register read-modify-write cycle */
+ void __iomem *base;
+};
+
+static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct imx8mp_audiomix_reset, rcdev);
+}
+
+static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
+ void __iomem *reg_addr = priv->base;
+ unsigned int mask, reg;
+ unsigned long flags;
+
+ mask = BIT(id);
+ spin_lock_irqsave(&priv->lock, flags);
+ reg = readl(reg_addr + EARC);
+ writel(reg & ~mask, reg_addr + EARC);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int imx8mp_audiomix_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
+ void __iomem *reg_addr = priv->base;
+ unsigned int mask, reg;
+ unsigned long flags;
+
+ mask = BIT(id);
+ spin_lock_irqsave(&priv->lock, flags);
+ reg = readl(reg_addr + EARC);
+ writel(reg | mask, reg_addr + EARC);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static const struct reset_control_ops imx8mp_audiomix_reset_ops = {
+ .assert = imx8mp_audiomix_reset_assert,
+ .deassert = imx8mp_audiomix_reset_deassert,
+};
+
+static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
+{
+ struct imx8mp_audiomix_reset *priv;
+ struct device *dev = &adev->dev;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->lock);
+
+ priv->rcdev.owner = THIS_MODULE;
+ priv->rcdev.nr_resets = fls(EARC_RESET_MASK);
+ priv->rcdev.ops = &imx8mp_audiomix_reset_ops;
+ priv->rcdev.of_node = dev->parent->of_node;
+ priv->rcdev.dev = dev;
+ priv->rcdev.of_reset_n_cells = 1;
+ priv->base = of_iomap(dev->parent->of_node, 0);
+ if (!priv->base)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, priv);
+
+ ret = devm_reset_controller_register(dev, &priv->rcdev);
+ if (ret)
+ goto out_unmap;
+
+ return 0;
+
+out_unmap:
+ iounmap(priv->base);
+ return ret;
+}
+
+static void imx8mp_audiomix_reset_remove(struct auxiliary_device *adev)
+{
+ struct imx8mp_audiomix_reset *priv = dev_get_drvdata(&adev->dev);
+
+ iounmap(priv->base);
+}
+
+static const struct auxiliary_device_id imx8mp_audiomix_reset_ids[] = {
+ {
+ .name = "clk_imx8mp_audiomix.reset",
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(auxiliary, imx8mp_audiomix_reset_ids);
+
+static struct auxiliary_driver imx8mp_audiomix_reset_driver = {
+ .probe = imx8mp_audiomix_reset_probe,
+ .remove = imx8mp_audiomix_reset_remove,
+ .id_table = imx8mp_audiomix_reset_ids,
+};
+
+module_auxiliary_driver(imx8mp_audiomix_reset_driver);
+
+MODULE_AUTHOR("Shengjiu Wang <[email protected]>");
+MODULE_DESCRIPTION("Freescale i.MX8MP Audio Block Controller reset driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/reset/reset-meson-audio-arb.c b/drivers/reset/reset-meson-audio-arb.c
index 7891d52fa899..894ad9d37a66 100644
--- a/drivers/reset/reset-meson-audio-arb.c
+++ b/drivers/reset/reset-meson-audio-arb.c
@@ -129,8 +129,6 @@ static int meson_audio_arb_remove(struct platform_device *pdev)
writel(0, arb->regs);
spin_unlock(&arb->lock);
- clk_disable_unprepare(arb->clk);
-
return 0;
}
@@ -150,7 +148,7 @@ static int meson_audio_arb_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, arb);
- arb->clk = devm_clk_get(dev, NULL);
+ arb->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(arb->clk))
return dev_err_probe(dev, PTR_ERR(arb->clk), "failed to get clock\n");
@@ -170,11 +168,6 @@ static int meson_audio_arb_probe(struct platform_device *pdev)
* In the initial state, all memory interfaces are disabled
* and the general bit is on
*/
- ret = clk_prepare_enable(arb->clk);
- if (ret) {
- dev_err(dev, "failed to enable arb clock\n");
- return ret;
- }
writel(BIT(ARB_GENERAL_BIT), arb->regs);
/* Register reset controller */
diff --git a/drivers/reset/reset-rzg2l-usbphy-ctrl.c b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
index a8dde4606360..255c894a4782 100644
--- a/drivers/reset/reset-rzg2l-usbphy-ctrl.c
+++ b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
@@ -10,10 +10,12 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/reset-controller.h>
#define RESET 0x000
+#define VBENCTL 0x03c
#define RESET_SEL_PLLRESET BIT(12)
#define RESET_PLLRESET BIT(8)
@@ -32,6 +34,7 @@ struct rzg2l_usbphy_ctrl_priv {
struct reset_controller_dev rcdev;
struct reset_control *rstc;
void __iomem *base;
+ struct platform_device *vdev;
spinlock_t lock;
};
@@ -100,10 +103,19 @@ static const struct reset_control_ops rzg2l_usbphy_ctrl_reset_ops = {
.status = rzg2l_usbphy_ctrl_status,
};
+static const struct regmap_config rzg2l_usb_regconf = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 1,
+};
+
static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rzg2l_usbphy_ctrl_priv *priv;
+ struct platform_device *vdev;
+ struct regmap *regmap;
unsigned long flags;
int error;
u32 val;
@@ -116,6 +128,10 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
+ regmap = devm_regmap_init_mmio(dev, priv->base + VBENCTL, &rzg2l_usb_regconf);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(priv->rstc))
return dev_err_probe(dev, PTR_ERR(priv->rstc),
@@ -125,25 +141,14 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
if (error)
return error;
- priv->rcdev.ops = &rzg2l_usbphy_ctrl_reset_ops;
- priv->rcdev.of_reset_n_cells = 1;
- priv->rcdev.nr_resets = NUM_PORTS;
- priv->rcdev.of_node = dev->of_node;
- priv->rcdev.dev = dev;
-
- error = devm_reset_controller_register(dev, &priv->rcdev);
- if (error)
- return error;
-
spin_lock_init(&priv->lock);
dev_set_drvdata(dev, priv);
pm_runtime_enable(&pdev->dev);
error = pm_runtime_resume_and_get(&pdev->dev);
if (error < 0) {
- pm_runtime_disable(&pdev->dev);
- reset_control_assert(priv->rstc);
- return dev_err_probe(&pdev->dev, error, "pm_runtime_resume_and_get failed");
+ dev_err_probe(&pdev->dev, error, "pm_runtime_resume_and_get failed");
+ goto err_pm_disable_reset_deassert;
}
/* put pll and phy into reset state */
@@ -153,13 +158,45 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
writel(val, priv->base + RESET);
spin_unlock_irqrestore(&priv->lock, flags);
+ priv->rcdev.ops = &rzg2l_usbphy_ctrl_reset_ops;
+ priv->rcdev.of_reset_n_cells = 1;
+ priv->rcdev.nr_resets = NUM_PORTS;
+ priv->rcdev.of_node = dev->of_node;
+ priv->rcdev.dev = dev;
+
+ error = devm_reset_controller_register(dev, &priv->rcdev);
+ if (error)
+ goto err_pm_runtime_put;
+
+ vdev = platform_device_alloc("rzg2l-usb-vbus-regulator", pdev->id);
+ if (!vdev) {
+ error = -ENOMEM;
+ goto err_pm_runtime_put;
+ }
+ vdev->dev.parent = dev;
+ priv->vdev = vdev;
+
+ error = platform_device_add(vdev);
+ if (error)
+ goto err_device_put;
+
return 0;
+
+err_device_put:
+ platform_device_put(vdev);
+err_pm_runtime_put:
+ pm_runtime_put(&pdev->dev);
+err_pm_disable_reset_deassert:
+ pm_runtime_disable(&pdev->dev);
+ reset_control_assert(priv->rstc);
+ return error;
}
static int rzg2l_usbphy_ctrl_remove(struct platform_device *pdev)
{
struct rzg2l_usbphy_ctrl_priv *priv = dev_get_drvdata(&pdev->dev);
+ platform_device_unregister(priv->vdev);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
reset_control_assert(priv->rstc);
diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig
index a2622e146b8b..0b599f7cf6ed 100644
--- a/drivers/reset/sti/Kconfig
+++ b/drivers/reset/sti/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
-if ARCH_STI
+if ARCH_STI || COMPILE_TEST
config STIH407_RESET
- bool
+ bool "STIH407 Reset Driver" if COMPILE_TEST
endif
diff --git a/drivers/reset/tegra/Kconfig b/drivers/reset/tegra/Kconfig
index e4a9a389e98c..4a2d26d1210a 100644
--- a/drivers/reset/tegra/Kconfig
+++ b/drivers/reset/tegra/Kconfig
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
config RESET_TEGRA_BPMP
- def_bool TEGRA_BPMP
+ bool "Tegra BPMP Reset Driver" if COMPILE_TEST
+ default TEGRA_BPMP
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 2f16f543079b..a76c6af9ea63 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -4906,7 +4906,7 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req)
ccw++;
if (dst) {
if (ccw->flags & CCW_FLAG_IDA)
- cda = *((char **)dma32_to_virt(ccw->cda));
+ cda = dma64_to_virt(*((dma64_t *)dma32_to_virt(ccw->cda)));
else
cda = dma32_to_virt(ccw->cda);
if (dst != cda) {
@@ -5525,7 +5525,7 @@ dasd_eckd_dump_ccw_range(struct dasd_device *device, struct ccw1 *from,
/* get pointer to data (consider IDALs) */
if (from->flags & CCW_FLAG_IDA)
- datap = (char *)*((addr_t *)dma32_to_virt(from->cda));
+ datap = dma64_to_virt(*((dma64_t *)dma32_to_virt(from->cda)));
else
datap = dma32_to_virt(from->cda);
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 361e9bd75257..9f2023a077c2 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -585,7 +585,7 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req)
ccw++;
if (dst) {
if (ccw->flags & CCW_FLAG_IDA)
- cda = *((char **)dma32_to_virt(ccw->cda));
+ cda = dma64_to_virt(*((dma64_t *)dma32_to_virt(ccw->cda)));
else
cda = dma32_to_virt(ccw->cda);
if (dst != cda) {
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 4533dd055ca8..1aa426b1dedd 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -68,7 +68,6 @@ int dasd_gendisk_alloc(struct dasd_block *block)
blk_mq_free_tag_set(&block->tag_set);
return PTR_ERR(gdp);
}
- blk_queue_flag_set(QUEUE_FLAG_NONROT, gdp->queue);
/* Initialize gendisk structure. */
gdp->major = DASD_MAJOR;
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 6d1689a2717e..d5a5d11ae0dc 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -548,6 +548,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
{
struct queue_limits lim = {
.logical_block_size = 4096,
+ .features = BLK_FEAT_DAX,
};
int rc, i, j, num_of_segments;
struct dcssblk_dev_info *dev_info;
@@ -643,7 +644,6 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
dev_info->gd->fops = &dcssblk_devops;
dev_info->gd->private_data = dev_info;
dev_info->gd->flags |= GENHD_FL_NO_PART;
- blk_queue_flag_set(QUEUE_FLAG_DAX, dev_info->gd->queue);
seg_byte_size = (dev_info->end - dev_info->start + 1);
set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors
diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c
index 1d456a5a3bfb..3fcfe029db1b 100644
--- a/drivers/s390/block/scm_blk.c
+++ b/drivers/s390/block/scm_blk.c
@@ -439,7 +439,6 @@ int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
.logical_block_size = 1 << 12,
};
unsigned int devindex;
- struct request_queue *rq;
int len, ret;
lim.max_segments = min(scmdev->nr_max_block,
@@ -474,10 +473,6 @@ int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
ret = PTR_ERR(bdev->gendisk);
goto out_tag;
}
- rq = bdev->rq = bdev->gendisk->queue;
- blk_queue_flag_set(QUEUE_FLAG_NONROT, rq);
- blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, rq);
-
bdev->gendisk->private_data = scmdev;
bdev->gendisk->fops = &scm_blk_devops;
bdev->gendisk->major = scm_major;
diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 6e5c508b1e07..5f6e10225627 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -490,13 +490,14 @@ static int ccwchain_fetch_tic(struct ccw1 *ccw,
struct channel_program *cp)
{
struct ccwchain *iter;
- u32 cda, ccw_head;
+ u32 offset, ccw_head;
list_for_each_entry(iter, &cp->ccwchain_list, next) {
ccw_head = iter->ch_iova;
if (is_cpa_within_range(ccw->cda, ccw_head, iter->ch_len)) {
- cda = (u64)iter->ch_ccw + dma32_to_u32(ccw->cda) - ccw_head;
- ccw->cda = u32_to_dma32(cda);
+ /* Calculate offset of TIC target */
+ offset = dma32_to_u32(ccw->cda) - ccw_head;
+ ccw->cda = virt_to_dma32((void *)iter->ch_ccw + offset);
return 0;
}
}
@@ -914,7 +915,7 @@ void cp_update_scsw(struct channel_program *cp, union scsw *scsw)
* in the ioctl directly. Path status changes etc.
*/
list_for_each_entry(chain, &cp->ccwchain_list, next) {
- ccw_head = (u32)(u64)chain->ch_ccw;
+ ccw_head = dma32_to_u32(virt_to_dma32(chain->ch_ccw));
/*
* On successful execution, cpa points just beyond the end
* of the chain.
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 065db86d6021..37c24ffea65c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -82,7 +82,6 @@ comment "SCSI support type (disk, tape, CD-ROM)"
config BLK_DEV_SD
tristate "SCSI disk support"
depends on SCSI
- select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY
help
If you want to use SCSI hard disks, Fibre Channel disks,
Serial ATA (SATA) or Parallel ATA (PATA) hard disks,
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 60688f18fac6..c708e1059638 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1057,15 +1057,15 @@ static umode_t iscsi_sw_tcp_attr_is_visible(int param_type, int param)
return 0;
}
-static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev)
+static int iscsi_sw_tcp_device_configure(struct scsi_device *sdev,
+ struct queue_limits *lim)
{
struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(sdev->host);
struct iscsi_session *session = tcp_sw_host->session;
struct iscsi_conn *conn = session->leadconn;
if (conn->datadgst_en)
- blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES,
- sdev->request_queue);
+ lim->features |= BLK_FEAT_STABLE_WRITES;
return 0;
}
@@ -1083,7 +1083,7 @@ static const struct scsi_host_template iscsi_sw_tcp_sht = {
.eh_device_reset_handler= iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target,
.dma_boundary = PAGE_SIZE - 1,
- .slave_configure = iscsi_sw_tcp_slave_configure,
+ .device_configure = iscsi_sw_tcp_device_configure,
.proc_name = "iscsi_tcp",
.this_id = -1,
.track_queue_depth = 1,
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 85948963fb97..03d6ec1eb970 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -145,6 +145,20 @@ static inline void sas_fail_probe(struct domain_device *dev, const char *func, i
func, dev->parent ? "exp-attached" :
"direct-attached",
SAS_ADDR(dev->sas_addr), err);
+
+ /*
+ * If the device probe failed, the expander phy attached address
+ * needs to be reset so that the phy will not be treated as flutter
+ * in the next revalidation
+ */
+ if (dev->parent && !dev_is_expander(dev->dev_type)) {
+ struct sas_phy *phy = dev->phy;
+ struct domain_device *parent = dev->parent;
+ struct ex_phy *ex_phy = &parent->ex_dev.ex_phy[phy->number];
+
+ memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
+ }
+
sas_unregister_dev(dev->port, dev);
}
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index 5297cacc8beb..0cef5d089f34 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -1363,6 +1363,16 @@ lpfc_nvmet_ls_abort(struct nvmet_fc_target_port *targetport,
atomic_inc(&lpfc_nvmet->xmt_ls_abort);
}
+static int
+lpfc_nvmet_host_traddr(void *hosthandle, u64 *wwnn, u64 *wwpn)
+{
+ struct lpfc_nodelist *ndlp = hosthandle;
+
+ *wwnn = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
+ *wwpn = wwn_to_u64(ndlp->nlp_portname.u.wwn);
+ return 0;
+}
+
static void
lpfc_nvmet_host_release(void *hosthandle)
{
@@ -1413,6 +1423,7 @@ static struct nvmet_fc_target_template lpfc_tgttemplate = {
.ls_req = lpfc_nvmet_ls_req,
.ls_abort = lpfc_nvmet_ls_abort,
.host_release = lpfc_nvmet_host_release,
+ .host_traddr = lpfc_nvmet_host_traddr,
.max_hw_queues = 1,
.max_sgl_segments = LPFC_NVMET_DEFAULT_SEGS,
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 88acefbf9aea..6c79c350a4d5 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -1981,8 +1981,6 @@ megasas_set_nvme_device_properties(struct scsi_device *sdev,
lim->max_hw_sectors = max_io_size / 512;
lim->virt_boundary_mask = mr_nvme_pg_size - 1;
-
- blk_queue_flag_set(QUEUE_FLAG_NOMERGES, sdev->request_queue);
}
/*
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 870ec2cb4af4..97c2472cd434 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2680,12 +2680,6 @@ scsih_device_configure(struct scsi_device *sdev, struct queue_limits *lim)
pcie_device_put(pcie_device);
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
mpt3sas_scsih_change_queue_depth(sdev, qdepth);
- /* Enable QUEUE_FLAG_NOMERGES flag, so that IOs won't be
- ** merged and can eliminate holes created during merging
- ** operation.
- **/
- blk_queue_flag_set(QUEUE_FLAG_NOMERGES,
- sdev->request_queue);
lim->virt_boundary_mask = ioc->page_size - 1;
return 0;
}
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index acf0592d63da..a9d8a9c62663 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -69,6 +69,8 @@ static const char *sdebug_version_date = "20210520";
/* Additional Sense Code (ASC) */
#define NO_ADDITIONAL_SENSE 0x0
+#define OVERLAP_ATOMIC_COMMAND_ASC 0x0
+#define OVERLAP_ATOMIC_COMMAND_ASCQ 0x23
#define LOGICAL_UNIT_NOT_READY 0x4
#define LOGICAL_UNIT_COMMUNICATION_FAILURE 0x8
#define UNRECOVERED_READ_ERR 0x11
@@ -103,6 +105,7 @@ static const char *sdebug_version_date = "20210520";
#define READ_BOUNDARY_ASCQ 0x7
#define ATTEMPT_ACCESS_GAP 0x9
#define INSUFF_ZONE_ASCQ 0xe
+/* see drivers/scsi/sense_codes.h */
/* Additional Sense Code Qualifier (ASCQ) */
#define ACK_NAK_TO 0x3
@@ -152,6 +155,12 @@ static const char *sdebug_version_date = "20210520";
#define DEF_VIRTUAL_GB 0
#define DEF_VPD_USE_HOSTNO 1
#define DEF_WRITESAME_LENGTH 0xFFFF
+#define DEF_ATOMIC_WR 0
+#define DEF_ATOMIC_WR_MAX_LENGTH 8192
+#define DEF_ATOMIC_WR_ALIGN 2
+#define DEF_ATOMIC_WR_GRAN 2
+#define DEF_ATOMIC_WR_MAX_LENGTH_BNDRY (DEF_ATOMIC_WR_MAX_LENGTH)
+#define DEF_ATOMIC_WR_MAX_BNDRY 128
#define DEF_STRICT 0
#define DEF_STATISTICS false
#define DEF_SUBMIT_QUEUES 1
@@ -374,7 +383,9 @@ struct sdebug_host_info {
/* There is an xarray of pointers to this struct's objects, one per host */
struct sdeb_store_info {
- rwlock_t macc_lck; /* for atomic media access on this store */
+ rwlock_t macc_data_lck; /* for media data access on this store */
+ rwlock_t macc_meta_lck; /* for atomic media meta access on this store */
+ rwlock_t macc_sector_lck; /* per-sector media data access on this store */
u8 *storep; /* user data storage (ram) */
struct t10_pi_tuple *dif_storep; /* protection info */
void *map_storep; /* provisioning map */
@@ -398,12 +409,20 @@ struct sdebug_defer {
enum sdeb_defer_type defer_t;
};
+struct sdebug_device_access_info {
+ bool atomic_write;
+ u64 lba;
+ u32 num;
+ struct scsi_cmnd *self;
+};
+
struct sdebug_queued_cmd {
/* corresponding bit set in in_use_bm[] in owning struct sdebug_queue
* instance indicates this slot is in use.
*/
struct sdebug_defer sd_dp;
struct scsi_cmnd *scmd;
+ struct sdebug_device_access_info *i;
};
struct sdebug_scsi_cmd {
@@ -463,7 +482,8 @@ enum sdeb_opcode_index {
SDEB_I_PRE_FETCH = 29, /* 10, 16 */
SDEB_I_ZONE_OUT = 30, /* 0x94+SA; includes no data xfer */
SDEB_I_ZONE_IN = 31, /* 0x95+SA; all have data-in */
- SDEB_I_LAST_ELEM_P1 = 32, /* keep this last (previous + 1) */
+ SDEB_I_ATOMIC_WRITE_16 = 32,
+ SDEB_I_LAST_ELEM_P1 = 33, /* keep this last (previous + 1) */
};
@@ -497,7 +517,8 @@ static const unsigned char opcode_ind_arr[256] = {
0, 0, 0, SDEB_I_VERIFY,
SDEB_I_PRE_FETCH, SDEB_I_SYNC_CACHE, 0, SDEB_I_WRITE_SAME,
SDEB_I_ZONE_OUT, SDEB_I_ZONE_IN, 0, 0,
- 0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN_16, SDEB_I_SERV_ACT_OUT_16,
+ 0, 0, 0, 0,
+ SDEB_I_ATOMIC_WRITE_16, 0, SDEB_I_SERV_ACT_IN_16, SDEB_I_SERV_ACT_OUT_16,
/* 0xa0; 0xa0->0xbf: 12 byte cdbs */
SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN,
SDEB_I_MAINT_OUT, 0, 0, 0,
@@ -547,6 +568,7 @@ static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_sync_cache(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_pre_fetch(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_report_zones(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_atomic_write(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_open_zone(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_close_zone(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_finish_zone(struct scsi_cmnd *, struct sdebug_dev_info *);
@@ -788,6 +810,11 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = {
resp_report_zones, zone_in_iarr, /* ZONE_IN(16), REPORT ZONES) */
{16, 0x0 /* SA */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xc7} },
+/* 31 */
+ {0, 0x0, 0x0, F_D_OUT | FF_MEDIA_IO,
+ resp_atomic_write, NULL, /* ATOMIC WRITE 16 */
+ {16, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} },
/* sentinel */
{0xff, 0, 0, 0, NULL, NULL, /* terminating element */
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
@@ -835,6 +862,13 @@ static unsigned int sdebug_unmap_granularity = DEF_UNMAP_GRANULARITY;
static unsigned int sdebug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
static unsigned int sdebug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
static unsigned int sdebug_write_same_length = DEF_WRITESAME_LENGTH;
+static unsigned int sdebug_atomic_wr = DEF_ATOMIC_WR;
+static unsigned int sdebug_atomic_wr_max_length = DEF_ATOMIC_WR_MAX_LENGTH;
+static unsigned int sdebug_atomic_wr_align = DEF_ATOMIC_WR_ALIGN;
+static unsigned int sdebug_atomic_wr_gran = DEF_ATOMIC_WR_GRAN;
+static unsigned int sdebug_atomic_wr_max_length_bndry =
+ DEF_ATOMIC_WR_MAX_LENGTH_BNDRY;
+static unsigned int sdebug_atomic_wr_max_bndry = DEF_ATOMIC_WR_MAX_BNDRY;
static int sdebug_uuid_ctl = DEF_UUID_CTL;
static bool sdebug_random = DEF_RANDOM;
static bool sdebug_per_host_store = DEF_PER_HOST_STORE;
@@ -926,6 +960,7 @@ static const int device_qfull_result =
static const int condition_met_result = SAM_STAT_CONDITION_MET;
static struct dentry *sdebug_debugfs_root;
+static ASYNC_DOMAIN_EXCLUSIVE(sdebug_async_domain);
static void sdebug_err_free(struct rcu_head *head)
{
@@ -1148,6 +1183,8 @@ static int sdebug_target_alloc(struct scsi_target *starget)
if (!targetip)
return -ENOMEM;
+ async_synchronize_full_domain(&sdebug_async_domain);
+
targetip->debugfs_entry = debugfs_create_dir(dev_name(&starget->dev),
sdebug_debugfs_root);
@@ -1174,7 +1211,8 @@ static void sdebug_target_destroy(struct scsi_target *starget)
targetip = (struct sdebug_target_info *)starget->hostdata;
if (targetip) {
starget->hostdata = NULL;
- async_schedule(sdebug_tartget_cleanup_async, targetip);
+ async_schedule_domain(sdebug_tartget_cleanup_async, targetip,
+ &sdebug_async_domain);
}
}
@@ -1188,6 +1226,11 @@ static inline bool scsi_debug_lbp(void)
(sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10);
}
+static inline bool scsi_debug_atomic_write(void)
+{
+ return sdebug_fake_rw == 0 && sdebug_atomic_wr;
+}
+
static void *lba2fake_store(struct sdeb_store_info *sip,
unsigned long long lba)
{
@@ -1815,6 +1858,14 @@ static int inquiry_vpd_b0(unsigned char *arr)
/* Maximum WRITE SAME Length */
put_unaligned_be64(sdebug_write_same_length, &arr[32]);
+ if (sdebug_atomic_wr) {
+ put_unaligned_be32(sdebug_atomic_wr_max_length, &arr[40]);
+ put_unaligned_be32(sdebug_atomic_wr_align, &arr[44]);
+ put_unaligned_be32(sdebug_atomic_wr_gran, &arr[48]);
+ put_unaligned_be32(sdebug_atomic_wr_max_length_bndry, &arr[52]);
+ put_unaligned_be32(sdebug_atomic_wr_max_bndry, &arr[56]);
+ }
+
return 0x3c; /* Mandatory page length for Logical Block Provisioning */
}
@@ -3377,16 +3428,238 @@ static inline struct sdeb_store_info *devip2sip(struct sdebug_dev_info *devip,
return xa_load(per_store_ap, devip->sdbg_host->si_idx);
}
+static inline void
+sdeb_read_lock(rwlock_t *lock)
+{
+ if (sdebug_no_rwlock)
+ __acquire(lock);
+ else
+ read_lock(lock);
+}
+
+static inline void
+sdeb_read_unlock(rwlock_t *lock)
+{
+ if (sdebug_no_rwlock)
+ __release(lock);
+ else
+ read_unlock(lock);
+}
+
+static inline void
+sdeb_write_lock(rwlock_t *lock)
+{
+ if (sdebug_no_rwlock)
+ __acquire(lock);
+ else
+ write_lock(lock);
+}
+
+static inline void
+sdeb_write_unlock(rwlock_t *lock)
+{
+ if (sdebug_no_rwlock)
+ __release(lock);
+ else
+ write_unlock(lock);
+}
+
+static inline void
+sdeb_data_read_lock(struct sdeb_store_info *sip)
+{
+ BUG_ON(!sip);
+
+ sdeb_read_lock(&sip->macc_data_lck);
+}
+
+static inline void
+sdeb_data_read_unlock(struct sdeb_store_info *sip)
+{
+ BUG_ON(!sip);
+
+ sdeb_read_unlock(&sip->macc_data_lck);
+}
+
+static inline void
+sdeb_data_write_lock(struct sdeb_store_info *sip)
+{
+ BUG_ON(!sip);
+
+ sdeb_write_lock(&sip->macc_data_lck);
+}
+
+static inline void
+sdeb_data_write_unlock(struct sdeb_store_info *sip)
+{
+ BUG_ON(!sip);
+
+ sdeb_write_unlock(&sip->macc_data_lck);
+}
+
+static inline void
+sdeb_data_sector_read_lock(struct sdeb_store_info *sip)
+{
+ BUG_ON(!sip);
+
+ sdeb_read_lock(&sip->macc_sector_lck);
+}
+
+static inline void
+sdeb_data_sector_read_unlock(struct sdeb_store_info *sip)
+{
+ BUG_ON(!sip);
+
+ sdeb_read_unlock(&sip->macc_sector_lck);
+}
+
+static inline void
+sdeb_data_sector_write_lock(struct sdeb_store_info *sip)
+{
+ BUG_ON(!sip);
+
+ sdeb_write_lock(&sip->macc_sector_lck);
+}
+
+static inline void
+sdeb_data_sector_write_unlock(struct sdeb_store_info *sip)
+{
+ BUG_ON(!sip);
+
+ sdeb_write_unlock(&sip->macc_sector_lck);
+}
+
+/*
+ * Atomic locking:
+ * We simplify the atomic model to allow only 1x atomic write and many non-
+ * atomic reads or writes for all LBAs.
+
+ * A RW lock has a similar bahaviour:
+ * Only 1x writer and many readers.
+
+ * So use a RW lock for per-device read and write locking:
+ * An atomic access grabs the lock as a writer and non-atomic grabs the lock
+ * as a reader.
+ */
+
+static inline void
+sdeb_data_lock(struct sdeb_store_info *sip, bool atomic)
+{
+ if (atomic)
+ sdeb_data_write_lock(sip);
+ else
+ sdeb_data_read_lock(sip);
+}
+
+static inline void
+sdeb_data_unlock(struct sdeb_store_info *sip, bool atomic)
+{
+ if (atomic)
+ sdeb_data_write_unlock(sip);
+ else
+ sdeb_data_read_unlock(sip);
+}
+
+/* Allow many reads but only 1x write per sector */
+static inline void
+sdeb_data_sector_lock(struct sdeb_store_info *sip, bool do_write)
+{
+ if (do_write)
+ sdeb_data_sector_write_lock(sip);
+ else
+ sdeb_data_sector_read_lock(sip);
+}
+
+static inline void
+sdeb_data_sector_unlock(struct sdeb_store_info *sip, bool do_write)
+{
+ if (do_write)
+ sdeb_data_sector_write_unlock(sip);
+ else
+ sdeb_data_sector_read_unlock(sip);
+}
+
+static inline void
+sdeb_meta_read_lock(struct sdeb_store_info *sip)
+{
+ if (sdebug_no_rwlock) {
+ if (sip)
+ __acquire(&sip->macc_meta_lck);
+ else
+ __acquire(&sdeb_fake_rw_lck);
+ } else {
+ if (sip)
+ read_lock(&sip->macc_meta_lck);
+ else
+ read_lock(&sdeb_fake_rw_lck);
+ }
+}
+
+static inline void
+sdeb_meta_read_unlock(struct sdeb_store_info *sip)
+{
+ if (sdebug_no_rwlock) {
+ if (sip)
+ __release(&sip->macc_meta_lck);
+ else
+ __release(&sdeb_fake_rw_lck);
+ } else {
+ if (sip)
+ read_unlock(&sip->macc_meta_lck);
+ else
+ read_unlock(&sdeb_fake_rw_lck);
+ }
+}
+
+static inline void
+sdeb_meta_write_lock(struct sdeb_store_info *sip)
+{
+ if (sdebug_no_rwlock) {
+ if (sip)
+ __acquire(&sip->macc_meta_lck);
+ else
+ __acquire(&sdeb_fake_rw_lck);
+ } else {
+ if (sip)
+ write_lock(&sip->macc_meta_lck);
+ else
+ write_lock(&sdeb_fake_rw_lck);
+ }
+}
+
+static inline void
+sdeb_meta_write_unlock(struct sdeb_store_info *sip)
+{
+ if (sdebug_no_rwlock) {
+ if (sip)
+ __release(&sip->macc_meta_lck);
+ else
+ __release(&sdeb_fake_rw_lck);
+ } else {
+ if (sip)
+ write_unlock(&sip->macc_meta_lck);
+ else
+ write_unlock(&sdeb_fake_rw_lck);
+ }
+}
+
/* Returns number of bytes copied or -1 if error. */
static int do_device_access(struct sdeb_store_info *sip, struct scsi_cmnd *scp,
- u32 sg_skip, u64 lba, u32 num, bool do_write,
- u8 group_number)
+ u32 sg_skip, u64 lba, u32 num, u8 group_number,
+ bool do_write, bool atomic)
{
int ret;
- u64 block, rest = 0;
+ u64 block;
enum dma_data_direction dir;
struct scsi_data_buffer *sdb = &scp->sdb;
u8 *fsp;
+ int i;
+
+ /*
+ * Even though reads are inherently atomic (in this driver), we expect
+ * the atomic flag only for writes.
+ */
+ if (!do_write && atomic)
+ return -1;
if (do_write) {
dir = DMA_TO_DEVICE;
@@ -3406,21 +3679,26 @@ static int do_device_access(struct sdeb_store_info *sip, struct scsi_cmnd *scp,
fsp = sip->storep;
block = do_div(lba, sdebug_store_sectors);
- if (block + num > sdebug_store_sectors)
- rest = block + num - sdebug_store_sectors;
- ret = sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
+ /* Only allow 1x atomic write or multiple non-atomic writes at any given time */
+ sdeb_data_lock(sip, atomic);
+ for (i = 0; i < num; i++) {
+ /* We shouldn't need to lock for atomic writes, but do it anyway */
+ sdeb_data_sector_lock(sip, do_write);
+ ret = sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
fsp + (block * sdebug_sector_size),
- (num - rest) * sdebug_sector_size, sg_skip, do_write);
- if (ret != (num - rest) * sdebug_sector_size)
- return ret;
-
- if (rest) {
- ret += sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
- fsp, rest * sdebug_sector_size,
- sg_skip + ((num - rest) * sdebug_sector_size),
- do_write);
+ sdebug_sector_size, sg_skip, do_write);
+ sdeb_data_sector_unlock(sip, do_write);
+ if (ret != sdebug_sector_size) {
+ ret += (i * sdebug_sector_size);
+ break;
+ }
+ sg_skip += sdebug_sector_size;
+ if (++block >= sdebug_store_sectors)
+ block = 0;
}
+ ret = num * sdebug_sector_size;
+ sdeb_data_unlock(sip, atomic);
return ret;
}
@@ -3596,70 +3874,6 @@ static int prot_verify_read(struct scsi_cmnd *scp, sector_t start_sec,
return ret;
}
-static inline void
-sdeb_read_lock(struct sdeb_store_info *sip)
-{
- if (sdebug_no_rwlock) {
- if (sip)
- __acquire(&sip->macc_lck);
- else
- __acquire(&sdeb_fake_rw_lck);
- } else {
- if (sip)
- read_lock(&sip->macc_lck);
- else
- read_lock(&sdeb_fake_rw_lck);
- }
-}
-
-static inline void
-sdeb_read_unlock(struct sdeb_store_info *sip)
-{
- if (sdebug_no_rwlock) {
- if (sip)
- __release(&sip->macc_lck);
- else
- __release(&sdeb_fake_rw_lck);
- } else {
- if (sip)
- read_unlock(&sip->macc_lck);
- else
- read_unlock(&sdeb_fake_rw_lck);
- }
-}
-
-static inline void
-sdeb_write_lock(struct sdeb_store_info *sip)
-{
- if (sdebug_no_rwlock) {
- if (sip)
- __acquire(&sip->macc_lck);
- else
- __acquire(&sdeb_fake_rw_lck);
- } else {
- if (sip)
- write_lock(&sip->macc_lck);
- else
- write_lock(&sdeb_fake_rw_lck);
- }
-}
-
-static inline void
-sdeb_write_unlock(struct sdeb_store_info *sip)
-{
- if (sdebug_no_rwlock) {
- if (sip)
- __release(&sip->macc_lck);
- else
- __release(&sdeb_fake_rw_lck);
- } else {
- if (sip)
- write_unlock(&sip->macc_lck);
- else
- write_unlock(&sdeb_fake_rw_lck);
- }
-}
-
static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
{
bool check_prot;
@@ -3669,6 +3883,7 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
u64 lba;
struct sdeb_store_info *sip = devip2sip(devip, true);
u8 *cmd = scp->cmnd;
+ bool meta_data_locked = false;
switch (cmd[0]) {
case READ_16:
@@ -3727,6 +3942,10 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
atomic_set(&sdeb_inject_pending, 0);
}
+ /*
+ * When checking device access params, for reads we only check data
+ * versus what is set at init time, so no need to lock.
+ */
ret = check_device_access_params(scp, lba, num, false);
if (ret)
return ret;
@@ -3746,29 +3965,33 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
return check_condition_result;
}
- sdeb_read_lock(sip);
+ if (sdebug_dev_is_zoned(devip) ||
+ (sdebug_dix && scsi_prot_sg_count(scp))) {
+ sdeb_meta_read_lock(sip);
+ meta_data_locked = true;
+ }
/* DIX + T10 DIF */
if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
switch (prot_verify_read(scp, lba, num, ei_lba)) {
case 1: /* Guard tag error */
if (cmd[1] >> 5 != 3) { /* RDPROTECT != 3 */
- sdeb_read_unlock(sip);
+ sdeb_meta_read_unlock(sip);
mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
return check_condition_result;
} else if (scp->prot_flags & SCSI_PROT_GUARD_CHECK) {
- sdeb_read_unlock(sip);
+ sdeb_meta_read_unlock(sip);
mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
return illegal_condition_result;
}
break;
case 3: /* Reference tag error */
if (cmd[1] >> 5 != 3) { /* RDPROTECT != 3 */
- sdeb_read_unlock(sip);
+ sdeb_meta_read_unlock(sip);
mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 3);
return check_condition_result;
} else if (scp->prot_flags & SCSI_PROT_REF_CHECK) {
- sdeb_read_unlock(sip);
+ sdeb_meta_read_unlock(sip);
mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 3);
return illegal_condition_result;
}
@@ -3776,8 +3999,9 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
}
}
- ret = do_device_access(sip, scp, 0, lba, num, false, 0);
- sdeb_read_unlock(sip);
+ ret = do_device_access(sip, scp, 0, lba, num, 0, false, false);
+ if (meta_data_locked)
+ sdeb_meta_read_unlock(sip);
if (unlikely(ret == -1))
return DID_ERROR << 16;
@@ -3967,6 +4191,7 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
u64 lba;
struct sdeb_store_info *sip = devip2sip(devip, true);
u8 *cmd = scp->cmnd;
+ bool meta_data_locked = false;
switch (cmd[0]) {
case WRITE_16:
@@ -4025,10 +4250,17 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
"to DIF device\n");
}
- sdeb_write_lock(sip);
+ if (sdebug_dev_is_zoned(devip) ||
+ (sdebug_dix && scsi_prot_sg_count(scp)) ||
+ scsi_debug_lbp()) {
+ sdeb_meta_write_lock(sip);
+ meta_data_locked = true;
+ }
+
ret = check_device_access_params(scp, lba, num, true);
if (ret) {
- sdeb_write_unlock(sip);
+ if (meta_data_locked)
+ sdeb_meta_write_unlock(sip);
return ret;
}
@@ -4037,22 +4269,22 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
switch (prot_verify_write(scp, lba, num, ei_lba)) {
case 1: /* Guard tag error */
if (scp->prot_flags & SCSI_PROT_GUARD_CHECK) {
- sdeb_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
return illegal_condition_result;
} else if (scp->cmnd[1] >> 5 != 3) { /* WRPROTECT != 3 */
- sdeb_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
return check_condition_result;
}
break;
case 3: /* Reference tag error */
if (scp->prot_flags & SCSI_PROT_REF_CHECK) {
- sdeb_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 3);
return illegal_condition_result;
} else if (scp->cmnd[1] >> 5 != 3) { /* WRPROTECT != 3 */
- sdeb_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 3);
return check_condition_result;
}
@@ -4060,13 +4292,16 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
}
}
- ret = do_device_access(sip, scp, 0, lba, num, true, group);
+ ret = do_device_access(sip, scp, 0, lba, num, group, true, false);
if (unlikely(scsi_debug_lbp()))
map_region(sip, lba, num);
+
/* If ZBC zone then bump its write pointer */
if (sdebug_dev_is_zoned(devip))
zbc_inc_wp(devip, lba, num);
- sdeb_write_unlock(sip);
+ if (meta_data_locked)
+ sdeb_meta_write_unlock(sip);
+
if (unlikely(-1 == ret))
return DID_ERROR << 16;
else if (unlikely(sdebug_verbose &&
@@ -4176,7 +4411,8 @@ static int resp_write_scat(struct scsi_cmnd *scp,
goto err_out;
}
- sdeb_write_lock(sip);
+ /* Just keep it simple and always lock for now */
+ sdeb_meta_write_lock(sip);
sg_off = lbdof_blen;
/* Spec says Buffer xfer Length field in number of LBs in dout */
cum_lb = 0;
@@ -4219,7 +4455,11 @@ static int resp_write_scat(struct scsi_cmnd *scp,
}
}
- ret = do_device_access(sip, scp, sg_off, lba, num, true, group);
+ /*
+ * Write ranges atomically to keep as close to pre-atomic
+ * writes behaviour as possible.
+ */
+ ret = do_device_access(sip, scp, sg_off, lba, num, group, true, true);
/* If ZBC zone then bump its write pointer */
if (sdebug_dev_is_zoned(devip))
zbc_inc_wp(devip, lba, num);
@@ -4258,7 +4498,7 @@ static int resp_write_scat(struct scsi_cmnd *scp,
}
ret = 0;
err_out_unlock:
- sdeb_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
err_out:
kfree(lrdp);
return ret;
@@ -4277,14 +4517,16 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
scp->device->hostdata, true);
u8 *fs1p;
u8 *fsp;
+ bool meta_data_locked = false;
- sdeb_write_lock(sip);
+ if (sdebug_dev_is_zoned(devip) || scsi_debug_lbp()) {
+ sdeb_meta_write_lock(sip);
+ meta_data_locked = true;
+ }
ret = check_device_access_params(scp, lba, num, true);
- if (ret) {
- sdeb_write_unlock(sip);
- return ret;
- }
+ if (ret)
+ goto out;
if (unmap && scsi_debug_lbp()) {
unmap_region(sip, lba, num);
@@ -4295,6 +4537,7 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
/* if ndob then zero 1 logical block, else fetch 1 logical block */
fsp = sip->storep;
fs1p = fsp + (block * lb_size);
+ sdeb_data_write_lock(sip);
if (ndob) {
memset(fs1p, 0, lb_size);
ret = 0;
@@ -4302,8 +4545,8 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
ret = fetch_to_dev_buffer(scp, fs1p, lb_size);
if (-1 == ret) {
- sdeb_write_unlock(sip);
- return DID_ERROR << 16;
+ ret = DID_ERROR << 16;
+ goto out;
} else if (sdebug_verbose && !ndob && (ret < lb_size))
sdev_printk(KERN_INFO, scp->device,
"%s: %s: lb size=%u, IO sent=%d bytes\n",
@@ -4320,10 +4563,12 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
/* If ZBC zone then bump its write pointer */
if (sdebug_dev_is_zoned(devip))
zbc_inc_wp(devip, lba, num);
+ sdeb_data_write_unlock(sip);
+ ret = 0;
out:
- sdeb_write_unlock(sip);
-
- return 0;
+ if (meta_data_locked)
+ sdeb_meta_write_unlock(sip);
+ return ret;
}
static int resp_write_same_10(struct scsi_cmnd *scp,
@@ -4466,25 +4711,30 @@ static int resp_comp_write(struct scsi_cmnd *scp,
return check_condition_result;
}
- sdeb_write_lock(sip);
-
ret = do_dout_fetch(scp, dnum, arr);
if (ret == -1) {
retval = DID_ERROR << 16;
- goto cleanup;
+ goto cleanup_free;
} else if (sdebug_verbose && (ret < (dnum * lb_size)))
sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb "
"indicated=%u, IO sent=%d bytes\n", my_name,
dnum * lb_size, ret);
+
+ sdeb_data_write_lock(sip);
+ sdeb_meta_write_lock(sip);
if (!comp_write_worker(sip, lba, num, arr, false)) {
mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0);
retval = check_condition_result;
- goto cleanup;
+ goto cleanup_unlock;
}
+
+ /* Cover sip->map_storep (which map_region()) sets with data lock */
if (scsi_debug_lbp())
map_region(sip, lba, num);
-cleanup:
- sdeb_write_unlock(sip);
+cleanup_unlock:
+ sdeb_meta_write_unlock(sip);
+ sdeb_data_write_unlock(sip);
+cleanup_free:
kfree(arr);
return retval;
}
@@ -4528,7 +4778,7 @@ static int resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
desc = (void *)&buf[8];
- sdeb_write_lock(sip);
+ sdeb_meta_write_lock(sip);
for (i = 0 ; i < descriptors ; i++) {
unsigned long long lba = get_unaligned_be64(&desc[i].lba);
@@ -4544,7 +4794,7 @@ static int resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
ret = 0;
out:
- sdeb_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
kfree(buf);
return ret;
@@ -4702,12 +4952,13 @@ static int resp_pre_fetch(struct scsi_cmnd *scp,
rest = block + nblks - sdebug_store_sectors;
/* Try to bring the PRE-FETCH range into CPU's cache */
- sdeb_read_lock(sip);
+ sdeb_data_read_lock(sip);
prefetch_range(fsp + (sdebug_sector_size * block),
(nblks - rest) * sdebug_sector_size);
if (rest)
prefetch_range(fsp, rest * sdebug_sector_size);
- sdeb_read_unlock(sip);
+
+ sdeb_data_read_unlock(sip);
fini:
if (cmd[1] & 0x2)
res = SDEG_RES_IMMED_MASK;
@@ -4866,7 +5117,7 @@ static int resp_verify(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
return check_condition_result;
}
/* Not changing store, so only need read access */
- sdeb_read_lock(sip);
+ sdeb_data_read_lock(sip);
ret = do_dout_fetch(scp, a_num, arr);
if (ret == -1) {
@@ -4888,7 +5139,7 @@ static int resp_verify(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
goto cleanup;
}
cleanup:
- sdeb_read_unlock(sip);
+ sdeb_data_read_unlock(sip);
kfree(arr);
return ret;
}
@@ -4934,7 +5185,7 @@ static int resp_report_zones(struct scsi_cmnd *scp,
return check_condition_result;
}
- sdeb_read_lock(sip);
+ sdeb_meta_read_lock(sip);
desc = arr + 64;
for (lba = zs_lba; lba < sdebug_capacity;
@@ -5032,11 +5283,70 @@ static int resp_report_zones(struct scsi_cmnd *scp,
ret = fill_from_dev_buffer(scp, arr, min_t(u32, alloc_len, rep_len));
fini:
- sdeb_read_unlock(sip);
+ sdeb_meta_read_unlock(sip);
kfree(arr);
return ret;
}
+static int resp_atomic_write(struct scsi_cmnd *scp,
+ struct sdebug_dev_info *devip)
+{
+ struct sdeb_store_info *sip;
+ u8 *cmd = scp->cmnd;
+ u16 boundary, len;
+ u64 lba, lba_tmp;
+ int ret;
+
+ if (!scsi_debug_atomic_write()) {
+ mk_sense_invalid_opcode(scp);
+ return check_condition_result;
+ }
+
+ sip = devip2sip(devip, true);
+
+ lba = get_unaligned_be64(cmd + 2);
+ boundary = get_unaligned_be16(cmd + 10);
+ len = get_unaligned_be16(cmd + 12);
+
+ lba_tmp = lba;
+ if (sdebug_atomic_wr_align &&
+ do_div(lba_tmp, sdebug_atomic_wr_align)) {
+ /* Does not meet alignment requirement */
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ return check_condition_result;
+ }
+
+ if (sdebug_atomic_wr_gran && len % sdebug_atomic_wr_gran) {
+ /* Does not meet alignment requirement */
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ return check_condition_result;
+ }
+
+ if (boundary > 0) {
+ if (boundary > sdebug_atomic_wr_max_bndry) {
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 12, -1);
+ return check_condition_result;
+ }
+
+ if (len > sdebug_atomic_wr_max_length_bndry) {
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 12, -1);
+ return check_condition_result;
+ }
+ } else {
+ if (len > sdebug_atomic_wr_max_length) {
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 12, -1);
+ return check_condition_result;
+ }
+ }
+
+ ret = do_device_access(sip, scp, 0, lba, len, 0, true, true);
+ if (unlikely(ret == -1))
+ return DID_ERROR << 16;
+ if (unlikely(ret != len * sdebug_sector_size))
+ return DID_ERROR << 16;
+ return 0;
+}
+
/* Logic transplanted from tcmu-runner, file_zbc.c */
static void zbc_open_all(struct sdebug_dev_info *devip)
{
@@ -5063,8 +5373,7 @@ static int resp_open_zone(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
mk_sense_invalid_opcode(scp);
return check_condition_result;
}
-
- sdeb_write_lock(sip);
+ sdeb_meta_write_lock(sip);
if (all) {
/* Check if all closed zones can be open */
@@ -5113,7 +5422,7 @@ static int resp_open_zone(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
zbc_open_zone(devip, zsp, true);
fini:
- sdeb_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
return res;
}
@@ -5140,7 +5449,7 @@ static int resp_close_zone(struct scsi_cmnd *scp,
return check_condition_result;
}
- sdeb_write_lock(sip);
+ sdeb_meta_write_lock(sip);
if (all) {
zbc_close_all(devip);
@@ -5169,7 +5478,7 @@ static int resp_close_zone(struct scsi_cmnd *scp,
zbc_close_zone(devip, zsp);
fini:
- sdeb_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
return res;
}
@@ -5212,7 +5521,7 @@ static int resp_finish_zone(struct scsi_cmnd *scp,
return check_condition_result;
}
- sdeb_write_lock(sip);
+ sdeb_meta_write_lock(sip);
if (all) {
zbc_finish_all(devip);
@@ -5241,7 +5550,7 @@ static int resp_finish_zone(struct scsi_cmnd *scp,
zbc_finish_zone(devip, zsp, true);
fini:
- sdeb_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
return res;
}
@@ -5292,7 +5601,7 @@ static int resp_rwp_zone(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
return check_condition_result;
}
- sdeb_write_lock(sip);
+ sdeb_meta_write_lock(sip);
if (all) {
zbc_rwp_all(devip);
@@ -5320,7 +5629,7 @@ static int resp_rwp_zone(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
zbc_rwp_zone(devip, zsp);
fini:
- sdeb_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
return res;
}
@@ -6284,6 +6593,7 @@ module_param_named(lbprz, sdebug_lbprz, int, S_IRUGO);
module_param_named(lbpu, sdebug_lbpu, int, S_IRUGO);
module_param_named(lbpws, sdebug_lbpws, int, S_IRUGO);
module_param_named(lbpws10, sdebug_lbpws10, int, S_IRUGO);
+module_param_named(atomic_wr, sdebug_atomic_wr, int, S_IRUGO);
module_param_named(lowest_aligned, sdebug_lowest_aligned, int, S_IRUGO);
module_param_named(lun_format, sdebug_lun_am_i, int, S_IRUGO | S_IWUSR);
module_param_named(max_luns, sdebug_max_luns, int, S_IRUGO | S_IWUSR);
@@ -6318,6 +6628,11 @@ module_param_named(unmap_alignment, sdebug_unmap_alignment, int, S_IRUGO);
module_param_named(unmap_granularity, sdebug_unmap_granularity, int, S_IRUGO);
module_param_named(unmap_max_blocks, sdebug_unmap_max_blocks, int, S_IRUGO);
module_param_named(unmap_max_desc, sdebug_unmap_max_desc, int, S_IRUGO);
+module_param_named(atomic_wr_max_length, sdebug_atomic_wr_max_length, int, S_IRUGO);
+module_param_named(atomic_wr_align, sdebug_atomic_wr_align, int, S_IRUGO);
+module_param_named(atomic_wr_gran, sdebug_atomic_wr_gran, int, S_IRUGO);
+module_param_named(atomic_wr_max_length_bndry, sdebug_atomic_wr_max_length_bndry, int, S_IRUGO);
+module_param_named(atomic_wr_max_bndry, sdebug_atomic_wr_max_bndry, int, S_IRUGO);
module_param_named(uuid_ctl, sdebug_uuid_ctl, int, S_IRUGO);
module_param_named(virtual_gb, sdebug_virtual_gb, int, S_IRUGO | S_IWUSR);
module_param_named(vpd_use_hostno, sdebug_vpd_use_hostno, int,
@@ -6361,6 +6676,7 @@ MODULE_PARM_DESC(lbprz,
MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
+MODULE_PARM_DESC(atomic_write, "enable ATOMIC WRITE support, support WRITE ATOMIC(16) (def=0)");
MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
MODULE_PARM_DESC(lun_format, "LUN format: 0->peripheral (def); 1 --> flat address method");
MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
@@ -6392,6 +6708,11 @@ MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"
MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
+MODULE_PARM_DESC(atomic_wr_max_length, "max # of blocks can be atomically written in one cmd (def=8192)");
+MODULE_PARM_DESC(atomic_wr_align, "minimum alignment of atomic write in blocks (def=2)");
+MODULE_PARM_DESC(atomic_wr_gran, "minimum granularity of atomic write in blocks (def=2)");
+MODULE_PARM_DESC(atomic_wr_max_length_bndry, "max # of blocks can be atomically written in one cmd with boundary set (def=8192)");
+MODULE_PARM_DESC(atomic_wr_max_bndry, "max # boundaries per atomic write (def=128)");
MODULE_PARM_DESC(uuid_ctl,
"1->use uuid for lu name, 0->don't, 2->all use same (def=0)");
MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)");
@@ -7563,6 +7884,7 @@ static int __init scsi_debug_init(void)
return -EINVAL;
}
}
+
xa_init_flags(per_store_ap, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
if (want_store) {
idx = sdebug_add_store();
@@ -7770,7 +8092,9 @@ static int sdebug_add_store(void)
map_region(sip, 0, 2);
}
- rwlock_init(&sip->macc_lck);
+ rwlock_init(&sip->macc_data_lck);
+ rwlock_init(&sip->macc_meta_lck);
+ rwlock_init(&sip->macc_sector_lck);
return (int)n_idx;
err:
sdebug_erase_store((int)n_idx, sip);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ec39acc986d6..3958a6d14bf4 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -631,8 +631,7 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
if (blk_update_request(req, error, bytes))
return true;
- // XXX:
- if (blk_queue_add_random(q))
+ if (q->limits.features & BLK_FEAT_ADD_RANDOM)
add_disk_randomness(req->q->disk);
WARN_ON_ONCE(!blk_rq_is_passthrough(req) &&
@@ -1140,9 +1139,9 @@ blk_status_t scsi_alloc_sgtables(struct scsi_cmnd *cmd)
*/
count = __blk_rq_map_sg(rq->q, rq, cmd->sdb.table.sgl, &last_sg);
- if (blk_rq_bytes(rq) & rq->q->dma_pad_mask) {
+ if (blk_rq_bytes(rq) & rq->q->limits.dma_pad_mask) {
unsigned int pad_len =
- (rq->q->dma_pad_mask & ~blk_rq_bytes(rq)) + 1;
+ (rq->q->limits.dma_pad_mask & ~blk_rq_bytes(rq)) + 1;
last_sg->length += pad_len;
cmd->extra_len += pad_len;
@@ -1987,7 +1986,7 @@ void scsi_init_limits(struct Scsi_Host *shost, struct queue_limits *lim)
shost->dma_alignment, dma_get_cache_alignment() - 1);
if (shost->no_highmem)
- lim->bounce = BLK_BOUNCE_HIGH;
+ lim->features |= BLK_FEAT_BOUNCE_HIGH;
dma_set_seg_boundary(dev, shost->dma_boundary);
dma_set_max_seg_size(dev, shost->max_segment_size);
diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c
index 41a950075913..3e47c4472a80 100644
--- a/drivers/scsi/scsi_trace.c
+++ b/drivers/scsi/scsi_trace.c
@@ -326,6 +326,26 @@ out:
}
static const char *
+scsi_trace_atomic_write16_out(struct trace_seq *p, unsigned char *cdb, int len)
+{
+ const char *ret = trace_seq_buffer_ptr(p);
+ unsigned int boundary_size;
+ unsigned int nr_blocks;
+ sector_t lba;
+
+ lba = get_unaligned_be64(&cdb[2]);
+ boundary_size = get_unaligned_be16(&cdb[10]);
+ nr_blocks = get_unaligned_be16(&cdb[12]);
+
+ trace_seq_printf(p, "lba=%llu txlen=%u boundary_size=%u",
+ lba, nr_blocks, boundary_size);
+
+ trace_seq_putc(p, 0);
+
+ return ret;
+}
+
+static const char *
scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
{
switch (SERVICE_ACTION32(cdb)) {
@@ -385,6 +405,8 @@ scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
return scsi_trace_zbc_in(p, cdb, len);
case ZBC_OUT:
return scsi_trace_zbc_out(p, cdb, len);
+ case WRITE_ATOMIC_16:
+ return scsi_trace_atomic_write16_out(p, cdb, len);
default:
return scsi_trace_misc(p, cdb, len);
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 6b64af7d4927..2e933fd1de70 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -102,12 +102,13 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_ZBC);
#define SD_MINORS 16
-static void sd_config_discard(struct scsi_disk *, unsigned int);
-static void sd_config_write_same(struct scsi_disk *);
+static void sd_config_discard(struct scsi_disk *sdkp, struct queue_limits *lim,
+ unsigned int mode);
+static void sd_config_write_same(struct scsi_disk *sdkp,
+ struct queue_limits *lim);
static int sd_revalidate_disk(struct gendisk *);
static void sd_unlock_native_capacity(struct gendisk *disk);
static void sd_shutdown(struct device *);
-static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
static void scsi_disk_release(struct device *cdev);
static DEFINE_IDA(sd_index_ida);
@@ -120,17 +121,18 @@ static const char *sd_cache_types[] = {
"write back, no read (daft)"
};
-static void sd_set_flush_flag(struct scsi_disk *sdkp)
+static void sd_set_flush_flag(struct scsi_disk *sdkp,
+ struct queue_limits *lim)
{
- bool wc = false, fua = false;
-
if (sdkp->WCE) {
- wc = true;
+ lim->features |= BLK_FEAT_WRITE_CACHE;
if (sdkp->DPOFUA)
- fua = true;
+ lim->features |= BLK_FEAT_FUA;
+ else
+ lim->features &= ~BLK_FEAT_FUA;
+ } else {
+ lim->features &= ~(BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA);
}
-
- blk_queue_write_cache(sdkp->disk->queue, wc, fua);
}
static ssize_t
@@ -168,9 +170,18 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
wce = (ct & 0x02) && !sdkp->write_prot ? 1 : 0;
if (sdkp->cache_override) {
+ struct queue_limits lim;
+
sdkp->WCE = wce;
sdkp->RCD = rcd;
- sd_set_flush_flag(sdkp);
+
+ lim = queue_limits_start_update(sdkp->disk->queue);
+ sd_set_flush_flag(sdkp, &lim);
+ blk_mq_freeze_queue(sdkp->disk->queue);
+ ret = queue_limits_commit_update(sdkp->disk->queue, &lim);
+ blk_mq_unfreeze_queue(sdkp->disk->queue);
+ if (ret)
+ return ret;
return count;
}
@@ -457,16 +468,12 @@ provisioning_mode_store(struct device *dev, struct device_attribute *attr,
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
struct scsi_device *sdp = sdkp->device;
- int mode;
+ struct queue_limits lim;
+ int mode, err;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (sd_is_zoned(sdkp)) {
- sd_config_discard(sdkp, SD_LBP_DISABLE);
- return count;
- }
-
if (sdp->type != TYPE_DISK)
return -EINVAL;
@@ -474,8 +481,13 @@ provisioning_mode_store(struct device *dev, struct device_attribute *attr,
if (mode < 0)
return -EINVAL;
- sd_config_discard(sdkp, mode);
-
+ lim = queue_limits_start_update(sdkp->disk->queue);
+ sd_config_discard(sdkp, &lim, mode);
+ blk_mq_freeze_queue(sdkp->disk->queue);
+ err = queue_limits_commit_update(sdkp->disk->queue, &lim);
+ blk_mq_unfreeze_queue(sdkp->disk->queue);
+ if (err)
+ return err;
return count;
}
static DEVICE_ATTR_RW(provisioning_mode);
@@ -558,6 +570,7 @@ max_write_same_blocks_store(struct device *dev, struct device_attribute *attr,
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
struct scsi_device *sdp = sdkp->device;
+ struct queue_limits lim;
unsigned long max;
int err;
@@ -579,8 +592,13 @@ max_write_same_blocks_store(struct device *dev, struct device_attribute *attr,
sdkp->max_ws_blocks = max;
}
- sd_config_write_same(sdkp);
-
+ lim = queue_limits_start_update(sdkp->disk->queue);
+ sd_config_write_same(sdkp, &lim);
+ blk_mq_freeze_queue(sdkp->disk->queue);
+ err = queue_limits_commit_update(sdkp->disk->queue, &lim);
+ blk_mq_unfreeze_queue(sdkp->disk->queue);
+ if (err)
+ return err;
return count;
}
static DEVICE_ATTR_RW(max_write_same_blocks);
@@ -823,25 +841,28 @@ static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd,
return protect;
}
-static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
+static void sd_disable_discard(struct scsi_disk *sdkp)
+{
+ sdkp->provisioning_mode = SD_LBP_DISABLE;
+ blk_queue_disable_discard(sdkp->disk->queue);
+}
+
+static void sd_config_discard(struct scsi_disk *sdkp, struct queue_limits *lim,
+ unsigned int mode)
{
- struct request_queue *q = sdkp->disk->queue;
unsigned int logical_block_size = sdkp->device->sector_size;
unsigned int max_blocks = 0;
- q->limits.discard_alignment =
- sdkp->unmap_alignment * logical_block_size;
- q->limits.discard_granularity =
- max(sdkp->physical_block_size,
- sdkp->unmap_granularity * logical_block_size);
+ lim->discard_alignment = sdkp->unmap_alignment * logical_block_size;
+ lim->discard_granularity = max(sdkp->physical_block_size,
+ sdkp->unmap_granularity * logical_block_size);
sdkp->provisioning_mode = mode;
switch (mode) {
case SD_LBP_FULL:
case SD_LBP_DISABLE:
- blk_queue_max_discard_sectors(q, 0);
- return;
+ break;
case SD_LBP_UNMAP:
max_blocks = min_not_zero(sdkp->max_unmap_blocks,
@@ -872,7 +893,8 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
break;
}
- blk_queue_max_discard_sectors(q, max_blocks * (logical_block_size >> 9));
+ lim->max_hw_discard_sectors = max_blocks *
+ (logical_block_size >> SECTOR_SHIFT);
}
static void *sd_set_special_bvec(struct request *rq, unsigned int data_len)
@@ -918,6 +940,64 @@ static blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd)
return scsi_alloc_sgtables(cmd);
}
+static void sd_config_atomic(struct scsi_disk *sdkp, struct queue_limits *lim)
+{
+ unsigned int logical_block_size = sdkp->device->sector_size,
+ physical_block_size_sectors, max_atomic, unit_min, unit_max;
+
+ if ((!sdkp->max_atomic && !sdkp->max_atomic_with_boundary) ||
+ sdkp->protection_type == T10_PI_TYPE2_PROTECTION)
+ return;
+
+ physical_block_size_sectors = sdkp->physical_block_size /
+ sdkp->device->sector_size;
+
+ unit_min = rounddown_pow_of_two(sdkp->atomic_granularity ?
+ sdkp->atomic_granularity :
+ physical_block_size_sectors);
+
+ /*
+ * Only use atomic boundary when we have the odd scenario of
+ * sdkp->max_atomic == 0, which the spec does permit.
+ */
+ if (sdkp->max_atomic) {
+ max_atomic = sdkp->max_atomic;
+ unit_max = rounddown_pow_of_two(sdkp->max_atomic);
+ sdkp->use_atomic_write_boundary = 0;
+ } else {
+ max_atomic = sdkp->max_atomic_with_boundary;
+ unit_max = rounddown_pow_of_two(sdkp->max_atomic_boundary);
+ sdkp->use_atomic_write_boundary = 1;
+ }
+
+ /*
+ * Ensure compliance with granularity and alignment. For now, keep it
+ * simple and just don't support atomic writes for values mismatched
+ * with max_{boundary}atomic, physical block size, and
+ * atomic_granularity itself.
+ *
+ * We're really being distrustful by checking unit_max also...
+ */
+ if (sdkp->atomic_granularity > 1) {
+ if (unit_min > 1 && unit_min % sdkp->atomic_granularity)
+ return;
+ if (unit_max > 1 && unit_max % sdkp->atomic_granularity)
+ return;
+ }
+
+ if (sdkp->atomic_alignment > 1) {
+ if (unit_min > 1 && unit_min % sdkp->atomic_alignment)
+ return;
+ if (unit_max > 1 && unit_max % sdkp->atomic_alignment)
+ return;
+ }
+
+ lim->atomic_write_hw_max = max_atomic * logical_block_size;
+ lim->atomic_write_hw_boundary = 0;
+ lim->atomic_write_hw_unit_min = unit_min * logical_block_size;
+ lim->atomic_write_hw_unit_max = unit_max * logical_block_size;
+}
+
static blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd,
bool unmap)
{
@@ -1000,9 +1080,16 @@ static blk_status_t sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd)
return sd_setup_write_same10_cmnd(cmd, false);
}
-static void sd_config_write_same(struct scsi_disk *sdkp)
+static void sd_disable_write_same(struct scsi_disk *sdkp)
+{
+ sdkp->device->no_write_same = 1;
+ sdkp->max_ws_blocks = 0;
+ blk_queue_disable_write_zeroes(sdkp->disk->queue);
+}
+
+static void sd_config_write_same(struct scsi_disk *sdkp,
+ struct queue_limits *lim)
{
- struct request_queue *q = sdkp->disk->queue;
unsigned int logical_block_size = sdkp->device->sector_size;
if (sdkp->device->no_write_same) {
@@ -1056,8 +1143,8 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
}
out:
- blk_queue_max_write_zeroes_sectors(q, sdkp->max_ws_blocks *
- (logical_block_size >> 9));
+ lim->max_write_zeroes_sectors =
+ sdkp->max_ws_blocks * (logical_block_size >> SECTOR_SHIFT);
}
static blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd)
@@ -1209,6 +1296,26 @@ static int sd_cdl_dld(struct scsi_disk *sdkp, struct scsi_cmnd *scmd)
return (hint - IOPRIO_HINT_DEV_DURATION_LIMIT_1) + 1;
}
+static blk_status_t sd_setup_atomic_cmnd(struct scsi_cmnd *cmd,
+ sector_t lba, unsigned int nr_blocks,
+ bool boundary, unsigned char flags)
+{
+ cmd->cmd_len = 16;
+ cmd->cmnd[0] = WRITE_ATOMIC_16;
+ cmd->cmnd[1] = flags;
+ put_unaligned_be64(lba, &cmd->cmnd[2]);
+ put_unaligned_be16(nr_blocks, &cmd->cmnd[12]);
+ if (boundary)
+ put_unaligned_be16(nr_blocks, &cmd->cmnd[10]);
+ else
+ put_unaligned_be16(0, &cmd->cmnd[10]);
+ put_unaligned_be16(nr_blocks, &cmd->cmnd[12]);
+ cmd->cmnd[14] = 0;
+ cmd->cmnd[15] = 0;
+
+ return BLK_STS_OK;
+}
+
static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)
{
struct request *rq = scsi_cmd_to_rq(cmd);
@@ -1274,6 +1381,10 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)
if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) {
ret = sd_setup_rw32_cmnd(cmd, write, lba, nr_blocks,
protect | fua, dld);
+ } else if (rq->cmd_flags & REQ_ATOMIC && write) {
+ ret = sd_setup_atomic_cmnd(cmd, lba, nr_blocks,
+ sdkp->use_atomic_write_boundary,
+ protect | fua);
} else if (sdp->use_16_for_rw || (nr_blocks > 0xffff)) {
ret = sd_setup_rw16_cmnd(cmd, write, lba, nr_blocks,
protect | fua, dld);
@@ -2247,15 +2358,14 @@ static int sd_done(struct scsi_cmnd *SCpnt)
case 0x24: /* INVALID FIELD IN CDB */
switch (SCpnt->cmnd[0]) {
case UNMAP:
- sd_config_discard(sdkp, SD_LBP_DISABLE);
+ sd_disable_discard(sdkp);
break;
case WRITE_SAME_16:
case WRITE_SAME:
if (SCpnt->cmnd[1] & 8) { /* UNMAP */
- sd_config_discard(sdkp, SD_LBP_DISABLE);
+ sd_disable_discard(sdkp);
} else {
- sdkp->device->no_write_same = 1;
- sd_config_write_same(sdkp);
+ sd_disable_write_same(sdkp);
req->rq_flags |= RQF_QUIET;
}
break;
@@ -2267,7 +2377,7 @@ static int sd_done(struct scsi_cmnd *SCpnt)
}
out:
- if (sd_is_zoned(sdkp))
+ if (sdkp->device->type == TYPE_ZBC)
good_bytes = sd_zbc_complete(SCpnt, good_bytes, &sshdr);
SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt,
@@ -2461,11 +2571,13 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer
return 0;
}
-static void sd_config_protection(struct scsi_disk *sdkp)
+static void sd_config_protection(struct scsi_disk *sdkp,
+ struct queue_limits *lim)
{
struct scsi_device *sdp = sdkp->device;
- sd_dif_config_host(sdkp);
+ if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY))
+ sd_dif_config_host(sdkp, lim);
if (!sdkp->protection_type)
return;
@@ -2514,7 +2626,7 @@ static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
#define READ_CAPACITY_RETRIES_ON_RESET 10
static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
- unsigned char *buffer)
+ struct queue_limits *lim, unsigned char *buffer)
{
unsigned char cmd[16];
struct scsi_sense_hdr sshdr;
@@ -2588,7 +2700,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
/* Lowest aligned logical block */
alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size;
- blk_queue_alignment_offset(sdp->request_queue, alignment);
+ lim->alignment_offset = alignment;
if (alignment && sdkp->first_scan)
sd_printk(KERN_NOTICE, sdkp,
"physical block alignment offset: %u\n", alignment);
@@ -2599,7 +2711,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
if (buffer[14] & 0x40) /* LBPRZ */
sdkp->lbprz = 1;
- sd_config_discard(sdkp, SD_LBP_WS16);
+ sd_config_discard(sdkp, lim, SD_LBP_WS16);
}
sdkp->capacity = lba + 1;
@@ -2702,13 +2814,14 @@ static int sd_try_rc16_first(struct scsi_device *sdp)
* read disk capacity
*/
static void
-sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
+sd_read_capacity(struct scsi_disk *sdkp, struct queue_limits *lim,
+ unsigned char *buffer)
{
int sector_size;
struct scsi_device *sdp = sdkp->device;
if (sd_try_rc16_first(sdp)) {
- sector_size = read_capacity_16(sdkp, sdp, buffer);
+ sector_size = read_capacity_16(sdkp, sdp, lim, buffer);
if (sector_size == -EOVERFLOW)
goto got_data;
if (sector_size == -ENODEV)
@@ -2728,7 +2841,7 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
int old_sector_size = sector_size;
sd_printk(KERN_NOTICE, sdkp, "Very big device. "
"Trying to use READ CAPACITY(16).\n");
- sector_size = read_capacity_16(sdkp, sdp, buffer);
+ sector_size = read_capacity_16(sdkp, sdp, lim, buffer);
if (sector_size < 0) {
sd_printk(KERN_NOTICE, sdkp,
"Using 0xffffffff as device size\n");
@@ -2787,9 +2900,8 @@ got_data:
*/
sector_size = 512;
}
- blk_queue_logical_block_size(sdp->request_queue, sector_size);
- blk_queue_physical_block_size(sdp->request_queue,
- sdkp->physical_block_size);
+ lim->logical_block_size = sector_size;
+ lim->physical_block_size = sdkp->physical_block_size;
sdkp->device->sector_size = sector_size;
if (sdkp->capacity > 0xffffffff)
@@ -3195,11 +3307,30 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
return;
}
-/**
- * sd_read_block_limits - Query disk device for preferred I/O sizes.
- * @sdkp: disk to query
+static unsigned int sd_discard_mode(struct scsi_disk *sdkp)
+{
+ if (!sdkp->lbpvpd) {
+ /* LBP VPD page not provided */
+ if (sdkp->max_unmap_blocks)
+ return SD_LBP_UNMAP;
+ return SD_LBP_WS16;
+ }
+
+ /* LBP VPD page tells us what to use */
+ if (sdkp->lbpu && sdkp->max_unmap_blocks)
+ return SD_LBP_UNMAP;
+ if (sdkp->lbpws)
+ return SD_LBP_WS16;
+ if (sdkp->lbpws10)
+ return SD_LBP_WS10;
+ return SD_LBP_DISABLE;
+}
+
+/*
+ * Query disk device for preferred I/O sizes.
*/
-static void sd_read_block_limits(struct scsi_disk *sdkp)
+static void sd_read_block_limits(struct scsi_disk *sdkp,
+ struct queue_limits *lim)
{
struct scsi_vpd *vpd;
@@ -3219,7 +3350,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
sdkp->max_ws_blocks = (u32)get_unaligned_be64(&vpd->data[36]);
if (!sdkp->lbpme)
- goto out;
+ goto config_atomic;
lba_count = get_unaligned_be32(&vpd->data[20]);
desc_count = get_unaligned_be32(&vpd->data[24]);
@@ -3233,23 +3364,16 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
sdkp->unmap_alignment =
get_unaligned_be32(&vpd->data[32]) & ~(1 << 31);
- if (!sdkp->lbpvpd) { /* LBP VPD page not provided */
-
- if (sdkp->max_unmap_blocks)
- sd_config_discard(sdkp, SD_LBP_UNMAP);
- else
- sd_config_discard(sdkp, SD_LBP_WS16);
-
- } else { /* LBP VPD page tells us what to use */
- if (sdkp->lbpu && sdkp->max_unmap_blocks)
- sd_config_discard(sdkp, SD_LBP_UNMAP);
- else if (sdkp->lbpws)
- sd_config_discard(sdkp, SD_LBP_WS16);
- else if (sdkp->lbpws10)
- sd_config_discard(sdkp, SD_LBP_WS10);
- else
- sd_config_discard(sdkp, SD_LBP_DISABLE);
- }
+ sd_config_discard(sdkp, lim, sd_discard_mode(sdkp));
+
+config_atomic:
+ sdkp->max_atomic = get_unaligned_be32(&vpd->data[44]);
+ sdkp->atomic_alignment = get_unaligned_be32(&vpd->data[48]);
+ sdkp->atomic_granularity = get_unaligned_be32(&vpd->data[52]);
+ sdkp->max_atomic_with_boundary = get_unaligned_be32(&vpd->data[56]);
+ sdkp->max_atomic_boundary = get_unaligned_be32(&vpd->data[60]);
+
+ sd_config_atomic(sdkp, lim);
}
out:
@@ -3268,13 +3392,10 @@ static void sd_read_block_limits_ext(struct scsi_disk *sdkp)
rcu_read_unlock();
}
-/**
- * sd_read_block_characteristics - Query block dev. characteristics
- * @sdkp: disk to query
- */
-static void sd_read_block_characteristics(struct scsi_disk *sdkp)
+/* Query block device characteristics */
+static void sd_read_block_characteristics(struct scsi_disk *sdkp,
+ struct queue_limits *lim)
{
- struct request_queue *q = sdkp->disk->queue;
struct scsi_vpd *vpd;
u16 rot;
@@ -3290,37 +3411,13 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
sdkp->zoned = (vpd->data[8] >> 4) & 3;
rcu_read_unlock();
- if (rot == 1) {
- blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
- blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
- }
-
-
-#ifdef CONFIG_BLK_DEV_ZONED /* sd_probe rejects ZBD devices early otherwise */
- if (sdkp->device->type == TYPE_ZBC) {
- /*
- * Host-managed.
- */
- disk_set_zoned(sdkp->disk);
-
- /*
- * Per ZBC and ZAC specifications, writes in sequential write
- * required zones of host-managed devices must be aligned to
- * the device physical block size.
- */
- blk_queue_zone_write_granularity(q, sdkp->physical_block_size);
- } else {
- /*
- * Host-aware devices are treated as conventional.
- */
- WARN_ON_ONCE(blk_queue_is_zoned(q));
- }
-#endif /* CONFIG_BLK_DEV_ZONED */
+ if (rot == 1)
+ lim->features &= ~(BLK_FEAT_ROTATIONAL | BLK_FEAT_ADD_RANDOM);
if (!sdkp->first_scan)
return;
- if (blk_queue_is_zoned(q))
+ if (sdkp->device->type == TYPE_ZBC)
sd_printk(KERN_NOTICE, sdkp, "Host-managed zoned block device\n");
else if (sdkp->zoned == 1)
sd_printk(KERN_NOTICE, sdkp, "Host-aware SMR disk used as regular disk\n");
@@ -3601,10 +3698,11 @@ static int sd_revalidate_disk(struct gendisk *disk)
{
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
- struct request_queue *q = sdkp->disk->queue;
sector_t old_capacity = sdkp->capacity;
+ struct queue_limits lim;
unsigned char *buffer;
- unsigned int dev_max, rw_max;
+ unsigned int dev_max;
+ int err;
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
"sd_revalidate_disk\n"));
@@ -3625,12 +3723,14 @@ static int sd_revalidate_disk(struct gendisk *disk)
sd_spinup_disk(sdkp);
+ lim = queue_limits_start_update(sdkp->disk->queue);
+
/*
* Without media there is no reason to ask; moreover, some devices
* react badly if we do.
*/
if (sdkp->media_present) {
- sd_read_capacity(sdkp, buffer);
+ sd_read_capacity(sdkp, &lim, buffer);
/*
* Some USB/UAS devices return generic values for mode pages
* until the media has been accessed. Trigger a READ operation
@@ -3644,15 +3744,14 @@ static int sd_revalidate_disk(struct gendisk *disk)
* cause this to be updated correctly and any device which
* doesn't support it should be treated as rotational.
*/
- blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
- blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
+ lim.features |= (BLK_FEAT_ROTATIONAL | BLK_FEAT_ADD_RANDOM);
if (scsi_device_supports_vpd(sdp)) {
sd_read_block_provisioning(sdkp);
- sd_read_block_limits(sdkp);
+ sd_read_block_limits(sdkp, &lim);
sd_read_block_limits_ext(sdkp);
- sd_read_block_characteristics(sdkp);
- sd_zbc_read_zones(sdkp, buffer);
+ sd_read_block_characteristics(sdkp, &lim);
+ sd_zbc_read_zones(sdkp, &lim, buffer);
sd_read_cpr(sdkp);
}
@@ -3664,64 +3763,50 @@ static int sd_revalidate_disk(struct gendisk *disk)
sd_read_app_tag_own(sdkp, buffer);
sd_read_write_same(sdkp, buffer);
sd_read_security(sdkp, buffer);
- sd_config_protection(sdkp);
+ sd_config_protection(sdkp, &lim);
}
/*
* We now have all cache related info, determine how we deal
* with flush requests.
*/
- sd_set_flush_flag(sdkp);
+ sd_set_flush_flag(sdkp, &lim);
/* Initial block count limit based on CDB TRANSFER LENGTH field size. */
dev_max = sdp->use_16_for_rw ? SD_MAX_XFER_BLOCKS : SD_DEF_XFER_BLOCKS;
/* Some devices report a maximum block count for READ/WRITE requests. */
dev_max = min_not_zero(dev_max, sdkp->max_xfer_blocks);
- q->limits.max_dev_sectors = logical_to_sectors(sdp, dev_max);
+ lim.max_dev_sectors = logical_to_sectors(sdp, dev_max);
if (sd_validate_min_xfer_size(sdkp))
- blk_queue_io_min(sdkp->disk->queue,
- logical_to_bytes(sdp, sdkp->min_xfer_blocks));
+ lim.io_min = logical_to_bytes(sdp, sdkp->min_xfer_blocks);
else
- blk_queue_io_min(sdkp->disk->queue, 0);
-
- if (sd_validate_opt_xfer_size(sdkp, dev_max)) {
- q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks);
- rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks);
- } else {
- q->limits.io_opt = 0;
- rw_max = min_not_zero(logical_to_sectors(sdp, dev_max),
- (sector_t)BLK_DEF_MAX_SECTORS_CAP);
- }
+ lim.io_min = 0;
/*
* Limit default to SCSI host optimal sector limit if set. There may be
* an impact on performance for when the size of a request exceeds this
* host limit.
*/
- rw_max = min_not_zero(rw_max, sdp->host->opt_sectors);
-
- /* Do not exceed controller limit */
- rw_max = min(rw_max, queue_max_hw_sectors(q));
-
- /*
- * Only update max_sectors if previously unset or if the current value
- * exceeds the capabilities of the hardware.
- */
- if (sdkp->first_scan ||
- q->limits.max_sectors > q->limits.max_dev_sectors ||
- q->limits.max_sectors > q->limits.max_hw_sectors) {
- q->limits.max_sectors = rw_max;
- q->limits.max_user_sectors = rw_max;
+ lim.io_opt = sdp->host->opt_sectors << SECTOR_SHIFT;
+ if (sd_validate_opt_xfer_size(sdkp, dev_max)) {
+ lim.io_opt = min_not_zero(lim.io_opt,
+ logical_to_bytes(sdp, sdkp->opt_xfer_blocks));
}
sdkp->first_scan = 0;
set_capacity_and_notify(disk, logical_to_sectors(sdp, sdkp->capacity));
- sd_config_write_same(sdkp);
+ sd_config_write_same(sdkp, &lim);
kfree(buffer);
+ blk_mq_freeze_queue(sdkp->disk->queue);
+ err = queue_limits_commit_update(sdkp->disk->queue, &lim);
+ blk_mq_unfreeze_queue(sdkp->disk->queue);
+ if (err)
+ return err;
+
/*
* For a zoned drive, revalidating the zones can be done only once
* the gendisk capacity is set. So if this fails, set back the gendisk
@@ -4119,8 +4204,6 @@ static int sd_resume(struct device *dev)
{
struct scsi_disk *sdkp = dev_get_drvdata(dev);
- sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
-
if (opal_unlock_from_suspend(sdkp->opal_dev)) {
sd_printk(KERN_NOTICE, sdkp, "OPAL unlock failed\n");
return -EIO;
@@ -4137,12 +4220,13 @@ static int sd_resume_common(struct device *dev, bool runtime)
if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */
return 0;
+ sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
+
if (!sd_do_start_stop(sdkp->device, runtime)) {
sdkp->suspended = false;
return 0;
}
- sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
ret = sd_start_stop_device(sdkp, 1);
if (!ret) {
sd_resume(dev);
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 49dd600bfa48..36382eca941c 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -115,6 +115,13 @@ struct scsi_disk {
u32 max_unmap_blocks;
u32 unmap_granularity;
u32 unmap_alignment;
+
+ u32 max_atomic;
+ u32 atomic_alignment;
+ u32 atomic_granularity;
+ u32 max_atomic_with_boundary;
+ u32 max_atomic_boundary;
+
u32 index;
unsigned int physical_block_size;
unsigned int max_medium_access_timeouts;
@@ -148,6 +155,7 @@ struct scsi_disk {
unsigned security : 1;
unsigned ignore_medium_access_errors : 1;
unsigned rscs : 1; /* reduced stream control support */
+ unsigned use_atomic_write_boundary : 1;
};
#define to_scsi_disk(obj) container_of(obj, struct scsi_disk, disk_dev)
@@ -220,26 +228,12 @@ static inline sector_t sectors_to_logical(struct scsi_device *sdev, sector_t sec
return sector >> (ilog2(sdev->sector_size) - 9);
}
-#ifdef CONFIG_BLK_DEV_INTEGRITY
-
-extern void sd_dif_config_host(struct scsi_disk *);
-
-#else /* CONFIG_BLK_DEV_INTEGRITY */
-
-static inline void sd_dif_config_host(struct scsi_disk *disk)
-{
-}
-
-#endif /* CONFIG_BLK_DEV_INTEGRITY */
-
-static inline int sd_is_zoned(struct scsi_disk *sdkp)
-{
- return sdkp->zoned == 1 || sdkp->device->type == TYPE_ZBC;
-}
+void sd_dif_config_host(struct scsi_disk *sdkp, struct queue_limits *lim);
#ifdef CONFIG_BLK_DEV_ZONED
-int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE]);
+int sd_zbc_read_zones(struct scsi_disk *sdkp, struct queue_limits *lim,
+ u8 buf[SD_BUF_SIZE]);
int sd_zbc_revalidate_zones(struct scsi_disk *sdkp);
blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
unsigned char op, bool all);
@@ -250,7 +244,8 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
#else /* CONFIG_BLK_DEV_ZONED */
-static inline int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE])
+static inline int sd_zbc_read_zones(struct scsi_disk *sdkp,
+ struct queue_limits *lim, u8 buf[SD_BUF_SIZE])
{
return 0;
}
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index 1df847b5f747..ae6ce6f5d622 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -24,14 +24,15 @@
/*
* Configure exchange of protection information between OS and HBA.
*/
-void sd_dif_config_host(struct scsi_disk *sdkp)
+void sd_dif_config_host(struct scsi_disk *sdkp, struct queue_limits *lim)
{
struct scsi_device *sdp = sdkp->device;
- struct gendisk *disk = sdkp->disk;
u8 type = sdkp->protection_type;
- struct blk_integrity bi;
+ struct blk_integrity *bi = &lim->integrity;
int dif, dix;
+ memset(bi, 0, sizeof(*bi));
+
dif = scsi_host_dif_capable(sdp->host, type);
dix = scsi_host_dix_capable(sdp->host, type);
@@ -39,45 +40,33 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
dif = 0; dix = 1;
}
- if (!dix) {
- blk_integrity_unregister(disk);
+ if (!dix)
return;
- }
-
- memset(&bi, 0, sizeof(bi));
/* Enable DMA of protection information */
- if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) {
- if (type == T10_PI_TYPE3_PROTECTION)
- bi.profile = &t10_pi_type3_ip;
- else
- bi.profile = &t10_pi_type1_ip;
+ if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP)
+ bi->csum_type = BLK_INTEGRITY_CSUM_IP;
+ else
+ bi->csum_type = BLK_INTEGRITY_CSUM_CRC;
- bi.flags |= BLK_INTEGRITY_IP_CHECKSUM;
- } else
- if (type == T10_PI_TYPE3_PROTECTION)
- bi.profile = &t10_pi_type3_crc;
- else
- bi.profile = &t10_pi_type1_crc;
+ if (type != T10_PI_TYPE3_PROTECTION)
+ bi->flags |= BLK_INTEGRITY_REF_TAG;
- bi.tuple_size = sizeof(struct t10_pi_tuple);
+ bi->tuple_size = sizeof(struct t10_pi_tuple);
if (dif && type) {
- bi.flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
+ bi->flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
if (!sdkp->ATO)
- goto out;
+ return;
if (type == T10_PI_TYPE3_PROTECTION)
- bi.tag_size = sizeof(u16) + sizeof(u32);
+ bi->tag_size = sizeof(u16) + sizeof(u32);
else
- bi.tag_size = sizeof(u16);
+ bi->tag_size = sizeof(u16);
}
sd_first_printk(KERN_NOTICE, sdkp,
"Enabling DIX %s, application tag size %u bytes\n",
- bi.profile->name, bi.tag_size);
-out:
- blk_integrity_register(disk, &bi);
+ blk_integrity_profile_name(bi), bi->tag_size);
}
-
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 806036e48abe..c8b9654d30f0 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -232,7 +232,7 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
int zone_idx = 0;
int ret;
- if (!sd_is_zoned(sdkp))
+ if (sdkp->device->type != TYPE_ZBC)
/* Not a zoned device */
return -EOPNOTSUPP;
@@ -300,7 +300,7 @@ static blk_status_t sd_zbc_cmnd_checks(struct scsi_cmnd *cmd)
struct scsi_disk *sdkp = scsi_disk(rq->q->disk);
sector_t sector = blk_rq_pos(rq);
- if (!sd_is_zoned(sdkp))
+ if (sdkp->device->type != TYPE_ZBC)
/* Not a zoned device */
return BLK_STS_IOERR;
@@ -521,7 +521,7 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp, unsigned char *buf,
static void sd_zbc_print_zones(struct scsi_disk *sdkp)
{
- if (!sd_is_zoned(sdkp) || !sdkp->capacity)
+ if (sdkp->device->type != TYPE_ZBC || !sdkp->capacity)
return;
if (sdkp->capacity & (sdkp->zone_info.zone_blocks - 1))
@@ -565,12 +565,6 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
sdkp->zone_info.zone_blocks = zone_blocks;
sdkp->zone_info.nr_zones = nr_zones;
- blk_queue_chunk_sectors(q,
- logical_to_sectors(sdkp->device, zone_blocks));
-
- /* Enable block layer zone append emulation */
- blk_queue_max_zone_append_sectors(q, 0);
-
flags = memalloc_noio_save();
ret = blk_revalidate_disk_zones(disk);
memalloc_noio_restore(flags);
@@ -588,27 +582,31 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
/**
* sd_zbc_read_zones - Read zone information and update the request queue
* @sdkp: SCSI disk pointer.
+ * @lim: queue limits to read into
* @buf: 512 byte buffer used for storing SCSI command output.
*
* Read zone information and update the request queue zone characteristics and
* also the zoned device information in *sdkp. Called by sd_revalidate_disk()
* before the gendisk capacity has been set.
*/
-int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE])
+int sd_zbc_read_zones(struct scsi_disk *sdkp, struct queue_limits *lim,
+ u8 buf[SD_BUF_SIZE])
{
- struct gendisk *disk = sdkp->disk;
- struct request_queue *q = disk->queue;
unsigned int nr_zones;
u32 zone_blocks = 0;
int ret;
- if (!sd_is_zoned(sdkp)) {
- /*
- * Device managed or normal SCSI disk, no special handling
- * required.
- */
+ if (sdkp->device->type != TYPE_ZBC)
return 0;
- }
+
+ lim->features |= BLK_FEAT_ZONED;
+
+ /*
+ * Per ZBC and ZAC specifications, writes in sequential write required
+ * zones of host-managed devices must be aligned to the device physical
+ * block size.
+ */
+ lim->zone_write_granularity = sdkp->physical_block_size;
/* READ16/WRITE16/SYNC16 is mandatory for ZBC devices */
sdkp->device->use_16_for_rw = 1;
@@ -625,18 +623,20 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE])
if (ret != 0)
goto err;
- /* The drive satisfies the kernel restrictions: set it up */
- blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
- if (sdkp->zones_max_open == U32_MAX)
- disk_set_max_open_zones(disk, 0);
- else
- disk_set_max_open_zones(disk, sdkp->zones_max_open);
- disk_set_max_active_zones(disk, 0);
nr_zones = round_up(sdkp->capacity, zone_blocks) >> ilog2(zone_blocks);
-
sdkp->early_zone_info.nr_zones = nr_zones;
sdkp->early_zone_info.zone_blocks = zone_blocks;
+ /* The drive satisfies the kernel restrictions: set it up */
+ if (sdkp->zones_max_open == U32_MAX)
+ lim->max_open_zones = 0;
+ else
+ lim->max_open_zones = sdkp->zones_max_open;
+ lim->max_active_zones = 0;
+ lim->chunk_sectors = logical_to_sectors(sdkp->device, zone_blocks);
+ /* Enable block layer zone append emulation */
+ lim->max_zone_append_sectors = 0;
+
return 0;
err:
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 7ab000942b97..3f491019103e 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -111,7 +111,7 @@ static struct lock_class_key sr_bio_compl_lkclass;
static int sr_open(struct cdrom_device_info *, int);
static void sr_release(struct cdrom_device_info *);
-static void get_sectorsize(struct scsi_cd *);
+static int get_sectorsize(struct scsi_cd *);
static int get_capabilities(struct scsi_cd *);
static unsigned int sr_check_events(struct cdrom_device_info *cdi,
@@ -473,15 +473,15 @@ static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt)
return BLK_STS_IOERR;
}
-static void sr_revalidate_disk(struct scsi_cd *cd)
+static int sr_revalidate_disk(struct scsi_cd *cd)
{
struct scsi_sense_hdr sshdr;
/* if the unit is not ready, nothing more to do */
if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr))
- return;
+ return 0;
sr_cd_check(&cd->cdi);
- get_sectorsize(cd);
+ return get_sectorsize(cd);
}
static int sr_block_open(struct gendisk *disk, blk_mode_t mode)
@@ -494,13 +494,16 @@ static int sr_block_open(struct gendisk *disk, blk_mode_t mode)
return -ENXIO;
scsi_autopm_get_device(sdev);
- if (disk_check_media_change(disk))
- sr_revalidate_disk(cd);
+ if (disk_check_media_change(disk)) {
+ ret = sr_revalidate_disk(cd);
+ if (ret)
+ goto out;
+ }
mutex_lock(&cd->lock);
ret = cdrom_open(&cd->cdi, mode);
mutex_unlock(&cd->lock);
-
+out:
scsi_autopm_put_device(sdev);
if (ret)
scsi_device_put(cd->device);
@@ -685,7 +688,9 @@ static int sr_probe(struct device *dev)
blk_pm_runtime_init(sdev->request_queue, dev);
dev_set_drvdata(dev, cd);
- sr_revalidate_disk(cd);
+ error = sr_revalidate_disk(cd);
+ if (error)
+ goto unregister_cdrom;
error = device_add_disk(&sdev->sdev_gendev, disk, NULL);
if (error)
@@ -714,13 +719,14 @@ fail:
}
-static void get_sectorsize(struct scsi_cd *cd)
+static int get_sectorsize(struct scsi_cd *cd)
{
+ struct request_queue *q = cd->device->request_queue;
static const u8 cmd[10] = { READ_CAPACITY };
unsigned char buffer[8] = { };
- int the_result;
+ struct queue_limits lim;
+ int err;
int sector_size;
- struct request_queue *queue;
struct scsi_failure failure_defs[] = {
{
.result = SCMD_FAILURE_RESULT_ANY,
@@ -736,10 +742,10 @@ static void get_sectorsize(struct scsi_cd *cd)
};
/* Do the command and wait.. */
- the_result = scsi_execute_cmd(cd->device, cmd, REQ_OP_DRV_IN, buffer,
+ err = scsi_execute_cmd(cd->device, cmd, REQ_OP_DRV_IN, buffer,
sizeof(buffer), SR_TIMEOUT, MAX_RETRIES,
&exec_args);
- if (the_result) {
+ if (err) {
cd->capacity = 0x1fffff;
sector_size = 2048; /* A guess, just in case */
} else {
@@ -789,10 +795,12 @@ static void get_sectorsize(struct scsi_cd *cd)
set_capacity(cd->disk, cd->capacity);
}
- queue = cd->device->request_queue;
- blk_queue_logical_block_size(queue, sector_size);
-
- return;
+ lim = queue_limits_start_update(q);
+ lim.logical_block_size = sector_size;
+ blk_mq_freeze_queue(q);
+ err = queue_limits_commit_update(q, &lim);
+ blk_mq_unfreeze_queue(q);
+ return err;
}
static int get_capabilities(struct scsi_cd *cd)
diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c
index 3f3039600357..a6453ffeb753 100644
--- a/drivers/soc/amlogic/meson-clk-measure.c
+++ b/drivers/soc/amlogic/meson-clk-measure.c
@@ -688,4 +688,5 @@ static struct platform_driver meson_msr_driver = {
},
};
module_platform_driver(meson_msr_driver);
+MODULE_DESCRIPTION("Amlogic Meson SoC Clock Measure driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/amlogic/meson-gx-socinfo.c b/drivers/soc/amlogic/meson-gx-socinfo.c
index 6abb730344ab..8809a948201a 100644
--- a/drivers/soc/amlogic/meson-gx-socinfo.c
+++ b/drivers/soc/amlogic/meson-gx-socinfo.c
@@ -63,7 +63,9 @@ static const struct meson_gx_package_id {
{ "962X", 0x24, 0x10, 0xf0 },
{ "962E", 0x24, 0x20, 0xf0 },
{ "A113X", 0x25, 0x37, 0xff },
+ { "A113X", 0x25, 0x43, 0xff },
{ "A113D", 0x25, 0x22, 0xff },
+ { "S905L", 0x26, 0, 0x0 },
{ "S905D2", 0x28, 0x10, 0xf0 },
{ "S905Y2", 0x28, 0x30, 0xf0 },
{ "S905X2", 0x28, 0x40, 0xf0 },
diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c
index ec87d9d878f3..fe111bae38c8 100644
--- a/drivers/soc/imx/soc-imx8m.c
+++ b/drivers/soc/imx/soc-imx8m.c
@@ -252,4 +252,5 @@ free_soc:
return ret;
}
device_initcall(imx8_soc_init);
+MODULE_DESCRIPTION("NXP i.MX8M SoC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/soc/ixp4xx/ixp4xx-npe.c b/drivers/soc/ixp4xx/ixp4xx-npe.c
index 35825ee95dff..34a6f187c220 100644
--- a/drivers/soc/ixp4xx/ixp4xx-npe.c
+++ b/drivers/soc/ixp4xx/ixp4xx-npe.c
@@ -764,6 +764,7 @@ static struct platform_driver ixp4xx_npe_driver = {
module_platform_driver(ixp4xx_npe_driver);
MODULE_AUTHOR("Krzysztof Halasa");
+MODULE_DESCRIPTION("Intel IXP4xx Network Processor Engine driver");
MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE(NPE_A_FIRMWARE);
MODULE_FIRMWARE(NPE_B_FIRMWARE);
diff --git a/drivers/soc/ixp4xx/ixp4xx-qmgr.c b/drivers/soc/ixp4xx/ixp4xx-qmgr.c
index 244ad8d7e80b..cb112f3643e9 100644
--- a/drivers/soc/ixp4xx/ixp4xx-qmgr.c
+++ b/drivers/soc/ixp4xx/ixp4xx-qmgr.c
@@ -465,6 +465,7 @@ static struct platform_driver ixp4xx_qmgr_driver = {
};
module_platform_driver(ixp4xx_qmgr_driver);
+MODULE_DESCRIPTION("Intel IXP4xx Queue Manager driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Krzysztof Halasa");
diff --git a/drivers/soc/litex/Kconfig b/drivers/soc/litex/Kconfig
index e6ba3573a772..f3f869639588 100644
--- a/drivers/soc/litex/Kconfig
+++ b/drivers/soc/litex/Kconfig
@@ -7,7 +7,7 @@ config LITEX
config LITEX_SOC_CONTROLLER
tristate "Enable LiteX SoC Controller driver"
- depends on OF || COMPILE_TEST
+ depends on OF
depends on HAS_IOMEM
select LITEX
help
diff --git a/drivers/soc/litex/litex_soc_ctrl.c b/drivers/soc/litex/litex_soc_ctrl.c
index 10813299aa10..72c44119dd54 100644
--- a/drivers/soc/litex/litex_soc_ctrl.c
+++ b/drivers/soc/litex/litex_soc_ctrl.c
@@ -82,13 +82,11 @@ static int litex_reset_handler(struct notifier_block *this, unsigned long mode,
return NOTIFY_DONE;
}
-#ifdef CONFIG_OF
static const struct of_device_id litex_soc_ctrl_of_match[] = {
{.compatible = "litex,soc-controller"},
{},
};
MODULE_DEVICE_TABLE(of, litex_soc_ctrl_of_match);
-#endif /* CONFIG_OF */
static int litex_soc_ctrl_probe(struct platform_device *pdev)
{
@@ -130,7 +128,7 @@ static void litex_soc_ctrl_remove(struct platform_device *pdev)
static struct platform_driver litex_soc_ctrl_driver = {
.driver = {
.name = "litex-soc-controller",
- .of_match_table = of_match_ptr(litex_soc_ctrl_of_match)
+ .of_match_table = litex_soc_ctrl_of_match,
},
.probe = litex_soc_ctrl_probe,
.remove_new = litex_soc_ctrl_remove,
diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
index 046522664dc1..a8fccedba83f 100644
--- a/drivers/soc/mediatek/mtk-cmdq-helper.c
+++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
@@ -15,6 +15,7 @@
/* dedicate the last GPR_R15 to assign the register address to be poll */
#define CMDQ_POLL_ADDR_GPR (15)
#define CMDQ_EOC_IRQ_EN BIT(0)
+#define CMDQ_IMMEDIATE_VALUE 0
#define CMDQ_REG_TYPE 1
#define CMDQ_JUMP_RELATIVE 0
#define CMDQ_JUMP_ABSOLUTE 1
@@ -45,6 +46,16 @@ struct cmdq_instruction {
u8 op;
};
+static inline u8 cmdq_operand_get_type(struct cmdq_operand *op)
+{
+ return op->reg ? CMDQ_REG_TYPE : CMDQ_IMMEDIATE_VALUE;
+}
+
+static inline u16 cmdq_operand_get_idx_value(struct cmdq_operand *op)
+{
+ return op->reg ? op->idx : op->value;
+}
+
int cmdq_dev_get_client_reg(struct device *dev,
struct cmdq_client_reg *client_reg, int idx)
{
@@ -461,6 +472,29 @@ int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mas
}
EXPORT_SYMBOL(cmdq_pkt_poll_addr);
+int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx,
+ struct cmdq_operand *left_operand,
+ enum cmdq_logic_op s_op,
+ struct cmdq_operand *right_operand)
+{
+ struct cmdq_instruction inst = { {0} };
+
+ if (!left_operand || !right_operand || s_op >= CMDQ_LOGIC_MAX)
+ return -EINVAL;
+
+ inst.op = CMDQ_CODE_LOGIC;
+ inst.dst_t = CMDQ_REG_TYPE;
+ inst.src_t = cmdq_operand_get_type(left_operand);
+ inst.arg_c_t = cmdq_operand_get_type(right_operand);
+ inst.sop = s_op;
+ inst.reg_dst = result_reg_idx;
+ inst.src_reg = cmdq_operand_get_idx_value(left_operand);
+ inst.arg_c = cmdq_operand_get_idx_value(right_operand);
+
+ return cmdq_pkt_append_command(pkt, inst);
+}
+EXPORT_SYMBOL(cmdq_pkt_logic_command);
+
int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value)
{
struct cmdq_instruction inst = {};
@@ -526,4 +560,5 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
}
EXPORT_SYMBOL(cmdq_pkt_finalize);
+MODULE_DESCRIPTION("MediaTek Command Queue (CMDQ) driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index f370f4ec4b88..938240714e54 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -236,6 +236,7 @@ void mtk_mmsys_mixer_in_config(struct device *dev, int idx, bool alpha_sel, u16
mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_ALPHA + (idx - 1) * 4, ~0,
alpha << 16 | alpha, cmdq_pkt);
+ mtk_mmsys_update_bits(mmsys, MT8195_VDO1_HDR_TOP_CFG, BIT(15 + idx), 0, cmdq_pkt);
mtk_mmsys_update_bits(mmsys, MT8195_VDO1_HDR_TOP_CFG, BIT(19 + idx),
alpha_sel << (19 + idx), cmdq_pkt);
mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_PAD + (idx - 1) * 4,
diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index b5af1fb5847e..01b129caf1eb 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -524,6 +524,7 @@ static const unsigned int mt8188_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_PAD0] = MT8195_MUTEX_MOD_MDP_PAD0,
[MUTEX_MOD_IDX_MDP_PAD2] = MT8195_MUTEX_MOD_MDP_PAD2,
[MUTEX_MOD_IDX_MDP_PAD3] = MT8195_MUTEX_MOD_MDP_PAD3,
+ [MUTEX_MOD_IDX_MDP_TCC0] = MT8195_MUTEX_MOD_MDP_TCC0,
[MUTEX_MOD_IDX_MDP_WROT0] = MT8195_MUTEX_MOD_MDP_WROT0,
[MUTEX_MOD_IDX_MDP_WROT2] = MT8195_MUTEX_MOD_MDP_WROT2,
[MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3,
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 5af33b0e3470..7f02f0525933 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -72,11 +72,28 @@ config QCOM_OCMEM
requirements. This is typically used by the GPU, camera/video, and
audio components on some Snapdragon SoCs.
+config QCOM_PD_MAPPER
+ tristate "Qualcomm Protection Domain Mapper"
+ select QCOM_QMI_HELPERS
+ select QCOM_PDR_MSG
+ select AUXILIARY_BUS
+ depends on NET && QRTR
+ default QCOM_RPROC_COMMON
+ help
+ The Protection Domain Mapper maps registered services to the domains
+ and instances handled by the remote DSPs. This is a kernel-space
+ implementation of the service. It is a simpler alternative to the
+ userspace daemon.
+
config QCOM_PDR_HELPERS
tristate
select QCOM_QMI_HELPERS
+ select QCOM_PDR_MSG
depends on NET
+config QCOM_PDR_MSG
+ tristate
+
config QCOM_PMIC_PDCHARGER_ULOG
tristate "Qualcomm PMIC PDCharger ULOG driver"
depends on RPMSG
@@ -194,6 +211,7 @@ config QCOM_SMP2P
config QCOM_SMSM
tristate "Qualcomm Shared Memory State Machine"
+ depends on MAILBOX
depends on QCOM_SMEM
select QCOM_SMEM_STATE
select IRQ_DOMAIN
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index ca0bece0dfff..d3560f861085 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -7,7 +7,9 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c
index fb323b3364db..e7851974084b 100644
--- a/drivers/soc/qcom/icc-bwmon.c
+++ b/drivers/soc/qcom/icc-bwmon.c
@@ -565,7 +565,7 @@ static void bwmon_start(struct icc_bwmon *bwmon)
int window;
/* No need to check for errors, as this must have succeeded before. */
- dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_low, 0);
+ dev_pm_opp_put(dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_low, 0));
bwmon_clear_counters(bwmon, true);
@@ -772,18 +772,25 @@ static int bwmon_probe(struct platform_device *pdev)
opp = dev_pm_opp_find_bw_floor(dev, &bwmon->max_bw_kbps, 0);
if (IS_ERR(opp))
return dev_err_probe(dev, PTR_ERR(opp), "failed to find max peak bandwidth\n");
+ dev_pm_opp_put(opp);
bwmon->min_bw_kbps = 0;
opp = dev_pm_opp_find_bw_ceil(dev, &bwmon->min_bw_kbps, 0);
if (IS_ERR(opp))
return dev_err_probe(dev, PTR_ERR(opp), "failed to find min peak bandwidth\n");
+ dev_pm_opp_put(opp);
bwmon->dev = dev;
bwmon_disable(bwmon);
- ret = devm_request_threaded_irq(dev, bwmon->irq, bwmon_intr,
- bwmon_intr_thread,
- IRQF_ONESHOT, dev_name(dev), bwmon);
+
+ /*
+ * SoCs with multiple cpu-bwmon instances can end up using a shared interrupt
+ * line. Using the devm_ variant might result in the IRQ handler being executed
+ * after bwmon_disable in bwmon_remove()
+ */
+ ret = request_threaded_irq(bwmon->irq, bwmon_intr, bwmon_intr_thread,
+ IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), bwmon);
if (ret)
return dev_err_probe(dev, ret, "failed to request IRQ\n");
@@ -798,6 +805,7 @@ static void bwmon_remove(struct platform_device *pdev)
struct icc_bwmon *bwmon = platform_get_drvdata(pdev);
bwmon_disable(bwmon);
+ free_irq(bwmon->irq, bwmon);
}
static const struct icc_bwmon_data msm8998_bwmon_data = {
diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
index cbef0dea1d5d..37e11e501728 100644
--- a/drivers/soc/qcom/llcc-qcom.c
+++ b/drivers/soc/qcom/llcc-qcom.c
@@ -7,6 +7,7 @@
#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/bitops.h>
+#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -150,6 +151,25 @@ enum llcc_reg_offset {
LLCC_COMMON_STATUS0,
};
+static const struct llcc_slice_config sa8775p_data[] = {
+ {LLCC_CPUSS, 1, 2048, 1, 0, 0x00FF, 0x0, 0, 0, 0, 1, 1, 0, 0},
+ {LLCC_VIDSC0, 2, 512, 3, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0},
+ {LLCC_CPUSS1, 3, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0},
+ {LLCC_CPUHWT, 5, 512, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0},
+ {LLCC_AUDIO, 6, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_CMPT, 10, 4096, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0},
+ {LLCC_GPUHTW, 11, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0},
+ {LLCC_GPU, 12, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 1, 0},
+ {LLCC_MMUHWT, 13, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 0, 1, 0, 0},
+ {LLCC_CMPTDMA, 15, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0},
+ {LLCC_DISP, 16, 4096, 2, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0},
+ {LLCC_VIDFW, 17, 3072, 1, 0, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0},
+ {LLCC_AUDHW, 22, 1024, 1, 1, 0x00FF, 0x0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_CVP, 28, 256, 3, 1, 0x00FF, 0x0, 0, 0, 0, 1, 0, 0, 0},
+ {LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xF0, 1, 0, 0, 1, 0, 0, 0},
+ {LLCC_WRCACHE, 31, 512, 1, 1, 0x00FF, 0x0, 0, 0, 0, 0, 1, 0, 0},
+};
+
static const struct llcc_slice_config sc7180_data[] = {
{ LLCC_CPUSS, 1, 256, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 1 },
{ LLCC_MDM, 8, 128, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 0 },
@@ -552,6 +572,16 @@ static const struct qcom_llcc_config qdu1000_cfg[] = {
},
};
+static const struct qcom_llcc_config sa8775p_cfg[] = {
+ {
+ .sct_data = sa8775p_data,
+ .size = ARRAY_SIZE(sa8775p_data),
+ .need_llcc_cfg = true,
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ },
+};
+
static const struct qcom_llcc_config sc7180_cfg[] = {
{
.sct_data = sc7180_data,
@@ -698,6 +728,11 @@ static const struct qcom_sct_config qdu1000_cfgs = {
.num_config = ARRAY_SIZE(qdu1000_cfg),
};
+static const struct qcom_sct_config sa8775p_cfgs = {
+ .llcc_config = sa8775p_cfg,
+ .num_config = ARRAY_SIZE(sa8775p_cfg),
+};
+
static const struct qcom_sct_config sc7180_cfgs = {
.llcc_config = sc7180_cfg,
.num_config = ARRAY_SIZE(sc7180_cfg),
@@ -821,6 +856,7 @@ EXPORT_SYMBOL_GPL(llcc_slice_putd);
static int llcc_update_act_ctrl(u32 sid,
u32 act_ctrl_reg_val, u32 status)
{
+ struct regmap *regmap;
u32 act_ctrl_reg;
u32 act_clear_reg;
u32 status_reg;
@@ -849,7 +885,8 @@ static int llcc_update_act_ctrl(u32 sid,
return ret;
if (drv_data->version >= LLCC_VERSION_4_1_0_0) {
- ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg,
+ regmap = drv_data->bcast_and_regmap ?: drv_data->bcast_regmap;
+ ret = regmap_read_poll_timeout(regmap, status_reg,
slice_status, (slice_status & ACT_COMPLETE),
0, LLCC_STATUS_READ_DELAY);
if (ret)
@@ -1258,16 +1295,13 @@ static int qcom_llcc_probe(struct platform_device *pdev)
/* Initialize rest of LLCC bank regmaps */
for (i = 1; i < num_banks; i++) {
- char *base = kasprintf(GFP_KERNEL, "llcc%d_base", i);
+ char *base __free(kfree) = kasprintf(GFP_KERNEL, "llcc%d_base", i);
drv_data->regmaps[i] = qcom_llcc_init_mmio(pdev, i, base);
if (IS_ERR(drv_data->regmaps[i])) {
ret = PTR_ERR(drv_data->regmaps[i]);
- kfree(base);
goto err;
}
-
- kfree(base);
}
drv_data->bcast_regmap = qcom_llcc_init_mmio(pdev, i, "llcc_broadcast_base");
@@ -1284,6 +1318,18 @@ static int qcom_llcc_probe(struct platform_device *pdev)
drv_data->version = version;
+ /* Applicable only when drv_data->version >= 4.1 */
+ if (drv_data->version >= LLCC_VERSION_4_1_0_0) {
+ drv_data->bcast_and_regmap = qcom_llcc_init_mmio(pdev, i + 1, "llcc_broadcast_and_base");
+ if (IS_ERR(drv_data->bcast_and_regmap)) {
+ ret = PTR_ERR(drv_data->bcast_and_regmap);
+ if (ret == -EINVAL)
+ drv_data->bcast_and_regmap = NULL;
+ else
+ goto err;
+ }
+ }
+
llcc_cfg = cfg->sct_data;
sz = cfg->size;
@@ -1332,6 +1378,7 @@ err:
static const struct of_device_id qcom_llcc_of_match[] = {
{ .compatible = "qcom,qdu1000-llcc", .data = &qdu1000_cfgs},
+ { .compatible = "qcom,sa8775p-llcc", .data = &sa8775p_cfgs },
{ .compatible = "qcom,sc7180-llcc", .data = &sc7180_cfgs },
{ .compatible = "qcom,sc7280-llcc", .data = &sc7280_cfgs },
{ .compatible = "qcom,sc8180x-llcc", .data = &sc8180x_cfgs },
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 6f177e46fa0f..b2c0fb55d4ae 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -7,6 +7,7 @@
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*/
+#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/elf.h>
#include <linux/firmware.h>
@@ -37,13 +38,12 @@ static ssize_t mdt_load_split_segment(void *ptr, const struct elf32_phdr *phdrs,
{
const struct elf32_phdr *phdr = &phdrs[segment];
const struct firmware *seg_fw;
- char *seg_name;
ssize_t ret;
if (strlen(fw_name) < 4)
return -EINVAL;
- seg_name = kstrdup(fw_name, GFP_KERNEL);
+ char *seg_name __free(kfree) = kstrdup(fw_name, GFP_KERNEL);
if (!seg_name)
return -ENOMEM;
@@ -52,7 +52,6 @@ static ssize_t mdt_load_split_segment(void *ptr, const struct elf32_phdr *phdrs,
ptr, phdr->p_filesz);
if (ret) {
dev_err(dev, "error %zd loading %s\n", ret, seg_name);
- kfree(seg_name);
return ret;
}
@@ -64,7 +63,6 @@ static ssize_t mdt_load_split_segment(void *ptr, const struct elf32_phdr *phdrs,
}
release_firmware(seg_fw);
- kfree(seg_name);
return ret;
}
diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c
index e8841d247953..6b6dd80cbc0f 100644
--- a/drivers/soc/qcom/ocmem.c
+++ b/drivers/soc/qcom/ocmem.c
@@ -10,6 +10,7 @@
*/
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -216,7 +217,6 @@ EXPORT_SYMBOL_GPL(of_get_ocmem);
struct ocmem_buf *ocmem_allocate(struct ocmem *ocmem, enum ocmem_client client,
unsigned long size)
{
- struct ocmem_buf *buf;
int ret;
/* TODO: add support for other clients... */
@@ -229,7 +229,7 @@ struct ocmem_buf *ocmem_allocate(struct ocmem *ocmem, enum ocmem_client client,
if (test_and_set_bit_lock(BIT(client), &ocmem->active_allocations))
return ERR_PTR(-EBUSY);
- buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ struct ocmem_buf *buf __free(kfree) = kzalloc(sizeof(*buf), GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto err_unlock;
@@ -247,7 +247,7 @@ struct ocmem_buf *ocmem_allocate(struct ocmem *ocmem, enum ocmem_client client,
if (ret) {
dev_err(ocmem->dev, "could not lock: %d\n", ret);
ret = -EINVAL;
- goto err_kfree;
+ goto err_unlock;
}
} else {
ocmem_write(ocmem, OCMEM_REG_GFX_MPU_START, buf->offset);
@@ -258,10 +258,8 @@ struct ocmem_buf *ocmem_allocate(struct ocmem *ocmem, enum ocmem_client client,
dev_dbg(ocmem->dev, "using %ldK of OCMEM at 0x%08lx for client %d\n",
size / 1024, buf->addr, client);
- return buf;
+ return_ptr(buf);
-err_kfree:
- kfree(buf);
err_unlock:
clear_bit_unlock(BIT(client), &ocmem->active_allocations);
diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
index a1b6a4081dea..328b6153b2be 100644
--- a/drivers/soc/qcom/pdr_interface.c
+++ b/drivers/soc/qcom/pdr_interface.c
@@ -3,6 +3,7 @@
* Copyright (C) 2020 The Linux Foundation. All rights reserved.
*/
+#include <linux/cleanup.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -76,12 +77,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
locator_hdl);
struct pdr_service *pds;
+ mutex_lock(&pdr->lock);
/* Create a local client port for QMI communication */
pdr->locator_addr.sq_family = AF_QIPCRTR;
pdr->locator_addr.sq_node = svc->node;
pdr->locator_addr.sq_port = svc->port;
- mutex_lock(&pdr->lock);
pdr->locator_init_complete = true;
mutex_unlock(&pdr->lock);
@@ -104,10 +105,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
mutex_lock(&pdr->lock);
pdr->locator_init_complete = false;
- mutex_unlock(&pdr->lock);
pdr->locator_addr.sq_node = 0;
pdr->locator_addr.sq_port = 0;
+ mutex_unlock(&pdr->lock);
}
static const struct qmi_ops pdr_locator_ops = {
@@ -365,12 +366,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
if (ret < 0)
return ret;
+ mutex_lock(&pdr->lock);
ret = qmi_send_request(&pdr->locator_hdl,
&pdr->locator_addr,
&txn, SERVREG_GET_DOMAIN_LIST_REQ,
SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
servreg_get_domain_list_req_ei,
req);
+ mutex_unlock(&pdr->lock);
if (ret < 0) {
qmi_txn_cancel(&txn);
return ret;
@@ -394,13 +397,13 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
{
- struct servreg_get_domain_list_resp *resp;
struct servreg_get_domain_list_req req;
struct servreg_location_entry *entry;
int domains_read = 0;
int ret, i;
- resp = kzalloc(sizeof(*resp), GFP_KERNEL);
+ struct servreg_get_domain_list_resp *resp __free(kfree) = kzalloc(sizeof(*resp),
+ GFP_KERNEL);
if (!resp)
return -ENOMEM;
@@ -413,9 +416,9 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
req.domain_offset = domains_read;
ret = pdr_get_domain_list(&req, resp, pdr);
if (ret < 0)
- goto out;
+ return ret;
- for (i = domains_read; i < resp->domain_list_len; i++) {
+ for (i = 0; i < resp->domain_list_len; i++) {
entry = &resp->domain_list[i];
if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
@@ -425,7 +428,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
pds->service_data_valid = entry->service_data_valid;
pds->service_data = entry->service_data;
pds->instance = entry->instance;
- goto out;
+ return 0;
}
}
@@ -438,8 +441,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
domains_read += resp->domain_list_len;
} while (domains_read < resp->total_domains);
-out:
- kfree(resp);
+
return ret;
}
@@ -515,8 +517,7 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
const char *service_name,
const char *service_path)
{
- struct pdr_service *pds, *tmp;
- int ret;
+ struct pdr_service *tmp;
if (IS_ERR_OR_NULL(pdr))
return ERR_PTR(-EINVAL);
@@ -525,7 +526,7 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
!service_path || strlen(service_path) > SERVREG_NAME_LENGTH)
return ERR_PTR(-EINVAL);
- pds = kzalloc(sizeof(*pds), GFP_KERNEL);
+ struct pdr_service *pds __free(kfree) = kzalloc(sizeof(*pds), GFP_KERNEL);
if (!pds)
return ERR_PTR(-ENOMEM);
@@ -540,8 +541,7 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
continue;
mutex_unlock(&pdr->list_lock);
- ret = -EALREADY;
- goto err;
+ return ERR_PTR(-EALREADY);
}
list_add(&pds->node, &pdr->lookups);
@@ -549,10 +549,7 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
schedule_work(&pdr->locator_work);
- return pds;
-err:
- kfree(pds);
- return ERR_PTR(ret);
+ return_ptr(pds);
}
EXPORT_SYMBOL_GPL(pdr_add_lookup);
@@ -649,13 +646,12 @@ struct pdr_handle *pdr_handle_alloc(void (*status)(int state,
char *service_path,
void *priv), void *priv)
{
- struct pdr_handle *pdr;
int ret;
if (!status)
return ERR_PTR(-EINVAL);
- pdr = kzalloc(sizeof(*pdr), GFP_KERNEL);
+ struct pdr_handle *pdr __free(kfree) = kzalloc(sizeof(*pdr), GFP_KERNEL);
if (!pdr)
return ERR_PTR(-ENOMEM);
@@ -674,10 +670,8 @@ struct pdr_handle *pdr_handle_alloc(void (*status)(int state,
INIT_WORK(&pdr->indack_work, pdr_indack_work);
pdr->notifier_wq = create_singlethread_workqueue("pdr_notifier_wq");
- if (!pdr->notifier_wq) {
- ret = -ENOMEM;
- goto free_pdr_handle;
- }
+ if (!pdr->notifier_wq)
+ return ERR_PTR(-ENOMEM);
pdr->indack_wq = alloc_ordered_workqueue("pdr_indack_wq", WQ_HIGHPRI);
if (!pdr->indack_wq) {
@@ -702,7 +696,7 @@ struct pdr_handle *pdr_handle_alloc(void (*status)(int state,
if (ret < 0)
goto release_qmi_handle;
- return pdr;
+ return_ptr(pdr);
release_qmi_handle:
qmi_handle_release(&pdr->locator_hdl);
@@ -710,8 +704,6 @@ destroy_indack:
destroy_workqueue(pdr->indack_wq);
destroy_notifier:
destroy_workqueue(pdr->notifier_wq);
-free_pdr_handle:
- kfree(pdr);
return ERR_PTR(ret);
}
diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
index 03c282b7f17e..8d17f7fb79e7 100644
--- a/drivers/soc/qcom/pdr_internal.h
+++ b/drivers/soc/qcom/pdr_internal.h
@@ -13,6 +13,8 @@
#define SERVREG_SET_ACK_REQ 0x23
#define SERVREG_RESTART_PD_REQ 0x24
+#define SERVREG_LOC_PFR_REQ 0x24
+
#define SERVREG_DOMAIN_LIST_LENGTH 32
#define SERVREG_RESTART_PD_REQ_MAX_LEN 67
#define SERVREG_REGISTER_LISTENER_REQ_LEN 71
@@ -20,6 +22,7 @@
#define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
#define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
#define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
+#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
struct servreg_location_entry {
char name[SERVREG_NAME_LENGTH + 1];
@@ -28,83 +31,12 @@ struct servreg_location_entry {
u32 instance;
};
-static const struct qmi_elem_info servreg_location_entry_ei[] = {
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0,
- .offset = offsetof(struct servreg_location_entry,
- name),
- },
- {
- .data_type = QMI_UNSIGNED_4_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = 0,
- .offset = offsetof(struct servreg_location_entry,
- instance),
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0,
- .offset = offsetof(struct servreg_location_entry,
- service_data_valid),
- },
- {
- .data_type = QMI_UNSIGNED_4_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = 0,
- .offset = offsetof(struct servreg_location_entry,
- service_data),
- },
- {}
-};
-
struct servreg_get_domain_list_req {
char service_name[SERVREG_NAME_LENGTH + 1];
u8 domain_offset_valid;
u32 domain_offset;
};
-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct servreg_get_domain_list_req,
- service_name),
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_get_domain_list_req,
- domain_offset_valid),
- },
- {
- .data_type = QMI_UNSIGNED_4_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_get_domain_list_req,
- domain_offset),
- },
- {}
-};
-
struct servreg_get_domain_list_resp {
struct qmi_response_type_v01 resp;
u8 total_domains_valid;
@@ -116,264 +48,60 @@ struct servreg_get_domain_list_resp {
struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
};
-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- total_domains_valid),
- },
- {
- .data_type = QMI_UNSIGNED_2_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u16),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- total_domains),
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x11,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- db_rev_count_valid),
- },
- {
- .data_type = QMI_UNSIGNED_2_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u16),
- .array_type = NO_ARRAY,
- .tlv_type = 0x11,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- db_rev_count),
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x12,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- domain_list_valid),
- },
- {
- .data_type = QMI_DATA_LEN,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x12,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- domain_list_len),
- },
- {
- .data_type = QMI_STRUCT,
- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
- .elem_size = sizeof(struct servreg_location_entry),
- .array_type = VAR_LEN_ARRAY,
- .tlv_type = 0x12,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- domain_list),
- .ei_array = servreg_location_entry_ei,
- },
- {}
-};
-
struct servreg_register_listener_req {
u8 enable;
char service_path[SERVREG_NAME_LENGTH + 1];
};
-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct servreg_register_listener_req,
- enable),
- },
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_register_listener_req,
- service_path),
- },
- {}
-};
-
struct servreg_register_listener_resp {
struct qmi_response_type_v01 resp;
u8 curr_state_valid;
enum servreg_service_state curr_state;
};
-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_register_listener_resp,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_register_listener_resp,
- curr_state_valid),
- },
- {
- .data_type = QMI_SIGNED_4_BYTE_ENUM,
- .elem_len = 1,
- .elem_size = sizeof(enum servreg_service_state),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_register_listener_resp,
- curr_state),
- },
- {}
-};
-
struct servreg_restart_pd_req {
char service_path[SERVREG_NAME_LENGTH + 1];
};
-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct servreg_restart_pd_req,
- service_path),
- },
- {}
-};
-
struct servreg_restart_pd_resp {
struct qmi_response_type_v01 resp;
};
-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_restart_pd_resp,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {}
-};
-
struct servreg_state_updated_ind {
enum servreg_service_state curr_state;
char service_path[SERVREG_NAME_LENGTH + 1];
u16 transaction_id;
};
-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
- {
- .data_type = QMI_SIGNED_4_BYTE_ENUM,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct servreg_state_updated_ind,
- curr_state),
- },
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_state_updated_ind,
- service_path),
- },
- {
- .data_type = QMI_UNSIGNED_2_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u16),
- .array_type = NO_ARRAY,
- .tlv_type = 0x03,
- .offset = offsetof(struct servreg_state_updated_ind,
- transaction_id),
- },
- {}
-};
-
struct servreg_set_ack_req {
char service_path[SERVREG_NAME_LENGTH + 1];
u16 transaction_id;
};
-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct servreg_set_ack_req,
- service_path),
- },
- {
- .data_type = QMI_UNSIGNED_2_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u16),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_set_ack_req,
- transaction_id),
- },
- {}
-};
-
struct servreg_set_ack_resp {
struct qmi_response_type_v01 resp;
};
-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_set_ack_resp,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {}
+struct servreg_loc_pfr_req {
+ char service[SERVREG_NAME_LENGTH + 1];
+ char reason[257];
};
+struct servreg_loc_pfr_resp {
+ struct qmi_response_type_v01 rsp;
+};
+
+extern const struct qmi_elem_info servreg_location_entry_ei[];
+extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+extern const struct qmi_elem_info servreg_register_listener_req_ei[];
+extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
+extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
+extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
+extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
#endif
diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c
index 40fb09d69014..9ebc0ba35947 100644
--- a/drivers/soc/qcom/pmic_glink.c
+++ b/drivers/soc/qcom/pmic_glink.c
@@ -348,11 +348,15 @@ static void pmic_glink_remove(struct platform_device *pdev)
mutex_unlock(&__pmic_glink_lock);
}
+static const unsigned long pmic_glink_sc8280xp_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
+ BIT(PMIC_GLINK_CLIENT_ALTMODE);
+
static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
BIT(PMIC_GLINK_CLIENT_ALTMODE) |
BIT(PMIC_GLINK_CLIENT_UCSI);
static const struct of_device_id pmic_glink_of_match[] = {
+ { .compatible = "qcom,sc8280xp-pmic-glink", .data = &pmic_glink_sc8280xp_client_mask },
{ .compatible = "qcom,pmic-glink", .data = &pmic_glink_sm8450_client_mask },
{}
};
@@ -369,8 +373,17 @@ static struct platform_driver pmic_glink_driver = {
static int pmic_glink_init(void)
{
- platform_driver_register(&pmic_glink_driver);
- register_rpmsg_driver(&pmic_glink_rpmsg_driver);
+ int ret;
+
+ ret = platform_driver_register(&pmic_glink_driver);
+ if (ret < 0)
+ return ret;
+
+ ret = register_rpmsg_driver(&pmic_glink_rpmsg_driver);
+ if (ret < 0) {
+ platform_driver_unregister(&pmic_glink_driver);
+ return ret;
+ }
return 0;
}
diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c
index b3808fc24c69..1e0808b3cb93 100644
--- a/drivers/soc/qcom/pmic_glink_altmode.c
+++ b/drivers/soc/qcom/pmic_glink_altmode.c
@@ -20,7 +20,7 @@
#include <linux/soc/qcom/pmic_glink.h>
-#define PMIC_GLINK_MAX_PORTS 2
+#define PMIC_GLINK_MAX_PORTS 3
#define USBC_SC8180X_NOTIFY_IND 0x13
#define USBC_CMD_WRITE_REQ 0x15
diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
new file mode 100644
index 000000000000..a4c007080665
--- /dev/null
+++ b/drivers/soc/qcom/qcom_pd_mapper.c
@@ -0,0 +1,677 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm Protection Domain mapper
+ *
+ * Copyright (c) 2023 Linaro Ltd.
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/refcount.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/qmi.h>
+
+#include "pdr_internal.h"
+
+#define SERVREG_QMI_VERSION 0x101
+#define SERVREG_QMI_INSTANCE 0
+
+#define TMS_SERVREG_SERVICE "tms/servreg"
+
+struct qcom_pdm_domain_data {
+ const char *domain;
+ u32 instance_id;
+ /* NULL-terminated array */
+ const char * services[];
+};
+
+struct qcom_pdm_domain {
+ struct list_head list;
+ const char *name;
+ u32 instance_id;
+};
+
+struct qcom_pdm_service {
+ struct list_head list;
+ struct list_head domains;
+ const char *name;
+};
+
+struct qcom_pdm_data {
+ refcount_t refcnt;
+ struct qmi_handle handle;
+ struct list_head services;
+};
+
+static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
+static struct qcom_pdm_data *__qcom_pdm_data;
+
+static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
+ const char *name)
+{
+ struct qcom_pdm_service *service;
+
+ list_for_each_entry(service, &data->services, list) {
+ if (!strcmp(service->name, name))
+ return service;
+ }
+
+ return NULL;
+}
+
+static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
+ const char *service_name,
+ const char *domain_name,
+ u32 instance_id)
+{
+ struct qcom_pdm_service *service;
+ struct qcom_pdm_domain *domain;
+
+ service = qcom_pdm_find(data, service_name);
+ if (service) {
+ list_for_each_entry(domain, &service->domains, list) {
+ if (!strcmp(domain->name, domain_name))
+ return -EBUSY;
+ }
+ } else {
+ service = kzalloc(sizeof(*service), GFP_KERNEL);
+ if (!service)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&service->domains);
+ service->name = service_name;
+
+ list_add_tail(&service->list, &data->services);
+ }
+
+ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+ if (!domain) {
+ if (list_empty(&service->domains)) {
+ list_del(&service->list);
+ kfree(service);
+ }
+
+ return -ENOMEM;
+ }
+
+ domain->name = domain_name;
+ domain->instance_id = instance_id;
+ list_add_tail(&domain->list, &service->domains);
+
+ return 0;
+}
+
+static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
+ const struct qcom_pdm_domain_data *domain)
+{
+ int ret;
+ int i;
+
+ ret = qcom_pdm_add_service_domain(data,
+ TMS_SERVREG_SERVICE,
+ domain->domain,
+ domain->instance_id);
+ if (ret)
+ return ret;
+
+ for (i = 0; domain->services[i]; i++) {
+ ret = qcom_pdm_add_service_domain(data,
+ domain->services[i],
+ domain->domain,
+ domain->instance_id);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+
+}
+
+static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
+{
+ struct qcom_pdm_service *service, *tservice;
+ struct qcom_pdm_domain *domain, *tdomain;
+
+ list_for_each_entry_safe(service, tservice, &data->services, list) {
+ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
+ list_del(&domain->list);
+ kfree(domain);
+ }
+
+ list_del(&service->list);
+ kfree(service);
+ }
+}
+
+static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
+ struct sockaddr_qrtr *sq,
+ struct qmi_txn *txn,
+ const void *decoded)
+{
+ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
+ const struct servreg_get_domain_list_req *req = decoded;
+ struct servreg_get_domain_list_resp *rsp;
+ struct qcom_pdm_service *service;
+ u32 offset;
+ int ret;
+
+ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
+ if (!rsp)
+ return;
+
+ offset = req->domain_offset_valid ? req->domain_offset : 0;
+
+ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
+ rsp->resp.error = QMI_ERR_NONE_V01;
+
+ rsp->db_rev_count_valid = true;
+ rsp->db_rev_count = 1;
+
+ rsp->total_domains_valid = true;
+ rsp->total_domains = 0;
+
+ mutex_lock(&qcom_pdm_mutex);
+
+ service = qcom_pdm_find(data, req->service_name);
+ if (service) {
+ struct qcom_pdm_domain *domain;
+
+ rsp->domain_list_valid = true;
+ rsp->domain_list_len = 0;
+
+ list_for_each_entry(domain, &service->domains, list) {
+ u32 i = rsp->total_domains++;
+
+ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
+ u32 j = rsp->domain_list_len++;
+
+ strscpy(rsp->domain_list[j].name, domain->name,
+ sizeof(rsp->domain_list[i].name));
+ rsp->domain_list[j].instance = domain->instance_id;
+
+ pr_debug("PDM: found %s / %d\n", domain->name,
+ domain->instance_id);
+ }
+ }
+ }
+
+ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
+ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
+
+ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
+ servreg_get_domain_list_resp_ei, rsp);
+ if (ret)
+ pr_err("Error sending servreg response: %d\n", ret);
+
+ mutex_unlock(&qcom_pdm_mutex);
+
+ kfree(rsp);
+}
+
+static void qcom_pdm_pfr(struct qmi_handle *qmi,
+ struct sockaddr_qrtr *sq,
+ struct qmi_txn *txn,
+ const void *decoded)
+{
+ const struct servreg_loc_pfr_req *req = decoded;
+ struct servreg_loc_pfr_resp rsp = {};
+ int ret;
+
+ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
+
+ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
+ rsp.rsp.error = QMI_ERR_NONE_V01;
+
+ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
+ SERVREG_LOC_PFR_RESP_MAX_LEN,
+ servreg_loc_pfr_resp_ei, &rsp);
+ if (ret)
+ pr_err("Error sending servreg response: %d\n", ret);
+}
+
+static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
+ {
+ .type = QMI_REQUEST,
+ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
+ .ei = servreg_get_domain_list_req_ei,
+ .decoded_size = sizeof(struct servreg_get_domain_list_req),
+ .fn = qcom_pdm_get_domain_list,
+ },
+ {
+ .type = QMI_REQUEST,
+ .msg_id = SERVREG_LOC_PFR_REQ,
+ .ei = servreg_loc_pfr_req_ei,
+ .decoded_size = sizeof(struct servreg_loc_pfr_req),
+ .fn = qcom_pdm_pfr,
+ },
+ { },
+};
+
+static const struct qcom_pdm_domain_data adsp_audio_pd = {
+ .domain = "msm/adsp/audio_pd",
+ .instance_id = 74,
+ .services = {
+ "avs/audio",
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data adsp_charger_pd = {
+ .domain = "msm/adsp/charger_pd",
+ .instance_id = 74,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data adsp_root_pd = {
+ .domain = "msm/adsp/root_pd",
+ .instance_id = 74,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
+ .domain = "msm/adsp/root_pd",
+ .instance_id = 74,
+ .services = {
+ "tms/pdr_enabled",
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data adsp_sensor_pd = {
+ .domain = "msm/adsp/sensor_pd",
+ .instance_id = 74,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
+ .domain = "msm/adsp/audio_pd",
+ .instance_id = 4,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
+ .domain = "msm/adsp/root_pd",
+ .instance_id = 4,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data cdsp_root_pd = {
+ .domain = "msm/cdsp/root_pd",
+ .instance_id = 76,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data slpi_root_pd = {
+ .domain = "msm/slpi/root_pd",
+ .instance_id = 90,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data slpi_sensor_pd = {
+ .domain = "msm/slpi/sensor_pd",
+ .instance_id = 90,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data mpss_root_pd = {
+ .domain = "msm/modem/root_pd",
+ .instance_id = 180,
+ .services = {
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
+ .domain = "msm/modem/root_pd",
+ .instance_id = 180,
+ .services = {
+ "gps/gps_service",
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
+ .domain = "msm/modem/root_pd",
+ .instance_id = 180,
+ .services = {
+ "gps/gps_service",
+ "tms/pdr_enabled",
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
+ .domain = "msm/modem/root_pd",
+ .instance_id = 100,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data mpss_wlan_pd = {
+ .domain = "msm/modem/wlan_pd",
+ .instance_id = 180,
+ .services = {
+ "kernel/elf_loader",
+ "wlan/fw",
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data *msm8996_domains[] = {
+ &msm8996_adsp_audio_pd,
+ &msm8996_adsp_root_pd,
+ &msm8996_mpss_root_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *msm8998_domains[] = {
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &mpss_root_pd_gps,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *qcs404_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sc7180_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd_pdr,
+ &adsp_sensor_pd,
+ &mpss_root_pd_gps_pdr,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sc7280_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd_pdr,
+ &adsp_charger_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps_pdr,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_charger_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd_pdr,
+ &adsp_charger_pd,
+ &cdsp_root_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sdm660_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sdm670_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sdm845_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ &slpi_root_pd,
+ &slpi_sensor_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm6115_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm6350_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm8150_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm8250_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &cdsp_root_pd,
+ &slpi_root_pd,
+ &slpi_sensor_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm8350_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd_pdr,
+ &adsp_charger_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ &slpi_root_pd,
+ &slpi_sensor_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm8550_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_charger_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ NULL,
+};
+
+static const struct of_device_id qcom_pdm_domains[] = {
+ { .compatible = "qcom,apq8064", .data = NULL, },
+ { .compatible = "qcom,apq8074", .data = NULL, },
+ { .compatible = "qcom,apq8084", .data = NULL, },
+ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
+ { .compatible = "qcom,msm8226", .data = NULL, },
+ { .compatible = "qcom,msm8974", .data = NULL, },
+ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
+ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
+ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
+ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
+ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
+ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
+ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
+ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
+ { .compatible = "qcom,sda660", .data = sdm660_domains, },
+ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
+ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
+ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
+ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
+ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
+ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
+ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
+ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
+ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
+ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
+ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
+ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
+ {},
+};
+
+static void qcom_pdm_stop(struct qcom_pdm_data *data)
+{
+ qcom_pdm_free_domains(data);
+
+ /* The server is removed automatically */
+ qmi_handle_release(&data->handle);
+
+ kfree(data);
+}
+
+static struct qcom_pdm_data *qcom_pdm_start(void)
+{
+ const struct qcom_pdm_domain_data * const *domains;
+ const struct of_device_id *match;
+ struct qcom_pdm_data *data;
+ struct device_node *root;
+ int ret, i;
+
+ root = of_find_node_by_path("/");
+ if (!root)
+ return ERR_PTR(-ENODEV);
+
+ match = of_match_node(qcom_pdm_domains, root);
+ of_node_put(root);
+ if (!match) {
+ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ domains = match->data;
+ if (!domains) {
+ pr_debug("PDM: no domains\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&data->services);
+
+ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ NULL, qcom_pdm_msg_handlers);
+ if (ret) {
+ kfree(data);
+ return ERR_PTR(ret);
+ }
+
+ refcount_set(&data->refcnt, 1);
+
+ for (i = 0; domains[i]; i++) {
+ ret = qcom_pdm_add_domain(data, domains[i]);
+ if (ret)
+ goto err_stop;
+ }
+
+ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
+ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
+ if (ret) {
+ pr_err("PDM: error adding server %d\n", ret);
+ goto err_stop;
+ }
+
+ return data;
+
+err_stop:
+ qcom_pdm_stop(data);
+
+ return ERR_PTR(ret);
+}
+
+static int qcom_pdm_probe(struct auxiliary_device *auxdev,
+ const struct auxiliary_device_id *id)
+
+{
+ struct qcom_pdm_data *data;
+ int ret = 0;
+
+ mutex_lock(&qcom_pdm_mutex);
+
+ if (!__qcom_pdm_data) {
+ data = qcom_pdm_start();
+
+ if (IS_ERR(data))
+ ret = PTR_ERR(data);
+ else
+ __qcom_pdm_data = data;
+ }
+
+ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
+
+ mutex_unlock(&qcom_pdm_mutex);
+
+ return ret;
+}
+
+static void qcom_pdm_remove(struct auxiliary_device *auxdev)
+{
+ struct qcom_pdm_data *data;
+
+ data = auxiliary_get_drvdata(auxdev);
+ if (!data)
+ return;
+
+ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
+ __qcom_pdm_data = NULL;
+ qcom_pdm_stop(data);
+ mutex_unlock(&qcom_pdm_mutex);
+ }
+}
+
+static const struct auxiliary_device_id qcom_pdm_table[] = {
+ { .name = "qcom_common.pd-mapper" },
+ {},
+};
+MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
+
+static struct auxiliary_driver qcom_pdm_drv = {
+ .name = "qcom-pdm-mapper",
+ .id_table = qcom_pdm_table,
+ .probe = qcom_pdm_probe,
+ .remove = qcom_pdm_remove,
+};
+module_auxiliary_driver(qcom_pdm_drv);
+
+MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
new file mode 100644
index 000000000000..bf3e4a47165e
--- /dev/null
+++ b/drivers/soc/qcom/qcom_pdr_msg.c
@@ -0,0 +1,353 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/soc/qcom/qmi.h>
+
+#include "pdr_internal.h"
+
+const struct qmi_elem_info servreg_location_entry_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_location_entry,
+ name),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_location_entry,
+ instance),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_location_entry,
+ service_data_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_location_entry,
+ service_data),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
+
+const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_get_domain_list_req,
+ service_name),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_get_domain_list_req,
+ domain_offset_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_get_domain_list_req,
+ domain_offset),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
+
+const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ total_domains_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ total_domains),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ db_rev_count_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ db_rev_count),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ domain_list_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ domain_list_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+ .elem_size = sizeof(struct servreg_location_entry),
+ .array_type = VAR_LEN_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ domain_list),
+ .ei_array = servreg_location_entry_ei,
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
+
+const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_register_listener_req,
+ enable),
+ },
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_register_listener_req,
+ service_path),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
+
+const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_register_listener_resp,
+ resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_register_listener_resp,
+ curr_state_valid),
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum servreg_service_state),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_register_listener_resp,
+ curr_state),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
+
+const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_restart_pd_req,
+ service_path),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
+
+const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_restart_pd_resp,
+ resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
+
+const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_state_updated_ind,
+ curr_state),
+ },
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_state_updated_ind,
+ service_path),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x03,
+ .offset = offsetof(struct servreg_state_updated_ind,
+ transaction_id),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
+
+const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_set_ack_req,
+ service_path),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_set_ack_req,
+ transaction_id),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
+
+const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_set_ack_resp,
+ resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
+const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = VAR_LEN_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_loc_pfr_req, service)
+ },
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = VAR_LEN_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_loc_pfr_req, reason)
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
+
+const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index 561d8037b50a..de86009ecd91 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -646,13 +646,14 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
{
struct tcs_group *tcs;
int tcs_id;
- unsigned long flags;
+
+ might_sleep();
tcs = get_tcs_for_msg(drv, msg);
if (IS_ERR(tcs))
return PTR_ERR(tcs);
- spin_lock_irqsave(&drv->lock, flags);
+ spin_lock_irq(&drv->lock);
/* Wait forever for a free tcs. It better be there eventually! */
wait_event_lock_irq(drv->tcs_wait,
@@ -670,7 +671,7 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0);
enable_tcs_irq(drv, tcs_id, true);
}
- spin_unlock_irqrestore(&drv->lock, flags);
+ spin_unlock_irq(&drv->lock);
/*
* These two can be done after the lock is released because:
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 9f26d7f9b9dc..8903ed956312 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -183,7 +183,6 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state,
}
if (state == RPMH_ACTIVE_ONLY_STATE) {
- WARN_ON(irqs_disabled());
ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg);
} else {
/* Clean up our call by spoofing tx_done */
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 7191fa0c087f..e40aac281b06 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -795,6 +795,39 @@ int qcom_smem_get_soc_id(u32 *id)
}
EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id);
+/**
+ * qcom_smem_get_feature_code() - return the feature code
+ * @code: On success, return the feature code here.
+ *
+ * Look up the feature code identifier from SMEM and return it.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int qcom_smem_get_feature_code(u32 *code)
+{
+ struct socinfo *info;
+ u32 raw_code;
+
+ info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL);
+ if (IS_ERR(info))
+ return PTR_ERR(info);
+
+ /* This only makes sense for socinfo >= 16 */
+ if (__le32_to_cpu(info->fmt) < SOCINFO_VERSION(0, 16))
+ return -EOPNOTSUPP;
+
+ raw_code = __le32_to_cpu(info->feature_code);
+
+ /* Ensure the value makes sense */
+ if (raw_code > SOCINFO_FC_INT_MAX)
+ raw_code = SOCINFO_FC_UNKNOWN;
+
+ *code = raw_code;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_smem_get_feature_code);
+
static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
{
struct smem_header *header;
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index a21241cbeec7..696c2a8387d0 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/pm_wakeirq.h>
#include <linux/regmap.h>
+#include <linux/seq_file.h>
#include <linux/soc/qcom/smem.h>
#include <linux/soc/qcom/smem_state.h>
#include <linux/spinlock.h>
@@ -353,11 +354,19 @@ static int smp2p_set_irq_type(struct irq_data *irqd, unsigned int type)
return 0;
}
+static void smp2p_irq_print_chip(struct irq_data *irqd, struct seq_file *p)
+{
+ struct smp2p_entry *entry = irq_data_get_irq_chip_data(irqd);
+
+ seq_printf(p, " %8s", dev_name(entry->smp2p->dev));
+}
+
static struct irq_chip smp2p_irq_chip = {
.name = "smp2p",
.irq_mask = smp2p_mask_irq,
.irq_unmask = smp2p_unmask_irq,
.irq_set_type = smp2p_set_irq_type,
+ .irq_print_chip = smp2p_irq_print_chip,
};
static int smp2p_irq_map(struct irq_domain *d,
@@ -617,7 +626,7 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(&pdev->dev, irq,
NULL, qcom_smp2p_intr,
IRQF_ONESHOT,
- "smp2p", (void *)smp2p);
+ NULL, (void *)smp2p);
if (ret) {
dev_err(&pdev->dev, "failed to request interrupt\n");
goto unwind_interfaces;
diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c
index e7c7e9a640a6..ffe78ae34386 100644
--- a/drivers/soc/qcom/smsm.c
+++ b/drivers/soc/qcom/smsm.c
@@ -5,6 +5,7 @@
*/
#include <linux/interrupt.h>
+#include <linux/mailbox_client.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_irq.h>
@@ -71,6 +72,7 @@ struct smsm_host;
* @lock: spinlock for read-modify-write of the outgoing state
* @entries: context for each of the entries
* @hosts: context for each of the hosts
+ * @mbox_client: mailbox client handle
*/
struct qcom_smsm {
struct device *dev;
@@ -88,6 +90,8 @@ struct qcom_smsm {
struct smsm_entry *entries;
struct smsm_host *hosts;
+
+ struct mbox_client mbox_client;
};
/**
@@ -120,11 +124,14 @@ struct smsm_entry {
* @ipc_regmap: regmap for outgoing interrupt
* @ipc_offset: offset in @ipc_regmap for outgoing interrupt
* @ipc_bit: bit in @ipc_regmap + @ipc_offset for outgoing interrupt
+ * @mbox_chan: apcs ipc mailbox channel handle
*/
struct smsm_host {
struct regmap *ipc_regmap;
int ipc_offset;
int ipc_bit;
+
+ struct mbox_chan *mbox_chan;
};
/**
@@ -172,7 +179,13 @@ static int smsm_update_bits(void *data, u32 mask, u32 value)
hostp = &smsm->hosts[host];
val = readl(smsm->subscription + host);
- if (val & changes && hostp->ipc_regmap) {
+ if (!(val & changes))
+ continue;
+
+ if (hostp->mbox_chan) {
+ mbox_send_message(hostp->mbox_chan, NULL);
+ mbox_client_txdone(hostp->mbox_chan, 0);
+ } else if (hostp->ipc_regmap) {
regmap_write(hostp->ipc_regmap,
hostp->ipc_offset,
BIT(hostp->ipc_bit));
@@ -353,6 +366,28 @@ static const struct irq_domain_ops smsm_irq_ops = {
};
/**
+ * smsm_parse_mbox() - requests an mbox channel
+ * @smsm: smsm driver context
+ * @host_id: index of the remote host to be resolved
+ *
+ * Requests the desired channel using the mbox interface which is needed for
+ * sending the outgoing interrupts to a remove hosts - identified by @host_id.
+ */
+static int smsm_parse_mbox(struct qcom_smsm *smsm, unsigned int host_id)
+{
+ struct smsm_host *host = &smsm->hosts[host_id];
+ int ret = 0;
+
+ host->mbox_chan = mbox_request_channel(&smsm->mbox_client, host_id);
+ if (IS_ERR(host->mbox_chan)) {
+ ret = PTR_ERR(host->mbox_chan);
+ host->mbox_chan = NULL;
+ }
+
+ return ret;
+}
+
+/**
* smsm_parse_ipc() - parses a qcom,ipc-%d device tree property
* @smsm: smsm driver context
* @host_id: index of the remote host to be resolved
@@ -521,8 +556,16 @@ static int qcom_smsm_probe(struct platform_device *pdev)
"qcom,local-host",
&smsm->local_host);
+ smsm->mbox_client.dev = &pdev->dev;
+ smsm->mbox_client.knows_txdone = true;
+
/* Parse the host properties */
for (id = 0; id < smsm->num_hosts; id++) {
+ /* Try using mbox interface first, otherwise fall back to syscon */
+ ret = smsm_parse_mbox(smsm, id);
+ if (!ret)
+ continue;
+
ret = smsm_parse_ipc(smsm, id);
if (ret < 0)
goto out_put;
@@ -609,6 +652,9 @@ unwind_interfaces:
qcom_smem_state_unregister(smsm->state);
out_put:
+ for (id = 0; id < smsm->num_hosts; id++)
+ mbox_free_channel(smsm->hosts[id].mbox_chan);
+
of_node_put(local_node);
return ret;
}
@@ -622,6 +668,9 @@ static void qcom_smsm_remove(struct platform_device *pdev)
if (smsm->entries[id].domain)
irq_domain_remove(smsm->entries[id].domain);
+ for (id = 0; id < smsm->num_hosts; id++)
+ mbox_free_channel(smsm->hosts[id].mbox_chan);
+
qcom_smem_state_unregister(smsm->state);
}
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 277c07a6603d..d7359a235e3c 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -21,14 +21,6 @@
#include <dt-bindings/arm/qcom,ids.h>
-/*
- * SoC version type with major number in the upper 16 bits and minor
- * number in the lower 16 bits.
- */
-#define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff)
-#define SOCINFO_MINOR(ver) ((ver) & 0xffff)
-#define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff))
-
/* Helper macros to create soc_id table */
#define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id)
#define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name)
@@ -124,6 +116,7 @@ static const char *const pmic_models[] = {
[50] = "PM8350B",
[51] = "PMR735A",
[52] = "PMR735B",
+ [54] = "PM6350",
[55] = "PM4125",
[58] = "PM8450",
[65] = "PM8010",
@@ -133,7 +126,8 @@ static const char *const pmic_models[] = {
[72] = "PMR735D",
[73] = "PM8550",
[74] = "PMK8550",
- [82] = "SMB2360",
+ [82] = "PMC8380",
+ [83] = "SMB2360",
};
struct socinfo_params {
@@ -348,6 +342,7 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(SDA630) },
{ qcom_board_id(MSM8905) },
{ qcom_board_id(SDX202) },
+ { qcom_board_id(SDM670) },
{ qcom_board_id(SDM450) },
{ qcom_board_id(SM8150) },
{ qcom_board_id(SDA845) },
@@ -445,6 +440,7 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(QCS8550) },
{ qcom_board_id(QCM8550) },
{ qcom_board_id(IPQ5300) },
+ { qcom_board_id(IPQ5321) },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)
diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c
index 06e2c4c2a4a8..f75659fff287 100644
--- a/drivers/soc/qcom/spm.c
+++ b/drivers/soc/qcom/spm.c
@@ -572,4 +572,5 @@ static int __init qcom_spm_init(void)
}
arch_initcall(qcom_spm_init);
+MODULE_DESCRIPTION("Qualcomm Subsystem Power Manager (SPM)");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/wcnss_ctrl.c b/drivers/soc/qcom/wcnss_ctrl.c
index 148bcbac332d..62b424e90d90 100644
--- a/drivers/soc/qcom/wcnss_ctrl.c
+++ b/drivers/soc/qcom/wcnss_ctrl.c
@@ -3,6 +3,7 @@
* Copyright (c) 2016, Linaro Ltd.
* Copyright (c) 2015, Sony Mobile Communications Inc.
*/
+#include <linux/cleanup.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -198,7 +199,6 @@ static int wcnss_request_version(struct wcnss_ctrl *wcnss)
*/
static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
{
- struct wcnss_download_nv_req *req;
const struct firmware *fw;
struct device *dev = wcnss->dev;
const char *nvbin = NVBIN_FILE;
@@ -206,18 +206,19 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
ssize_t left;
int ret;
- req = kzalloc(sizeof(*req) + NV_FRAGMENT_SIZE, GFP_KERNEL);
+ struct wcnss_download_nv_req *req __free(kfree) = kzalloc(sizeof(*req) + NV_FRAGMENT_SIZE,
+ GFP_KERNEL);
if (!req)
return -ENOMEM;
ret = of_property_read_string(dev->of_node, "firmware-name", &nvbin);
if (ret < 0 && ret != -EINVAL)
- goto free_req;
+ return ret;
ret = request_firmware(&fw, nvbin, dev);
if (ret < 0) {
dev_err(dev, "Failed to load nv file %s: %d\n", nvbin, ret);
- goto free_req;
+ return ret;
}
data = fw->data;
@@ -263,8 +264,6 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
release_fw:
release_firmware(fw);
-free_req:
- kfree(req);
return ret;
}
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index fd8b6ac06656..a0123070a816 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -129,14 +129,30 @@ static int tensor_set_bits_atomic(void *ctx, unsigned int offset, u32 val,
return ret;
}
-static int tensor_sec_update_bits(void *ctx, unsigned int reg,
- unsigned int mask, unsigned int val)
+static bool tensor_is_atomic(unsigned int reg)
{
/*
* Use atomic operations for PMU_ALIVE registers (offset 0~0x3FFF)
- * as the target registers can be accessed by multiple masters.
+ * as the target registers can be accessed by multiple masters. SFRs
+ * that don't support atomic are added to the switch statement below.
*/
if (reg > PMUALIVE_MASK)
+ return false;
+
+ switch (reg) {
+ case GS101_SYSIP_DAT0:
+ case GS101_SYSTEM_CONFIGURATION:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static int tensor_sec_update_bits(void *ctx, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+
+ if (!tensor_is_atomic(reg))
return tensor_sec_reg_rmw(ctx, reg, mask, val);
return tensor_set_bits_atomic(ctx, reg, val, mask);
diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index 6eb6cf06278e..2781a091a6a6 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -33,7 +33,6 @@ struct sunxi_sram_data {
u8 offset;
u8 width;
struct sunxi_sram_func *func;
- struct list_head list;
};
struct sunxi_sram_desc {
@@ -103,7 +102,6 @@ static const struct of_device_id sunxi_sram_dt_ids[] = {
};
static struct device *sram_dev;
-static LIST_HEAD(claimed_sram);
static DEFINE_SPINLOCK(sram_lock);
static void __iomem *base;
@@ -346,7 +344,7 @@ static void sunxi_sram_unlock(void *_lock)
spin_unlock(lock);
}
-static struct regmap_config sunxi_sram_regmap_config = {
+static const struct regmap_config sunxi_sram_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 91d0ad6ddefc..6c37d6eb8b49 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -2891,15 +2891,11 @@ static int tegra_pmc_probe(struct platform_device *pdev)
pmc->aotag = base;
pmc->scratch = base;
} else {
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "wake");
- pmc->wake = devm_ioremap_resource(&pdev->dev, res);
+ pmc->wake = devm_platform_ioremap_resource_byname(pdev, "wake");
if (IS_ERR(pmc->wake))
return PTR_ERR(pmc->wake);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "aotag");
- pmc->aotag = devm_ioremap_resource(&pdev->dev, res);
+ pmc->aotag = devm_platform_ioremap_resource_byname(pdev, "aotag");
if (IS_ERR(pmc->aotag))
return PTR_ERR(pmc->aotag);
diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c
index 59101bf7cf23..4fb0f0a24828 100644
--- a/drivers/soc/ti/k3-socinfo.c
+++ b/drivers/soc/ti/k3-socinfo.c
@@ -61,7 +61,7 @@ static const struct k3_soc_id {
};
static const char * const j721e_rev_string_map[] = {
- "1.0", "1.1",
+ "1.0", "1.1", "2.0",
};
static int
diff --git a/drivers/soc/ti/knav_qmss.h b/drivers/soc/ti/knav_qmss.h
index a01eda720bf6..9325e8ce2e25 100644
--- a/drivers/soc/ti/knav_qmss.h
+++ b/drivers/soc/ti/knav_qmss.h
@@ -333,7 +333,7 @@ struct knav_range_info {
void *queue_base_inst;
unsigned flags;
struct list_head list;
- struct knav_range_ops *ops;
+ const struct knav_range_ops *ops;
struct knav_acc_info acc_info;
struct knav_acc_channel *acc;
unsigned num_irqs;
diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c
index 3d388646ed43..269b4e75ae40 100644
--- a/drivers/soc/ti/knav_qmss_acc.c
+++ b/drivers/soc/ti/knav_qmss_acc.c
@@ -450,7 +450,7 @@ static int knav_acc_free_range(struct knav_range_info *range)
return 0;
}
-static struct knav_range_ops knav_acc_range_ops = {
+static const struct knav_range_ops knav_acc_range_ops = {
.set_notify = knav_acc_set_notify,
.init_queue = knav_acc_init_queue,
.open_queue = knav_acc_open_queue,
diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c
index 06fb5505c22c..f2055a76f84c 100644
--- a/drivers/soc/ti/knav_qmss_queue.c
+++ b/drivers/soc/ti/knav_qmss_queue.c
@@ -411,7 +411,7 @@ static int knav_gp_close_queue(struct knav_range_info *range,
return 0;
}
-static struct knav_range_ops knav_gp_range_ops = {
+static const struct knav_range_ops knav_gp_range_ops = {
.set_notify = knav_gp_set_notify,
.open_queue = knav_gp_open_queue,
.close_queue = knav_gp_close_queue,
diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c
index 8e983c3c4e03..3a56bbf3268a 100644
--- a/drivers/soc/ti/pm33xx.c
+++ b/drivers/soc/ti/pm33xx.c
@@ -450,14 +450,14 @@ static int am33xx_pm_rtc_setup(void)
rtc_base_virt = of_iomap(np, 0);
if (!rtc_base_virt) {
- pr_warn("PM: could not iomap rtc");
+ pr_warn("PM: could not iomap rtc\n");
error = -ENODEV;
goto err_clk_put;
}
omap_rtc = rtc_class_open("rtc0");
if (!omap_rtc) {
- pr_warn("PM: rtc0 not available");
+ pr_warn("PM: rtc0 not available\n");
error = -EPROBE_DEFER;
goto err_iounmap;
}
diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c
index 253299e4214d..f529e1346247 100644
--- a/drivers/soc/xilinx/xlnx_event_manager.c
+++ b/drivers/soc/xilinx/xlnx_event_manager.c
@@ -3,6 +3,7 @@
* Xilinx Event Management Driver
*
* Copyright (C) 2021 Xilinx, Inc.
+ * Copyright (C) 2024 Advanced Micro Devices, Inc.
*
* Abhyuday Godhasara <[email protected]>
*/
@@ -19,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-static DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number1);
+static DEFINE_PER_CPU_READ_MOSTLY(int, dummy_cpu_number);
static int virq_sgi;
static int event_manager_availability = -EACCES;
@@ -35,7 +36,6 @@ static int event_manager_availability = -EACCES;
#define MAX_BITS (32U) /* Number of bits available for error mask */
-#define FIRMWARE_VERSION_MASK (0xFFFFU)
#define REGISTER_NOTIFIER_FIRMWARE_VERSION (2U)
static DEFINE_HASHTABLE(reg_driver_map, REGISTERED_DRIVER_MAX_ORDER);
@@ -570,7 +570,6 @@ static void xlnx_disable_percpu_irq(void *data)
static int xlnx_event_init_sgi(struct platform_device *pdev)
{
int ret = 0;
- int cpu;
/*
* IRQ related structures are used for the following:
* for each SGI interrupt ensure its mapped by GIC IRQ domain
@@ -607,11 +606,8 @@ static int xlnx_event_init_sgi(struct platform_device *pdev)
sgi_fwspec.param[0] = sgi_num;
virq_sgi = irq_create_fwspec_mapping(&sgi_fwspec);
- cpu = get_cpu();
- per_cpu(cpu_number1, cpu) = cpu;
ret = request_percpu_irq(virq_sgi, xlnx_event_handler, "xlnx_event_mgmt",
- &cpu_number1);
- put_cpu();
+ &dummy_cpu_number);
WARN_ON(ret);
if (ret) {
@@ -627,16 +623,12 @@ static int xlnx_event_init_sgi(struct platform_device *pdev)
static void xlnx_event_cleanup_sgi(struct platform_device *pdev)
{
- int cpu = smp_processor_id();
-
- per_cpu(cpu_number1, cpu) = cpu;
-
cpuhp_remove_state(CPUHP_AP_ONLINE_DYN);
on_each_cpu(xlnx_disable_percpu_irq, NULL, 1);
irq_clear_status_flags(virq_sgi, IRQ_PER_CPU);
- free_percpu_irq(virq_sgi, &cpu_number1);
+ free_percpu_irq(virq_sgi, &dummy_cpu_number);
irq_dispose_mapping(virq_sgi);
}
diff --git a/drivers/soc/xilinx/zynqmp_power.c b/drivers/soc/xilinx/zynqmp_power.c
index 965b1143936a..411d33f2fb05 100644
--- a/drivers/soc/xilinx/zynqmp_power.c
+++ b/drivers/soc/xilinx/zynqmp_power.c
@@ -30,9 +30,27 @@ struct zynqmp_pm_work_struct {
u32 args[CB_ARG_CNT];
};
-static struct zynqmp_pm_work_struct *zynqmp_pm_init_suspend_work;
+/**
+ * struct zynqmp_pm_event_info - event related information
+ * @cb_fun: Function pointer to store the callback function.
+ * @cb_type: Type of callback from pm_api_cb_id,
+ * PM_NOTIFY_CB - for Error Events,
+ * PM_INIT_SUSPEND_CB - for suspend callback.
+ * @node_id: Node-Id related to event.
+ * @event: Event Mask for the Error Event.
+ * @wake: Flag specifying whether the subsystem should be woken upon
+ * event notification.
+ */
+struct zynqmp_pm_event_info {
+ event_cb_func_t cb_fun;
+ enum pm_api_cb_id cb_type;
+ u32 node_id;
+ u32 event;
+ bool wake;
+};
+
+static struct zynqmp_pm_work_struct *zynqmp_pm_init_suspend_work, *zynqmp_pm_init_restart_work;
static struct mbox_chan *rx_chan;
-static bool event_registered;
enum pm_suspend_mode {
PM_SUSPEND_MODE_FIRST = 0,
@@ -54,6 +72,19 @@ static void zynqmp_pm_get_callback_data(u32 *buf)
zynqmp_pm_invoke_fn(GET_CALLBACK_DATA, buf, 0);
}
+static void subsystem_restart_event_callback(const u32 *payload, void *data)
+{
+ /* First element is callback API ID, others are callback arguments */
+ if (work_pending(&zynqmp_pm_init_restart_work->callback_work))
+ return;
+
+ /* Copy callback arguments into work's structure */
+ memcpy(zynqmp_pm_init_restart_work->args, &payload[0],
+ sizeof(zynqmp_pm_init_restart_work->args));
+
+ queue_work(system_unbound_wq, &zynqmp_pm_init_restart_work->callback_work);
+}
+
static void suspend_event_callback(const u32 *payload, void *data)
{
/* First element is callback API ID, others are callback arguments */
@@ -120,6 +151,37 @@ static void ipi_receive_callback(struct mbox_client *cl, void *data)
}
/**
+ * zynqmp_pm_subsystem_restart_work_fn - Initiate Subsystem restart
+ * @work: Pointer to work_struct
+ *
+ * Bottom-half of PM callback IRQ handler.
+ */
+static void zynqmp_pm_subsystem_restart_work_fn(struct work_struct *work)
+{
+ int ret;
+ struct zynqmp_pm_work_struct *pm_work = container_of(work, struct zynqmp_pm_work_struct,
+ callback_work);
+
+ /* First element is callback API ID, others are callback arguments */
+ if (pm_work->args[0] == PM_NOTIFY_CB) {
+ if (pm_work->args[2] == EVENT_SUBSYSTEM_RESTART) {
+ ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
+ ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM);
+ if (ret) {
+ pr_err("unable to set shutdown scope\n");
+ return;
+ }
+
+ kernel_restart(NULL);
+ } else {
+ pr_err("%s Unsupported Event - %d\n", __func__, pm_work->args[2]);
+ }
+ } else {
+ pr_err("%s() Unsupported Callback %d\n", __func__, pm_work->args[0]);
+ }
+}
+
+/**
* zynqmp_pm_init_suspend_work_fn - Initialize suspend
* @work: Pointer to work_struct
*
@@ -184,13 +246,51 @@ static ssize_t suspend_mode_store(struct device *dev,
static DEVICE_ATTR_RW(suspend_mode);
+static void unregister_event(struct device *dev, void *res)
+{
+ struct zynqmp_pm_event_info *event_info = res;
+
+ xlnx_unregister_event(event_info->cb_type, event_info->node_id,
+ event_info->event, event_info->cb_fun, NULL);
+}
+
+static int register_event(struct device *dev, const enum pm_api_cb_id cb_type, const u32 node_id,
+ const u32 event, const bool wake, event_cb_func_t cb_fun)
+{
+ int ret;
+ struct zynqmp_pm_event_info *event_info;
+
+ event_info = devres_alloc(unregister_event, sizeof(struct zynqmp_pm_event_info),
+ GFP_KERNEL);
+ if (!event_info)
+ return -ENOMEM;
+
+ event_info->cb_type = cb_type;
+ event_info->node_id = node_id;
+ event_info->event = event;
+ event_info->wake = wake;
+ event_info->cb_fun = cb_fun;
+
+ ret = xlnx_register_event(event_info->cb_type, event_info->node_id,
+ event_info->event, event_info->wake, event_info->cb_fun, NULL);
+ if (ret) {
+ devres_free(event_info);
+ return ret;
+ }
+
+ devres_add(dev, event_info);
+ return 0;
+}
+
static int zynqmp_pm_probe(struct platform_device *pdev)
{
int ret, irq;
- u32 pm_api_version;
+ u32 pm_api_version, pm_family_code, pm_sub_family_code, node_id;
struct mbox_client *client;
- zynqmp_pm_get_api_version(&pm_api_version);
+ ret = zynqmp_pm_get_api_version(&pm_api_version);
+ if (ret)
+ return ret;
/* Check PM API version number */
if (pm_api_version < ZYNQMP_PM_VERSION)
@@ -203,21 +303,43 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
* is not available to use) or -ENODEV(Xilinx Event Manager not compiled),
* then use ipi-mailbox or interrupt method.
*/
- ret = xlnx_register_event(PM_INIT_SUSPEND_CB, 0, 0, false,
- suspend_event_callback, NULL);
+ ret = register_event(&pdev->dev, PM_INIT_SUSPEND_CB, 0, 0, false,
+ suspend_event_callback);
if (!ret) {
zynqmp_pm_init_suspend_work = devm_kzalloc(&pdev->dev,
sizeof(struct zynqmp_pm_work_struct),
GFP_KERNEL);
- if (!zynqmp_pm_init_suspend_work) {
- xlnx_unregister_event(PM_INIT_SUSPEND_CB, 0, 0,
- suspend_event_callback, NULL);
+ if (!zynqmp_pm_init_suspend_work)
return -ENOMEM;
- }
- event_registered = true;
INIT_WORK(&zynqmp_pm_init_suspend_work->callback_work,
zynqmp_pm_init_suspend_work_fn);
+
+ ret = zynqmp_pm_get_family_info(&pm_family_code, &pm_sub_family_code);
+ if (ret < 0)
+ return ret;
+
+ if (pm_sub_family_code == VERSALNET_SUB_FAMILY_CODE)
+ node_id = PM_DEV_ACPU_0_0;
+ else
+ node_id = PM_DEV_ACPU_0;
+
+ ret = register_event(&pdev->dev, PM_NOTIFY_CB, node_id, EVENT_SUBSYSTEM_RESTART,
+ false, subsystem_restart_event_callback);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to Register with Xilinx Event manager %d\n",
+ ret);
+ return ret;
+ }
+
+ zynqmp_pm_init_restart_work = devm_kzalloc(&pdev->dev,
+ sizeof(struct zynqmp_pm_work_struct),
+ GFP_KERNEL);
+ if (!zynqmp_pm_init_restart_work)
+ return -ENOMEM;
+
+ INIT_WORK(&zynqmp_pm_init_restart_work->callback_work,
+ zynqmp_pm_subsystem_restart_work_fn);
} else if (ret != -EACCES && ret != -ENODEV) {
dev_err(&pdev->dev, "Failed to Register with Xilinx Event manager %d\n", ret);
return ret;
@@ -264,15 +386,8 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
}
ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_suspend_mode.attr);
- if (ret) {
- if (event_registered) {
- xlnx_unregister_event(PM_INIT_SUSPEND_CB, 0, 0, suspend_event_callback,
- NULL);
- event_registered = false;
- }
- dev_err(&pdev->dev, "unable to create sysfs interface\n");
+ if (ret)
return ret;
- }
return 0;
}
@@ -280,8 +395,6 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
static void zynqmp_pm_remove(struct platform_device *pdev)
{
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_suspend_mode.attr);
- if (event_registered)
- xlnx_unregister_event(PM_INIT_SUSPEND_CB, 0, 0, suspend_event_callback, NULL);
if (!rx_chan)
mbox_free_channel(rx_chan);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index a2c99ff33e0a..ec1550c698d5 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -277,6 +277,12 @@ config SPI_CADENCE_XSPI
device with a Cadence XSPI controller and want to access the
Flash as an MTD device.
+config SPI_CH341
+ tristate "CH341 USB2SPI adapter"
+ depends on SPI_MASTER && USB
+ help
+ Enables the SPI controller on the CH341a USB to serial chip
+
config SPI_CLPS711X
tristate "CLPS711X host SPI controller"
depends on ARCH_CLPS711X || COMPILE_TEST
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e694254dec04..a9b1bc259b68 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
obj-$(CONFIG_SPI_CADENCE) += spi-cadence.o
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += spi-cadence-quadspi.o
obj-$(CONFIG_SPI_CADENCE_XSPI) += spi-cadence-xspi.o
+obj-$(CONFIG_SPI_CH341) += spi-ch341.o
obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o
obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
obj-$(CONFIG_SPI_CS42L43) += spi-cs42l43.o
@@ -107,7 +108,8 @@ obj-$(CONFIG_SPI_PIC32) += spi-pic32.o
obj-$(CONFIG_SPI_PIC32_SQI) += spi-pic32-sqi.o
obj-$(CONFIG_SPI_PL022) += spi-pl022.o
obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o
-spi-pxa2xx-platform-objs := spi-pxa2xx.o spi-pxa2xx-dma.o
+obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-core.o
+spi-pxa2xx-core-y := spi-pxa2xx.o spi-pxa2xx-dma.o
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o
obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
obj-$(CONFIG_SPI_QCOM_GENI) += spi-geni-qcom.o
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index 370c4d1572ed..5aaff3bee1b7 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -756,8 +756,15 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev)
struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
int ret;
- clk_prepare(aq->pclk);
- clk_prepare(aq->qspick);
+ ret = clk_prepare(aq->pclk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare(aq->qspick);
+ if (ret) {
+ clk_unprepare(aq->pclk);
+ return ret;
+ }
ret = pm_runtime_force_resume(dev);
if (ret < 0)
diff --git a/drivers/spi/internals.h b/drivers/spi/internals.h
index 4a28a8395552..1f459b895891 100644
--- a/drivers/spi/internals.h
+++ b/drivers/spi/internals.h
@@ -40,4 +40,12 @@ static inline void spi_unmap_buf(struct spi_controller *ctlr,
}
#endif /* CONFIG_HAS_DMA */
+static inline bool spi_xfer_is_dma_mapped(struct spi_controller *ctlr,
+ struct spi_device *spi,
+ struct spi_transfer *xfer)
+{
+ return ctlr->can_dma && ctlr->can_dma(ctlr, spi, xfer) &&
+ (xfer->tx_sg_mapped || xfer->rx_sg_mapped);
+}
+
#endif /* __LINUX_SPI_INTERNALS_H */
diff --git a/drivers/spi/spi-altera-core.c b/drivers/spi/spi-altera-core.c
index 87e37f48f196..7af097929116 100644
--- a/drivers/spi/spi-altera-core.c
+++ b/drivers/spi/spi-altera-core.c
@@ -219,4 +219,5 @@ void altera_spi_init_host(struct spi_controller *host)
}
EXPORT_SYMBOL_GPL(altera_spi_init_host);
+MODULE_DESCRIPTION("Altera SPI Controller driver core");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c
index e358ac5b4509..447e5a962dee 100644
--- a/drivers/spi/spi-axi-spi-engine.c
+++ b/drivers/spi/spi-axi-spi-engine.c
@@ -46,6 +46,7 @@
#define SPI_ENGINE_INST_ASSERT 0x1
#define SPI_ENGINE_INST_WRITE 0x2
#define SPI_ENGINE_INST_MISC 0x3
+#define SPI_ENGINE_INST_CS_INV 0x4
#define SPI_ENGINE_CMD_REG_CLK_DIV 0x0
#define SPI_ENGINE_CMD_REG_CONFIG 0x1
@@ -73,6 +74,8 @@
SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SLEEP, (delay))
#define SPI_ENGINE_CMD_SYNC(id) \
SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SYNC, (id))
+#define SPI_ENGINE_CMD_CS_INV(flags) \
+ SPI_ENGINE_CMD(SPI_ENGINE_INST_CS_INV, 0, (flags))
struct spi_engine_program {
unsigned int length;
@@ -111,6 +114,8 @@ struct spi_engine {
struct spi_engine_message_state msg_state;
struct completion msg_complete;
unsigned int int_enable;
+ /* shadows hardware CS inversion flag state */
+ u8 cs_inv;
};
static void spi_engine_program_add_cmd(struct spi_engine_program *p,
@@ -164,16 +169,20 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry,
}
static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry,
- int delay_ns, u32 sclk_hz)
+ int delay_ns, int inst_ns, u32 sclk_hz)
{
unsigned int t;
- /* negative delay indicates error, e.g. from spi_delay_to_ns() */
- if (delay_ns <= 0)
+ /*
+ * Negative delay indicates error, e.g. from spi_delay_to_ns(). And if
+ * delay is less that the instruction execution time, there is no need
+ * for an extra sleep instruction since the instruction execution time
+ * will already cover the required delay.
+ */
+ if (delay_ns < 0 || delay_ns <= inst_ns)
return;
- /* rounding down since executing the instruction adds a couple of ticks delay */
- t = DIV_ROUND_DOWN_ULL((u64)delay_ns * sclk_hz, NSEC_PER_SEC);
+ t = DIV_ROUND_UP_ULL((u64)(delay_ns - inst_ns) * sclk_hz, NSEC_PER_SEC);
while (t) {
unsigned int n = min(t, 256U);
@@ -220,10 +229,16 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
struct spi_device *spi = msg->spi;
struct spi_controller *host = spi->controller;
struct spi_transfer *xfer;
- int clk_div, new_clk_div;
+ int clk_div, new_clk_div, inst_ns;
bool keep_cs = false;
u8 bits_per_word = 0;
+ /*
+ * Take into account instruction execution time for more accurate sleep
+ * times, especially when the delay is small.
+ */
+ inst_ns = DIV_ROUND_UP(NSEC_PER_SEC, host->max_speed_hz);
+
clk_div = 1;
spi_engine_program_add_cmd(p, dry,
@@ -252,7 +267,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
spi_engine_gen_xfer(p, dry, xfer);
spi_engine_gen_sleep(p, dry, spi_delay_to_ns(&xfer->delay, xfer),
- xfer->effective_speed_hz);
+ inst_ns, xfer->effective_speed_hz);
if (xfer->cs_change) {
if (list_is_last(&xfer->transfer_list, &msg->transfers)) {
@@ -262,7 +277,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
spi_engine_gen_cs(p, dry, spi, false);
spi_engine_gen_sleep(p, dry, spi_delay_to_ns(
- &xfer->cs_change_delay, xfer),
+ &xfer->cs_change_delay, xfer), inst_ns,
xfer->effective_speed_hz);
if (!list_next_entry(xfer, transfer_list)->cs_off)
@@ -530,6 +545,29 @@ static int spi_engine_unoptimize_message(struct spi_message *msg)
return 0;
}
+static int spi_engine_setup(struct spi_device *device)
+{
+ struct spi_controller *host = device->controller;
+ struct spi_engine *spi_engine = spi_controller_get_devdata(host);
+
+ if (device->mode & SPI_CS_HIGH)
+ spi_engine->cs_inv |= BIT(spi_get_chipselect(device, 0));
+ else
+ spi_engine->cs_inv &= ~BIT(spi_get_chipselect(device, 0));
+
+ writel_relaxed(SPI_ENGINE_CMD_CS_INV(spi_engine->cs_inv),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+
+ /*
+ * In addition to setting the flags, we have to do a CS assert command
+ * to make the new setting actually take effect.
+ */
+ writel_relaxed(SPI_ENGINE_CMD_ASSERT(0, 0xff),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+
+ return 0;
+}
+
static int spi_engine_transfer_one_message(struct spi_controller *host,
struct spi_message *msg)
{
@@ -653,16 +691,16 @@ static int spi_engine_probe(struct platform_device *pdev)
host->unoptimize_message = spi_engine_unoptimize_message;
host->num_chipselect = 8;
+ /* Some features depend of the IP core version. */
+ if (ADI_AXI_PCORE_VER_MINOR(version) >= 2) {
+ host->mode_bits |= SPI_CS_HIGH;
+ host->setup = spi_engine_setup;
+ }
+
if (host->max_speed_hz == 0)
return dev_err_probe(&pdev->dev, -EINVAL, "spi_clk rate is 0");
- ret = devm_spi_register_controller(&pdev->dev, host);
- if (ret)
- return ret;
-
- platform_set_drvdata(pdev, host);
-
- return 0;
+ return devm_spi_register_controller(&pdev->dev, host);
}
static const struct of_device_id spi_engine_match_table[] = {
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c
index ca5cc67555c5..afb1b1105ec2 100644
--- a/drivers/spi/spi-bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -38,33 +38,24 @@
* working quickly, or testing for differences that aren't speed related.
*/
+typedef unsigned int (*spi_bb_txrx_bufs_fn)(struct spi_device *, spi_bb_txrx_word_fn,
+ unsigned int, struct spi_transfer *,
+ unsigned int);
+
struct spi_bitbang_cs {
- unsigned nsecs; /* (clock cycle time)/2 */
- u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs,
- u32 word, u8 bits, unsigned flags);
- unsigned (*txrx_bufs)(struct spi_device *,
- u32 (*txrx_word)(
- struct spi_device *spi,
- unsigned nsecs,
- u32 word, u8 bits,
- unsigned flags),
- unsigned, struct spi_transfer *,
- unsigned);
+ unsigned int nsecs; /* (clock cycle time) / 2 */
+ spi_bb_txrx_word_fn txrx_word;
+ spi_bb_txrx_bufs_fn txrx_bufs;
};
-static unsigned bitbang_txrx_8(
- struct spi_device *spi,
- u32 (*txrx_word)(struct spi_device *spi,
- unsigned nsecs,
- u32 word, u8 bits,
- unsigned flags),
- unsigned ns,
+static unsigned int bitbang_txrx_8(struct spi_device *spi,
+ spi_bb_txrx_word_fn txrx_word,
+ unsigned int ns,
struct spi_transfer *t,
- unsigned flags
-)
+ unsigned int flags)
{
- unsigned bits = t->bits_per_word;
- unsigned count = t->len;
+ unsigned int bits = t->bits_per_word;
+ unsigned int count = t->len;
const u8 *tx = t->tx_buf;
u8 *rx = t->rx_buf;
@@ -81,19 +72,14 @@ static unsigned bitbang_txrx_8(
return t->len - count;
}
-static unsigned bitbang_txrx_16(
- struct spi_device *spi,
- u32 (*txrx_word)(struct spi_device *spi,
- unsigned nsecs,
- u32 word, u8 bits,
- unsigned flags),
- unsigned ns,
+static unsigned int bitbang_txrx_16(struct spi_device *spi,
+ spi_bb_txrx_word_fn txrx_word,
+ unsigned int ns,
struct spi_transfer *t,
- unsigned flags
-)
+ unsigned int flags)
{
- unsigned bits = t->bits_per_word;
- unsigned count = t->len;
+ unsigned int bits = t->bits_per_word;
+ unsigned int count = t->len;
const u16 *tx = t->tx_buf;
u16 *rx = t->rx_buf;
@@ -110,19 +96,14 @@ static unsigned bitbang_txrx_16(
return t->len - count;
}
-static unsigned bitbang_txrx_32(
- struct spi_device *spi,
- u32 (*txrx_word)(struct spi_device *spi,
- unsigned nsecs,
- u32 word, u8 bits,
- unsigned flags),
- unsigned ns,
+static unsigned int bitbang_txrx_32(struct spi_device *spi,
+ spi_bb_txrx_word_fn txrx_word,
+ unsigned int ns,
struct spi_transfer *t,
- unsigned flags
-)
+ unsigned int flags)
{
- unsigned bits = t->bits_per_word;
- unsigned count = t->len;
+ unsigned int bits = t->bits_per_word;
+ unsigned int count = t->len;
const u32 *tx = t->tx_buf;
u32 *rx = t->rx_buf;
@@ -234,7 +215,7 @@ EXPORT_SYMBOL_GPL(spi_bitbang_cleanup);
static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
{
struct spi_bitbang_cs *cs = spi->controller_state;
- unsigned nsecs = cs->nsecs;
+ unsigned int nsecs = cs->nsecs;
struct spi_bitbang *bitbang;
bitbang = spi_controller_get_devdata(spi->controller);
@@ -247,7 +228,7 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
}
if (spi->mode & SPI_3WIRE) {
- unsigned flags;
+ unsigned int flags;
flags = t->tx_buf ? SPI_CONTROLLER_NO_RX : SPI_CONTROLLER_NO_TX;
return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t, flags);
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
index e5140532071d..e07e081de5ea 100644
--- a/drivers/spi/spi-cadence.c
+++ b/drivers/spi/spi-cadence.c
@@ -18,6 +18,7 @@
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/reset.h>
#include <linux/spi/spi.h>
/* Name of this driver */
@@ -111,6 +112,7 @@
* @dev_busy: Device busy flag
* @is_decoded_cs: Flag for decoder property set or not
* @tx_fifo_depth: Depth of the TX FIFO
+ * @rstc: Optional reset control for SPI controller
*/
struct cdns_spi {
void __iomem *regs;
@@ -125,6 +127,7 @@ struct cdns_spi {
u8 dev_busy;
u32 is_decoded_cs;
unsigned int tx_fifo_depth;
+ struct reset_control *rstc;
};
/* Macros for the SPI controller read/write */
@@ -588,14 +591,24 @@ static int cdns_spi_probe(struct platform_device *pdev)
goto remove_ctlr;
}
- if (!spi_controller_is_target(ctlr)) {
- xspi->ref_clk = devm_clk_get_enabled(&pdev->dev, "ref_clk");
- if (IS_ERR(xspi->ref_clk)) {
- dev_err(&pdev->dev, "ref_clk clock not found.\n");
- ret = PTR_ERR(xspi->ref_clk);
- goto remove_ctlr;
- }
+ xspi->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, "spi");
+ if (IS_ERR(xspi->rstc)) {
+ ret = dev_err_probe(&pdev->dev, PTR_ERR(xspi->rstc),
+ "Cannot get SPI reset.\n");
+ goto remove_ctlr;
+ }
+
+ reset_control_assert(xspi->rstc);
+ reset_control_deassert(xspi->rstc);
+ xspi->ref_clk = devm_clk_get_enabled(&pdev->dev, "ref_clk");
+ if (IS_ERR(xspi->ref_clk)) {
+ dev_err(&pdev->dev, "ref_clk clock not found.\n");
+ ret = PTR_ERR(xspi->ref_clk);
+ goto remove_ctlr;
+ }
+
+ if (!spi_controller_is_target(ctlr)) {
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
pm_runtime_get_noresume(&pdev->dev);
diff --git a/drivers/spi/spi-ch341.c b/drivers/spi/spi-ch341.c
new file mode 100644
index 000000000000..d2351812d310
--- /dev/null
+++ b/drivers/spi/spi-ch341.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// QiHeng Electronics ch341a USB-to-SPI adapter driver
+//
+// Copyright (C) 2024 Johannes Thumshirn <[email protected]>
+//
+// Based on ch341a_spi.c from the flashrom project.
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/spi/spi.h>
+
+#define CH341_PACKET_LENGTH 32
+#define CH341_DEFAULT_TIMEOUT 1000
+
+#define CH341A_CMD_UIO_STREAM 0xab
+
+#define CH341A_CMD_UIO_STM_END 0x20
+#define CH341A_CMD_UIO_STM_DIR 0x40
+#define CH341A_CMD_UIO_STM_OUT 0x80
+
+#define CH341A_CMD_I2C_STREAM 0xaa
+#define CH341A_CMD_I2C_STM_SET 0x60
+#define CH341A_CMD_I2C_STM_END 0x00
+
+#define CH341A_CMD_SPI_STREAM 0xa8
+
+#define CH341A_STM_I2C_100K 0x01
+
+struct ch341_spi_dev {
+ struct spi_controller *ctrl;
+ struct usb_device *udev;
+ unsigned int write_pipe;
+ unsigned int read_pipe;
+ int rx_len;
+ void *rx_buf;
+ u8 *tx_buf;
+ struct urb *rx_urb;
+ struct spi_device *spidev;
+};
+
+static void ch341_set_cs(struct spi_device *spi, bool is_high)
+{
+ struct ch341_spi_dev *ch341 =
+ spi_controller_get_devdata(spi->controller);
+ int err;
+
+ memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
+ ch341->tx_buf[0] = CH341A_CMD_UIO_STREAM;
+ ch341->tx_buf[1] = CH341A_CMD_UIO_STM_OUT | (is_high ? 0x36 : 0x37);
+
+ if (is_high) {
+ ch341->tx_buf[2] = CH341A_CMD_UIO_STM_DIR | 0x3f;
+ ch341->tx_buf[3] = CH341A_CMD_UIO_STM_END;
+ } else {
+ ch341->tx_buf[2] = CH341A_CMD_UIO_STM_END;
+ }
+
+ err = usb_bulk_msg(ch341->udev, ch341->write_pipe, ch341->tx_buf,
+ (is_high ? 4 : 3), NULL, CH341_DEFAULT_TIMEOUT);
+ if (err)
+ dev_err(&spi->dev,
+ "error sending USB message for setting CS (%d)\n", err);
+}
+
+static int ch341_transfer_one(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *trans)
+{
+ struct ch341_spi_dev *ch341 =
+ spi_controller_get_devdata(spi->controller);
+ int len;
+ int ret;
+
+ len = min(CH341_PACKET_LENGTH, trans->len + 1);
+
+ memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
+
+ ch341->tx_buf[0] = CH341A_CMD_SPI_STREAM;
+
+ memcpy(ch341->tx_buf + 1, trans->tx_buf, len);
+
+ ret = usb_bulk_msg(ch341->udev, ch341->write_pipe, ch341->tx_buf, len,
+ NULL, CH341_DEFAULT_TIMEOUT);
+ if (ret)
+ return ret;
+
+ return usb_bulk_msg(ch341->udev, ch341->read_pipe, trans->rx_buf,
+ len - 1, NULL, CH341_DEFAULT_TIMEOUT);
+}
+
+static void ch341_recv(struct urb *urb)
+{
+ struct ch341_spi_dev *ch341 = urb->context;
+ struct usb_device *udev = ch341->udev;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ENOENT:
+ case -ECONNRESET:
+ case -EPIPE:
+ case -ESHUTDOWN:
+ dev_dbg(&udev->dev, "rx urb terminated with status: %d\n",
+ urb->status);
+ return;
+ default:
+ dev_dbg(&udev->dev, "rx urb error: %d\n", urb->status);
+ break;
+ }
+}
+
+static int ch341_config_stream(struct ch341_spi_dev *ch341)
+{
+ memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
+ ch341->tx_buf[0] = CH341A_CMD_I2C_STREAM;
+ ch341->tx_buf[1] = CH341A_CMD_I2C_STM_SET | CH341A_STM_I2C_100K;
+ ch341->tx_buf[2] = CH341A_CMD_I2C_STM_END;
+
+ return usb_bulk_msg(ch341->udev, ch341->write_pipe, ch341->tx_buf, 3,
+ NULL, CH341_DEFAULT_TIMEOUT);
+}
+
+static int ch341_enable_pins(struct ch341_spi_dev *ch341, bool enable)
+{
+ memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
+ ch341->tx_buf[0] = CH341A_CMD_UIO_STREAM;
+ ch341->tx_buf[1] = CH341A_CMD_UIO_STM_OUT | 0x37;
+ ch341->tx_buf[2] = CH341A_CMD_UIO_STM_DIR | (enable ? 0x3f : 0x00);
+ ch341->tx_buf[3] = CH341A_CMD_UIO_STM_END;
+
+ return usb_bulk_msg(ch341->udev, ch341->write_pipe, ch341->tx_buf, 4,
+ NULL, CH341_DEFAULT_TIMEOUT);
+}
+
+static struct spi_board_info chip = {
+ .modalias = "spi-ch341a",
+};
+
+static int ch341_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_endpoint_descriptor *in, *out;
+ struct ch341_spi_dev *ch341;
+ struct spi_controller *ctrl;
+ int ret;
+
+ ret = usb_find_common_endpoints(intf->cur_altsetting, &in, &out, NULL,
+ NULL);
+ if (ret)
+ return ret;
+
+ ctrl = devm_spi_alloc_master(&udev->dev, sizeof(struct ch341_spi_dev));
+ if (!ctrl)
+ return -ENOMEM;
+
+ ch341 = spi_controller_get_devdata(ctrl);
+ ch341->ctrl = ctrl;
+ ch341->udev = udev;
+ ch341->write_pipe = usb_sndbulkpipe(udev, usb_endpoint_num(out));
+ ch341->read_pipe = usb_rcvbulkpipe(udev, usb_endpoint_num(in));
+
+ ch341->rx_len = usb_endpoint_maxp(in);
+ ch341->rx_buf = devm_kzalloc(&udev->dev, ch341->rx_len, GFP_KERNEL);
+ if (!ch341->rx_buf)
+ return -ENOMEM;
+
+ ch341->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ch341->rx_urb)
+ return -ENOMEM;
+
+ ch341->tx_buf =
+ devm_kzalloc(&udev->dev, CH341_PACKET_LENGTH, GFP_KERNEL);
+ if (!ch341->tx_buf)
+ return -ENOMEM;
+
+ usb_fill_bulk_urb(ch341->rx_urb, udev, ch341->read_pipe, ch341->rx_buf,
+ ch341->rx_len, ch341_recv, ch341);
+
+ ret = usb_submit_urb(ch341->rx_urb, GFP_KERNEL);
+ if (ret) {
+ usb_free_urb(ch341->rx_urb);
+ return -ENOMEM;
+ }
+
+ ctrl->bus_num = -1;
+ ctrl->mode_bits = SPI_CPHA;
+ ctrl->transfer_one = ch341_transfer_one;
+ ctrl->set_cs = ch341_set_cs;
+ ctrl->auto_runtime_pm = false;
+
+ usb_set_intfdata(intf, ch341);
+
+ ret = ch341_config_stream(ch341);
+ if (ret)
+ return ret;
+
+ ret = ch341_enable_pins(ch341, true);
+ if (ret)
+ return ret;
+
+ ret = spi_register_controller(ctrl);
+ if (ret)
+ return ret;
+
+ ch341->spidev = spi_new_device(ctrl, &chip);
+ if (!ch341->spidev)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void ch341_disconnect(struct usb_interface *intf)
+{
+ struct ch341_spi_dev *ch341 = usb_get_intfdata(intf);
+
+ spi_unregister_device(ch341->spidev);
+ spi_unregister_controller(ch341->ctrl);
+ ch341_enable_pins(ch341, false);
+ usb_free_urb(ch341->rx_urb);
+}
+
+static const struct usb_device_id ch341_id_table[] = {
+ { USB_DEVICE(0x1a86, 0x5512) },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, ch341_id_table);
+
+static struct usb_driver ch341a_usb_driver = {
+ .name = "spi-ch341",
+ .probe = ch341_probe,
+ .disconnect = ch341_disconnect,
+ .id_table = ch341_id_table,
+};
+module_usb_driver(ch341a_usb_driver);
+
+MODULE_AUTHOR("Johannes Thumshirn <[email protected]>");
+MODULE_DESCRIPTION("QiHeng Electronics ch341 USB2SPI");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c
index 8b618ef0f711..5b8ed65f8094 100644
--- a/drivers/spi/spi-cs42l43.c
+++ b/drivers/spi/spi-cs42l43.c
@@ -9,6 +9,7 @@
#include <linux/array_size.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/gpio/machine.h>
@@ -44,28 +45,10 @@ static const unsigned int cs42l43_clock_divs[] = {
2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30
};
-static const struct software_node ampl = {
- .name = "cs35l56-left",
-};
-
-static const struct software_node ampr = {
- .name = "cs35l56-right",
-};
-
-static struct spi_board_info ampl_info = {
- .modalias = "cs35l56",
- .max_speed_hz = 11 * HZ_PER_MHZ,
- .chip_select = 0,
- .mode = SPI_MODE_0,
- .swnode = &ampl,
-};
-
-static struct spi_board_info ampr_info = {
+static struct spi_board_info amp_info_template = {
.modalias = "cs35l56",
.max_speed_hz = 11 * HZ_PER_MHZ,
- .chip_select = 1,
.mode = SPI_MODE_0,
- .swnode = &ampr,
};
static const struct software_node cs42l43_gpiochip_swnode = {
@@ -246,11 +229,10 @@ static size_t cs42l43_spi_max_length(struct spi_device *spi)
return CS42L43_SPI_MAX_LENGTH;
}
-static bool cs42l43_has_sidecar(struct fwnode_handle *fwnode)
+static struct fwnode_handle *cs42l43_find_xu_node(struct fwnode_handle *fwnode)
{
static const u32 func_smart_amp = 0x1;
struct fwnode_handle *child_fwnode, *ext_fwnode;
- unsigned int val;
u32 function;
int ret;
@@ -266,21 +248,45 @@ static bool cs42l43_has_sidecar(struct fwnode_handle *fwnode)
if (!ext_fwnode)
continue;
- ret = fwnode_property_read_u32(ext_fwnode,
- "01fa-sidecar-instances",
- &val);
+ fwnode_handle_put(child_fwnode);
- fwnode_handle_put(ext_fwnode);
+ return ext_fwnode;
+ }
- if (ret)
- continue;
+ return NULL;
+}
- fwnode_handle_put(child_fwnode);
+static struct spi_board_info *cs42l43_create_bridge_amp(struct cs42l43_spi *priv,
+ const char * const name,
+ int cs, int spkid)
+{
+ struct property_entry *props = NULL;
+ struct software_node *swnode;
+ struct spi_board_info *info;
- return !!val;
+ if (spkid >= 0) {
+ props = devm_kmalloc(priv->dev, sizeof(*props), GFP_KERNEL);
+ if (!props)
+ return NULL;
+
+ *props = PROPERTY_ENTRY_U32("cirrus,speaker-id", spkid);
}
- return false;
+ swnode = devm_kmalloc(priv->dev, sizeof(*swnode), GFP_KERNEL);
+ if (!swnode)
+ return NULL;
+
+ *swnode = SOFTWARE_NODE(name, props, NULL);
+
+ info = devm_kmemdup(priv->dev, &amp_info_template,
+ sizeof(amp_info_template), GFP_KERNEL);
+ if (!info)
+ return NULL;
+
+ info->chip_select = cs;
+ info->swnode = swnode;
+
+ return info;
}
static void cs42l43_release_of_node(void *data)
@@ -298,7 +304,8 @@ static int cs42l43_spi_probe(struct platform_device *pdev)
struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent);
struct cs42l43_spi *priv;
struct fwnode_handle *fwnode = dev_fwnode(cs42l43->dev);
- bool has_sidecar = cs42l43_has_sidecar(fwnode);
+ struct fwnode_handle *xu_fwnode __free(fwnode_handle) = cs42l43_find_xu_node(fwnode);
+ int nsidecars = 0;
int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -350,7 +357,9 @@ static int cs42l43_spi_probe(struct platform_device *pdev)
return ret;
}
- if (has_sidecar) {
+ fwnode_property_read_u32(xu_fwnode, "01fa-sidecar-instances", &nsidecars);
+
+ if (nsidecars) {
ret = software_node_register(&cs42l43_gpiochip_swnode);
if (ret)
return dev_err_probe(priv->dev, ret,
@@ -373,12 +382,28 @@ static int cs42l43_spi_probe(struct platform_device *pdev)
return dev_err_probe(priv->dev, ret,
"Failed to register SPI controller\n");
- if (has_sidecar) {
- if (!spi_new_device(priv->ctlr, &ampl_info))
+ if (nsidecars) {
+ struct spi_board_info *ampl_info;
+ struct spi_board_info *ampr_info;
+ int spkid = -EINVAL;
+
+ fwnode_property_read_u32(xu_fwnode, "01fa-spk-id-val", &spkid);
+
+ dev_dbg(priv->dev, "Found speaker ID %d\n", spkid);
+
+ ampl_info = cs42l43_create_bridge_amp(priv, "cs35l56-left", 0, spkid);
+ if (!ampl_info)
+ return -ENOMEM;
+
+ ampr_info = cs42l43_create_bridge_amp(priv, "cs35l56-right", 1, spkid);
+ if (!ampr_info)
+ return -ENOMEM;
+
+ if (!spi_new_device(priv->ctlr, ampl_info))
return dev_err_probe(priv->dev, -ENODEV,
"Failed to create left amp slave\n");
- if (!spi_new_device(priv->ctlr, &ampr_info))
+ if (!spi_new_device(priv->ctlr, ampr_info))
return dev_err_probe(priv->dev, -ENODEV,
"Failed to create right amp slave\n");
}
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index be3998104bfb..f7e8b5efa50e 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -984,6 +984,9 @@ static int davinci_spi_probe(struct platform_device *pdev)
return ret;
free_dma:
+ /* This bit needs to be cleared to disable dpsi->clk */
+ clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
+
if (dspi->dma_rx) {
dma_release_channel(dspi->dma_rx);
dma_release_channel(dspi->dma_tx);
@@ -1013,6 +1016,9 @@ static void davinci_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&dspi->bitbang);
+ /* This bit needs to be cleared to disable dpsi->clk */
+ clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
+
if (dspi->dma_rx) {
dma_release_channel(dspi->dma_rx);
dma_release_channel(dspi->dma_tx);
diff --git a/drivers/spi/spi-dw-bt1.c b/drivers/spi/spi-dw-bt1.c
index 5391bcac305c..4577e8096cd9 100644
--- a/drivers/spi/spi-dw-bt1.c
+++ b/drivers/spi/spi-dw-bt1.c
@@ -55,13 +55,15 @@ static int dw_spi_bt1_dirmap_create(struct spi_mem_dirmap_desc *desc)
!dwsbt1->dws.mem_ops.supports_op(desc->mem, &desc->info.op_tmpl))
return -EOPNOTSUPP;
+ if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
+ return -EOPNOTSUPP;
+
/*
* Make sure the requested region doesn't go out of the physically
- * mapped flash memory bounds and the operation is read-only.
+ * mapped flash memory bounds.
*/
- if (desc->info.offset + desc->info.length > dwsbt1->map_len ||
- desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
- return -EOPNOTSUPP;
+ if (desc->info.offset + desc->info.length > dwsbt1->map_len)
+ return -EINVAL;
return 0;
}
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index ddfdb903047a..431788dd848c 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/of.h>
+#include "internals.h"
#include "spi-dw.h"
#ifdef CONFIG_DEBUG_FS
@@ -438,8 +439,7 @@ static int dw_spi_transfer_one(struct spi_controller *host,
transfer->effective_speed_hz = dws->current_freq;
/* Check if current transfer is a DMA transaction */
- if (host->can_dma && host->can_dma(host, spi, transfer))
- dws->dma_mapped = host->cur_msg_mapped;
+ dws->dma_mapped = spi_xfer_is_dma_mapped(host, spi, transfer);
/* For poll mode just disable all interrupts */
dw_spi_mask_intr(dws, 0xff);
diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c
index e335132080bf..23ad1249f121 100644
--- a/drivers/spi/spi-fsl-cpm.c
+++ b/drivers/spi/spi-fsl-cpm.c
@@ -415,4 +415,5 @@ void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
}
EXPORT_SYMBOL_GPL(fsl_spi_cpm_free);
+MODULE_DESCRIPTION("Freescale SPI controller driver CPM functions");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 0a2730cd07c6..191de1917f83 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -1006,6 +1006,7 @@ static int dspi_setup(struct spi_device *spi)
struct chip_data *chip;
unsigned long clkrate;
bool cs = true;
+ int val;
/* Only alloc on first setup */
chip = spi_get_ctldata(spi);
@@ -1018,11 +1019,19 @@ static int dspi_setup(struct spi_device *spi)
pdata = dev_get_platdata(&dspi->pdev->dev);
if (!pdata) {
- of_property_read_u32(spi->dev.of_node, "fsl,spi-cs-sck-delay",
- &cs_sck_delay);
-
- of_property_read_u32(spi->dev.of_node, "fsl,spi-sck-cs-delay",
- &sck_cs_delay);
+ val = spi_delay_to_ns(&spi->cs_setup, NULL);
+ cs_sck_delay = val >= 0 ? val : 0;
+ if (!cs_sck_delay)
+ of_property_read_u32(spi->dev.of_node,
+ "fsl,spi-cs-sck-delay",
+ &cs_sck_delay);
+
+ val = spi_delay_to_ns(&spi->cs_hold, NULL);
+ sck_cs_delay = val >= 0 ? val : 0;
+ if (!sck_cs_delay)
+ of_property_read_u32(spi->dev.of_node,
+ "fsl,spi-sck-cs-delay",
+ &sck_cs_delay);
} else {
cs_sck_delay = pdata->cs_sck_delay;
sck_cs_delay = pdata->sck_cs_delay;
diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c
index 4fc2c56555b5..bb7a625db5b0 100644
--- a/drivers/spi/spi-fsl-lib.c
+++ b/drivers/spi/spi-fsl-lib.c
@@ -158,4 +158,5 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
}
EXPORT_SYMBOL_GPL(of_mpc8xxx_spi_probe);
+MODULE_DESCRIPTION("Freescale SPI/eSPI controller driver library");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index aa5ed254be46..32baa14dfd83 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -960,13 +960,13 @@ static void fsl_lpspi_remove(struct platform_device *pdev)
pm_runtime_disable(fsl_lpspi->dev);
}
-static int __maybe_unused fsl_lpspi_suspend(struct device *dev)
+static int fsl_lpspi_suspend(struct device *dev)
{
pinctrl_pm_select_sleep_state(dev);
return pm_runtime_force_suspend(dev);
}
-static int __maybe_unused fsl_lpspi_resume(struct device *dev)
+static int fsl_lpspi_resume(struct device *dev)
{
int ret;
@@ -984,14 +984,14 @@ static int __maybe_unused fsl_lpspi_resume(struct device *dev)
static const struct dev_pm_ops fsl_lpspi_pm_ops = {
SET_RUNTIME_PM_OPS(fsl_lpspi_runtime_suspend,
fsl_lpspi_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(fsl_lpspi_suspend, fsl_lpspi_resume)
+ SYSTEM_SLEEP_PM_OPS(fsl_lpspi_suspend, fsl_lpspi_resume)
};
static struct platform_driver fsl_lpspi_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = fsl_lpspi_dt_ids,
- .pm = &fsl_lpspi_pm_ops,
+ .pm = pm_ptr(&fsl_lpspi_pm_ops),
},
.probe = fsl_lpspi_probe,
.remove_new = fsl_lpspi_remove,
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 909cce109bba..36c587be9e28 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -5,17 +5,17 @@
* Copyright (C) 2006,2008 David Brownell
* Copyright (C) 2017 Linus Walleij
*/
+#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/of.h>
+#include <linux/property.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/spi/spi_gpio.h>
-
/*
* This bitbanging SPI host driver should help make systems usable
* when a native hardware SPI engine is not available, perhaps because
@@ -239,8 +239,8 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
static int spi_gpio_setup(struct spi_device *spi)
{
struct gpio_desc *cs;
- int status = 0;
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
+ int ret;
/*
* The CS GPIOs have already been
@@ -248,15 +248,14 @@ static int spi_gpio_setup(struct spi_device *spi)
*/
if (spi_gpio->cs_gpios) {
cs = spi_gpio->cs_gpios[spi_get_chipselect(spi, 0)];
- if (!spi->controller_state && cs)
- status = gpiod_direction_output(cs,
- !(spi->mode & SPI_CS_HIGH));
+ if (!spi->controller_state && cs) {
+ ret = gpiod_direction_output(cs, !(spi->mode & SPI_CS_HIGH));
+ if (ret)
+ return ret;
+ }
}
- if (!status)
- status = spi_bitbang_setup(spi);
-
- return status;
+ return spi_bitbang_setup(spi);
}
static int spi_gpio_set_direction(struct spi_device *spi, bool output)
@@ -326,29 +325,6 @@ static int spi_gpio_request(struct device *dev, struct spi_gpio *spi_gpio)
return PTR_ERR_OR_ZERO(spi_gpio->sck);
}
-#ifdef CONFIG_OF
-static const struct of_device_id spi_gpio_dt_ids[] = {
- { .compatible = "spi-gpio" },
- {}
-};
-MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids);
-
-static int spi_gpio_probe_dt(struct platform_device *pdev,
- struct spi_controller *host)
-{
- host->dev.of_node = pdev->dev.of_node;
- host->use_gpio_descriptors = true;
-
- return 0;
-}
-#else
-static inline int spi_gpio_probe_dt(struct platform_device *pdev,
- struct spi_controller *host)
-{
- return 0;
-}
-#endif
-
static int spi_gpio_probe_pdata(struct platform_device *pdev,
struct spi_controller *host)
{
@@ -389,19 +365,21 @@ static int spi_gpio_probe(struct platform_device *pdev)
struct spi_controller *host;
struct spi_gpio *spi_gpio;
struct device *dev = &pdev->dev;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
struct spi_bitbang *bb;
host = devm_spi_alloc_host(dev, sizeof(*spi_gpio));
if (!host)
return -ENOMEM;
- if (pdev->dev.of_node)
- status = spi_gpio_probe_dt(pdev, host);
- else
+ if (fwnode) {
+ device_set_node(&host->dev, fwnode);
+ host->use_gpio_descriptors = true;
+ } else {
status = spi_gpio_probe_pdata(pdev, host);
-
- if (status)
- return status;
+ if (status)
+ return status;
+ }
spi_gpio = spi_controller_get_devdata(host);
@@ -459,10 +437,16 @@ static int spi_gpio_probe(struct platform_device *pdev)
MODULE_ALIAS("platform:" DRIVER_NAME);
+static const struct of_device_id spi_gpio_dt_ids[] = {
+ { .compatible = "spi-gpio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids);
+
static struct platform_driver spi_gpio_driver = {
.driver = {
.name = DRIVER_NAME,
- .of_match_table = of_match_ptr(spi_gpio_dt_ids),
+ .of_match_table = spi_gpio_dt_ids,
},
.probe = spi_gpio_probe,
};
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 33164ebdb583..85bd1a82a34e 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1050,7 +1050,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
.rx_available = mx31_rx_available,
.reset = mx31_reset,
.fifo_size = 8,
- .has_dmamode = true,
+ .has_dmamode = false,
.dynamic_burst = false,
.has_targetmode = false,
.devtype = IMX35_CSPI,
@@ -1656,10 +1656,6 @@ static int spi_imx_setup(struct spi_device *spi)
return 0;
}
-static void spi_imx_cleanup(struct spi_device *spi)
-{
-}
-
static int
spi_imx_prepare_message(struct spi_controller *controller, struct spi_message *msg)
{
@@ -1756,7 +1752,6 @@ static int spi_imx_probe(struct platform_device *pdev)
controller->transfer_one = spi_imx_transfer_one;
controller->setup = spi_imx_setup;
- controller->cleanup = spi_imx_cleanup;
controller->prepare_message = spi_imx_prepare_message;
controller->unprepare_message = spi_imx_unprepare_message;
controller->target_abort = spi_imx_target_abort;
@@ -1903,7 +1898,7 @@ static void spi_imx_remove(struct platform_device *pdev)
spi_imx_sdma_exit(spi_imx);
}
-static int __maybe_unused spi_imx_runtime_resume(struct device *dev)
+static int spi_imx_runtime_resume(struct device *dev)
{
struct spi_controller *controller = dev_get_drvdata(dev);
struct spi_imx_data *spi_imx;
@@ -1924,7 +1919,7 @@ static int __maybe_unused spi_imx_runtime_resume(struct device *dev)
return 0;
}
-static int __maybe_unused spi_imx_runtime_suspend(struct device *dev)
+static int spi_imx_runtime_suspend(struct device *dev)
{
struct spi_controller *controller = dev_get_drvdata(dev);
struct spi_imx_data *spi_imx;
@@ -1937,29 +1932,28 @@ static int __maybe_unused spi_imx_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused spi_imx_suspend(struct device *dev)
+static int spi_imx_suspend(struct device *dev)
{
pinctrl_pm_select_sleep_state(dev);
return 0;
}
-static int __maybe_unused spi_imx_resume(struct device *dev)
+static int spi_imx_resume(struct device *dev)
{
pinctrl_pm_select_default_state(dev);
return 0;
}
static const struct dev_pm_ops imx_spi_pm = {
- SET_RUNTIME_PM_OPS(spi_imx_runtime_suspend,
- spi_imx_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(spi_imx_suspend, spi_imx_resume)
+ RUNTIME_PM_OPS(spi_imx_runtime_suspend, spi_imx_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(spi_imx_suspend, spi_imx_resume)
};
static struct platform_driver spi_imx_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = spi_imx_dt_ids,
- .pm = &imx_spi_pm,
+ .pm = pm_ptr(&imx_spi_pm),
},
.probe = spi_imx_probe,
.remove_new = spi_imx_remove,
diff --git a/drivers/spi/spi-ingenic.c b/drivers/spi/spi-ingenic.c
index 003a6d21c4c3..318b0768701e 100644
--- a/drivers/spi/spi-ingenic.c
+++ b/drivers/spi/spi-ingenic.c
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
+#include "internals.h"
#define REG_SSIDR 0x0
#define REG_SSICR0 0x4
@@ -242,11 +243,10 @@ static int spi_ingenic_transfer_one(struct spi_controller *ctlr,
{
struct ingenic_spi *priv = spi_controller_get_devdata(ctlr);
unsigned int bits = xfer->bits_per_word ?: spi->bits_per_word;
- bool can_dma = ctlr->can_dma && ctlr->can_dma(ctlr, spi, xfer);
spi_ingenic_prepare_transfer(priv, spi, xfer);
- if (ctlr->cur_msg_mapped && can_dma)
+ if (spi_xfer_is_dma_mapped(ctlr, spi, xfer))
return spi_ingenic_dma_tx(ctlr, xfer, bits);
if (bits > 16)
diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
index fc75492e50ff..8838a98b04c2 100644
--- a/drivers/spi/spi-meson-spicc.c
+++ b/drivers/spi/spi-meson-spicc.c
@@ -514,7 +514,9 @@ static int meson_spicc_prepare_message(struct spi_controller *host,
/* Setup no wait cycles by default */
writel_relaxed(0, spicc->base + SPICC_PERIODREG);
- writel_bits_relaxed(SPICC_LBC_W1, 0, spicc->base + SPICC_TESTREG);
+ writel_bits_relaxed(SPICC_LBC_W1,
+ spi->mode & SPI_LOOP ? SPICC_LBC_W1 : 0,
+ spicc->base + SPICC_TESTREG);
return 0;
}
@@ -644,11 +646,13 @@ static int meson_spicc_pow2_clk_init(struct meson_spicc_device *spicc)
snprintf(name, sizeof(name), "%s#pow2_fixed_div", dev_name(dev));
init.name = name;
init.ops = &clk_fixed_factor_ops;
- init.flags = 0;
- if (spicc->data->has_pclk)
+ if (spicc->data->has_pclk) {
+ init.flags = CLK_SET_RATE_PARENT;
parent_data[0].hw = __clk_get_hw(spicc->pclk);
- else
+ } else {
+ init.flags = 0;
parent_data[0].hw = __clk_get_hw(spicc->core);
+ }
init.num_parents = 1;
pow2_fixed_div->mult = 1,
@@ -708,11 +712,13 @@ static int meson_spicc_enh_clk_init(struct meson_spicc_device *spicc)
snprintf(name, sizeof(name), "%s#enh_fixed_div", dev_name(dev));
init.name = name;
init.ops = &clk_fixed_factor_ops;
- init.flags = 0;
- if (spicc->data->has_pclk)
+ if (spicc->data->has_pclk) {
+ init.flags = CLK_SET_RATE_PARENT;
parent_data[0].hw = __clk_get_hw(spicc->pclk);
- else
+ } else {
+ init.flags = 0;
parent_data[0].hw = __clk_get_hw(spicc->core);
+ }
init.num_parents = 1;
enh_fixed_div->mult = 1,
@@ -846,7 +852,7 @@ static int meson_spicc_probe(struct platform_device *pdev)
host->num_chipselect = 4;
host->dev.of_node = pdev->dev.of_node;
- host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH;
+ host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LOOP;
host->bits_per_word_mask = SPI_BPW_MASK(32) |
SPI_BPW_MASK(24) |
SPI_BPW_MASK(16) |
diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c
index 634364c7cfe6..6246254e1dff 100644
--- a/drivers/spi/spi-microchip-core.c
+++ b/drivers/spi/spi-microchip-core.c
@@ -21,7 +21,7 @@
#include <linux/spi/spi.h>
#define MAX_LEN (0xffff)
-#define MAX_CS (8)
+#define MAX_CS (1)
#define DEFAULT_FRAMESIZE (8)
#define FIFO_DEPTH (32)
#define CLK_GEN_MODE1_MAX (255)
@@ -258,6 +258,9 @@ static int mchp_corespi_setup(struct spi_device *spi)
struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller);
u32 reg;
+ if (spi_is_csgpiod(spi))
+ return 0;
+
/*
* Active high targets need to be specifically set to their inactive
* states during probe by adding them to the "control group" & thus
@@ -516,6 +519,7 @@ static int mchp_corespi_probe(struct platform_device *pdev)
host->num_chipselect = num_cs;
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+ host->use_gpio_descriptors = true;
host->setup = mchp_corespi_setup;
host->bits_per_word_mask = SPI_BPW_MASK(8);
host->transfer_one = mchp_corespi_transfer_one;
diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c
index 5d72e3d59df8..c02c4204442f 100644
--- a/drivers/spi/spi-mux.c
+++ b/drivers/spi/spi-mux.c
@@ -158,12 +158,14 @@ static int spi_mux_probe(struct spi_device *spi)
/* supported modes are the same as our parent's */
ctlr->mode_bits = spi->controller->mode_bits;
ctlr->flags = spi->controller->flags;
+ ctlr->bits_per_word_mask = spi->controller->bits_per_word_mask;
ctlr->transfer_one_message = spi_mux_transfer_one_message;
ctlr->setup = spi_mux_setup;
ctlr->num_chipselect = mux_control_states(priv->mux);
ctlr->bus_num = -1;
ctlr->dev.of_node = spi->dev.of_node;
ctlr->must_async = true;
+ ctlr->defer_optimize_message = true;
ret = devm_spi_register_controller(&spi->dev, ctlr);
if (ret)
diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index 60c9f3048ac9..6156d691630a 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -496,7 +496,7 @@ static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
struct mxic_spi *mxic = spi_controller_get_devdata(desc->mem->spi->controller);
if (!mxic->linear.map)
- return -EINVAL;
+ return -EOPNOTSUPP;
if (desc->info.offset + desc->info.length > U32_MAX)
return -EINVAL;
diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c
index 210a98d903fa..03b820e85651 100644
--- a/drivers/spi/spi-omap-uwire.c
+++ b/drivers/spi/spi-omap-uwire.c
@@ -541,5 +541,6 @@ static void __exit omap_uwire_exit(void)
subsys_initcall(omap_uwire_init);
module_exit(omap_uwire_exit);
+MODULE_DESCRIPTION("MicroWire interface driver for OMAP");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 7e3083b83534..2c043817c66a 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -27,6 +27,8 @@
#include <linux/spi/spi.h>
+#include "internals.h"
+
#include <linux/platform_data/spi-omap2-mcspi.h>
#define OMAP2_MCSPI_MAX_FREQ 48000000
@@ -1208,8 +1210,7 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
unsigned count;
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
- ctlr->cur_msg_mapped &&
- ctlr->can_dma(ctlr, spi, t))
+ spi_xfer_is_dma_mapped(ctlr, spi, t))
omap2_mcspi_set_fifo(spi, t, 1);
omap2_mcspi_set_enable(spi, 1);
@@ -1220,8 +1221,7 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
+ OMAP2_MCSPI_TX0);
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
- ctlr->cur_msg_mapped &&
- ctlr->can_dma(ctlr, spi, t))
+ spi_xfer_is_dma_mapped(ctlr, spi, t))
count = omap2_mcspi_txrx_dma(spi, t);
else
count = omap2_mcspi_txrx_pio(spi, t);
@@ -1277,24 +1277,11 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
/*
* Check if this transfer contains only one word;
- * OR contains 1 to 4 words, with bits_per_word == 8 and no delay between each word
- * OR contains 1 to 2 words, with bits_per_word == 16 and no delay between each word
- *
- * If one of the two last case is true, this also change the bits_per_word of this
- * transfer to make it a bit faster.
- * It's not an issue to change the bits_per_word here even if the multi-mode is not
- * applicable for this message, the signal on the wire will be the same.
*/
if (bits_per_word < 8 && tr->len == 1) {
/* multi-mode is applicable, only one word (1..7 bits) */
- } else if (tr->word_delay.value == 0 && bits_per_word == 8 && tr->len <= 4) {
- /* multi-mode is applicable, only one "bigger" word (8,16,24,32 bits) */
- tr->bits_per_word = tr->len * bits_per_word;
- } else if (tr->word_delay.value == 0 && bits_per_word == 16 && tr->len <= 2) {
- /* multi-mode is applicable, only one "bigger" word (16,32 bits) */
- tr->bits_per_word = tr->len * bits_per_word / 2;
} else if (bits_per_word >= 8 && tr->len == bits_per_word / 8) {
- /* multi-mode is applicable, only one word (9..15,17..32 bits) */
+ /* multi-mode is applicable, only one word (8..32 bits) */
} else {
/* multi-mode is not applicable: more than one word in the transfer */
mcspi->use_multi_mode = false;
@@ -1671,4 +1658,5 @@ static struct platform_driver omap2_mcspi_driver = {
};
module_platform_driver(omap2_mcspi_driver);
+MODULE_DESCRIPTION("OMAP2 McSPI controller driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c
index cc18d320370f..fc98979eba48 100644
--- a/drivers/spi/spi-pci1xxxx.c
+++ b/drivers/spi/spi-pci1xxxx.c
@@ -6,6 +6,7 @@
#include <linux/bitfield.h>
+#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
@@ -15,7 +16,7 @@
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/spi/spi.h>
-#include <linux/delay.h>
+#include "internals.h"
#define DRV_NAME "spi-pci1xxxx"
@@ -567,7 +568,7 @@ error:
static int pci1xxxx_spi_transfer_one(struct spi_controller *spi_ctlr,
struct spi_device *spi, struct spi_transfer *xfer)
{
- if (spi_ctlr->can_dma(spi_ctlr, spi, xfer) && spi_ctlr->cur_msg_mapped)
+ if (spi_xfer_is_dma_mapped(spi_ctlr, spi, xfer))
return pci1xxxx_spi_transfer_with_dma(spi_ctlr, spi, xfer);
else
return pci1xxxx_spi_transfer_with_io(spi_ctlr, spi, xfer);
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
index 6d2efdb0e95f..616d032f1a89 100644
--- a/drivers/spi/spi-pxa2xx-pci.c
+++ b/drivers/spi/spi-pxa2xx-pci.c
@@ -10,8 +10,7 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/property.h>
+#include <linux/pm.h>
#include <linux/sprintf.h>
#include <linux/string.h>
#include <linux/types.h>
@@ -265,10 +264,8 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
const struct pxa_spi_info *info;
- struct platform_device_info pi;
int ret;
- struct platform_device *pdev;
- struct pxa2xx_spi_controller spi_pdata;
+ struct pxa2xx_spi_controller *pdata;
struct ssp_device *ssp;
ret = pcim_enable_device(dev);
@@ -279,15 +276,17 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
if (ret)
return ret;
- memset(&spi_pdata, 0, sizeof(spi_pdata));
+ pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
- ssp = &spi_pdata.ssp;
+ ssp = &pdata->ssp;
ssp->dev = &dev->dev;
ssp->phys_base = pci_resource_start(dev, 0);
ssp->mmio_base = pcim_iomap_table(dev)[0];
info = (struct pxa_spi_info *)ent->driver_data;
- ret = info->setup(dev, &spi_pdata);
+ ret = info->setup(dev, pdata);
if (ret)
return ret;
@@ -298,28 +297,12 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
return ret;
ssp->irq = pci_irq_vector(dev, 0);
- memset(&pi, 0, sizeof(pi));
- pi.fwnode = dev_fwnode(&dev->dev);
- pi.parent = &dev->dev;
- pi.name = "pxa2xx-spi";
- pi.id = ssp->port_id;
- pi.data = &spi_pdata;
- pi.size_data = sizeof(spi_pdata);
-
- pdev = platform_device_register_full(&pi);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- pci_set_drvdata(dev, pdev);
-
- return 0;
+ return pxa2xx_spi_probe(&dev->dev, ssp);
}
static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
{
- struct platform_device *pdev = pci_get_drvdata(dev);
-
- platform_device_unregister(pdev);
+ pxa2xx_spi_remove(&dev->dev);
}
static const struct pci_device_id pxa2xx_spi_pci_devices[] = {
@@ -341,6 +324,9 @@ MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices);
static struct pci_driver pxa2xx_spi_pci_driver = {
.name = "pxa2xx_spi_pci",
.id_table = pxa2xx_spi_pci_devices,
+ .driver = {
+ .pm = pm_ptr(&pxa2xx_spi_pm_ops),
+ },
.probe = pxa2xx_spi_pci_probe,
.remove = pxa2xx_spi_pci_remove,
};
@@ -349,4 +335,5 @@ module_pci_driver(pxa2xx_spi_pci_driver);
MODULE_DESCRIPTION("CE4100/LPSS PCI-SPI glue code for PXA's driver");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(SPI_PXA2xx);
MODULE_AUTHOR("Sebastian Andrzej Siewior <[email protected]>");
diff --git a/drivers/spi/spi-pxa2xx-platform.c b/drivers/spi/spi-pxa2xx-platform.c
new file mode 100644
index 000000000000..98a8ceb7db6f
--- /dev/null
+++ b/drivers/spi/spi-pxa2xx-platform.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
+#include "spi-pxa2xx.h"
+
+static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
+{
+ return param == chan->device->dev;
+}
+
+static int
+pxa2xx_spi_init_ssp(struct platform_device *pdev, struct ssp_device *ssp, enum pxa_ssp_type type)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ int status;
+ u64 uid;
+
+ ssp->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(ssp->mmio_base))
+ return PTR_ERR(ssp->mmio_base);
+
+ ssp->phys_base = res->start;
+
+ ssp->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(ssp->clk))
+ return PTR_ERR(ssp->clk);
+
+ ssp->irq = platform_get_irq(pdev, 0);
+ if (ssp->irq < 0)
+ return ssp->irq;
+
+ ssp->type = type;
+ ssp->dev = dev;
+
+ status = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &uid);
+ if (status)
+ ssp->port_id = -1;
+ else
+ ssp->port_id = uid;
+
+ return 0;
+}
+
+static void pxa2xx_spi_ssp_release(void *ssp)
+{
+ pxa_ssp_free(ssp);
+}
+
+static struct ssp_device *pxa2xx_spi_ssp_request(struct platform_device *pdev)
+{
+ struct ssp_device *ssp;
+ int status;
+
+ ssp = pxa_ssp_request(pdev->id, pdev->name);
+ if (!ssp)
+ return ssp;
+
+ status = devm_add_action_or_reset(&pdev->dev, pxa2xx_spi_ssp_release, ssp);
+ if (status)
+ return ERR_PTR(status);
+
+ return ssp;
+}
+
+static struct pxa2xx_spi_controller *
+pxa2xx_spi_init_pdata(struct platform_device *pdev)
+{
+ struct pxa2xx_spi_controller *pdata;
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+ const void *match = device_get_match_data(dev);
+ enum pxa_ssp_type type = SSP_UNDEFINED;
+ struct ssp_device *ssp;
+ bool is_lpss_priv;
+ u32 num_cs = 1;
+ int status;
+
+ ssp = pxa2xx_spi_ssp_request(pdev);
+ if (IS_ERR(ssp))
+ return ERR_CAST(ssp);
+ if (ssp) {
+ type = ssp->type;
+ } else if (match) {
+ type = (enum pxa_ssp_type)(uintptr_t)match;
+ } else {
+ u32 value;
+
+ status = device_property_read_u32(dev, "intel,spi-pxa2xx-type", &value);
+ if (status)
+ return ERR_PTR(status);
+
+ type = (enum pxa_ssp_type)value;
+ }
+
+ /* Validate the SSP type correctness */
+ if (!(type > SSP_UNDEFINED && type < SSP_MAX))
+ return ERR_PTR(-EINVAL);
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ /* Platforms with iDMA 64-bit */
+ is_lpss_priv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpss_priv");
+ if (is_lpss_priv) {
+ pdata->tx_param = parent;
+ pdata->rx_param = parent;
+ pdata->dma_filter = pxa2xx_spi_idma_filter;
+ }
+
+ /* Read number of chip select pins, if provided */
+ device_property_read_u32(dev, "num-cs", &num_cs);
+
+ pdata->num_chipselect = num_cs;
+ pdata->is_target = device_property_read_bool(dev, "spi-slave");
+ pdata->enable_dma = true;
+ pdata->dma_burst_size = 1;
+
+ /* If SSP has been already enumerated, use it */
+ if (ssp)
+ return pdata;
+
+ status = pxa2xx_spi_init_ssp(pdev, &pdata->ssp, type);
+ if (status)
+ return ERR_PTR(status);
+
+ return pdata;
+}
+
+static int pxa2xx_spi_platform_probe(struct platform_device *pdev)
+{
+ struct pxa2xx_spi_controller *platform_info;
+ struct device *dev = &pdev->dev;
+ struct ssp_device *ssp;
+
+ platform_info = dev_get_platdata(dev);
+ if (!platform_info) {
+ platform_info = pxa2xx_spi_init_pdata(pdev);
+ if (IS_ERR(platform_info))
+ return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");
+
+ dev->platform_data = platform_info;
+ }
+
+ ssp = pxa2xx_spi_ssp_request(pdev);
+ if (IS_ERR(ssp))
+ return PTR_ERR(ssp);
+ if (!ssp)
+ ssp = &platform_info->ssp;
+
+ return pxa2xx_spi_probe(dev, ssp);
+}
+
+static void pxa2xx_spi_platform_remove(struct platform_device *pdev)
+{
+ pxa2xx_spi_remove(&pdev->dev);
+}
+
+static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
+ { "80860F0E" },
+ { "8086228E" },
+ { "INT33C0" },
+ { "INT33C1" },
+ { "INT3430" },
+ { "INT3431" },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
+
+static const struct of_device_id pxa2xx_spi_of_match[] = {
+ { .compatible = "marvell,mmp2-ssp", .data = (void *)MMP2_SSP },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pxa2xx_spi_of_match);
+
+static struct platform_driver driver = {
+ .driver = {
+ .name = "pxa2xx-spi",
+ .pm = pm_ptr(&pxa2xx_spi_pm_ops),
+ .acpi_match_table = pxa2xx_spi_acpi_match,
+ .of_match_table = pxa2xx_spi_of_match,
+ },
+ .probe = pxa2xx_spi_platform_probe,
+ .remove_new = pxa2xx_spi_platform_remove,
+};
+
+static int __init pxa2xx_spi_init(void)
+{
+ return platform_driver_register(&driver);
+}
+subsys_initcall(pxa2xx_spi_init);
+
+static void __exit pxa2xx_spi_exit(void)
+{
+ platform_driver_unregister(&driver);
+}
+module_exit(pxa2xx_spi_exit);
+
+MODULE_AUTHOR("Stephen Street");
+MODULE_DESCRIPTION("PXA2xx SSP SPI Controller platform driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SPI_PXA2xx);
+MODULE_ALIAS("platform:pxa2xx-spi");
+MODULE_SOFTDEP("pre: dw_dmac");
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index efe76d0c21bb..16b96eb176cd 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -4,7 +4,6 @@
* Copyright (C) 2013, 2021 Intel Corporation
*/
-#include <linux/acpi.h>
#include <linux/atomic.h>
#include <linux/bitops.h>
#include <linux/bug.h>
@@ -14,15 +13,12 @@
#include <linux/dmaengine.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
-#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/math64.h>
#include <linux/minmax.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/slab.h>
@@ -30,13 +26,9 @@
#include <linux/spi/spi.h>
+#include "internals.h"
#include "spi-pxa2xx.h"
-MODULE_AUTHOR("Stephen Street");
-MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-spi");
-
#define TIMOUT_DFLT 1000
/*
@@ -99,7 +91,6 @@ struct lpss_config {
/* Chip select control */
unsigned cs_sel_shift;
unsigned cs_sel_mask;
- unsigned cs_num;
/* Quirks */
unsigned cs_clk_stays_gated : 1;
};
@@ -137,7 +128,6 @@ static const struct lpss_config lpss_platforms[] = {
.tx_threshold_hi = 224,
.cs_sel_shift = 2,
.cs_sel_mask = 1 << 2,
- .cs_num = 2,
},
{ /* LPSS_SPT_SSP */
.offset = 0x200,
@@ -1004,11 +994,8 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller,
}
dma_thresh = SSCR1_RxTresh(RX_THRESH_DFLT) | SSCR1_TxTresh(TX_THRESH_DFLT);
- dma_mapped = controller->can_dma &&
- controller->can_dma(controller, spi, transfer) &&
- controller->cur_msg_mapped;
+ dma_mapped = spi_xfer_is_dma_mapped(controller, spi, transfer);
if (dma_mapped) {
-
/* Ensure we have the correct interrupt handler */
drv_data->transfer_handler = pxa2xx_spi_dma_transfer;
@@ -1265,135 +1252,24 @@ static void cleanup(struct spi_device *spi)
kfree(chip);
}
-static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
-{
- return param == chan->device->dev;
-}
-
-static int
-pxa2xx_spi_init_ssp(struct platform_device *pdev, struct ssp_device *ssp, enum pxa_ssp_type type)
-{
- struct device *dev = &pdev->dev;
- struct resource *res;
- int status;
- u64 uid;
-
- ssp->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
- if (IS_ERR(ssp->mmio_base))
- return PTR_ERR(ssp->mmio_base);
-
- ssp->phys_base = res->start;
-
- ssp->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(ssp->clk))
- return PTR_ERR(ssp->clk);
-
- ssp->irq = platform_get_irq(pdev, 0);
- if (ssp->irq < 0)
- return ssp->irq;
-
- ssp->type = type;
- ssp->dev = dev;
-
- status = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &uid);
- if (status)
- ssp->port_id = -1;
- else
- ssp->port_id = uid;
-
- return 0;
-}
-
-static struct pxa2xx_spi_controller *
-pxa2xx_spi_init_pdata(struct platform_device *pdev)
-{
- struct pxa2xx_spi_controller *pdata;
- struct device *dev = &pdev->dev;
- struct device *parent = dev->parent;
- enum pxa_ssp_type type = SSP_UNDEFINED;
- struct ssp_device *ssp = NULL;
- const void *match;
- bool is_lpss_priv;
- u32 num_cs = 1;
- int status;
-
- is_lpss_priv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpss_priv");
-
- match = device_get_match_data(dev);
- if (match)
- type = (uintptr_t)match;
- else if (is_lpss_priv) {
- u32 value;
-
- status = device_property_read_u32(dev, "intel,spi-pxa2xx-type", &value);
- if (status)
- return ERR_PTR(status);
-
- type = (enum pxa_ssp_type)value;
- } else {
- ssp = pxa_ssp_request(pdev->id, pdev->name);
- if (ssp) {
- type = ssp->type;
- pxa_ssp_free(ssp);
- }
- }
-
- /* Validate the SSP type correctness */
- if (!(type > SSP_UNDEFINED && type < SSP_MAX))
- return ERR_PTR(-EINVAL);
-
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return ERR_PTR(-ENOMEM);
-
- /* Platforms with iDMA 64-bit */
- if (is_lpss_priv) {
- pdata->tx_param = parent;
- pdata->rx_param = parent;
- pdata->dma_filter = pxa2xx_spi_idma_filter;
- }
-
- /* Read number of chip select pins, if provided */
- device_property_read_u32(dev, "num-cs", &num_cs);
-
- pdata->num_chipselect = num_cs;
- pdata->is_target = device_property_read_bool(dev, "spi-slave");
- pdata->enable_dma = true;
- pdata->dma_burst_size = 1;
-
- /* If SSP has been already enumerated, use it */
- if (ssp)
- return pdata;
-
- status = pxa2xx_spi_init_ssp(pdev, &pdata->ssp, type);
- if (status)
- return ERR_PTR(status);
-
- return pdata;
-}
-
static int pxa2xx_spi_fw_translate_cs(struct spi_controller *controller,
unsigned int cs)
{
struct driver_data *drv_data = spi_controller_get_devdata(controller);
- if (has_acpi_companion(drv_data->ssp->dev)) {
- switch (drv_data->ssp_type) {
- /*
- * For Atoms the ACPI DeviceSelection used by the Windows
- * driver starts from 1 instead of 0 so translate it here
- * to match what Linux expects.
- */
- case LPSS_BYT_SSP:
- case LPSS_BSW_SSP:
- return cs - 1;
+ switch (drv_data->ssp_type) {
+ /*
+ * For some of Intel Atoms the ACPI DeviceSelection used by the Windows
+ * driver starts from 1 instead of 0 so translate it here to match what
+ * Linux expects.
+ */
+ case LPSS_BYT_SSP:
+ case LPSS_BSW_SSP:
+ return cs - 1;
- default:
- break;
- }
+ default:
+ return cs;
}
-
- return cs;
}
static size_t pxa2xx_spi_max_dma_transfer_size(struct spi_device *spi)
@@ -1401,41 +1277,23 @@ static size_t pxa2xx_spi_max_dma_transfer_size(struct spi_device *spi)
return MAX_DMA_LEN;
}
-static int pxa2xx_spi_probe(struct platform_device *pdev)
+int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp)
{
- struct device *dev = &pdev->dev;
struct pxa2xx_spi_controller *platform_info;
struct spi_controller *controller;
struct driver_data *drv_data;
- struct ssp_device *ssp;
const struct lpss_config *config;
int status;
u32 tmp;
platform_info = dev_get_platdata(dev);
- if (!platform_info) {
- platform_info = pxa2xx_spi_init_pdata(pdev);
- if (IS_ERR(platform_info))
- return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");
- }
- dev_dbg(dev, "DMA burst size set to %u\n", platform_info->dma_burst_size);
-
- ssp = pxa_ssp_request(pdev->id, pdev->name);
- if (!ssp)
- ssp = &platform_info->ssp;
-
- if (!ssp->mmio_base)
- return dev_err_probe(dev, -ENODEV, "failed to get SSP\n");
-
if (platform_info->is_target)
controller = devm_spi_alloc_target(dev, sizeof(*drv_data));
else
controller = devm_spi_alloc_host(dev, sizeof(*drv_data));
+ if (!controller)
+ return dev_err_probe(dev, -ENOMEM, "cannot alloc spi_controller\n");
- if (!controller) {
- status = dev_err_probe(dev, -ENOMEM, "cannot alloc spi_controller\n");
- goto out_error_controller_alloc;
- }
drv_data = spi_controller_get_devdata(controller);
drv_data->controller = controller;
drv_data->controller_info = platform_info;
@@ -1486,10 +1344,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev),
drv_data);
- if (status < 0) {
- dev_err_probe(dev, status, "cannot get IRQ %d\n", ssp->irq);
- goto out_error_controller_alloc;
- }
+ if (status < 0)
+ return dev_err_probe(dev, status, "cannot get IRQ %d\n", ssp->irq);
/* Setup DMA if requested */
if (platform_info->enable_dma) {
@@ -1502,6 +1358,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
controller->max_dma_len = MAX_DMA_LEN;
controller->max_transfer_size =
pxa2xx_spi_max_dma_transfer_size;
+
+ dev_dbg(dev, "DMA burst size set to %u\n", platform_info->dma_burst_size);
}
}
@@ -1578,8 +1436,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
tmp &= LPSS_CAPS_CS_EN_MASK;
tmp >>= LPSS_CAPS_CS_EN_SHIFT;
platform_info->num_chipselect = ffz(tmp);
- } else if (config->cs_num) {
- platform_info->num_chipselect = config->cs_num;
}
}
controller->num_chipselect = platform_info->num_chipselect;
@@ -1594,13 +1450,13 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
}
}
- pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(dev, 50);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
/* Register with the SPI framework */
- platform_set_drvdata(pdev, drv_data);
+ dev_set_drvdata(dev, drv_data);
status = spi_register_controller(controller);
if (status) {
dev_err_probe(dev, status, "problem registering SPI controller\n");
@@ -1610,7 +1466,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
return status;
out_error_pm_runtime_enabled:
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_disable(dev);
out_error_clock_enabled:
clk_disable_unprepare(ssp->clk);
@@ -1619,17 +1475,16 @@ out_error_dma_irq_alloc:
pxa2xx_spi_dma_release(drv_data);
free_irq(ssp->irq, drv_data);
-out_error_controller_alloc:
- pxa_ssp_free(ssp);
return status;
}
+EXPORT_SYMBOL_NS_GPL(pxa2xx_spi_probe, SPI_PXA2xx);
-static void pxa2xx_spi_remove(struct platform_device *pdev)
+void pxa2xx_spi_remove(struct device *dev)
{
- struct driver_data *drv_data = platform_get_drvdata(pdev);
+ struct driver_data *drv_data = dev_get_drvdata(dev);
struct ssp_device *ssp = drv_data->ssp;
- pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_get_sync(dev);
spi_unregister_controller(drv_data->controller);
@@ -1641,15 +1496,13 @@ static void pxa2xx_spi_remove(struct platform_device *pdev)
if (drv_data->controller_info->enable_dma)
pxa2xx_spi_dma_release(drv_data);
- pm_runtime_put_noidle(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(dev);
+ pm_runtime_disable(dev);
/* Release IRQ */
free_irq(ssp->irq, drv_data);
-
- /* Release SSP */
- pxa_ssp_free(ssp);
}
+EXPORT_SYMBOL_NS_GPL(pxa2xx_spi_remove, SPI_PXA2xx);
static int pxa2xx_spi_suspend(struct device *dev)
{
@@ -1701,49 +1554,11 @@ static int pxa2xx_spi_runtime_resume(struct device *dev)
return clk_prepare_enable(drv_data->ssp->clk);
}
-static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
+EXPORT_NS_GPL_DEV_PM_OPS(pxa2xx_spi_pm_ops, SPI_PXA2xx) = {
SYSTEM_SLEEP_PM_OPS(pxa2xx_spi_suspend, pxa2xx_spi_resume)
RUNTIME_PM_OPS(pxa2xx_spi_runtime_suspend, pxa2xx_spi_runtime_resume, NULL)
};
-static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
- { "80860F0E", LPSS_BYT_SSP },
- { "8086228E", LPSS_BSW_SSP },
- { "INT33C0", LPSS_LPT_SSP },
- { "INT33C1", LPSS_LPT_SSP },
- { "INT3430", LPSS_LPT_SSP },
- { "INT3431", LPSS_LPT_SSP },
- {}
-};
-MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
-
-static const struct of_device_id pxa2xx_spi_of_match[] = {
- { .compatible = "marvell,mmp2-ssp", .data = (void *)MMP2_SSP },
- {}
-};
-MODULE_DEVICE_TABLE(of, pxa2xx_spi_of_match);
-
-static struct platform_driver driver = {
- .driver = {
- .name = "pxa2xx-spi",
- .pm = pm_ptr(&pxa2xx_spi_pm_ops),
- .acpi_match_table = pxa2xx_spi_acpi_match,
- .of_match_table = pxa2xx_spi_of_match,
- },
- .probe = pxa2xx_spi_probe,
- .remove_new = pxa2xx_spi_remove,
-};
-
-static int __init pxa2xx_spi_init(void)
-{
- return platform_driver_register(&driver);
-}
-subsys_initcall(pxa2xx_spi_init);
-
-static void __exit pxa2xx_spi_exit(void)
-{
- platform_driver_unregister(&driver);
-}
-module_exit(pxa2xx_spi_exit);
-
-MODULE_SOFTDEP("pre: dw_dmac");
+MODULE_AUTHOR("Stephen Street");
+MODULE_DESCRIPTION("PXA2xx SSP SPI Controller core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index 93e1e471e1c6..a470d3d634d3 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -14,6 +14,7 @@
#include <linux/pxa2xx_ssp.h>
+struct device;
struct gpio_desc;
/*
@@ -131,4 +132,9 @@ extern void pxa2xx_spi_dma_stop(struct driver_data *drv_data);
extern int pxa2xx_spi_dma_setup(struct driver_data *drv_data);
extern void pxa2xx_spi_dma_release(struct driver_data *drv_data);
+int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp);
+void pxa2xx_spi_remove(struct device *dev);
+
+extern const struct dev_pm_ops pxa2xx_spi_pm_ops;
+
#endif /* SPI_PXA2XX_H */
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
index 2af63040ac6e..1a2f9cd92b3c 100644
--- a/drivers/spi/spi-qup.c
+++ b/drivers/spi/spi-qup.c
@@ -5,6 +5,8 @@
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
#include <linux/err.h>
#include <linux/interconnect.h>
#include <linux/interrupt.h>
@@ -16,8 +18,7 @@
#include <linux/pm_opp.h>
#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
-#include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
+#include "internals.h"
#define QUP_CONFIG 0x0000
#define QUP_STATE 0x0004
@@ -709,9 +710,7 @@ static int spi_qup_io_prep(struct spi_device *spi, struct spi_transfer *xfer)
if (controller->n_words <= (controller->in_fifo_sz / sizeof(u32)))
controller->mode = QUP_IO_M_MODE_FIFO;
- else if (spi->controller->can_dma &&
- spi->controller->can_dma(spi->controller, spi, xfer) &&
- spi->controller->cur_msg_mapped)
+ else if (spi_xfer_is_dma_mapped(spi->controller, spi, xfer))
controller->mode = QUP_IO_M_MODE_BAM;
else
controller->mode = QUP_IO_M_MODE_BLOCK;
@@ -1369,5 +1368,6 @@ static struct platform_driver spi_qup_driver = {
};
module_platform_driver(spi_qup_driver);
+MODULE_DESCRIPTION("Qualcomm SPI controller with QUP interface");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:spi_qup");
diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c
index e11146932828..d3f07fd719bd 100644
--- a/drivers/spi/spi-rpc-if.c
+++ b/drivers/spi/spi-rpc-if.c
@@ -95,16 +95,16 @@ static int rpcif_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
spi_controller_get_devdata(desc->mem->spi->controller);
if (desc->info.offset + desc->info.length > U32_MAX)
- return -ENOTSUPP;
+ return -EINVAL;
if (!rpcif_spi_mem_supports_op(desc->mem, &desc->info.op_tmpl))
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
- if (!rpc->dirmap && desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN)
- return -ENOTSUPP;
+ if (!rpc->dirmap)
+ return -EOPNOTSUPP;
- if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT)
- return -ENOTSUPP;
+ if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
+ return -EOPNOTSUPP;
return 0;
}
diff --git a/drivers/spi/spi-wpcm-fiu.c b/drivers/spi/spi-wpcm-fiu.c
index 6b16a22cc3a4..886d6d7771d4 100644
--- a/drivers/spi/spi-wpcm-fiu.c
+++ b/drivers/spi/spi-wpcm-fiu.c
@@ -378,7 +378,7 @@ static int wpcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc)
int cs = spi_get_chipselect(desc->mem->spi, 0);
if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
/*
* Unfortunately, FIU only supports a 16 MiB direct mapping window (per
@@ -387,11 +387,11 @@ static int wpcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc)
* flashes that are bigger than 16 MiB.
*/
if (desc->info.offset + desc->info.length > MAX_MEMORY_SIZE_PER_CS)
- return -ENOTSUPP;
+ return -EINVAL;
/* Don't read past the memory window */
if (cs * MAX_MEMORY_SIZE_PER_CS + desc->info.offset + desc->info.length > fiu->memory_size)
- return -ENOTSUPP;
+ return -EINVAL;
return 0;
}
diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c
index 63354dd3110f..846f00e23b71 100644
--- a/drivers/spi/spi-xcomm.c
+++ b/drivers/spi/spi-xcomm.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/i2c.h>
+#include <linux/gpio/driver.h>
#include <linux/spi/spi.h>
#include <asm/unaligned.h>
@@ -26,24 +27,63 @@
#define SPI_XCOMM_CMD_UPDATE_CONFIG 0x03
#define SPI_XCOMM_CMD_WRITE 0x04
+#define SPI_XCOMM_CMD_GPIO_SET 0x05
#define SPI_XCOMM_CLOCK 48000000
struct spi_xcomm {
struct i2c_client *i2c;
- uint16_t settings;
- uint16_t chipselect;
+ struct gpio_chip gc;
+
+ u16 settings;
+ u16 chipselect;
unsigned int current_speed;
- uint8_t buf[63];
+ u8 buf[63];
};
+static void spi_xcomm_gpio_set_value(struct gpio_chip *chip,
+ unsigned int offset, int val)
+{
+ struct spi_xcomm *spi_xcomm = gpiochip_get_data(chip);
+ unsigned char buf[2];
+
+ buf[0] = SPI_XCOMM_CMD_GPIO_SET;
+ buf[1] = !!val;
+
+ i2c_master_send(spi_xcomm->i2c, buf, 2);
+}
+
+static int spi_xcomm_gpio_get_direction(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ return GPIO_LINE_DIRECTION_OUT;
+}
+
+static int spi_xcomm_gpio_add(struct spi_xcomm *spi_xcomm)
+{
+ struct device *dev = &spi_xcomm->i2c->dev;
+
+ if (!IS_ENABLED(CONFIG_GPIOLIB))
+ return 0;
+
+ spi_xcomm->gc.get_direction = spi_xcomm_gpio_get_direction;
+ spi_xcomm->gc.set = spi_xcomm_gpio_set_value;
+ spi_xcomm->gc.can_sleep = 1;
+ spi_xcomm->gc.base = -1;
+ spi_xcomm->gc.ngpio = 1;
+ spi_xcomm->gc.label = spi_xcomm->i2c->name;
+ spi_xcomm->gc.owner = THIS_MODULE;
+
+ return devm_gpiochip_add_data(dev, &spi_xcomm->gc, spi_xcomm);
+}
+
static int spi_xcomm_sync_config(struct spi_xcomm *spi_xcomm, unsigned int len)
{
- uint16_t settings;
- uint8_t *buf = spi_xcomm->buf;
+ u16 settings;
+ u8 *buf = spi_xcomm->buf;
settings = spi_xcomm->settings;
settings |= len << SPI_XCOMM_SETTINGS_LEN_OFFSET;
@@ -56,10 +96,10 @@ static int spi_xcomm_sync_config(struct spi_xcomm *spi_xcomm, unsigned int len)
}
static void spi_xcomm_chipselect(struct spi_xcomm *spi_xcomm,
- struct spi_device *spi, int is_active)
+ struct spi_device *spi, int is_active)
{
unsigned long cs = spi_get_chipselect(spi, 0);
- uint16_t chipselect = spi_xcomm->chipselect;
+ u16 chipselect = spi_xcomm->chipselect;
if (is_active)
chipselect |= BIT(cs);
@@ -70,7 +110,8 @@ static void spi_xcomm_chipselect(struct spi_xcomm *spi_xcomm,
}
static int spi_xcomm_setup_transfer(struct spi_xcomm *spi_xcomm,
- struct spi_device *spi, struct spi_transfer *t, unsigned int *settings)
+ struct spi_device *spi, struct spi_transfer *t,
+ unsigned int *settings)
{
if (t->len > 62)
return -EINVAL;
@@ -108,7 +149,7 @@ static int spi_xcomm_setup_transfer(struct spi_xcomm *spi_xcomm,
}
static int spi_xcomm_txrx_bufs(struct spi_xcomm *spi_xcomm,
- struct spi_device *spi, struct spi_transfer *t)
+ struct spi_device *spi, struct spi_transfer *t)
{
int ret;
@@ -119,13 +160,13 @@ static int spi_xcomm_txrx_bufs(struct spi_xcomm *spi_xcomm,
ret = i2c_master_send(spi_xcomm->i2c, spi_xcomm->buf, t->len + 1);
if (ret < 0)
return ret;
- else if (ret != t->len + 1)
+ if (ret != t->len + 1)
return -EIO;
} else if (t->rx_buf) {
ret = i2c_master_recv(spi_xcomm->i2c, t->rx_buf, t->len);
if (ret < 0)
return ret;
- else if (ret != t->len)
+ if (ret != t->len)
return -EIO;
}
@@ -133,12 +174,12 @@ static int spi_xcomm_txrx_bufs(struct spi_xcomm *spi_xcomm,
}
static int spi_xcomm_transfer_one(struct spi_controller *host,
- struct spi_message *msg)
+ struct spi_message *msg)
{
struct spi_xcomm *spi_xcomm = spi_controller_get_devdata(host);
unsigned int settings = spi_xcomm->settings;
struct spi_device *spi = msg->spi;
- unsigned cs_change = 0;
+ unsigned int cs_change = 0;
struct spi_transfer *t;
bool is_first = true;
int status = 0;
@@ -147,7 +188,6 @@ static int spi_xcomm_transfer_one(struct spi_controller *host,
spi_xcomm_chipselect(spi_xcomm, spi, true);
list_for_each_entry(t, &msg->transfers, transfer_list) {
-
if (!t->tx_buf && !t->rx_buf && t->len) {
status = -EINVAL;
break;
@@ -208,7 +248,7 @@ static int spi_xcomm_probe(struct i2c_client *i2c)
struct spi_controller *host;
int ret;
- host = spi_alloc_host(&i2c->dev, sizeof(*spi_xcomm));
+ host = devm_spi_alloc_host(&i2c->dev, sizeof(*spi_xcomm));
if (!host)
return -ENOMEM;
@@ -221,13 +261,12 @@ static int spi_xcomm_probe(struct i2c_client *i2c)
host->flags = SPI_CONTROLLER_HALF_DUPLEX;
host->transfer_one_message = spi_xcomm_transfer_one;
host->dev.of_node = i2c->dev.of_node;
- i2c_set_clientdata(i2c, host);
ret = devm_spi_register_controller(&i2c->dev, host);
if (ret < 0)
- spi_controller_put(host);
+ return ret;
- return ret;
+ return spi_xcomm_gpio_add(spi_xcomm);
}
static const struct i2c_device_id spi_xcomm_ids[] = {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index fc13fa192189..d4da5464dbd0 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1222,11 +1222,6 @@ void spi_unmap_buf(struct spi_controller *ctlr, struct device *dev,
spi_unmap_buf_attrs(ctlr, dev, sgt, dir, 0);
}
-/* Dummy SG for unidirect transfers */
-static struct scatterlist dummy_sg = {
- .page_link = SG_END,
-};
-
static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
{
struct device *tx_dev, *rx_dev;
@@ -1265,8 +1260,8 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
attrs);
if (ret != 0)
return ret;
- } else {
- xfer->tx_sg.sgl = &dummy_sg;
+
+ xfer->tx_sg_mapped = true;
}
if (xfer->rx_buf != NULL) {
@@ -1280,8 +1275,8 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
return ret;
}
- } else {
- xfer->rx_sg.sgl = &dummy_sg;
+
+ xfer->rx_sg_mapped = true;
}
}
/* No transfer has been mapped, bail out with success */
@@ -1290,7 +1285,6 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
ctlr->cur_rx_dma_dev = rx_dev;
ctlr->cur_tx_dma_dev = tx_dev;
- ctlr->cur_msg_mapped = true;
return 0;
}
@@ -1301,57 +1295,46 @@ static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg)
struct device *tx_dev = ctlr->cur_tx_dma_dev;
struct spi_transfer *xfer;
- if (!ctlr->cur_msg_mapped || !ctlr->can_dma)
- return 0;
-
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
/* The sync has already been done after each transfer. */
unsigned long attrs = DMA_ATTR_SKIP_CPU_SYNC;
- if (!ctlr->can_dma(ctlr, msg->spi, xfer))
- continue;
+ if (xfer->rx_sg_mapped)
+ spi_unmap_buf_attrs(ctlr, rx_dev, &xfer->rx_sg,
+ DMA_FROM_DEVICE, attrs);
+ xfer->rx_sg_mapped = false;
- spi_unmap_buf_attrs(ctlr, rx_dev, &xfer->rx_sg,
- DMA_FROM_DEVICE, attrs);
- spi_unmap_buf_attrs(ctlr, tx_dev, &xfer->tx_sg,
- DMA_TO_DEVICE, attrs);
+ if (xfer->tx_sg_mapped)
+ spi_unmap_buf_attrs(ctlr, tx_dev, &xfer->tx_sg,
+ DMA_TO_DEVICE, attrs);
+ xfer->tx_sg_mapped = false;
}
- ctlr->cur_msg_mapped = false;
-
return 0;
}
-static void spi_dma_sync_for_device(struct spi_controller *ctlr, struct spi_message *msg,
+static void spi_dma_sync_for_device(struct spi_controller *ctlr,
struct spi_transfer *xfer)
{
struct device *rx_dev = ctlr->cur_rx_dma_dev;
struct device *tx_dev = ctlr->cur_tx_dma_dev;
- if (!ctlr->cur_msg_mapped)
- return;
-
- if (!ctlr->can_dma(ctlr, msg->spi, xfer))
- return;
-
- dma_sync_sgtable_for_device(tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
- dma_sync_sgtable_for_device(rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
+ if (xfer->tx_sg_mapped)
+ dma_sync_sgtable_for_device(tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
+ if (xfer->rx_sg_mapped)
+ dma_sync_sgtable_for_device(rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
}
-static void spi_dma_sync_for_cpu(struct spi_controller *ctlr, struct spi_message *msg,
+static void spi_dma_sync_for_cpu(struct spi_controller *ctlr,
struct spi_transfer *xfer)
{
struct device *rx_dev = ctlr->cur_rx_dma_dev;
struct device *tx_dev = ctlr->cur_tx_dma_dev;
- if (!ctlr->cur_msg_mapped)
- return;
-
- if (!ctlr->can_dma(ctlr, msg->spi, xfer))
- return;
-
- dma_sync_sgtable_for_cpu(rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
- dma_sync_sgtable_for_cpu(tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
+ if (xfer->rx_sg_mapped)
+ dma_sync_sgtable_for_cpu(rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
+ if (xfer->tx_sg_mapped)
+ dma_sync_sgtable_for_cpu(tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
}
#else /* !CONFIG_HAS_DMA */
static inline int __spi_map_msg(struct spi_controller *ctlr,
@@ -1367,13 +1350,11 @@ static inline int __spi_unmap_msg(struct spi_controller *ctlr,
}
static void spi_dma_sync_for_device(struct spi_controller *ctrl,
- struct spi_message *msg,
struct spi_transfer *xfer)
{
}
static void spi_dma_sync_for_cpu(struct spi_controller *ctrl,
- struct spi_message *msg,
struct spi_transfer *xfer)
{
}
@@ -1645,13 +1626,13 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
reinit_completion(&ctlr->xfer_completion);
fallback_pio:
- spi_dma_sync_for_device(ctlr, msg, xfer);
+ spi_dma_sync_for_device(ctlr, xfer);
ret = ctlr->transfer_one(ctlr, msg->spi, xfer);
if (ret < 0) {
- spi_dma_sync_for_cpu(ctlr, msg, xfer);
+ spi_dma_sync_for_cpu(ctlr, xfer);
- if (ctlr->cur_msg_mapped &&
- (xfer->error & SPI_TRANS_FAIL_NO_START)) {
+ if ((xfer->tx_sg_mapped || xfer->rx_sg_mapped) &&
+ (xfer->error & SPI_TRANS_FAIL_NO_START)) {
__spi_unmap_msg(ctlr, msg);
ctlr->fallback = true;
xfer->error &= ~SPI_TRANS_FAIL_NO_START;
@@ -1673,7 +1654,7 @@ fallback_pio:
msg->status = ret;
}
- spi_dma_sync_for_cpu(ctlr, msg, xfer);
+ spi_dma_sync_for_cpu(ctlr, xfer);
} else {
if (xfer->len)
dev_err(&msg->spi->dev,
@@ -2151,7 +2132,8 @@ static void __spi_unoptimize_message(struct spi_message *msg)
*/
static void spi_maybe_unoptimize_message(struct spi_message *msg)
{
- if (!msg->pre_optimized && msg->optimized)
+ if (!msg->pre_optimized && msg->optimized &&
+ !msg->spi->controller->defer_optimize_message)
__spi_unoptimize_message(msg);
}
@@ -2230,11 +2212,8 @@ static int spi_start_queue(struct spi_controller *ctlr)
static int spi_stop_queue(struct spi_controller *ctlr)
{
+ unsigned int limit = 500;
unsigned long flags;
- unsigned limit = 500;
- int ret = 0;
-
- spin_lock_irqsave(&ctlr->queue_lock, flags);
/*
* This is a bit lame, but is optimized for the common execution path.
@@ -2242,20 +2221,18 @@ static int spi_stop_queue(struct spi_controller *ctlr)
* execution path (pump_messages) would be required to call wake_up or
* friends on every SPI message. Do this instead.
*/
- while ((!list_empty(&ctlr->queue) || ctlr->busy) && limit--) {
+ do {
+ spin_lock_irqsave(&ctlr->queue_lock, flags);
+ if (list_empty(&ctlr->queue) && !ctlr->busy) {
+ ctlr->running = false;
+ spin_unlock_irqrestore(&ctlr->queue_lock, flags);
+ return 0;
+ }
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
usleep_range(10000, 11000);
- spin_lock_irqsave(&ctlr->queue_lock, flags);
- }
-
- if (!list_empty(&ctlr->queue) || ctlr->busy)
- ret = -EBUSY;
- else
- ctlr->running = false;
+ } while (--limit);
- spin_unlock_irqrestore(&ctlr->queue_lock, flags);
-
- return ret;
+ return -EBUSY;
}
static int spi_destroy_queue(struct spi_controller *ctlr)
@@ -2594,7 +2571,7 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi,
{
struct spi_controller *ctlr = spi->controller;
struct spi_device *ancillary;
- int rc = 0;
+ int rc;
/* Alloc an spi_device */
ancillary = spi_alloc_device(ctlr);
@@ -2740,7 +2717,7 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
return -ENODEV;
if (ctlr) {
- if (ACPI_HANDLE(ctlr->dev.parent) != parent_handle)
+ if (!device_match_acpi_handle(ctlr->dev.parent, parent_handle))
return -ENODEV;
} else {
struct acpi_device *adev;
@@ -2839,7 +2816,7 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
if (!lookup.max_speed_hz &&
ACPI_SUCCESS(acpi_get_parent(adev->handle, &parent_handle)) &&
- ACPI_HANDLE(lookup.ctlr->dev.parent) == parent_handle) {
+ device_match_acpi_handle(lookup.ctlr->dev.parent, parent_handle)) {
/* Apple does not use _CRS but nested devices for SPI slaves */
acpi_spi_parse_apple_properties(adev, &lookup);
}
@@ -3925,7 +3902,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
int spi_setup(struct spi_device *spi)
{
unsigned bad_bits, ugly_bits;
- int status = 0;
+ int status;
/*
* Check mode to prevent that any two of DUAL, QUAD and NO_MOSI/MISO
@@ -4294,6 +4271,11 @@ static int __spi_optimize_message(struct spi_device *spi,
static int spi_maybe_optimize_message(struct spi_device *spi,
struct spi_message *msg)
{
+ if (spi->controller->defer_optimize_message) {
+ msg->spi = spi;
+ return 0;
+ }
+
if (msg->pre_optimized)
return 0;
@@ -4324,6 +4306,13 @@ int spi_optimize_message(struct spi_device *spi, struct spi_message *msg)
{
int ret;
+ /*
+ * Pre-optimization is not supported and optimization is deferred e.g.
+ * when using spi-mux.
+ */
+ if (spi->controller->defer_optimize_message)
+ return 0;
+
ret = __spi_optimize_message(spi, msg);
if (ret)
return ret;
@@ -4350,6 +4339,9 @@ EXPORT_SYMBOL_GPL(spi_optimize_message);
*/
void spi_unoptimize_message(struct spi_message *msg)
{
+ if (msg->spi->controller->defer_optimize_message)
+ return;
+
__spi_unoptimize_message(msg);
msg->pre_optimized = false;
}
@@ -4382,6 +4374,34 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
return ctlr->transfer(spi, message);
}
+static void devm_spi_unoptimize_message(void *msg)
+{
+ spi_unoptimize_message(msg);
+}
+
+/**
+ * devm_spi_optimize_message - managed version of spi_optimize_message()
+ * @dev: the device that manages @msg (usually @spi->dev)
+ * @spi: the device that will be used for the message
+ * @msg: the message to optimize
+ * Return: zero on success, else a negative error code
+ *
+ * spi_unoptimize_message() will automatically be called when the device is
+ * removed.
+ */
+int devm_spi_optimize_message(struct device *dev, struct spi_device *spi,
+ struct spi_message *msg)
+{
+ int ret;
+
+ ret = spi_optimize_message(spi, msg);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dev, devm_spi_unoptimize_message, msg);
+}
+EXPORT_SYMBOL_GPL(devm_spi_optimize_message);
+
/**
* spi_async - asynchronous SPI transfer
* @spi: device with which data will be exchanged
@@ -4432,8 +4452,6 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags);
- spi_maybe_unoptimize_message(message);
-
return ret;
}
EXPORT_SYMBOL_GPL(spi_async);
diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c
index 2a115a8fc263..5217aacfcf54 100644
--- a/drivers/staging/greybus/gpio.c
+++ b/drivers/staging/greybus/gpio.c
@@ -579,7 +579,7 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev,
if (ret)
goto exit_line_free;
- ret = gpiochip_add(gpio);
+ ret = gpiochip_add_data(gpio, NULL);
if (ret) {
dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret);
goto exit_line_free;
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 7f6ca8177845..a3e09adc4e76 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -148,35 +148,38 @@ static int iblock_configure_device(struct se_device *dev)
dev->dev_attrib.is_nonrot = 1;
bi = bdev_get_integrity(bd);
- if (bi) {
- struct bio_set *bs = &ib_dev->ibd_bio_set;
-
- if (!strcmp(bi->profile->name, "T10-DIF-TYPE3-IP") ||
- !strcmp(bi->profile->name, "T10-DIF-TYPE1-IP")) {
- pr_err("IBLOCK export of blk_integrity: %s not"
- " supported\n", bi->profile->name);
- ret = -ENOSYS;
- goto out_blkdev_put;
- }
+ if (!bi)
+ return 0;
- if (!strcmp(bi->profile->name, "T10-DIF-TYPE3-CRC")) {
- dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE3_PROT;
- } else if (!strcmp(bi->profile->name, "T10-DIF-TYPE1-CRC")) {
+ switch (bi->csum_type) {
+ case BLK_INTEGRITY_CSUM_IP:
+ pr_err("IBLOCK export of blk_integrity: %s not supported\n",
+ blk_integrity_profile_name(bi));
+ ret = -ENOSYS;
+ goto out_blkdev_put;
+ case BLK_INTEGRITY_CSUM_CRC:
+ if (bi->flags & BLK_INTEGRITY_REF_TAG)
dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE1_PROT;
- }
+ else
+ dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE3_PROT;
+ break;
+ default:
+ break;
+ }
- if (dev->dev_attrib.pi_prot_type) {
- if (bioset_integrity_create(bs, IBLOCK_BIO_POOL_SIZE) < 0) {
- pr_err("Unable to allocate bioset for PI\n");
- ret = -ENOMEM;
- goto out_blkdev_put;
- }
- pr_debug("IBLOCK setup BIP bs->bio_integrity_pool: %p\n",
- &bs->bio_integrity_pool);
+ if (dev->dev_attrib.pi_prot_type) {
+ struct bio_set *bs = &ib_dev->ibd_bio_set;
+
+ if (bioset_integrity_create(bs, IBLOCK_BIO_POOL_SIZE) < 0) {
+ pr_err("Unable to allocate bioset for PI\n");
+ ret = -ENOMEM;
+ goto out_blkdev_put;
}
- dev->dev_attrib.hw_pi_prot_type = dev->dev_attrib.pi_prot_type;
+ pr_debug("IBLOCK setup BIP bs->bio_integrity_pool: %p\n",
+ &bs->bio_integrity_pool);
}
+ dev->dev_attrib.hw_pi_prot_type = dev->dev_attrib.pi_prot_type;
return 0;
out_blkdev_put:
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 3235e1c719e8..3e73efa51bba 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -660,7 +660,9 @@ static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev,
const struct ffa_ops *ops)
{
const struct ffa_msg_ops *msg_ops = ops->msg_ops;
- struct ffa_send_direct_data data = { OPTEE_FFA_GET_API_VERSION };
+ struct ffa_send_direct_data data = {
+ .data0 = OPTEE_FFA_GET_API_VERSION,
+ };
int rc;
msg_ops->mode_32bit_set(ffa_dev);
@@ -677,7 +679,9 @@ static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev,
return false;
}
- data = (struct ffa_send_direct_data){ OPTEE_FFA_GET_OS_VERSION };
+ data = (struct ffa_send_direct_data){
+ .data0 = OPTEE_FFA_GET_OS_VERSION,
+ };
rc = msg_ops->sync_send_receive(ffa_dev, &data);
if (rc) {
pr_err("Unexpected error %d\n", rc);
@@ -698,7 +702,9 @@ static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev,
unsigned int *rpc_param_count,
unsigned int *max_notif_value)
{
- struct ffa_send_direct_data data = { OPTEE_FFA_EXCHANGE_CAPABILITIES };
+ struct ffa_send_direct_data data = {
+ .data0 = OPTEE_FFA_EXCHANGE_CAPABILITIES,
+ };
int rc;
rc = ops->msg_ops->sync_send_receive(ffa_dev, &data);
diff --git a/drivers/tee/optee/notif.c b/drivers/tee/optee/notif.c
index 0d7878e770cd..1970880c796f 100644
--- a/drivers/tee/optee/notif.c
+++ b/drivers/tee/optee/notif.c
@@ -29,7 +29,7 @@ static bool have_key(struct optee *optee, u_int key)
return false;
}
-int optee_notif_wait(struct optee *optee, u_int key)
+int optee_notif_wait(struct optee *optee, u_int key, u32 timeout)
{
unsigned long flags;
struct notif_entry *entry;
@@ -70,7 +70,12 @@ int optee_notif_wait(struct optee *optee, u_int key)
* Unlock temporarily and wait for completion.
*/
spin_unlock_irqrestore(&optee->notif.lock, flags);
- wait_for_completion(&entry->c);
+ if (timeout != 0) {
+ if (!wait_for_completion_timeout(&entry->c, timeout))
+ rc = -ETIMEDOUT;
+ } else {
+ wait_for_completion(&entry->c);
+ }
spin_lock_irqsave(&optee->notif.lock, flags);
list_del(&entry->link);
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index 429cc20be5cc..424898cdc4e9 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -26,6 +26,9 @@
#define TEEC_ERROR_BUSY 0xFFFF000D
#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
+/* API Return Codes are from the GP TEE Internal Core API Specification */
+#define TEE_ERROR_TIMEOUT 0xFFFF3001
+
#define TEEC_ORIGIN_COMMS 0x00000002
/*
@@ -252,7 +255,7 @@ struct optee_call_ctx {
int optee_notif_init(struct optee *optee, u_int max_key);
void optee_notif_uninit(struct optee *optee);
-int optee_notif_wait(struct optee *optee, u_int key);
+int optee_notif_wait(struct optee *optee, u_int key, u32 timeout);
int optee_notif_send(struct optee *optee, u_int key);
u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
diff --git a/drivers/tee/optee/optee_rpc_cmd.h b/drivers/tee/optee/optee_rpc_cmd.h
index f3f06e0994a7..4576751b490c 100644
--- a/drivers/tee/optee/optee_rpc_cmd.h
+++ b/drivers/tee/optee/optee_rpc_cmd.h
@@ -41,6 +41,7 @@
* Waiting on notification
* [in] value[0].a OPTEE_RPC_NOTIFICATION_WAIT
* [in] value[0].b notification value
+ * [in] value[0].c timeout in milliseconds or 0 if no timeout
*
* Sending a synchronous notification
* [in] value[0].a OPTEE_RPC_NOTIFICATION_SEND
diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
index f086812f1179..5de4504665be 100644
--- a/drivers/tee/optee/rpc.c
+++ b/drivers/tee/optee/rpc.c
@@ -130,6 +130,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
static void handle_rpc_func_cmd_wq(struct optee *optee,
struct optee_msg_arg *arg)
{
+ int rc = 0;
+
if (arg->num_params != 1)
goto bad;
@@ -139,7 +141,8 @@ static void handle_rpc_func_cmd_wq(struct optee *optee,
switch (arg->params[0].u.value.a) {
case OPTEE_RPC_NOTIFICATION_WAIT:
- if (optee_notif_wait(optee, arg->params[0].u.value.b))
+ rc = optee_notif_wait(optee, arg->params[0].u.value.b, arg->params[0].u.value.c);
+ if (rc)
goto bad;
break;
case OPTEE_RPC_NOTIFICATION_SEND:
@@ -153,7 +156,10 @@ static void handle_rpc_func_cmd_wq(struct optee *optee,
arg->ret = TEEC_SUCCESS;
return;
bad:
- arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ if (rc == -ETIMEDOUT)
+ arg->ret = TEE_ERROR_TIMEOUT;
+ else
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
}
static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c
index 45f04a25255a..1b2345a697c5 100644
--- a/drivers/thermal/gov_power_allocator.c
+++ b/drivers/thermal/gov_power_allocator.c
@@ -759,6 +759,9 @@ static void power_allocator_manage(struct thermal_zone_device *tz)
return;
}
+ if (!params->trip_max)
+ return;
+
allocate_power(tz, params->trip_max->temperature);
params->update_cdevs = true;
}
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 1b0ab2790860..ecc748d15eb7 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -300,6 +300,8 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)
thermal_zone_device_set_polling(tz, tz->passive_delay_jiffies);
else if (tz->polling_delay_jiffies)
thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies);
+ else if (tz->temperature == THERMAL_TEMP_INVALID)
+ thermal_zone_device_set_polling(tz, msecs_to_jiffies(THERMAL_RECHECK_DELAY_MS));
}
static struct thermal_governor *thermal_get_tz_governor(struct thermal_zone_device *tz)
@@ -482,16 +484,14 @@ static void thermal_trip_crossed(struct thermal_zone_device *tz,
thermal_governor_trip_crossed(governor, tz, trip, crossed_up);
}
-static int thermal_trip_notify_cmp(void *ascending, const struct list_head *a,
+static int thermal_trip_notify_cmp(void *not_used, const struct list_head *a,
const struct list_head *b)
{
struct thermal_trip_desc *tda = container_of(a, struct thermal_trip_desc,
notify_list_node);
struct thermal_trip_desc *tdb = container_of(b, struct thermal_trip_desc,
notify_list_node);
- int ret = tdb->notify_temp - tda->notify_temp;
-
- return ascending ? ret : -ret;
+ return tda->notify_temp - tdb->notify_temp;
}
void __thermal_zone_device_update(struct thermal_zone_device *tz,
@@ -511,7 +511,7 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
update_temperature(tz);
if (tz->temperature == THERMAL_TEMP_INVALID)
- return;
+ goto monitor;
__thermal_zone_set_trips(tz);
@@ -520,12 +520,12 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
for_each_trip_desc(tz, td)
handle_thermal_trip(tz, td, &way_up_list, &way_down_list);
- list_sort(&way_up_list, &way_up_list, thermal_trip_notify_cmp);
+ list_sort(NULL, &way_up_list, thermal_trip_notify_cmp);
list_for_each_entry(td, &way_up_list, notify_list_node)
thermal_trip_crossed(tz, &td->trip, governor, true);
list_sort(NULL, &way_down_list, thermal_trip_notify_cmp);
- list_for_each_entry(td, &way_down_list, notify_list_node)
+ list_for_each_entry_reverse(td, &way_down_list, notify_list_node)
thermal_trip_crossed(tz, &td->trip, governor, false);
if (governor->manage)
@@ -533,6 +533,7 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
thermal_debug_update_trip_stats(tz);
+monitor:
monitor_thermal_zone(tz);
}
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 66f67e54e0c8..94eeb4011a48 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -133,6 +133,12 @@ struct thermal_zone_device {
struct thermal_trip_desc trips[] __counted_by(num_trips);
};
+/*
+ * Default delay after a failing thermal zone temperature check before
+ * attempting to check it again.
+ */
+#define THERMAL_RECHECK_DELAY_MS 250
+
/* Default Thermal Governor */
#if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
#define DEFAULT_THERMAL_GOVERNOR "step_wise"
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index ddac0a13cf84..1af9aed99c65 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -672,7 +672,8 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
* https://www.ti.com/lit/pdf/sprz536
*/
if (priv->habit & UART_RX_TIMEOUT_QUIRK &&
- (iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT) {
+ (iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT &&
+ serial_port_in(port, UART_OMAP_RX_LVL) == 0) {
unsigned char efr2, timeout_h, timeout_l;
efr2 = serial_in(up, UART_OMAP_EFR2);
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index f4f40c9373c2..ff32cd2d2863 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -120,6 +120,7 @@
#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */
#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */
#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */
+#define UFCR_RXTL_MASK 0x3F /* Receiver trigger 6 bits wide */
#define UFCR_DCEDTE (1<<6) /* DCE/DTE mode select */
#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */
#define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7)
@@ -1551,6 +1552,7 @@ static void imx_uart_shutdown(struct uart_port *port)
struct imx_port *sport = (struct imx_port *)port;
unsigned long flags;
u32 ucr1, ucr2, ucr4, uts;
+ int loops;
if (sport->dma_is_enabled) {
dmaengine_terminate_sync(sport->dma_chan_tx);
@@ -1613,6 +1615,56 @@ static void imx_uart_shutdown(struct uart_port *port)
ucr4 &= ~UCR4_TCEN;
imx_uart_writel(sport, ucr4, UCR4);
+ /*
+ * We have to ensure the tx state machine ends up in OFF. This
+ * is especially important for rs485 where we must not leave
+ * the RTS signal high, blocking the bus indefinitely.
+ *
+ * All interrupts are now disabled, so imx_uart_stop_tx() will
+ * no longer be called from imx_uart_transmit_buffer(). It may
+ * still be called via the hrtimers, and if those are in play,
+ * we have to honour the delays.
+ */
+ if (sport->tx_state == WAIT_AFTER_RTS || sport->tx_state == SEND)
+ imx_uart_stop_tx(port);
+
+ /*
+ * In many cases (rs232 mode, or if tx_state was
+ * WAIT_AFTER_RTS, or if tx_state was SEND and there is no
+ * delay_rts_after_send), this will have moved directly to
+ * OFF. In rs485 mode, tx_state might already have been
+ * WAIT_AFTER_SEND and the hrtimer thus already started, or
+ * the above imx_uart_stop_tx() call could have started it. In
+ * those cases, we have to wait for the hrtimer to fire and
+ * complete the transition to OFF.
+ */
+ loops = port->rs485.flags & SER_RS485_ENABLED ?
+ port->rs485.delay_rts_after_send : 0;
+ while (sport->tx_state != OFF && loops--) {
+ uart_port_unlock_irqrestore(&sport->port, flags);
+ msleep(1);
+ uart_port_lock_irqsave(&sport->port, &flags);
+ }
+
+ if (sport->tx_state != OFF) {
+ dev_warn(sport->port.dev, "unexpected tx_state %d\n",
+ sport->tx_state);
+ /*
+ * This machine may be busted, but ensure the RTS
+ * signal is inactive in order not to block other
+ * devices.
+ */
+ if (port->rs485.flags & SER_RS485_ENABLED) {
+ ucr2 = imx_uart_readl(sport, UCR2);
+ if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+ imx_uart_rts_active(sport, &ucr2);
+ else
+ imx_uart_rts_inactive(sport, &ucr2);
+ imx_uart_writel(sport, ucr2, UCR2);
+ }
+ sport->tx_state = OFF;
+ }
+
uart_port_unlock_irqrestore(&sport->port, flags);
clk_disable_unprepare(sport->clk_per);
@@ -1933,7 +1985,7 @@ static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termio
struct serial_rs485 *rs485conf)
{
struct imx_port *sport = (struct imx_port *)port;
- u32 ucr2;
+ u32 ucr2, ufcr;
if (rs485conf->flags & SER_RS485_ENABLED) {
/* Enable receiver if low-active RTS signal is requested */
@@ -1953,7 +2005,10 @@ static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termio
/* Make sure Rx is enabled in case Tx is active with Rx disabled */
if (!(rs485conf->flags & SER_RS485_ENABLED) ||
rs485conf->flags & SER_RS485_RX_DURING_TX) {
- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+ /* If the receiver trigger is 0, set it to a default value */
+ ufcr = imx_uart_readl(sport, UFCR);
+ if ((ufcr & UFCR_RXTL_MASK) == 0)
+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
imx_uart_start_rx(port);
}
diff --git a/drivers/tty/serial/ma35d1_serial.c b/drivers/tty/serial/ma35d1_serial.c
index 19f0a305cc43..3b4206e815fe 100644
--- a/drivers/tty/serial/ma35d1_serial.c
+++ b/drivers/tty/serial/ma35d1_serial.c
@@ -688,12 +688,13 @@ static int ma35d1serial_probe(struct platform_device *pdev)
struct uart_ma35d1_port *up;
int ret = 0;
- if (pdev->dev.of_node) {
- ret = of_alias_get_id(pdev->dev.of_node, "serial");
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", ret);
- return ret;
- }
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ ret = of_alias_get_id(pdev->dev.of_node, "serial");
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", ret);
+ return ret;
}
up = &ma35d1serial_ports[ret];
up->port.line = ret;
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 2bd25afe0d92..69a632fefc41 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -649,15 +649,25 @@ static void qcom_geni_serial_start_tx_dma(struct uart_port *uport)
static void qcom_geni_serial_start_tx_fifo(struct uart_port *uport)
{
+ unsigned char c;
u32 irq_en;
- if (qcom_geni_serial_main_active(uport) ||
- !qcom_geni_serial_tx_empty(uport))
- return;
+ /*
+ * Start a new transfer in case the previous command was cancelled and
+ * left data in the FIFO which may prevent the watermark interrupt
+ * from triggering. Note that the stale data is discarded.
+ */
+ if (!qcom_geni_serial_main_active(uport) &&
+ !qcom_geni_serial_tx_empty(uport)) {
+ if (uart_fifo_out(uport, &c, 1) == 1) {
+ writel(M_CMD_DONE_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
+ qcom_geni_serial_setup_tx(uport, 1);
+ writel(c, uport->membase + SE_GENI_TX_FIFOn);
+ }
+ }
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN;
-
writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG);
writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
}
@@ -665,13 +675,17 @@ static void qcom_geni_serial_start_tx_fifo(struct uart_port *uport)
static void qcom_geni_serial_stop_tx_fifo(struct uart_port *uport)
{
u32 irq_en;
- struct qcom_geni_serial_port *port = to_dev_port(uport);
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
irq_en &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN);
writel(0, uport->membase + SE_GENI_TX_WATERMARK_REG);
writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
- /* Possible stop tx is called multiple times. */
+}
+
+static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport)
+{
+ struct qcom_geni_serial_port *port = to_dev_port(uport);
+
if (!qcom_geni_serial_main_active(uport))
return;
@@ -684,6 +698,8 @@ static void qcom_geni_serial_stop_tx_fifo(struct uart_port *uport)
writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
}
writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
+
+ port->tx_remaining = 0;
}
static void qcom_geni_serial_handle_rx_fifo(struct uart_port *uport, bool drop)
@@ -862,7 +878,7 @@ static void qcom_geni_serial_send_chunk_fifo(struct uart_port *uport,
memset(buf, 0, sizeof(buf));
tx_bytes = min(remaining, BYTES_PER_FIFO_WORD);
- tx_bytes = uart_fifo_out(uport, buf, tx_bytes);
+ uart_fifo_out(uport, buf, tx_bytes);
iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1);
@@ -890,13 +906,17 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport,
else
pending = kfifo_len(&tport->xmit_fifo);
- /* All data has been transmitted and acknowledged as received */
- if (!pending && !status && done) {
+ /* All data has been transmitted or command has been cancelled */
+ if (!pending && done) {
qcom_geni_serial_stop_tx_fifo(uport);
goto out_write_wakeup;
}
- avail = port->tx_fifo_depth - (status & TX_FIFO_WC);
+ if (active)
+ avail = port->tx_fifo_depth - (status & TX_FIFO_WC);
+ else
+ avail = port->tx_fifo_depth;
+
avail *= BYTES_PER_FIFO_WORD;
chunk = min(avail, pending);
@@ -1069,11 +1089,15 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport)
{
disable_irq(uport->irq);
- if (uart_console(uport))
- return;
-
qcom_geni_serial_stop_tx(uport);
qcom_geni_serial_stop_rx(uport);
+
+ qcom_geni_serial_cancel_tx_cmd(uport);
+}
+
+static void qcom_geni_serial_flush_buffer(struct uart_port *uport)
+{
+ qcom_geni_serial_cancel_tx_cmd(uport);
}
static int qcom_geni_serial_port_setup(struct uart_port *uport)
@@ -1532,6 +1556,7 @@ static const struct uart_ops qcom_geni_console_pops = {
.request_port = qcom_geni_serial_request_port,
.config_port = qcom_geni_serial_config_port,
.shutdown = qcom_geni_serial_shutdown,
+ .flush_buffer = qcom_geni_serial_flush_buffer,
.type = qcom_geni_serial_get_type,
.set_mctrl = qcom_geni_serial_set_mctrl,
.get_mctrl = qcom_geni_serial_get_mctrl,
diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index 8944548c30fa..c532416aec22 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -105,16 +105,15 @@ EXPORT_SYMBOL_GPL(ufshcd_mcq_config_mac);
* @hba: per adapter instance
* @req: pointer to the request to be issued
*
- * Return: the hardware queue instance on which the request would
- * be queued.
+ * Return: the hardware queue instance on which the request will be or has
+ * been queued. %NULL if the request has already been freed.
*/
struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba,
struct request *req)
{
- u32 utag = blk_mq_unique_tag(req);
- u32 hwq = blk_mq_unique_tag_to_hwq(utag);
+ struct blk_mq_hw_ctx *hctx = READ_ONCE(req->mq_hctx);
- return &hba->uhq[hwq];
+ return hctx ? &hba->uhq[hctx->queue_num] : NULL;
}
/**
@@ -515,6 +514,8 @@ int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag)
if (!cmd)
return -EINVAL;
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd));
+ if (!hwq)
+ return 0;
} else {
hwq = hba->dev_cmd_queue;
}
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 1b65e6ae4137..702fa1996992 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -5193,17 +5193,19 @@ static int ufshcd_change_queue_depth(struct scsi_device *sdev, int depth)
}
/**
- * ufshcd_slave_configure - adjust SCSI device configurations
+ * ufshcd_device_configure - adjust SCSI device configurations
* @sdev: pointer to SCSI device
+ * @lim: queue limits
*
* Return: 0 (success).
*/
-static int ufshcd_slave_configure(struct scsi_device *sdev)
+static int ufshcd_device_configure(struct scsi_device *sdev,
+ struct queue_limits *lim)
{
struct ufs_hba *hba = shost_priv(sdev->host);
struct request_queue *q = sdev->request_queue;
- blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1);
+ lim->dma_pad_mask = PRDT_DATA_BYTE_COUNT_PAD - 1;
/*
* Block runtime-pm until all consumers are added.
@@ -6456,6 +6458,8 @@ static bool ufshcd_abort_one(struct request *rq, void *priv)
/* Release cmd in MCQ mode if abort succeeds */
if (is_mcq_enabled(hba) && (*ret == 0)) {
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd));
+ if (!hwq)
+ return 0;
spin_lock_irqsave(&hwq->cq_lock, flags);
if (ufshcd_cmd_inflight(lrbp->cmd))
ufshcd_release_scsi_cmd(hba, lrbp);
@@ -8908,7 +8912,7 @@ static const struct scsi_host_template ufshcd_driver_template = {
.queuecommand = ufshcd_queuecommand,
.mq_poll = ufshcd_poll,
.slave_alloc = ufshcd_slave_alloc,
- .slave_configure = ufshcd_slave_configure,
+ .device_configure = ufshcd_device_configure,
.slave_destroy = ufshcd_slave_destroy,
.change_queue_depth = ufshcd_change_queue_depth,
.eh_abort_handler = ufshcd_abort,
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 3362af165ef5..880d52c0949d 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -291,6 +291,20 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
if (ifp->desc.bNumEndpoints >= num_ep)
goto skip_to_next_endpoint_or_interface_descriptor;
+ /* Save a copy of the descriptor and use it instead of the original */
+ endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
+ memcpy(&endpoint->desc, d, n);
+ d = &endpoint->desc;
+
+ /* Clear the reserved bits in bEndpointAddress */
+ i = d->bEndpointAddress &
+ (USB_ENDPOINT_DIR_MASK | USB_ENDPOINT_NUMBER_MASK);
+ if (i != d->bEndpointAddress) {
+ dev_notice(ddev, "config %d interface %d altsetting %d has an endpoint descriptor with address 0x%X, changing to 0x%X\n",
+ cfgno, inum, asnum, d->bEndpointAddress, i);
+ endpoint->desc.bEndpointAddress = i;
+ }
+
/* Check for duplicate endpoint addresses */
if (config_endpoint_is_duplicate(config, inum, asnum, d)) {
dev_notice(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
@@ -308,10 +322,8 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
}
}
- endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
+ /* Accept this endpoint */
++ifp->desc.bNumEndpoints;
-
- memcpy(&endpoint->desc, d, n);
INIT_LIST_HEAD(&endpoint->urb_list);
/*
diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c
index f1a499ee482c..763e4122ed5b 100644
--- a/drivers/usb/core/of.c
+++ b/drivers/usb/core/of.c
@@ -84,9 +84,12 @@ static bool usb_of_has_devices_or_graph(const struct usb_device *hub)
if (of_graph_is_present(np))
return true;
- for_each_child_of_node(np, child)
- if (of_property_present(child, "reg"))
+ for_each_child_of_node(np, child) {
+ if (of_property_present(child, "reg")) {
+ of_node_put(child);
return true;
+ }
+ }
return false;
}
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index b4783574b8e6..13171454f959 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -506,6 +506,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x1b1c, 0x1b38), .driver_info = USB_QUIRK_DELAY_INIT |
USB_QUIRK_DELAY_CTRL_MSG },
+ /* START BP-850k Printer */
+ { USB_DEVICE(0x1bc3, 0x0003), .driver_info = USB_QUIRK_NO_SET_INTF },
+
/* MIDI keyboard WORLDE MINI */
{ USB_DEVICE(0x1c75, 0x0204), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 9ef821ca2fc7..052852f80146 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -54,6 +54,10 @@
#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
#define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e
#define PCI_DEVICE_ID_INTEL_TGL 0x9a15
+#define PCI_DEVICE_ID_INTEL_PTLH 0xe332
+#define PCI_DEVICE_ID_INTEL_PTLH_PCH 0xe37e
+#define PCI_DEVICE_ID_INTEL_PTLU 0xe432
+#define PCI_DEVICE_ID_INTEL_PTLU_PCH 0xe47e
#define PCI_DEVICE_ID_AMD_MR 0x163a
#define PCI_INTEL_BXT_DSM_GUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
@@ -430,6 +434,10 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) },
+ { PCI_DEVICE_DATA(INTEL, PTLH, &dwc3_pci_intel_swnode) },
+ { PCI_DEVICE_DATA(INTEL, PTLH_PCH, &dwc3_pci_intel_swnode) },
+ { PCI_DEVICE_DATA(INTEL, PTLU, &dwc3_pci_intel_swnode) },
+ { PCI_DEVICE_DATA(INTEL, PTLU_PCH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(AMD, NL_USB, &dwc3_pci_amd_swnode) },
{ PCI_DEVICE_DATA(AMD, MR, &dwc3_pci_amd_mr_swnode) },
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index ce3cfa1f36f5..0e7c1e947c0a 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -115,9 +115,12 @@ static int usb_string_copy(const char *s, char **s_copy)
int ret;
char *str;
char *copy = *s_copy;
+
ret = strlen(s);
if (ret > USB_MAX_STRING_LEN)
return -EOVERFLOW;
+ if (ret < 1)
+ return -EINVAL;
if (copy) {
str = copy;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 37eb37b0affa..0a8cf6c17f82 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1125,10 +1125,20 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
xhci_dbg(xhci, "Start the secondary HCD\n");
retval = xhci_run(xhci->shared_hcd);
}
-
+ if (retval)
+ return retval;
+ /*
+ * Resume roothubs unconditionally as PORTSC change bits are not
+ * immediately visible after xHC reset
+ */
hcd->state = HC_STATE_SUSPENDED;
- if (xhci->shared_hcd)
+
+ if (xhci->shared_hcd) {
xhci->shared_hcd->state = HC_STATE_SUSPENDED;
+ usb_hcd_resume_root_hub(xhci->shared_hcd);
+ }
+ usb_hcd_resume_root_hub(hcd);
+
goto done;
}
@@ -1152,7 +1162,6 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
xhci_dbc_resume(xhci);
- done:
if (retval == 0) {
/*
* Resume roothubs only if there are pending events.
@@ -1178,6 +1187,7 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
usb_hcd_resume_root_hub(hcd);
}
}
+done:
/*
* If system is subject to the Quirk, Compliance Mode Timer needs to
* be re-initialized Always after a system resume. Ports are subject
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 8b0308d84270..85697466b147 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1737,6 +1737,49 @@ static void mos7840_port_remove(struct usb_serial_port *port)
kfree(mos7840_port);
}
+static int mos7840_suspend(struct usb_serial *serial, pm_message_t message)
+{
+ struct moschip_port *mos7840_port;
+ struct usb_serial_port *port;
+ int i;
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (!tty_port_initialized(&port->port))
+ continue;
+
+ mos7840_port = usb_get_serial_port_data(port);
+
+ usb_kill_urb(mos7840_port->read_urb);
+ mos7840_port->read_urb_busy = false;
+ }
+
+ return 0;
+}
+
+static int mos7840_resume(struct usb_serial *serial)
+{
+ struct moschip_port *mos7840_port;
+ struct usb_serial_port *port;
+ int res;
+ int i;
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (!tty_port_initialized(&port->port))
+ continue;
+
+ mos7840_port = usb_get_serial_port_data(port);
+
+ mos7840_port->read_urb_busy = true;
+ res = usb_submit_urb(mos7840_port->read_urb, GFP_NOIO);
+ if (res)
+ mos7840_port->read_urb_busy = false;
+ }
+
+ return 0;
+}
+
static struct usb_serial_driver moschip7840_4port_device = {
.driver = {
.owner = THIS_MODULE,
@@ -1764,6 +1807,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
.port_probe = mos7840_port_probe,
.port_remove = mos7840_port_remove,
.read_bulk_callback = mos7840_bulk_in_callback,
+ .suspend = mos7840_suspend,
+ .resume = mos7840_resume,
};
static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 8a5846d4adf6..311040f9b935 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1425,6 +1425,10 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1901, 0xff), /* Telit LN940 (MBIM) */
.driver_info = NCTRL(0) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x3000, 0xff), /* Telit FN912 */
+ .driver_info = RSVD(0) | NCTRL(3) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x3001, 0xff), /* Telit FN912 */
+ .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7010, 0xff), /* Telit LE910-S1 (RNDIS) */
.driver_info = NCTRL(2) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7011, 0xff), /* Telit LE910-S1 (ECM) */
@@ -1433,6 +1437,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(2) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x701b, 0xff), /* Telit LE910R1 (ECM) */
.driver_info = NCTRL(2) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x9000, 0xff), /* Telit generic core-dump device */
+ .driver_info = NCTRL(0) },
{ USB_DEVICE(TELIT_VENDOR_ID, 0x9010), /* Telit SBL FN980 flashing device */
.driver_info = NCTRL(0) | ZLP },
{ USB_DEVICE(TELIT_VENDOR_ID, 0x9200), /* Telit LE910S1 flashing device */
@@ -2224,6 +2230,10 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x7126, 0xff, 0x00, 0x00),
+ .driver_info = NCTRL(2) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x7127, 0xff, 0x00, 0x00),
+ .driver_info = NCTRL(2) | NCTRL(3) | NCTRL(4) },
{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MPL200),
.driver_info = RSVD(1) | RSVD(4) },
@@ -2284,6 +2294,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(3) },
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe0f0, 0xff), /* Foxconn T99W373 MBIM */
.driver_info = RSVD(3) },
+ { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe145, 0xff), /* Foxconn T99W651 RNDIS */
+ .driver_info = RSVD(5) | RSVD(6) },
{ USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */
.driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
{ USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */
@@ -2321,6 +2333,32 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0115, 0xff), /* Rolling RW135-GL (laptop MBIM) */
.driver_info = RSVD(5) },
+ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0802, 0xff), /* Rolling RW350-GL (laptop MBIM) */
+ .driver_info = RSVD(5) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Global */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0101, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WRD for Global SKU */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0101, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0101, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0106, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WRD for China SKU */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0106, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0106, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0111, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for SA */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0111, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0111, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0112, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for EU */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0112, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0112, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0113, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for NA */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0113, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0113, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0115, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for China EDU */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0115, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0115, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Golbal EDU */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 987c7921affa..ba0ce0075b2f 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1260,7 +1260,7 @@ static int vfio_pci_ioctl_get_pci_hot_reset_info(
struct vfio_pci_hot_reset_info hdr;
struct vfio_pci_fill_info fill = {};
bool slot = false;
- int ret, count;
+ int ret, count = 0;
if (copy_from_user(&hdr, arg, minsz))
return -EFAULT;
diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c
index 654290a8e1ba..f714009b9ff7 100644
--- a/drivers/virt/coco/sev-guest/sev-guest.c
+++ b/drivers/virt/coco/sev-guest/sev-guest.c
@@ -2,7 +2,7 @@
/*
* AMD Secure Encrypted Virtualization (SEV) guest driver interface
*
- * Copyright (C) 2021 Advanced Micro Devices, Inc.
+ * Copyright (C) 2021-2024 Advanced Micro Devices, Inc.
*
* Author: Brijesh Singh <[email protected]>
*/
@@ -23,6 +23,7 @@
#include <linux/sockptr.h>
#include <linux/cleanup.h>
#include <linux/uuid.h>
+#include <linux/configfs.h>
#include <uapi/linux/sev-guest.h>
#include <uapi/linux/psp-sev.h>
@@ -38,6 +39,8 @@
#define SNP_REQ_MAX_RETRY_DURATION (60*HZ)
#define SNP_REQ_RETRY_DELAY (2*HZ)
+#define SVSM_MAX_RETRIES 3
+
struct snp_guest_crypto {
struct crypto_aead *tfm;
u8 *iv, *authtag;
@@ -70,8 +73,15 @@ struct snp_guest_dev {
u8 *vmpck;
};
-static u32 vmpck_id;
-module_param(vmpck_id, uint, 0444);
+/*
+ * The VMPCK ID represents the key used by the SNP guest to communicate with the
+ * SEV firmware in the AMD Secure Processor (ASP, aka PSP). By default, the key
+ * used will be the key associated with the VMPL at which the guest is running.
+ * Should the default key be wiped (see snp_disable_vmpck()), this parameter
+ * allows for using one of the remaining VMPCKs.
+ */
+static int vmpck_id = -1;
+module_param(vmpck_id, int, 0444);
MODULE_PARM_DESC(vmpck_id, "The VMPCK ID to use when communicating with the PSP.");
/* Mutex to serialize the shared buffer access and command handling. */
@@ -783,6 +793,143 @@ struct snp_msg_cert_entry {
u32 length;
};
+static int sev_svsm_report_new(struct tsm_report *report, void *data)
+{
+ unsigned int rep_len, man_len, certs_len;
+ struct tsm_desc *desc = &report->desc;
+ struct svsm_attest_call ac = {};
+ unsigned int retry_count;
+ void *rep, *man, *certs;
+ struct svsm_call call;
+ unsigned int size;
+ bool try_again;
+ void *buffer;
+ u64 call_id;
+ int ret;
+
+ /*
+ * Allocate pages for the request:
+ * - Report blob (4K)
+ * - Manifest blob (4K)
+ * - Certificate blob (16K)
+ *
+ * Above addresses must be 4K aligned
+ */
+ rep_len = SZ_4K;
+ man_len = SZ_4K;
+ certs_len = SEV_FW_BLOB_MAX_SIZE;
+
+ guard(mutex)(&snp_cmd_mutex);
+
+ if (guid_is_null(&desc->service_guid)) {
+ call_id = SVSM_ATTEST_CALL(SVSM_ATTEST_SERVICES);
+ } else {
+ export_guid(ac.service_guid, &desc->service_guid);
+ ac.service_manifest_ver = desc->service_manifest_version;
+
+ call_id = SVSM_ATTEST_CALL(SVSM_ATTEST_SINGLE_SERVICE);
+ }
+
+ retry_count = 0;
+
+retry:
+ memset(&call, 0, sizeof(call));
+
+ size = rep_len + man_len + certs_len;
+ buffer = alloc_pages_exact(size, __GFP_ZERO);
+ if (!buffer)
+ return -ENOMEM;
+
+ rep = buffer;
+ ac.report_buf.pa = __pa(rep);
+ ac.report_buf.len = rep_len;
+
+ man = rep + rep_len;
+ ac.manifest_buf.pa = __pa(man);
+ ac.manifest_buf.len = man_len;
+
+ certs = man + man_len;
+ ac.certificates_buf.pa = __pa(certs);
+ ac.certificates_buf.len = certs_len;
+
+ ac.nonce.pa = __pa(desc->inblob);
+ ac.nonce.len = desc->inblob_len;
+
+ ret = snp_issue_svsm_attest_req(call_id, &call, &ac);
+ if (ret) {
+ free_pages_exact(buffer, size);
+
+ switch (call.rax_out) {
+ case SVSM_ERR_INVALID_PARAMETER:
+ try_again = false;
+
+ if (ac.report_buf.len > rep_len) {
+ rep_len = PAGE_ALIGN(ac.report_buf.len);
+ try_again = true;
+ }
+
+ if (ac.manifest_buf.len > man_len) {
+ man_len = PAGE_ALIGN(ac.manifest_buf.len);
+ try_again = true;
+ }
+
+ if (ac.certificates_buf.len > certs_len) {
+ certs_len = PAGE_ALIGN(ac.certificates_buf.len);
+ try_again = true;
+ }
+
+ /* If one of the buffers wasn't large enough, retry the request */
+ if (try_again && retry_count < SVSM_MAX_RETRIES) {
+ retry_count++;
+ goto retry;
+ }
+
+ return -EINVAL;
+ default:
+ pr_err_ratelimited("SVSM attestation request failed (%d / 0x%llx)\n",
+ ret, call.rax_out);
+ return -EINVAL;
+ }
+ }
+
+ /*
+ * Allocate all the blob memory buffers at once so that the cleanup is
+ * done for errors that occur after the first allocation (i.e. before
+ * using no_free_ptr()).
+ */
+ rep_len = ac.report_buf.len;
+ void *rbuf __free(kvfree) = kvzalloc(rep_len, GFP_KERNEL);
+
+ man_len = ac.manifest_buf.len;
+ void *mbuf __free(kvfree) = kvzalloc(man_len, GFP_KERNEL);
+
+ certs_len = ac.certificates_buf.len;
+ void *cbuf __free(kvfree) = certs_len ? kvzalloc(certs_len, GFP_KERNEL) : NULL;
+
+ if (!rbuf || !mbuf || (certs_len && !cbuf)) {
+ free_pages_exact(buffer, size);
+ return -ENOMEM;
+ }
+
+ memcpy(rbuf, rep, rep_len);
+ report->outblob = no_free_ptr(rbuf);
+ report->outblob_len = rep_len;
+
+ memcpy(mbuf, man, man_len);
+ report->manifestblob = no_free_ptr(mbuf);
+ report->manifestblob_len = man_len;
+
+ if (certs_len) {
+ memcpy(cbuf, certs, certs_len);
+ report->auxblob = no_free_ptr(cbuf);
+ report->auxblob_len = certs_len;
+ }
+
+ free_pages_exact(buffer, size);
+
+ return 0;
+}
+
static int sev_report_new(struct tsm_report *report, void *data)
{
struct snp_msg_cert_entry *cert_table;
@@ -797,6 +944,13 @@ static int sev_report_new(struct tsm_report *report, void *data)
if (desc->inblob_len != SNP_REPORT_USER_DATA_SIZE)
return -EINVAL;
+ if (desc->service_provider) {
+ if (strcmp(desc->service_provider, "svsm"))
+ return -EINVAL;
+
+ return sev_svsm_report_new(report, data);
+ }
+
void *buf __free(kvfree) = kvzalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -885,9 +1039,42 @@ static int sev_report_new(struct tsm_report *report, void *data)
return 0;
}
-static const struct tsm_ops sev_tsm_ops = {
+static bool sev_report_attr_visible(int n)
+{
+ switch (n) {
+ case TSM_REPORT_GENERATION:
+ case TSM_REPORT_PROVIDER:
+ case TSM_REPORT_PRIVLEVEL:
+ case TSM_REPORT_PRIVLEVEL_FLOOR:
+ return true;
+ case TSM_REPORT_SERVICE_PROVIDER:
+ case TSM_REPORT_SERVICE_GUID:
+ case TSM_REPORT_SERVICE_MANIFEST_VER:
+ return snp_vmpl;
+ }
+
+ return false;
+}
+
+static bool sev_report_bin_attr_visible(int n)
+{
+ switch (n) {
+ case TSM_REPORT_INBLOB:
+ case TSM_REPORT_OUTBLOB:
+ case TSM_REPORT_AUXBLOB:
+ return true;
+ case TSM_REPORT_MANIFESTBLOB:
+ return snp_vmpl;
+ }
+
+ return false;
+}
+
+static struct tsm_ops sev_tsm_ops = {
.name = KBUILD_MODNAME,
.report_new = sev_report_new,
+ .report_attr_visible = sev_report_attr_visible,
+ .report_bin_attr_visible = sev_report_bin_attr_visible,
};
static void unregister_sev_tsm(void *data)
@@ -923,6 +1110,10 @@ static int __init sev_guest_probe(struct platform_device *pdev)
if (!snp_dev)
goto e_unmap;
+ /* Adjust the default VMPCK key based on the executing VMPL level */
+ if (vmpck_id == -1)
+ vmpck_id = snp_vmpl;
+
ret = -EINVAL;
snp_dev->vmpck = get_vmpck(vmpck_id, secrets, &snp_dev->os_area_msg_seqno);
if (!snp_dev->vmpck) {
@@ -968,7 +1159,10 @@ static int __init sev_guest_probe(struct platform_device *pdev)
snp_dev->input.resp_gpa = __pa(snp_dev->response);
snp_dev->input.data_gpa = __pa(snp_dev->certs_data);
- ret = tsm_register(&sev_tsm_ops, snp_dev, &tsm_report_extra_type);
+ /* Set the privlevel_floor attribute based on the vmpck_id */
+ sev_tsm_ops.privlevel_floor = vmpck_id;
+
+ ret = tsm_register(&sev_tsm_ops, snp_dev);
if (ret)
goto e_free_cert_data;
@@ -1009,8 +1203,13 @@ static void __exit sev_guest_remove(struct platform_device *pdev)
* This driver is meant to be a common SEV guest interface driver and to
* support any SEV guest API. As such, even though it has been introduced
* with the SEV-SNP support, it is named "sev-guest".
+ *
+ * sev_guest_remove() lives in .exit.text. For drivers registered via
+ * module_platform_driver_probe() this is ok because they cannot get unbound
+ * at runtime. So mark the driver struct with __refdata to prevent modpost
+ * triggering a section mismatch warning.
*/
-static struct platform_driver sev_guest_driver = {
+static struct platform_driver sev_guest_driver __refdata = {
.remove_new = __exit_p(sev_guest_remove),
.driver = {
.name = "sev-guest",
diff --git a/drivers/virt/coco/tdx-guest/tdx-guest.c b/drivers/virt/coco/tdx-guest/tdx-guest.c
index 1253bf76b570..2acba56ad42e 100644
--- a/drivers/virt/coco/tdx-guest/tdx-guest.c
+++ b/drivers/virt/coco/tdx-guest/tdx-guest.c
@@ -249,6 +249,28 @@ done:
return ret;
}
+static bool tdx_report_attr_visible(int n)
+{
+ switch (n) {
+ case TSM_REPORT_GENERATION:
+ case TSM_REPORT_PROVIDER:
+ return true;
+ }
+
+ return false;
+}
+
+static bool tdx_report_bin_attr_visible(int n)
+{
+ switch (n) {
+ case TSM_REPORT_INBLOB:
+ case TSM_REPORT_OUTBLOB:
+ return true;
+ }
+
+ return false;
+}
+
static long tdx_guest_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -281,6 +303,8 @@ MODULE_DEVICE_TABLE(x86cpu, tdx_guest_ids);
static const struct tsm_ops tdx_tsm_ops = {
.name = KBUILD_MODNAME,
.report_new = tdx_report_new,
+ .report_attr_visible = tdx_report_attr_visible,
+ .report_bin_attr_visible = tdx_report_bin_attr_visible,
};
static int __init tdx_guest_init(void)
@@ -301,7 +325,7 @@ static int __init tdx_guest_init(void)
goto free_misc;
}
- ret = tsm_register(&tdx_tsm_ops, NULL, NULL);
+ ret = tsm_register(&tdx_tsm_ops, NULL);
if (ret)
goto free_quote;
diff --git a/drivers/virt/coco/tsm.c b/drivers/virt/coco/tsm.c
index d1c2db83a8ca..9432d4e303f1 100644
--- a/drivers/virt/coco/tsm.c
+++ b/drivers/virt/coco/tsm.c
@@ -14,7 +14,6 @@
static struct tsm_provider {
const struct tsm_ops *ops;
- const struct config_item_type *type;
void *data;
} provider;
static DECLARE_RWSEM(tsm_rwsem);
@@ -35,7 +34,7 @@ static DECLARE_RWSEM(tsm_rwsem);
* The attestation report format is TSM provider specific, when / if a standard
* materializes that can be published instead of the vendor layout. Until then
* the 'provider' attribute indicates the format of 'outblob', and optionally
- * 'auxblob'.
+ * 'auxblob' and 'manifestblob'.
*/
struct tsm_report_state {
@@ -48,6 +47,7 @@ struct tsm_report_state {
enum tsm_data_select {
TSM_REPORT,
TSM_CERTS,
+ TSM_MANIFEST,
};
static struct tsm_report *to_tsm_report(struct config_item *cfg)
@@ -119,6 +119,74 @@ static ssize_t tsm_report_privlevel_floor_show(struct config_item *cfg,
}
CONFIGFS_ATTR_RO(tsm_report_, privlevel_floor);
+static ssize_t tsm_report_service_provider_store(struct config_item *cfg,
+ const char *buf, size_t len)
+{
+ struct tsm_report *report = to_tsm_report(cfg);
+ size_t sp_len;
+ char *sp;
+ int rc;
+
+ guard(rwsem_write)(&tsm_rwsem);
+ rc = try_advance_write_generation(report);
+ if (rc)
+ return rc;
+
+ sp_len = (buf[len - 1] != '\n') ? len : len - 1;
+
+ sp = kstrndup(buf, sp_len, GFP_KERNEL);
+ if (!sp)
+ return -ENOMEM;
+ kfree(report->desc.service_provider);
+
+ report->desc.service_provider = sp;
+
+ return len;
+}
+CONFIGFS_ATTR_WO(tsm_report_, service_provider);
+
+static ssize_t tsm_report_service_guid_store(struct config_item *cfg,
+ const char *buf, size_t len)
+{
+ struct tsm_report *report = to_tsm_report(cfg);
+ int rc;
+
+ guard(rwsem_write)(&tsm_rwsem);
+ rc = try_advance_write_generation(report);
+ if (rc)
+ return rc;
+
+ report->desc.service_guid = guid_null;
+
+ rc = guid_parse(buf, &report->desc.service_guid);
+ if (rc)
+ return rc;
+
+ return len;
+}
+CONFIGFS_ATTR_WO(tsm_report_, service_guid);
+
+static ssize_t tsm_report_service_manifest_version_store(struct config_item *cfg,
+ const char *buf, size_t len)
+{
+ struct tsm_report *report = to_tsm_report(cfg);
+ unsigned int val;
+ int rc;
+
+ rc = kstrtouint(buf, 0, &val);
+ if (rc)
+ return rc;
+
+ guard(rwsem_write)(&tsm_rwsem);
+ rc = try_advance_write_generation(report);
+ if (rc)
+ return rc;
+ report->desc.service_manifest_version = val;
+
+ return len;
+}
+CONFIGFS_ATTR_WO(tsm_report_, service_manifest_version);
+
static ssize_t tsm_report_inblob_write(struct config_item *cfg,
const void *buf, size_t count)
{
@@ -163,6 +231,9 @@ static ssize_t __read_report(struct tsm_report *report, void *buf, size_t count,
if (select == TSM_REPORT) {
out = report->outblob;
len = report->outblob_len;
+ } else if (select == TSM_MANIFEST) {
+ out = report->manifestblob;
+ len = report->manifestblob_len;
} else {
out = report->auxblob;
len = report->auxblob_len;
@@ -188,7 +259,7 @@ static ssize_t read_cached_report(struct tsm_report *report, void *buf,
/*
* A given TSM backend always fills in ->outblob regardless of
- * whether the report includes an auxblob or not.
+ * whether the report includes an auxblob/manifestblob or not.
*/
if (!report->outblob ||
state->read_generation != state->write_generation)
@@ -224,8 +295,10 @@ static ssize_t tsm_report_read(struct tsm_report *report, void *buf,
kvfree(report->outblob);
kvfree(report->auxblob);
+ kvfree(report->manifestblob);
report->outblob = NULL;
report->auxblob = NULL;
+ report->manifestblob = NULL;
rc = ops->report_new(report, provider.data);
if (rc < 0)
return rc;
@@ -252,34 +325,31 @@ static ssize_t tsm_report_auxblob_read(struct config_item *cfg, void *buf,
}
CONFIGFS_BIN_ATTR_RO(tsm_report_, auxblob, NULL, TSM_OUTBLOB_MAX);
-#define TSM_DEFAULT_ATTRS() \
- &tsm_report_attr_generation, \
- &tsm_report_attr_provider
+static ssize_t tsm_report_manifestblob_read(struct config_item *cfg, void *buf,
+ size_t count)
+{
+ struct tsm_report *report = to_tsm_report(cfg);
-static struct configfs_attribute *tsm_report_attrs[] = {
- TSM_DEFAULT_ATTRS(),
- NULL,
-};
+ return tsm_report_read(report, buf, count, TSM_MANIFEST);
+}
+CONFIGFS_BIN_ATTR_RO(tsm_report_, manifestblob, NULL, TSM_OUTBLOB_MAX);
-static struct configfs_attribute *tsm_report_extra_attrs[] = {
- TSM_DEFAULT_ATTRS(),
- &tsm_report_attr_privlevel,
- &tsm_report_attr_privlevel_floor,
+static struct configfs_attribute *tsm_report_attrs[] = {
+ [TSM_REPORT_GENERATION] = &tsm_report_attr_generation,
+ [TSM_REPORT_PROVIDER] = &tsm_report_attr_provider,
+ [TSM_REPORT_PRIVLEVEL] = &tsm_report_attr_privlevel,
+ [TSM_REPORT_PRIVLEVEL_FLOOR] = &tsm_report_attr_privlevel_floor,
+ [TSM_REPORT_SERVICE_PROVIDER] = &tsm_report_attr_service_provider,
+ [TSM_REPORT_SERVICE_GUID] = &tsm_report_attr_service_guid,
+ [TSM_REPORT_SERVICE_MANIFEST_VER] = &tsm_report_attr_service_manifest_version,
NULL,
};
-#define TSM_DEFAULT_BIN_ATTRS() \
- &tsm_report_attr_inblob, \
- &tsm_report_attr_outblob
-
static struct configfs_bin_attribute *tsm_report_bin_attrs[] = {
- TSM_DEFAULT_BIN_ATTRS(),
- NULL,
-};
-
-static struct configfs_bin_attribute *tsm_report_bin_extra_attrs[] = {
- TSM_DEFAULT_BIN_ATTRS(),
- &tsm_report_attr_auxblob,
+ [TSM_REPORT_INBLOB] = &tsm_report_attr_inblob,
+ [TSM_REPORT_OUTBLOB] = &tsm_report_attr_outblob,
+ [TSM_REPORT_AUXBLOB] = &tsm_report_attr_auxblob,
+ [TSM_REPORT_MANIFESTBLOB] = &tsm_report_attr_manifestblob,
NULL,
};
@@ -288,8 +358,10 @@ static void tsm_report_item_release(struct config_item *cfg)
struct tsm_report *report = to_tsm_report(cfg);
struct tsm_report_state *state = to_state(report);
+ kvfree(report->manifestblob);
kvfree(report->auxblob);
kvfree(report->outblob);
+ kfree(report->desc.service_provider);
kfree(state);
}
@@ -297,21 +369,44 @@ static struct configfs_item_operations tsm_report_item_ops = {
.release = tsm_report_item_release,
};
-const struct config_item_type tsm_report_default_type = {
- .ct_owner = THIS_MODULE,
- .ct_bin_attrs = tsm_report_bin_attrs,
- .ct_attrs = tsm_report_attrs,
- .ct_item_ops = &tsm_report_item_ops,
+static bool tsm_report_is_visible(struct config_item *item,
+ struct configfs_attribute *attr, int n)
+{
+ guard(rwsem_read)(&tsm_rwsem);
+ if (!provider.ops)
+ return false;
+
+ if (!provider.ops->report_attr_visible)
+ return true;
+
+ return provider.ops->report_attr_visible(n);
+}
+
+static bool tsm_report_is_bin_visible(struct config_item *item,
+ struct configfs_bin_attribute *attr, int n)
+{
+ guard(rwsem_read)(&tsm_rwsem);
+ if (!provider.ops)
+ return false;
+
+ if (!provider.ops->report_bin_attr_visible)
+ return true;
+
+ return provider.ops->report_bin_attr_visible(n);
+}
+
+static struct configfs_group_operations tsm_report_attr_group_ops = {
+ .is_visible = tsm_report_is_visible,
+ .is_bin_visible = tsm_report_is_bin_visible,
};
-EXPORT_SYMBOL_GPL(tsm_report_default_type);
-const struct config_item_type tsm_report_extra_type = {
+static const struct config_item_type tsm_report_type = {
.ct_owner = THIS_MODULE,
- .ct_bin_attrs = tsm_report_bin_extra_attrs,
- .ct_attrs = tsm_report_extra_attrs,
+ .ct_bin_attrs = tsm_report_bin_attrs,
+ .ct_attrs = tsm_report_attrs,
.ct_item_ops = &tsm_report_item_ops,
+ .ct_group_ops = &tsm_report_attr_group_ops,
};
-EXPORT_SYMBOL_GPL(tsm_report_extra_type);
static struct config_item *tsm_report_make_item(struct config_group *group,
const char *name)
@@ -326,7 +421,7 @@ static struct config_item *tsm_report_make_item(struct config_group *group,
if (!state)
return ERR_PTR(-ENOMEM);
- config_item_init_type_name(&state->cfg, name, provider.type);
+ config_item_init_type_name(&state->cfg, name, &tsm_report_type);
return &state->cfg;
}
@@ -353,16 +448,10 @@ static struct configfs_subsystem tsm_configfs = {
.su_mutex = __MUTEX_INITIALIZER(tsm_configfs.su_mutex),
};
-int tsm_register(const struct tsm_ops *ops, void *priv,
- const struct config_item_type *type)
+int tsm_register(const struct tsm_ops *ops, void *priv)
{
const struct tsm_ops *conflict;
- if (!type)
- type = &tsm_report_default_type;
- if (!(type == &tsm_report_default_type || type == &tsm_report_extra_type))
- return -EINVAL;
-
guard(rwsem_write)(&tsm_rwsem);
conflict = provider.ops;
if (conflict) {
@@ -372,7 +461,6 @@ int tsm_register(const struct tsm_ops *ops, void *priv,
provider.ops = ops;
provider.data = priv;
- provider.type = type;
return 0;
}
EXPORT_SYMBOL_GPL(tsm_register);
@@ -384,7 +472,6 @@ int tsm_unregister(const struct tsm_ops *ops)
return -EBUSY;
provider.ops = NULL;
provider.data = NULL;
- provider.type = NULL;
return 0;
}
EXPORT_SYMBOL_GPL(tsm_unregister);
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index 2196474ce6ef..4e23d53d269e 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
+#include <linux/string_choices.h>
#include <asm/byteorder.h>
#include <asm/setup.h>
@@ -152,7 +153,7 @@ static int __init amiga_zorro_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, bus);
pr_info("Zorro: Probing AutoConfig expansion devices: %u device%s\n",
- zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
+ zorro_num_autocon, str_plural(zorro_num_autocon));
/* First identify all devices ... */
for (i = 0; i < zorro_num_autocon; i++) {
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 15bb7989c387..3acf5e050072 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -512,7 +512,7 @@ static int afs_iget5_set_root(struct inode *inode, void *opaque)
struct afs_vnode *vnode = AFS_FS_I(inode);
vnode->volume = as->volume;
- vnode->fid.vid = as->volume->vid,
+ vnode->fid.vid = as->volume->vid;
vnode->fid.vnode = 1;
vnode->fid.unique = 1;
inode->i_ino = 1;
@@ -545,7 +545,7 @@ struct inode *afs_root_iget(struct super_block *sb, struct key *key)
BUG_ON(!(inode->i_state & I_NEW));
vnode = AFS_FS_I(inode);
- vnode->cb_v_check = atomic_read(&as->volume->cb_v_break),
+ vnode->cb_v_check = atomic_read(&as->volume->cb_v_break);
afs_set_netfs_context(vnode);
op = afs_alloc_operation(key, as->volume);
diff --git a/fs/aio.c b/fs/aio.c
index 57c9f7c077e6..93ef59d358b3 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1516,7 +1516,7 @@ static void aio_complete_rw(struct kiocb *kiocb, long res)
iocb_put(iocb);
}
-static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
+static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb, int rw_type)
{
int ret;
@@ -1542,7 +1542,7 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
} else
req->ki_ioprio = get_current_ioprio();
- ret = kiocb_set_rw_flags(req, iocb->aio_rw_flags);
+ ret = kiocb_set_rw_flags(req, iocb->aio_rw_flags, rw_type);
if (unlikely(ret))
return ret;
@@ -1594,7 +1594,7 @@ static int aio_read(struct kiocb *req, const struct iocb *iocb,
struct file *file;
int ret;
- ret = aio_prep_rw(req, iocb);
+ ret = aio_prep_rw(req, iocb, READ);
if (ret)
return ret;
file = req->ki_filp;
@@ -1621,7 +1621,7 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb,
struct file *file;
int ret;
- ret = aio_prep_rw(req, iocb);
+ ret = aio_prep_rw(req, iocb, WRITE);
if (ret)
return ret;
file = req->ki_filp;
diff --git a/fs/attr.c b/fs/attr.c
index 960a310581eb..825007d5cda4 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -17,8 +17,6 @@
#include <linux/filelock.h>
#include <linux/security.h>
-#include "internal.h"
-
/**
* setattr_should_drop_sgid - determine whether the setgid bit needs to be
* removed
diff --git a/fs/autofs/init.c b/fs/autofs/init.c
index b5e4dfa04ed0..1d644a35ffa0 100644
--- a/fs/autofs/init.c
+++ b/fs/autofs/init.c
@@ -38,4 +38,5 @@ static void __exit exit_autofs_fs(void)
module_init(init_autofs_fs)
module_exit(exit_autofs_fs)
+MODULE_DESCRIPTION("Kernel automounter support");
MODULE_LICENSE("GPL");
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index 1f5db6863663..cf792d4de4f1 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -126,7 +126,7 @@ enum {
const struct fs_parameter_spec autofs_param_specs[] = {
fsparam_flag ("direct", Opt_direct),
fsparam_fd ("fd", Opt_fd),
- fsparam_u32 ("gid", Opt_gid),
+ fsparam_gid ("gid", Opt_gid),
fsparam_flag ("ignore", Opt_ignore),
fsparam_flag ("indirect", Opt_indirect),
fsparam_u32 ("maxproto", Opt_maxproto),
@@ -134,7 +134,7 @@ const struct fs_parameter_spec autofs_param_specs[] = {
fsparam_flag ("offset", Opt_offset),
fsparam_u32 ("pgrp", Opt_pgrp),
fsparam_flag ("strictexpire", Opt_strictexpire),
- fsparam_u32 ("uid", Opt_uid),
+ fsparam_uid ("uid", Opt_uid),
{}
};
@@ -193,8 +193,6 @@ static int autofs_parse_param(struct fs_context *fc, struct fs_parameter *param)
struct autofs_fs_context *ctx = fc->fs_private;
struct autofs_sb_info *sbi = fc->s_fs_info;
struct fs_parse_result result;
- kuid_t uid;
- kgid_t gid;
int opt;
opt = fs_parse(fc, autofs_param_specs, param, &result);
@@ -205,16 +203,10 @@ static int autofs_parse_param(struct fs_context *fc, struct fs_parameter *param)
case Opt_fd:
return autofs_parse_fd(fc, sbi, param, &result);
case Opt_uid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- return invalfc(fc, "Invalid uid");
- ctx->uid = uid;
+ ctx->uid = result.uid;
break;
case Opt_gid:
- gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(gid))
- return invalfc(fc, "Invalid gid");
- ctx->gid = gid;
+ ctx->gid = result.gid;
break;
case Opt_pgrp:
ctx->pgrp = result.uint_32;
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c
index 1de9fac3bcf4..658f11aebda1 100644
--- a/fs/bcachefs/alloc_background.c
+++ b/fs/bcachefs/alloc_background.c
@@ -3,6 +3,7 @@
#include "alloc_background.h"
#include "alloc_foreground.h"
#include "backpointers.h"
+#include "bkey_buf.h"
#include "btree_cache.h"
#include "btree_io.h"
#include "btree_key_cache.h"
@@ -1553,13 +1554,13 @@ err:
}
static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
- struct btree_iter *alloc_iter)
+ struct btree_iter *alloc_iter,
+ struct bkey_buf *last_flushed)
{
struct bch_fs *c = trans->c;
- struct btree_iter lru_iter;
struct bch_alloc_v4 a_convert;
const struct bch_alloc_v4 *a;
- struct bkey_s_c alloc_k, lru_k;
+ struct bkey_s_c alloc_k;
struct printbuf buf = PRINTBUF;
int ret;
@@ -1573,6 +1574,14 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
a = bch2_alloc_to_v4(alloc_k, &a_convert);
+ if (a->fragmentation_lru) {
+ ret = bch2_lru_check_set(trans, BCH_LRU_FRAGMENTATION_START,
+ a->fragmentation_lru,
+ alloc_k, last_flushed);
+ if (ret)
+ return ret;
+ }
+
if (a->data_type != BCH_DATA_cached)
return 0;
@@ -1597,41 +1606,30 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
a = &a_mut->v;
}
- lru_k = bch2_bkey_get_iter(trans, &lru_iter, BTREE_ID_lru,
- lru_pos(alloc_k.k->p.inode,
- bucket_to_u64(alloc_k.k->p),
- a->io_time[READ]), 0);
- ret = bkey_err(lru_k);
+ ret = bch2_lru_check_set(trans, alloc_k.k->p.inode, a->io_time[READ],
+ alloc_k, last_flushed);
if (ret)
- return ret;
-
- if (fsck_err_on(lru_k.k->type != KEY_TYPE_set, c,
- alloc_key_to_missing_lru_entry,
- "missing lru entry\n"
- " %s",
- (printbuf_reset(&buf),
- bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
- ret = bch2_lru_set(trans,
- alloc_k.k->p.inode,
- bucket_to_u64(alloc_k.k->p),
- a->io_time[READ]);
- if (ret)
- goto err;
- }
+ goto err;
err:
fsck_err:
- bch2_trans_iter_exit(trans, &lru_iter);
printbuf_exit(&buf);
return ret;
}
int bch2_check_alloc_to_lru_refs(struct bch_fs *c)
{
+ struct bkey_buf last_flushed;
+
+ bch2_bkey_buf_init(&last_flushed);
+ bkey_init(&last_flushed.k->k);
+
int ret = bch2_trans_run(c,
for_each_btree_key_commit(trans, iter, BTREE_ID_alloc,
POS_MIN, BTREE_ITER_prefetch, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
- bch2_check_alloc_to_lru_ref(trans, &iter)));
+ bch2_check_alloc_to_lru_ref(trans, &iter, &last_flushed)));
+
+ bch2_bkey_buf_exit(&last_flushed, c);
bch_err_fn(c, ret);
return ret;
}
diff --git a/fs/bcachefs/alloc_foreground.c b/fs/bcachefs/alloc_foreground.c
index 9d3d64746a5b..27d97c22ae27 100644
--- a/fs/bcachefs/alloc_foreground.c
+++ b/fs/bcachefs/alloc_foreground.c
@@ -1703,6 +1703,7 @@ void bch2_fs_alloc_debug_to_text(struct printbuf *out, struct bch_fs *c)
for (unsigned i = 0; i < ARRAY_SIZE(c->open_buckets); i++)
nr[c->open_buckets[i].data_type]++;
+ printbuf_tabstops_reset(out);
printbuf_tabstop_push(out, 24);
percpu_down_read(&c->mark_lock);
@@ -1736,6 +1737,7 @@ void bch2_dev_alloc_debug_to_text(struct printbuf *out, struct bch_dev *ca)
for (unsigned i = 0; i < ARRAY_SIZE(c->open_buckets); i++)
nr[c->open_buckets[i].data_type]++;
+ printbuf_tabstops_reset(out);
printbuf_tabstop_push(out, 12);
printbuf_tabstop_push(out, 16);
printbuf_tabstop_push(out, 16);
diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c
index 4321f9fb73bd..6d8b1bc90be0 100644
--- a/fs/bcachefs/backpointers.c
+++ b/fs/bcachefs/backpointers.c
@@ -434,13 +434,6 @@ int bch2_check_btree_backpointers(struct bch_fs *c)
return ret;
}
-static inline bool bkey_and_val_eq(struct bkey_s_c l, struct bkey_s_c r)
-{
- return bpos_eq(l.k->p, r.k->p) &&
- bkey_bytes(l.k) == bkey_bytes(r.k) &&
- !memcmp(l.v, r.v, bkey_val_bytes(l.k));
-}
-
struct extents_to_bp_state {
struct bpos bucket_start;
struct bpos bucket_end;
@@ -536,11 +529,8 @@ static int check_bp_exists(struct btree_trans *trans,
struct btree_iter other_extent_iter = {};
struct printbuf buf = PRINTBUF;
struct bkey_s_c bp_k;
- struct bkey_buf tmp;
int ret = 0;
- bch2_bkey_buf_init(&tmp);
-
struct bch_dev *ca = bch2_dev_bucket_tryget(c, bucket);
if (!ca) {
prt_str(&buf, "extent for nonexistent device:bucket ");
@@ -565,22 +555,9 @@ static int check_bp_exists(struct btree_trans *trans,
if (bp_k.k->type != KEY_TYPE_backpointer ||
memcmp(bkey_s_c_to_backpointer(bp_k).v, &bp, sizeof(bp))) {
- bch2_bkey_buf_reassemble(&tmp, c, orig_k);
-
- if (!bkey_and_val_eq(orig_k, bkey_i_to_s_c(s->last_flushed.k))) {
- if (bp.level) {
- bch2_trans_unlock(trans);
- bch2_btree_interior_updates_flush(c);
- }
-
- ret = bch2_btree_write_buffer_flush_sync(trans);
- if (ret)
- goto err;
-
- bch2_bkey_buf_copy(&s->last_flushed, c, tmp.k);
- ret = -BCH_ERR_transaction_restart_write_buffer_flush;
- goto out;
- }
+ ret = bch2_btree_write_buffer_maybe_flush(trans, orig_k, &s->last_flushed);
+ if (ret)
+ goto err;
goto check_existing_bp;
}
@@ -589,7 +566,6 @@ err:
fsck_err:
bch2_trans_iter_exit(trans, &other_extent_iter);
bch2_trans_iter_exit(trans, &bp_iter);
- bch2_bkey_buf_exit(&tmp, c);
bch2_dev_put(ca);
printbuf_exit(&buf);
return ret;
@@ -794,6 +770,8 @@ static int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
!((1U << btree) & btree_interior_mask))
continue;
+ bch2_trans_begin(trans);
+
__for_each_btree_node(trans, iter, btree,
btree == start.btree ? start.pos : POS_MIN,
0, depth, BTREE_ITER_prefetch, b, ret) {
@@ -905,7 +883,7 @@ static int check_one_backpointer(struct btree_trans *trans,
struct bbpos start,
struct bbpos end,
struct bkey_s_c_backpointer bp,
- struct bpos *last_flushed_pos)
+ struct bkey_buf *last_flushed)
{
struct bch_fs *c = trans->c;
struct btree_iter iter;
@@ -925,20 +903,18 @@ static int check_one_backpointer(struct btree_trans *trans,
if (ret)
return ret;
- if (!k.k && !bpos_eq(*last_flushed_pos, bp.k->p)) {
- *last_flushed_pos = bp.k->p;
- ret = bch2_btree_write_buffer_flush_sync(trans) ?:
- -BCH_ERR_transaction_restart_write_buffer_flush;
- goto out;
- }
+ if (!k.k) {
+ ret = bch2_btree_write_buffer_maybe_flush(trans, bp.s_c, last_flushed);
+ if (ret)
+ goto out;
- if (fsck_err_on(!k.k, c,
- backpointer_to_missing_ptr,
- "backpointer for missing %s\n %s",
- bp.v->level ? "btree node" : "extent",
- (bch2_bkey_val_to_text(&buf, c, bp.s_c), buf.buf))) {
- ret = bch2_btree_delete_at_buffered(trans, BTREE_ID_backpointers, bp.k->p);
- goto out;
+ if (fsck_err(c, backpointer_to_missing_ptr,
+ "backpointer for missing %s\n %s",
+ bp.v->level ? "btree node" : "extent",
+ (bch2_bkey_val_to_text(&buf, c, bp.s_c), buf.buf))) {
+ ret = bch2_btree_delete_at_buffered(trans, BTREE_ID_backpointers, bp.k->p);
+ goto out;
+ }
}
out:
fsck_err:
@@ -951,14 +927,20 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans,
struct bbpos start,
struct bbpos end)
{
- struct bpos last_flushed_pos = SPOS_MAX;
+ struct bkey_buf last_flushed;
- return for_each_btree_key_commit(trans, iter, BTREE_ID_backpointers,
+ bch2_bkey_buf_init(&last_flushed);
+ bkey_init(&last_flushed.k->k);
+
+ int ret = for_each_btree_key_commit(trans, iter, BTREE_ID_backpointers,
POS_MIN, BTREE_ITER_prefetch, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
check_one_backpointer(trans, start, end,
bkey_s_c_to_backpointer(k),
- &last_flushed_pos));
+ &last_flushed));
+
+ bch2_bkey_buf_exit(&last_flushed, trans->c);
+ return ret;
}
int bch2_check_backpointers_to_extents(struct bch_fs *c)
diff --git a/fs/bcachefs/bkey.c b/fs/bcachefs/bkey.c
index 94a1d1982fa8..587d7318a2e8 100644
--- a/fs/bcachefs/bkey.c
+++ b/fs/bcachefs/bkey.c
@@ -660,8 +660,9 @@ int bch2_bkey_format_invalid(struct bch_fs *c,
bch2_bkey_format_field_overflows(f, i)) {
unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i];
u64 unpacked_max = ~((~0ULL << 1) << (unpacked_bits - 1));
- u64 packed_max = f->bits_per_field[i]
- ? ~((~0ULL << 1) << (f->bits_per_field[i] - 1))
+ unsigned packed_bits = min(64, f->bits_per_field[i]);
+ u64 packed_max = packed_bits
+ ? ~((~0ULL << 1) << (packed_bits - 1))
: 0;
prt_printf(err, "field %u too large: %llu + %llu > %llu",
diff --git a/fs/bcachefs/bkey.h b/fs/bcachefs/bkey.h
index fcd43915df07..936357149cf0 100644
--- a/fs/bcachefs/bkey.h
+++ b/fs/bcachefs/bkey.h
@@ -194,6 +194,13 @@ static inline struct bpos bkey_max(struct bpos l, struct bpos r)
return bkey_gt(l, r) ? l : r;
}
+static inline bool bkey_and_val_eq(struct bkey_s_c l, struct bkey_s_c r)
+{
+ return bpos_eq(l.k->p, r.k->p) &&
+ bkey_bytes(l.k) == bkey_bytes(r.k) &&
+ !memcmp(l.v, r.v, bkey_val_bytes(l.k));
+}
+
void bch2_bpos_swab(struct bpos *);
void bch2_bkey_swab_key(const struct bkey_format *, struct bkey_packed *);
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index 0e477a926579..a0deb8266011 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -641,16 +641,30 @@ static int bch2_gc_btree(struct btree_trans *trans, enum btree_id btree, bool in
target_depth = 0;
/* root */
- mutex_lock(&c->btree_root_lock);
- struct btree *b = bch2_btree_id_root(c, btree)->b;
- if (!btree_node_fake(b)) {
+ do {
+retry_root:
+ bch2_trans_begin(trans);
+
+ struct btree_iter iter;
+ bch2_trans_node_iter_init(trans, &iter, btree, POS_MIN,
+ 0, bch2_btree_id_root(c, btree)->b->c.level, 0);
+ struct btree *b = bch2_btree_iter_peek_node(&iter);
+ ret = PTR_ERR_OR_ZERO(b);
+ if (ret)
+ goto err_root;
+
+ if (b != btree_node_root(c, b)) {
+ bch2_trans_iter_exit(trans, &iter);
+ goto retry_root;
+ }
+
gc_pos_set(c, gc_pos_btree(btree, b->c.level + 1, SPOS_MAX));
- ret = lockrestart_do(trans,
- bch2_gc_mark_key(trans, b->c.btree_id, b->c.level + 1,
- NULL, NULL, bkey_i_to_s_c(&b->key), initial));
+ struct bkey_s_c k = bkey_i_to_s_c(&b->key);
+ ret = bch2_gc_mark_key(trans, btree, b->c.level + 1, NULL, NULL, k, initial);
level = b->c.level;
- }
- mutex_unlock(&c->btree_root_lock);
+err_root:
+ bch2_trans_iter_exit(trans, &iter);
+ } while (bch2_err_matches(ret, BCH_ERR_transaction_restart));
if (ret)
return ret;
@@ -903,6 +917,8 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
bch2_dev_usage_update(c, ca, &old_gc, &gc, 0, true);
percpu_up_read(&c->mark_lock);
+ gc.fragmentation_lru = alloc_lru_idx_fragmentation(gc, ca);
+
if (fsck_err_on(new.data_type != gc.data_type, c,
alloc_key_data_type_wrong,
"bucket %llu:%llu gen %u has wrong data_type"
@@ -916,23 +932,19 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
#define copy_bucket_field(_errtype, _f) \
if (fsck_err_on(new._f != gc._f, c, _errtype, \
"bucket %llu:%llu gen %u data type %s has wrong " #_f \
- ": got %u, should be %u", \
+ ": got %llu, should be %llu", \
iter->pos.inode, iter->pos.offset, \
gc.gen, \
bch2_data_type_str(gc.data_type), \
- new._f, gc._f)) \
+ (u64) new._f, (u64) gc._f)) \
new._f = gc._f; \
- copy_bucket_field(alloc_key_gen_wrong,
- gen);
- copy_bucket_field(alloc_key_dirty_sectors_wrong,
- dirty_sectors);
- copy_bucket_field(alloc_key_cached_sectors_wrong,
- cached_sectors);
- copy_bucket_field(alloc_key_stripe_wrong,
- stripe);
- copy_bucket_field(alloc_key_stripe_redundancy_wrong,
- stripe_redundancy);
+ copy_bucket_field(alloc_key_gen_wrong, gen);
+ copy_bucket_field(alloc_key_dirty_sectors_wrong, dirty_sectors);
+ copy_bucket_field(alloc_key_cached_sectors_wrong, cached_sectors);
+ copy_bucket_field(alloc_key_stripe_wrong, stripe);
+ copy_bucket_field(alloc_key_stripe_redundancy_wrong, stripe_redundancy);
+ copy_bucket_field(alloc_key_fragmentation_lru_wrong, fragmentation_lru);
#undef copy_bucket_field
if (!bch2_alloc_v4_cmp(*old, new))
@@ -946,7 +958,7 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
a->v = new;
/*
- * The trigger normally makes sure this is set, but we're not running
+ * The trigger normally makes sure these are set, but we're not running
* triggers:
*/
if (a->v.data_type == BCH_DATA_cached && !a->v.io_time[READ])
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index 0ed9e6574fcd..19352a08ea20 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -996,7 +996,7 @@ retry_all:
bch2_trans_unlock(trans);
cond_resched();
- trans->locked = true;
+ trans_set_locked(trans);
if (unlikely(trans->memory_allocation_failure)) {
struct closure cl;
@@ -3089,7 +3089,8 @@ u32 bch2_trans_begin(struct btree_trans *trans)
bch2_trans_srcu_unlock(trans);
trans->last_begin_ip = _RET_IP_;
- trans->locked = true;
+
+ trans_set_locked(trans);
if (trans->restarted) {
bch2_btree_path_traverse_all(trans);
@@ -3159,7 +3160,6 @@ got_trans:
trans->last_begin_time = local_clock();
trans->fn_idx = fn_idx;
trans->locking_wait.task = current;
- trans->locked = true;
trans->journal_replay_not_finished =
unlikely(!test_bit(JOURNAL_replay_done, &c->journal.flags)) &&
atomic_inc_not_zero(&c->journal_keys.ref);
@@ -3193,6 +3193,7 @@ got_trans:
trans->srcu_idx = srcu_read_lock(&c->btree_trans_barrier);
trans->srcu_lock_time = jiffies;
trans->srcu_held = true;
+ trans_set_locked(trans);
closure_init_stack_release(&trans->ref);
return trans;
diff --git a/fs/bcachefs/btree_locking.c b/fs/bcachefs/btree_locking.c
index d66fff22109a..c51826fd557f 100644
--- a/fs/bcachefs/btree_locking.c
+++ b/fs/bcachefs/btree_locking.c
@@ -231,7 +231,7 @@ static noinline int break_cycle(struct lock_graph *g, struct printbuf *cycle)
prt_newline(&buf);
}
- bch2_print_string_as_lines(KERN_ERR, buf.buf);
+ bch2_print_string_as_lines_nonblocking(KERN_ERR, buf.buf);
printbuf_exit(&buf);
BUG();
}
@@ -792,7 +792,7 @@ static inline int __bch2_trans_relock(struct btree_trans *trans, bool trace)
return bch2_trans_relock_fail(trans, path, &f, trace);
}
- trans->locked = true;
+ trans_set_locked(trans);
out:
bch2_trans_verify_locks(trans);
return 0;
@@ -812,16 +812,14 @@ void bch2_trans_unlock_noassert(struct btree_trans *trans)
{
__bch2_trans_unlock(trans);
- trans->locked = false;
- trans->last_unlock_ip = _RET_IP_;
+ trans_set_unlocked(trans);
}
void bch2_trans_unlock(struct btree_trans *trans)
{
__bch2_trans_unlock(trans);
- trans->locked = false;
- trans->last_unlock_ip = _RET_IP_;
+ trans_set_unlocked(trans);
}
void bch2_trans_unlock_long(struct btree_trans *trans)
diff --git a/fs/bcachefs/btree_locking.h b/fs/bcachefs/btree_locking.h
index 7f41545b9147..75a6274c7d27 100644
--- a/fs/bcachefs/btree_locking.h
+++ b/fs/bcachefs/btree_locking.h
@@ -193,6 +193,28 @@ int bch2_six_check_for_deadlock(struct six_lock *lock, void *p);
/* lock: */
+static inline void trans_set_locked(struct btree_trans *trans)
+{
+ if (!trans->locked) {
+ trans->locked = true;
+ trans->last_unlock_ip = 0;
+
+ trans->pf_memalloc_nofs = (current->flags & PF_MEMALLOC_NOFS) != 0;
+ current->flags |= PF_MEMALLOC_NOFS;
+ }
+}
+
+static inline void trans_set_unlocked(struct btree_trans *trans)
+{
+ if (trans->locked) {
+ trans->locked = false;
+ trans->last_unlock_ip = _RET_IP_;
+
+ if (!trans->pf_memalloc_nofs)
+ current->flags &= ~PF_MEMALLOC_NOFS;
+ }
+}
+
static inline int __btree_node_lock_nopath(struct btree_trans *trans,
struct btree_bkey_cached_common *b,
enum six_lock_type type,
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h
index 87f485e9c552..48cb1a7d31c5 100644
--- a/fs/bcachefs/btree_types.h
+++ b/fs/bcachefs/btree_types.h
@@ -484,6 +484,7 @@ struct btree_trans {
bool lock_may_not_fail:1;
bool srcu_held:1;
bool locked:1;
+ bool pf_memalloc_nofs:1;
bool write_locked:1;
bool used_mempool:1;
bool in_traverse_all:1;
diff --git a/fs/bcachefs/btree_write_buffer.c b/fs/bcachefs/btree_write_buffer.c
index 75c8a196b3f6..d0e92d948002 100644
--- a/fs/bcachefs/btree_write_buffer.c
+++ b/fs/bcachefs/btree_write_buffer.c
@@ -1,11 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
#include "bcachefs.h"
+#include "bkey_buf.h"
#include "btree_locking.h"
#include "btree_update.h"
#include "btree_update_interior.h"
#include "btree_write_buffer.h"
#include "error.h"
+#include "extents.h"
#include "journal.h"
#include "journal_io.h"
#include "journal_reclaim.h"
@@ -492,6 +494,41 @@ int bch2_btree_write_buffer_tryflush(struct btree_trans *trans)
return ret;
}
+/**
+ * In check and repair code, when checking references to write buffer btrees we
+ * need to issue a flush before we have a definitive error: this issues a flush
+ * if this is a key we haven't yet checked.
+ */
+int bch2_btree_write_buffer_maybe_flush(struct btree_trans *trans,
+ struct bkey_s_c referring_k,
+ struct bkey_buf *last_flushed)
+{
+ struct bch_fs *c = trans->c;
+ struct bkey_buf tmp;
+ int ret = 0;
+
+ bch2_bkey_buf_init(&tmp);
+
+ if (!bkey_and_val_eq(referring_k, bkey_i_to_s_c(last_flushed->k))) {
+ bch2_bkey_buf_reassemble(&tmp, c, referring_k);
+
+ if (bkey_is_btree_ptr(referring_k.k)) {
+ bch2_trans_unlock(trans);
+ bch2_btree_interior_updates_flush(c);
+ }
+
+ ret = bch2_btree_write_buffer_flush_sync(trans);
+ if (ret)
+ goto err;
+
+ bch2_bkey_buf_copy(last_flushed, c, tmp.k);
+ ret = -BCH_ERR_transaction_restart_write_buffer_flush;
+ }
+err:
+ bch2_bkey_buf_exit(&tmp, c);
+ return ret;
+}
+
static void bch2_btree_write_buffer_flush_work(struct work_struct *work)
{
struct bch_fs *c = container_of(work, struct bch_fs, btree_write_buffer.flush_work);
diff --git a/fs/bcachefs/btree_write_buffer.h b/fs/bcachefs/btree_write_buffer.h
index eebcd2b15249..dd5e64218b50 100644
--- a/fs/bcachefs/btree_write_buffer.h
+++ b/fs/bcachefs/btree_write_buffer.h
@@ -23,6 +23,9 @@ int bch2_btree_write_buffer_flush_sync(struct btree_trans *);
int bch2_btree_write_buffer_flush_nocheck_rw(struct btree_trans *);
int bch2_btree_write_buffer_tryflush(struct btree_trans *);
+struct bkey_buf;
+int bch2_btree_write_buffer_maybe_flush(struct btree_trans *, struct bkey_s_c, struct bkey_buf *);
+
struct journal_keys_to_wb {
struct btree_write_buffer_keys *wb;
size_t room;
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index 743d57eba760..314ee3e0187f 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -805,7 +805,7 @@ int bch2_bucket_ref_update(struct btree_trans *trans, struct bch_dev *ca,
"bucket %u:%zu gen %u (mem gen %u) data type %s: stale dirty ptr (gen %u)\n"
"while marking %s",
ptr->dev, bucket_nr, b_gen,
- *bucket_gen(ca, bucket_nr),
+ bucket_gen_get(ca, bucket_nr),
bch2_data_type_str(bucket_data_type ?: ptr_data_type),
ptr->gen,
(printbuf_reset(&buf),
diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h
index 80ee0be9793e..8ad4be73860c 100644
--- a/fs/bcachefs/buckets.h
+++ b/fs/bcachefs/buckets.h
@@ -116,6 +116,14 @@ static inline u8 *bucket_gen(struct bch_dev *ca, size_t b)
return gens->b + b;
}
+static inline u8 bucket_gen_get(struct bch_dev *ca, size_t b)
+{
+ rcu_read_lock();
+ u8 gen = *bucket_gen(ca, b);
+ rcu_read_unlock();
+ return gen;
+}
+
static inline size_t PTR_BUCKET_NR(const struct bch_dev *ca,
const struct bch_extent_ptr *ptr)
{
diff --git a/fs/bcachefs/clock.c b/fs/bcachefs/clock.c
index 363644451106..0f40b585ce2b 100644
--- a/fs/bcachefs/clock.c
+++ b/fs/bcachefs/clock.c
@@ -132,14 +132,9 @@ static struct io_timer *get_expired_timer(struct io_clock *clock,
{
struct io_timer *ret = NULL;
- spin_lock(&clock->timer_lock);
-
if (clock->timers.used &&
time_after_eq(now, clock->timers.data[0]->expire))
heap_pop(&clock->timers, ret, io_timer_cmp, NULL);
-
- spin_unlock(&clock->timer_lock);
-
return ret;
}
@@ -148,8 +143,10 @@ void __bch2_increment_clock(struct io_clock *clock, unsigned sectors)
struct io_timer *timer;
unsigned long now = atomic64_add_return(sectors, &clock->now);
+ spin_lock(&clock->timer_lock);
while ((timer = get_expired_timer(clock, now)))
timer->fn(timer);
+ spin_unlock(&clock->timer_lock);
}
void bch2_io_timers_to_text(struct printbuf *out, struct io_clock *clock)
diff --git a/fs/bcachefs/data_update.c b/fs/bcachefs/data_update.c
index 1a0072eef109..0087b8555ead 100644
--- a/fs/bcachefs/data_update.c
+++ b/fs/bcachefs/data_update.c
@@ -5,7 +5,9 @@
#include "bkey_buf.h"
#include "btree_update.h"
#include "buckets.h"
+#include "compress.h"
#include "data_update.h"
+#include "disk_groups.h"
#include "ec.h"
#include "error.h"
#include "extents.h"
@@ -454,6 +456,38 @@ static void bch2_update_unwritten_extent(struct btree_trans *trans,
}
}
+void bch2_data_update_opts_to_text(struct printbuf *out, struct bch_fs *c,
+ struct bch_io_opts *io_opts,
+ struct data_update_opts *data_opts)
+{
+ printbuf_tabstop_push(out, 20);
+ prt_str(out, "rewrite ptrs:\t");
+ bch2_prt_u64_base2(out, data_opts->rewrite_ptrs);
+ prt_newline(out);
+
+ prt_str(out, "kill ptrs:\t");
+ bch2_prt_u64_base2(out, data_opts->kill_ptrs);
+ prt_newline(out);
+
+ prt_str(out, "target:\t");
+ bch2_target_to_text(out, c, data_opts->target);
+ prt_newline(out);
+
+ prt_str(out, "compression:\t");
+ bch2_compression_opt_to_text(out, background_compression(*io_opts));
+ prt_newline(out);
+
+ prt_str(out, "extra replicas:\t");
+ prt_u64(out, data_opts->extra_replicas);
+}
+
+void bch2_data_update_to_text(struct printbuf *out, struct data_update *m)
+{
+ bch2_bkey_val_to_text(out, m->op.c, bkey_i_to_s_c(m->k.k));
+ prt_newline(out);
+ bch2_data_update_opts_to_text(out, m->op.c, &m->op.opts, &m->data_opts);
+}
+
int bch2_extent_drop_ptrs(struct btree_trans *trans,
struct btree_iter *iter,
struct bkey_s_c k,
@@ -643,6 +677,16 @@ int bch2_data_update_init(struct btree_trans *trans,
if (!(durability_have + durability_removing))
m->op.nr_replicas = max((unsigned) m->op.nr_replicas, 1);
+ if (!m->op.nr_replicas) {
+ struct printbuf buf = PRINTBUF;
+
+ bch2_data_update_to_text(&buf, m);
+ WARN(1, "trying to move an extent, but nr_replicas=0\n%s", buf.buf);
+ printbuf_exit(&buf);
+ ret = -BCH_ERR_data_update_done;
+ goto done;
+ }
+
m->op.nr_replicas_required = m->op.nr_replicas;
if (reserve_sectors) {
diff --git a/fs/bcachefs/data_update.h b/fs/bcachefs/data_update.h
index 991095bbd469..8d36365bdea8 100644
--- a/fs/bcachefs/data_update.h
+++ b/fs/bcachefs/data_update.h
@@ -17,6 +17,9 @@ struct data_update_opts {
unsigned write_flags;
};
+void bch2_data_update_opts_to_text(struct printbuf *, struct bch_fs *,
+ struct bch_io_opts *, struct data_update_opts *);
+
struct data_update {
/* extent being updated: */
enum btree_id btree_id;
@@ -27,6 +30,8 @@ struct data_update {
struct bch_write_op op;
};
+void bch2_data_update_to_text(struct printbuf *, struct data_update *);
+
int bch2_data_update_index_update(struct bch_write_op *);
void bch2_data_update_read_done(struct data_update *,
diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c
index f0d4727c4dc2..ebabab171fe5 100644
--- a/fs/bcachefs/debug.c
+++ b/fs/bcachefs/debug.c
@@ -610,7 +610,7 @@ restart:
list_sort(&c->btree_trans_list, list_ptr_order_cmp);
list_for_each_entry(trans, &c->btree_trans_list, list) {
- if ((ulong) trans < i->iter)
+ if ((ulong) trans <= i->iter)
continue;
i->iter = (ulong) trans;
@@ -832,16 +832,16 @@ static const struct file_operations btree_transaction_stats_op = {
static void btree_deadlock_to_text(struct printbuf *out, struct bch_fs *c)
{
struct btree_trans *trans;
- pid_t iter = 0;
+ ulong iter = 0;
restart:
seqmutex_lock(&c->btree_trans_lock);
- list_for_each_entry(trans, &c->btree_trans_list, list) {
- struct task_struct *task = READ_ONCE(trans->locking_wait.task);
+ list_sort(&c->btree_trans_list, list_ptr_order_cmp);
- if (!task || task->pid <= iter)
+ list_for_each_entry(trans, &c->btree_trans_list, list) {
+ if ((ulong) trans <= iter)
continue;
- iter = task->pid;
+ iter = (ulong) trans;
if (!closure_get_not_zero(&trans->ref))
continue;
diff --git a/fs/bcachefs/eytzinger.h b/fs/bcachefs/eytzinger.h
index 24840aee335c..795f4fc0bab1 100644
--- a/fs/bcachefs/eytzinger.h
+++ b/fs/bcachefs/eytzinger.h
@@ -48,7 +48,7 @@ static inline unsigned eytzinger1_right_child(unsigned i)
static inline unsigned eytzinger1_first(unsigned size)
{
- return rounddown_pow_of_two(size);
+ return size ? rounddown_pow_of_two(size) : 0;
}
static inline unsigned eytzinger1_last(unsigned size)
@@ -101,7 +101,9 @@ static inline unsigned eytzinger1_prev(unsigned i, unsigned size)
static inline unsigned eytzinger1_extra(unsigned size)
{
- return (size + 1 - rounddown_pow_of_two(size)) << 1;
+ return size
+ ? (size + 1 - rounddown_pow_of_two(size)) << 1
+ : 0;
}
static inline unsigned __eytzinger1_to_inorder(unsigned i, unsigned size,
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index f9c9a95d7d4c..0c7d1bc0548a 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -194,6 +194,12 @@ static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_ino
* discard_new_inode() expects it to be set...
*/
inode->v.i_flags |= I_NEW;
+ /*
+ * We don't want bch2_evict_inode() to delete the inode on disk,
+ * we just raced and had another inode in cache. Normally new
+ * inodes don't have nlink == 0 - except tmpfiles do...
+ */
+ set_nlink(&inode->v, 1);
discard_new_inode(&inode->v);
inode = old;
} else {
@@ -238,7 +244,6 @@ static struct bch_inode_info *__bch2_new_inode(struct bch_fs *c)
inode->ei_flags = 0;
mutex_init(&inode->ei_quota_lock);
memset(&inode->ei_devs_need_flush, 0, sizeof(inode->ei_devs_need_flush));
- inode->v.i_state = 0;
if (unlikely(inode_init_always(c->vfs_sb, &inode->v))) {
kmem_cache_free(bch2_inode_cache, inode);
@@ -2026,6 +2031,8 @@ err_put_super:
__bch2_fs_stop(c);
deactivate_locked_super(sb);
err:
+ if (ret)
+ pr_err("error: %s", bch2_err_str(ret));
/*
* On an inconsistency error in recovery we might see an -EROFS derived
* errorcode (from the journal), but we don't want to return that to
diff --git a/fs/bcachefs/io_misc.c b/fs/bcachefs/io_misc.c
index 4ec979b4b23e..4583c9386e8c 100644
--- a/fs/bcachefs/io_misc.c
+++ b/fs/bcachefs/io_misc.c
@@ -125,7 +125,7 @@ err_noprint:
bch2_bkey_buf_exit(&old, c);
if (closure_nr_remaining(&cl) != 1) {
- bch2_trans_unlock(trans);
+ bch2_trans_unlock_long(trans);
closure_sync(&cl);
}
diff --git a/fs/bcachefs/io_read.c b/fs/bcachefs/io_read.c
index c97fa7002b06..ebf39ef72fb2 100644
--- a/fs/bcachefs/io_read.c
+++ b/fs/bcachefs/io_read.c
@@ -389,7 +389,6 @@ retry:
bch2_bkey_buf_reassemble(&sk, c, k);
k = bkey_i_to_s_c(sk.k);
- bch2_trans_unlock(trans);
if (!bch2_bkey_matches_ptr(c, k,
rbio->pick.ptr,
@@ -1004,6 +1003,9 @@ get_bio:
rbio->promote = promote;
INIT_WORK(&rbio->work, NULL);
+ if (flags & BCH_READ_NODECODE)
+ orig->pick = pick;
+
rbio->bio.bi_opf = orig->bio.bi_opf;
rbio->bio.bi_iter.bi_sector = pick.ptr.offset;
rbio->bio.bi_end_io = bch2_read_endio;
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index 13669dd0e375..10b19791ec98 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -1095,7 +1095,7 @@ unlock:
return ret;
}
-int bch2_dev_journal_alloc(struct bch_dev *ca)
+int bch2_dev_journal_alloc(struct bch_dev *ca, bool new_fs)
{
unsigned nr;
int ret;
@@ -1117,7 +1117,7 @@ int bch2_dev_journal_alloc(struct bch_dev *ca)
min(1 << 13,
(1 << 24) / ca->mi.bucket_size));
- ret = __bch2_set_nr_journal_buckets(ca, nr, true, NULL);
+ ret = __bch2_set_nr_journal_buckets(ca, nr, new_fs, NULL);
err:
bch_err_fn(ca, ret);
return ret;
@@ -1129,7 +1129,7 @@ int bch2_fs_journal_alloc(struct bch_fs *c)
if (ca->journal.nr)
continue;
- int ret = bch2_dev_journal_alloc(ca);
+ int ret = bch2_dev_journal_alloc(ca, true);
if (ret) {
percpu_ref_put(&ca->io_ref);
return ret;
@@ -1184,9 +1184,11 @@ void bch2_fs_journal_stop(struct journal *j)
journal_quiesce(j);
cancel_delayed_work_sync(&j->write_work);
- BUG_ON(!bch2_journal_error(j) &&
- test_bit(JOURNAL_replay_done, &j->flags) &&
- j->last_empty_seq != journal_cur_seq(j));
+ WARN(!bch2_journal_error(j) &&
+ test_bit(JOURNAL_replay_done, &j->flags) &&
+ j->last_empty_seq != journal_cur_seq(j),
+ "journal shutdown error: cur seq %llu but last empty seq %llu",
+ journal_cur_seq(j), j->last_empty_seq);
if (!bch2_journal_error(j))
clear_bit(JOURNAL_running, &j->flags);
@@ -1418,8 +1420,8 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
unsigned long now = jiffies;
u64 nr_writes = j->nr_flush_writes + j->nr_noflush_writes;
- if (!out->nr_tabstops)
- printbuf_tabstop_push(out, 28);
+ printbuf_tabstops_reset(out);
+ printbuf_tabstop_push(out, 28);
out->atomic++;
rcu_read_lock();
diff --git a/fs/bcachefs/journal.h b/fs/bcachefs/journal.h
index fd1f7cdaa8bc..bc6b9c39dcb4 100644
--- a/fs/bcachefs/journal.h
+++ b/fs/bcachefs/journal.h
@@ -433,7 +433,7 @@ bool bch2_journal_seq_pins_to_text(struct printbuf *, struct journal *, u64 *);
int bch2_set_nr_journal_buckets(struct bch_fs *, struct bch_dev *,
unsigned nr);
-int bch2_dev_journal_alloc(struct bch_dev *);
+int bch2_dev_journal_alloc(struct bch_dev *, bool);
int bch2_fs_journal_alloc(struct bch_fs *);
void bch2_dev_journal_stop(struct journal *, struct bch_dev *);
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c
index db24ce21b2ac..2326e2cb9cd2 100644
--- a/fs/bcachefs/journal_io.c
+++ b/fs/bcachefs/journal_io.c
@@ -415,6 +415,8 @@ static int journal_entry_btree_keys_validate(struct bch_fs *c,
flags|BCH_VALIDATE_journal);
if (ret == FSCK_DELETED_KEY)
continue;
+ else if (ret)
+ return ret;
k = bkey_next(k);
}
@@ -1762,11 +1764,13 @@ static CLOSURE_CALLBACK(journal_write_preflush)
if (j->seq_ondisk + 1 != le64_to_cpu(w->data->seq)) {
spin_lock(&j->lock);
- closure_wait(&j->async_wait, cl);
+ if (j->seq_ondisk + 1 != le64_to_cpu(w->data->seq)) {
+ closure_wait(&j->async_wait, cl);
+ spin_unlock(&j->lock);
+ continue_at(cl, journal_write_preflush, j->wq);
+ return;
+ }
spin_unlock(&j->lock);
-
- continue_at(cl, journal_write_preflush, j->wq);
- return;
}
if (w->separate_flush) {
diff --git a/fs/bcachefs/lru.c b/fs/bcachefs/lru.c
index a40d116224ed..b12894ef44f3 100644
--- a/fs/bcachefs/lru.c
+++ b/fs/bcachefs/lru.c
@@ -77,6 +77,45 @@ static const char * const bch2_lru_types[] = {
NULL
};
+int bch2_lru_check_set(struct btree_trans *trans,
+ u16 lru_id, u64 time,
+ struct bkey_s_c referring_k,
+ struct bkey_buf *last_flushed)
+{
+ struct bch_fs *c = trans->c;
+ struct printbuf buf = PRINTBUF;
+ struct btree_iter lru_iter;
+ struct bkey_s_c lru_k =
+ bch2_bkey_get_iter(trans, &lru_iter, BTREE_ID_lru,
+ lru_pos(lru_id,
+ bucket_to_u64(referring_k.k->p),
+ time), 0);
+ int ret = bkey_err(lru_k);
+ if (ret)
+ return ret;
+
+ if (lru_k.k->type != KEY_TYPE_set) {
+ ret = bch2_btree_write_buffer_maybe_flush(trans, referring_k, last_flushed);
+ if (ret)
+ goto err;
+
+ if (fsck_err(c, alloc_key_to_missing_lru_entry,
+ "missing %s lru entry\n"
+ " %s",
+ bch2_lru_types[lru_type(lru_k)],
+ (bch2_bkey_val_to_text(&buf, c, referring_k), buf.buf))) {
+ ret = bch2_lru_set(trans, lru_id, bucket_to_u64(referring_k.k->p), time);
+ if (ret)
+ goto err;
+ }
+ }
+err:
+fsck_err:
+ bch2_trans_iter_exit(trans, &lru_iter);
+ printbuf_exit(&buf);
+ return ret;
+}
+
static int bch2_check_lru_key(struct btree_trans *trans,
struct btree_iter *lru_iter,
struct bkey_s_c lru_k,
diff --git a/fs/bcachefs/lru.h b/fs/bcachefs/lru.h
index bd71ba77de07..ed75bcf59d47 100644
--- a/fs/bcachefs/lru.h
+++ b/fs/bcachefs/lru.h
@@ -61,6 +61,9 @@ int bch2_lru_del(struct btree_trans *, u16, u64, u64);
int bch2_lru_set(struct btree_trans *, u16, u64, u64);
int bch2_lru_change(struct btree_trans *, u16, u64, u64, u64);
+struct bkey_buf;
+int bch2_lru_check_set(struct btree_trans *, u16, u64, struct bkey_s_c, struct bkey_buf *);
+
int bch2_check_lrus(struct bch_fs *);
#endif /* _BCACHEFS_LRU_H */
diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c
index 6e477fadaa2a..e714e3bd5bbb 100644
--- a/fs/bcachefs/move.c
+++ b/fs/bcachefs/move.c
@@ -36,31 +36,6 @@ const char * const bch2_data_ops_strs[] = {
NULL
};
-static void bch2_data_update_opts_to_text(struct printbuf *out, struct bch_fs *c,
- struct bch_io_opts *io_opts,
- struct data_update_opts *data_opts)
-{
- printbuf_tabstop_push(out, 20);
- prt_str(out, "rewrite ptrs:\t");
- bch2_prt_u64_base2(out, data_opts->rewrite_ptrs);
- prt_newline(out);
-
- prt_str(out, "kill ptrs:\t");
- bch2_prt_u64_base2(out, data_opts->kill_ptrs);
- prt_newline(out);
-
- prt_str(out, "target:\t");
- bch2_target_to_text(out, c, data_opts->target);
- prt_newline(out);
-
- prt_str(out, "compression:\t");
- bch2_compression_opt_to_text(out, background_compression(*io_opts));
- prt_newline(out);
-
- prt_str(out, "extra replicas:\t");
- prt_u64(out, data_opts->extra_replicas);
-}
-
static void trace_move_extent2(struct bch_fs *c, struct bkey_s_c k,
struct bch_io_opts *io_opts,
struct data_update_opts *data_opts)
diff --git a/fs/bcachefs/sb-errors_format.h b/fs/bcachefs/sb-errors_format.h
index d6f35a99c429..d54121ec093f 100644
--- a/fs/bcachefs/sb-errors_format.h
+++ b/fs/bcachefs/sb-errors_format.h
@@ -286,7 +286,8 @@ enum bch_fsck_flags {
x(accounting_mismatch, 272, 0) \
x(accounting_replicas_not_marked, 273, 0) \
x(invalid_btree_id, 274, 0) \
- x(alloc_key_io_time_bad, 275, 0)
+ x(alloc_key_io_time_bad, 275, 0) \
+ x(alloc_key_fragmentation_lru_wrong, 276, FSCK_AUTOFIX)
enum bch_sb_error_id {
#define x(t, n, ...) BCH_FSCK_ERR_##t = n,
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index fb906467201e..da735608d47c 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -563,8 +563,11 @@ static void __bch2_fs_free(struct bch_fs *c)
BUG_ON(atomic_read(&c->journal_keys.ref));
bch2_fs_btree_write_buffer_exit(c);
percpu_free_rwsem(&c->mark_lock);
- EBUG_ON(c->online_reserved && percpu_u64_get(c->online_reserved));
- free_percpu(c->online_reserved);
+ if (c->online_reserved) {
+ u64 v = percpu_u64_get(c->online_reserved);
+ WARN(v, "online_reserved not 0 at shutdown: %lli", v);
+ free_percpu(c->online_reserved);
+ }
darray_exit(&c->btree_roots_extra);
free_percpu(c->pcpu);
@@ -1769,7 +1772,7 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
if (ret)
goto err;
- ret = bch2_dev_journal_alloc(ca);
+ ret = bch2_dev_journal_alloc(ca, true);
bch_err_msg(c, ret, "allocating journal");
if (ret)
goto err;
@@ -1929,7 +1932,7 @@ int bch2_dev_online(struct bch_fs *c, const char *path)
}
if (!ca->journal.nr) {
- ret = bch2_dev_journal_alloc(ca);
+ ret = bch2_dev_journal_alloc(ca, false);
bch_err_msg(ca, ret, "allocating journal");
if (ret)
goto err;
diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c
index de331dec2a99..4ec7e44d6e36 100644
--- a/fs/bcachefs/util.c
+++ b/fs/bcachefs/util.c
@@ -252,8 +252,10 @@ void bch2_prt_u64_base2(struct printbuf *out, u64 v)
bch2_prt_u64_base2_nbits(out, v, fls64(v) ?: 1);
}
-void bch2_print_string_as_lines(const char *prefix, const char *lines)
+static void __bch2_print_string_as_lines(const char *prefix, const char *lines,
+ bool nonblocking)
{
+ bool locked = false;
const char *p;
if (!lines) {
@@ -261,7 +263,13 @@ void bch2_print_string_as_lines(const char *prefix, const char *lines)
return;
}
- console_lock();
+ if (!nonblocking) {
+ console_lock();
+ locked = true;
+ } else {
+ locked = console_trylock();
+ }
+
while (1) {
p = strchrnul(lines, '\n');
printk("%s%.*s\n", prefix, (int) (p - lines), lines);
@@ -269,7 +277,18 @@ void bch2_print_string_as_lines(const char *prefix, const char *lines)
break;
lines = p + 1;
}
- console_unlock();
+ if (locked)
+ console_unlock();
+}
+
+void bch2_print_string_as_lines(const char *prefix, const char *lines)
+{
+ return __bch2_print_string_as_lines(prefix, lines, false);
+}
+
+void bch2_print_string_as_lines_nonblocking(const char *prefix, const char *lines)
+{
+ return __bch2_print_string_as_lines(prefix, lines, true);
}
int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *task, unsigned skipnr,
diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h
index 5d2c470a49ac..5b0533ec4c7e 100644
--- a/fs/bcachefs/util.h
+++ b/fs/bcachefs/util.h
@@ -315,6 +315,7 @@ void bch2_prt_u64_base2_nbits(struct printbuf *, u64, unsigned);
void bch2_prt_u64_base2(struct printbuf *, u64);
void bch2_print_string_as_lines(const char *prefix, const char *lines);
+void bch2_print_string_as_lines_nonblocking(const char *prefix, const char *lines);
typedef DARRAY(unsigned long) bch_stacktrace;
int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *, unsigned, gfp_t);
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index d76f406d3b2e..f92f108840f5 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -475,6 +475,7 @@ static int befs_symlink_read_folio(struct file *unused, struct folio *folio)
befs_data_stream *data = &befs_ino->i_data.ds;
befs_off_t len = data->size;
char *link = folio_address(folio);
+ int err = -EIO;
if (len == 0 || len > PAGE_SIZE) {
befs_error(sb, "Long symlink with illegal length");
@@ -487,13 +488,10 @@ static int befs_symlink_read_folio(struct file *unused, struct folio *folio)
goto fail;
}
link[len - 1] = '\0';
- folio_mark_uptodate(folio);
- folio_unlock(folio);
- return 0;
+ err = 0;
fail:
- folio_set_error(folio);
- folio_unlock(folio);
- return -EIO;
+ folio_end_read(folio, err == 0);
+ return err;
}
/*
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index a43897b03ce9..6fdec541f8bf 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1216,7 +1216,6 @@ out_free_interp:
}
reloc_func_desc = interp_load_addr;
- allow_write_access(interpreter);
fput(interpreter);
kfree(interp_elf_ex);
@@ -1308,7 +1307,6 @@ out_free_dentry:
kfree(interp_elf_ex);
kfree(interp_elf_phdata);
out_free_file:
- allow_write_access(interpreter);
if (interpreter)
fput(interpreter);
out_free_ph:
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index b799701454a9..28a3439f163a 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -394,7 +394,6 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
goto error;
}
- allow_write_access(interpreter);
fput(interpreter);
interpreter = NULL;
}
@@ -466,10 +465,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
retval = 0;
error:
- if (interpreter) {
- allow_write_access(interpreter);
+ if (interpreter)
fput(interpreter);
- }
kfree(interpreter_name);
kfree(exec_params.phdrs);
kfree(exec_params.loadmap);
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 68fa225f89e5..31660d8cc2c6 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -247,13 +247,10 @@ static int load_misc_binary(struct linux_binprm *bprm)
if (retval < 0)
goto ret;
- if (fmt->flags & MISC_FMT_OPEN_FILE) {
+ if (fmt->flags & MISC_FMT_OPEN_FILE)
interp_file = file_clone_open(fmt->interp_file);
- if (!IS_ERR(interp_file))
- deny_write_access(interp_file);
- } else {
+ else
interp_file = open_exec(fmt->interpreter);
- }
retval = PTR_ERR(interp_file);
if (IS_ERR(interp_file))
goto ret;
@@ -1086,4 +1083,5 @@ static void __exit exit_misc_binfmt(void)
core_initcall(init_misc_binfmt);
module_exit(exit_misc_binfmt);
+MODULE_DESCRIPTION("Kernel support for miscellaneous binaries");
MODULE_LICENSE("GPL");
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c
index 1b6625e95958..637daf6e4d45 100644
--- a/fs/binfmt_script.c
+++ b/fs/binfmt_script.c
@@ -155,4 +155,5 @@ static void __exit exit_script_binfmt(void)
core_initcall(init_script_binfmt);
module_exit(exit_script_binfmt);
+MODULE_DESCRIPTION("Kernel support for scripts starting with #!");
MODULE_LICENSE("GPL");
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 1a66be33bb04..60066822b532 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -1924,8 +1924,17 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
next:
if (ret) {
/* Refcount held by the reclaim_bgs list after splice. */
- btrfs_get_block_group(bg);
- list_add_tail(&bg->bg_list, &retry_list);
+ spin_lock(&fs_info->unused_bgs_lock);
+ /*
+ * This block group might be added to the unused list
+ * during the above process. Move it back to the
+ * reclaim list otherwise.
+ */
+ if (list_empty(&bg->bg_list)) {
+ btrfs_get_block_group(bg);
+ list_add_tail(&bg->bg_list, &retry_list);
+ }
+ spin_unlock(&fs_info->unused_bgs_lock);
}
btrfs_put_block_group(bg);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 38cdb8875e8e..cabb558dbdaa 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2856,6 +2856,8 @@ static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_block
if (ret)
return ret;
+ spin_lock_init(&fs_info->extent_map_shrinker_lock);
+
ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL);
if (ret)
return ret;
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index f688fab55251..958155cc43a8 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3553,7 +3553,7 @@ err:
for (int i = 0; i < num_folios; i++) {
if (eb->folios[i]) {
detach_extent_buffer_folio(eb, eb->folios[i]);
- __folio_put(eb->folios[i]);
+ folio_put(eb->folios[i]);
}
}
__free_extent_buffer(eb);
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 744e8952abb0..b4c9a6aa118c 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -1028,7 +1028,14 @@ out_free_pre:
return ret;
}
-static long btrfs_scan_inode(struct btrfs_inode *inode, long *scanned, long nr_to_scan)
+struct btrfs_em_shrink_ctx {
+ long nr_to_scan;
+ long scanned;
+ u64 last_ino;
+ u64 last_root;
+};
+
+static long btrfs_scan_inode(struct btrfs_inode *inode, struct btrfs_em_shrink_ctx *ctx)
{
const u64 cur_fs_gen = btrfs_get_fs_generation(inode->root->fs_info);
struct extent_map_tree *tree = &inode->extent_tree;
@@ -1057,14 +1064,25 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, long *scanned, long nr_t
if (!down_read_trylock(&inode->i_mmap_lock))
return 0;
- write_lock(&tree->lock);
+ /*
+ * We want to be fast because we can be called from any path trying to
+ * allocate memory, so if the lock is busy we don't want to spend time
+ * waiting for it - either some task is about to do IO for the inode or
+ * we may have another task shrinking extent maps, here in this code, so
+ * skip this inode.
+ */
+ if (!write_trylock(&tree->lock)) {
+ up_read(&inode->i_mmap_lock);
+ return 0;
+ }
+
node = rb_first_cached(&tree->map);
while (node) {
struct extent_map *em;
em = rb_entry(node, struct extent_map, rb_node);
node = rb_next(node);
- (*scanned)++;
+ ctx->scanned++;
if (em->flags & EXTENT_FLAG_PINNED)
goto next;
@@ -1085,16 +1103,18 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, long *scanned, long nr_t
free_extent_map(em);
nr_dropped++;
next:
- if (*scanned >= nr_to_scan)
+ if (ctx->scanned >= ctx->nr_to_scan)
break;
/*
- * Restart if we had to reschedule, and any extent maps that were
- * pinned before may have become unpinned after we released the
- * lock and took it again.
+ * Stop if we need to reschedule or there's contention on the
+ * lock. This is to avoid slowing other tasks trying to take the
+ * lock and because the shrinker might be called during a memory
+ * allocation path and we want to avoid taking a very long time
+ * and slowing down all sorts of tasks.
*/
- if (cond_resched_rwlock_write(&tree->lock))
- node = rb_first_cached(&tree->map);
+ if (need_resched() || rwlock_needbreak(&tree->lock))
+ break;
}
write_unlock(&tree->lock);
up_read(&inode->i_mmap_lock);
@@ -1102,25 +1122,30 @@ next:
return nr_dropped;
}
-static long btrfs_scan_root(struct btrfs_root *root, long *scanned, long nr_to_scan)
+static long btrfs_scan_root(struct btrfs_root *root, struct btrfs_em_shrink_ctx *ctx)
{
- struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_inode *inode;
long nr_dropped = 0;
- u64 min_ino = fs_info->extent_map_shrinker_last_ino + 1;
+ u64 min_ino = ctx->last_ino + 1;
inode = btrfs_find_first_inode(root, min_ino);
while (inode) {
- nr_dropped += btrfs_scan_inode(inode, scanned, nr_to_scan);
+ nr_dropped += btrfs_scan_inode(inode, ctx);
min_ino = btrfs_ino(inode) + 1;
- fs_info->extent_map_shrinker_last_ino = btrfs_ino(inode);
- iput(&inode->vfs_inode);
+ ctx->last_ino = btrfs_ino(inode);
+ btrfs_add_delayed_iput(inode);
- if (*scanned >= nr_to_scan)
+ if (ctx->scanned >= ctx->nr_to_scan)
+ break;
+
+ /*
+ * We may be called from memory allocation paths, so we don't
+ * want to take too much time and slowdown tasks.
+ */
+ if (need_resched())
break;
- cond_resched();
inode = btrfs_find_first_inode(root, min_ino);
}
@@ -1132,14 +1157,14 @@ static long btrfs_scan_root(struct btrfs_root *root, long *scanned, long nr_to_s
* inode if there is one or we will find out this was the last
* one and move to the next root.
*/
- fs_info->extent_map_shrinker_last_root = btrfs_root_id(root);
+ ctx->last_root = btrfs_root_id(root);
} else {
/*
* No more inodes in this root, set extent_map_shrinker_last_ino to 0 so
* that when processing the next root we start from its first inode.
*/
- fs_info->extent_map_shrinker_last_ino = 0;
- fs_info->extent_map_shrinker_last_root = btrfs_root_id(root) + 1;
+ ctx->last_ino = 0;
+ ctx->last_root = btrfs_root_id(root) + 1;
}
return nr_dropped;
@@ -1147,19 +1172,41 @@ static long btrfs_scan_root(struct btrfs_root *root, long *scanned, long nr_to_s
long btrfs_free_extent_maps(struct btrfs_fs_info *fs_info, long nr_to_scan)
{
- const u64 start_root_id = fs_info->extent_map_shrinker_last_root;
- u64 next_root_id = start_root_id;
+ struct btrfs_em_shrink_ctx ctx;
+ u64 start_root_id;
+ u64 next_root_id;
bool cycled = false;
long nr_dropped = 0;
- long scanned = 0;
+
+ ctx.scanned = 0;
+ ctx.nr_to_scan = nr_to_scan;
+
+ /*
+ * In case we have multiple tasks running this shrinker, make the next
+ * one start from the next inode in case it starts before we finish.
+ */
+ spin_lock(&fs_info->extent_map_shrinker_lock);
+ ctx.last_ino = fs_info->extent_map_shrinker_last_ino;
+ fs_info->extent_map_shrinker_last_ino++;
+ ctx.last_root = fs_info->extent_map_shrinker_last_root;
+ spin_unlock(&fs_info->extent_map_shrinker_lock);
+
+ start_root_id = ctx.last_root;
+ next_root_id = ctx.last_root;
if (trace_btrfs_extent_map_shrinker_scan_enter_enabled()) {
s64 nr = percpu_counter_sum_positive(&fs_info->evictable_extent_maps);
- trace_btrfs_extent_map_shrinker_scan_enter(fs_info, nr_to_scan, nr);
+ trace_btrfs_extent_map_shrinker_scan_enter(fs_info, nr_to_scan,
+ nr, ctx.last_root,
+ ctx.last_ino);
}
- while (scanned < nr_to_scan) {
+ /*
+ * We may be called from memory allocation paths, so we don't want to
+ * take too much time and slowdown tasks, so stop if we need reschedule.
+ */
+ while (ctx.scanned < ctx.nr_to_scan && !need_resched()) {
struct btrfs_root *root;
unsigned long count;
@@ -1171,8 +1218,8 @@ long btrfs_free_extent_maps(struct btrfs_fs_info *fs_info, long nr_to_scan)
spin_unlock(&fs_info->fs_roots_radix_lock);
if (start_root_id > 0 && !cycled) {
next_root_id = 0;
- fs_info->extent_map_shrinker_last_root = 0;
- fs_info->extent_map_shrinker_last_ino = 0;
+ ctx.last_root = 0;
+ ctx.last_ino = 0;
cycled = true;
continue;
}
@@ -1186,15 +1233,33 @@ long btrfs_free_extent_maps(struct btrfs_fs_info *fs_info, long nr_to_scan)
continue;
if (is_fstree(btrfs_root_id(root)))
- nr_dropped += btrfs_scan_root(root, &scanned, nr_to_scan);
+ nr_dropped += btrfs_scan_root(root, &ctx);
btrfs_put_root(root);
}
+ /*
+ * In case of multiple tasks running this extent map shrinking code this
+ * isn't perfect but it's simple and silences things like KCSAN. It's
+ * not possible to know which task made more progress because we can
+ * cycle back to the first root and first inode if it's not the first
+ * time the shrinker ran, see the above logic. Also a task that started
+ * later may finish ealier than another task and made less progress. So
+ * make this simple and update to the progress of the last task that
+ * finished, with the occasional possiblity of having two consecutive
+ * runs of the shrinker process the same inodes.
+ */
+ spin_lock(&fs_info->extent_map_shrinker_lock);
+ fs_info->extent_map_shrinker_last_ino = ctx.last_ino;
+ fs_info->extent_map_shrinker_last_root = ctx.last_root;
+ spin_unlock(&fs_info->extent_map_shrinker_lock);
+
if (trace_btrfs_extent_map_shrinker_scan_exit_enabled()) {
s64 nr = percpu_counter_sum_positive(&fs_info->evictable_extent_maps);
- trace_btrfs_extent_map_shrinker_scan_exit(fs_info, nr_dropped, nr);
+ trace_btrfs_extent_map_shrinker_scan_exit(fs_info, nr_dropped,
+ nr, ctx.last_root,
+ ctx.last_ino);
}
return nr_dropped;
diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h
index 89f0650631cd..833dc3fe0a38 100644
--- a/fs/btrfs/fs.h
+++ b/fs/btrfs/fs.h
@@ -630,6 +630,7 @@ struct btrfs_fs_info {
s32 delalloc_batch;
struct percpu_counter evictable_extent_maps;
+ spinlock_t extent_map_shrinker_lock;
u64 extent_map_shrinker_last_root;
u64 extent_map_shrinker_last_ino;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 753db965f7c0..d62c96f00ff8 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5587,7 +5587,7 @@ static struct inode *btrfs_iget_locked(struct super_block *s, u64 ino,
args.ino = ino;
args.root = root;
- inode = iget5_locked(s, hashval, btrfs_find_actor,
+ inode = iget5_locked_rcu(s, hashval, btrfs_find_actor,
btrfs_init_locked_inode,
(void *)&args);
return inode;
@@ -10385,7 +10385,7 @@ out_unlock:
out_folios:
for (i = 0; i < nr_folios; i++) {
if (folios[i])
- __folio_put(folios[i]);
+ folio_put(folios[i]);
}
kvfree(folios);
out:
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index efd5d6e9589e..6ad524b894fc 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4627,7 +4627,7 @@ static int btrfs_ioctl_encoded_write(struct file *file, void __user *argp, bool
goto out_iov;
init_sync_kiocb(&kiocb, file);
- ret = kiocb_set_rw_flags(&kiocb, 0);
+ ret = kiocb_set_rw_flags(&kiocb, 0, WRITE);
if (ret)
goto out_iov;
kiocb.ki_pos = pos;
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index bf0f81d59b6b..39a15cca58ca 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -3062,8 +3062,6 @@ int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info,
struct btrfs_qgroup_inherit *inherit,
size_t size)
{
- if (!btrfs_qgroup_enabled(fs_info))
- return 0;
if (inherit->flags & ~BTRFS_QGROUP_INHERIT_FLAGS_SUPP)
return -EOPNOTSUPP;
if (size < sizeof(*inherit) || size > PAGE_SIZE)
@@ -3085,6 +3083,14 @@ int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info,
return -EINVAL;
/*
+ * Skip the inherit source qgroups check if qgroup is not enabled.
+ * Qgroup can still be later enabled causing problems, but in that case
+ * btrfs_qgroup_inherit() would just ignore those invalid ones.
+ */
+ if (!btrfs_qgroup_enabled(fs_info))
+ return 0;
+
+ /*
* Now check all the remaining qgroups, they should all:
*
* - Exist
diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c
index cf531255ab76..9522a8b79d22 100644
--- a/fs/btrfs/ref-verify.c
+++ b/fs/btrfs/ref-verify.c
@@ -441,7 +441,8 @@ static int process_extent_item(struct btrfs_fs_info *fs_info,
u32 item_size = btrfs_item_size(leaf, slot);
unsigned long end, ptr;
u64 offset, flags, count;
- int type, ret;
+ int type;
+ int ret = 0;
ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
flags = btrfs_extent_flags(leaf, ei);
@@ -486,7 +487,11 @@ static int process_extent_item(struct btrfs_fs_info *fs_info,
key->objectid, key->offset);
break;
case BTRFS_EXTENT_OWNER_REF_KEY:
- WARN_ON(!btrfs_fs_incompat(fs_info, SIMPLE_QUOTA));
+ if (!btrfs_fs_incompat(fs_info, SIMPLE_QUOTA)) {
+ btrfs_err(fs_info,
+ "found extent owner ref without simple quotas enabled");
+ ret = -EINVAL;
+ }
break;
default:
btrfs_err(fs_info, "invalid key type in iref");
diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c
index d620323d08ea..ae8c56442549 100644
--- a/fs/btrfs/space-info.c
+++ b/fs/btrfs/space-info.c
@@ -373,11 +373,18 @@ static u64 calc_available_free_space(struct btrfs_fs_info *fs_info,
* "optimal" chunk size based on the fs size. However when we actually
* allocate the chunk we will strip this down further, making it no more
* than 10% of the disk or 1G, whichever is smaller.
+ *
+ * On the zoned mode, we need to use zone_size (=
+ * data_sinfo->chunk_size) as it is.
*/
data_sinfo = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA);
- data_chunk_size = min(data_sinfo->chunk_size,
- mult_perc(fs_info->fs_devices->total_rw_bytes, 10));
- data_chunk_size = min_t(u64, data_chunk_size, SZ_1G);
+ if (!btrfs_is_zoned(fs_info)) {
+ data_chunk_size = min(data_sinfo->chunk_size,
+ mult_perc(fs_info->fs_devices->total_rw_bytes, 10));
+ data_chunk_size = min_t(u64, data_chunk_size, SZ_1G);
+ } else {
+ data_chunk_size = data_sinfo->chunk_size;
+ }
/*
* Since data allocations immediately use block groups as part of the
@@ -405,6 +412,17 @@ static u64 calc_available_free_space(struct btrfs_fs_info *fs_info,
avail >>= 3;
else
avail >>= 1;
+
+ /*
+ * On the zoned mode, we always allocate one zone as one chunk.
+ * Returning non-zone size alingned bytes here will result in
+ * less pressure for the async metadata reclaim process, and it
+ * will over-commit too much leading to ENOSPC. Align down to the
+ * zone size to avoid that.
+ */
+ if (btrfs_is_zoned(fs_info))
+ avail = ALIGN_DOWN(avail, fs_info->zone_size);
+
return avail;
}
diff --git a/fs/buffer.c b/fs/buffer.c
index 8c19e705b9c3..dbe8f411ce52 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -258,7 +258,6 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
} else {
clear_buffer_uptodate(bh);
buffer_io_error(bh, ", async page read");
- folio_set_error(folio);
}
/*
@@ -391,7 +390,6 @@ static void end_buffer_async_write(struct buffer_head *bh, int uptodate)
buffer_io_error(bh, ", lost async page write");
mark_buffer_write_io_error(bh);
clear_buffer_uptodate(bh);
- folio_set_error(folio);
}
first = folio_buffers(folio);
@@ -1960,7 +1958,6 @@ recover:
clear_buffer_dirty(bh);
}
} while ((bh = bh->b_this_page) != head);
- folio_set_error(folio);
BUG_ON(folio_test_writeback(folio));
mapping_set_error(folio->mapping, err);
folio_start_writeback(folio);
@@ -2405,10 +2402,8 @@ int block_read_full_folio(struct folio *folio, get_block_t *get_block)
if (iblock < lblock) {
WARN_ON(bh->b_size != blocksize);
err = get_block(inode, iblock, bh, 0);
- if (err) {
- folio_set_error(folio);
+ if (err)
page_error = true;
- }
}
if (!buffer_mapped(bh)) {
folio_zero_range(folio, i * blocksize,
diff --git a/fs/cachefiles/cache.c b/fs/cachefiles/cache.c
index f449f7340aad..9fb06dc16520 100644
--- a/fs/cachefiles/cache.c
+++ b/fs/cachefiles/cache.c
@@ -8,6 +8,7 @@
#include <linux/slab.h>
#include <linux/statfs.h>
#include <linux/namei.h>
+#include <trace/events/fscache.h>
#include "internal.h"
/*
@@ -312,19 +313,59 @@ static void cachefiles_withdraw_objects(struct cachefiles_cache *cache)
}
/*
- * Withdraw volumes.
+ * Withdraw fscache volumes.
+ */
+static void cachefiles_withdraw_fscache_volumes(struct cachefiles_cache *cache)
+{
+ struct list_head *cur;
+ struct cachefiles_volume *volume;
+ struct fscache_volume *vcookie;
+
+ _enter("");
+retry:
+ spin_lock(&cache->object_list_lock);
+ list_for_each(cur, &cache->volumes) {
+ volume = list_entry(cur, struct cachefiles_volume, cache_link);
+
+ if (atomic_read(&volume->vcookie->n_accesses) == 0)
+ continue;
+
+ vcookie = fscache_try_get_volume(volume->vcookie,
+ fscache_volume_get_withdraw);
+ if (vcookie) {
+ spin_unlock(&cache->object_list_lock);
+ fscache_withdraw_volume(vcookie);
+ fscache_put_volume(vcookie, fscache_volume_put_withdraw);
+ goto retry;
+ }
+ }
+ spin_unlock(&cache->object_list_lock);
+
+ _leave("");
+}
+
+/*
+ * Withdraw cachefiles volumes.
*/
static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache)
{
_enter("");
for (;;) {
+ struct fscache_volume *vcookie = NULL;
struct cachefiles_volume *volume = NULL;
spin_lock(&cache->object_list_lock);
if (!list_empty(&cache->volumes)) {
volume = list_first_entry(&cache->volumes,
struct cachefiles_volume, cache_link);
+ vcookie = fscache_try_get_volume(volume->vcookie,
+ fscache_volume_get_withdraw);
+ if (!vcookie) {
+ spin_unlock(&cache->object_list_lock);
+ cpu_relax();
+ continue;
+ }
list_del_init(&volume->cache_link);
}
spin_unlock(&cache->object_list_lock);
@@ -332,6 +373,7 @@ static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache)
break;
cachefiles_withdraw_volume(volume);
+ fscache_put_volume(vcookie, fscache_volume_put_withdraw);
}
_leave("");
@@ -371,6 +413,7 @@ void cachefiles_withdraw_cache(struct cachefiles_cache *cache)
pr_info("File cache on %s unregistering\n", fscache->name);
fscache_withdraw_cache(fscache);
+ cachefiles_withdraw_fscache_volumes(cache);
/* we now have to destroy all the active objects pertaining to this
* cache - which we do by passing them off to thread pool to be
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c
index 06cdf1a8a16f..89b11336a836 100644
--- a/fs/cachefiles/daemon.c
+++ b/fs/cachefiles/daemon.c
@@ -366,14 +366,14 @@ static __poll_t cachefiles_daemon_poll(struct file *file,
if (cachefiles_in_ondemand_mode(cache)) {
if (!xa_empty(&cache->reqs)) {
- rcu_read_lock();
+ xas_lock(&xas);
xas_for_each_marked(&xas, req, ULONG_MAX, CACHEFILES_REQ_NEW) {
if (!cachefiles_ondemand_is_reopening_read(req)) {
mask |= EPOLLIN;
break;
}
}
- rcu_read_unlock();
+ xas_unlock(&xas);
}
} else {
if (test_bit(CACHEFILES_STATE_CHANGED, &cache->flags))
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index 6845a90cdfcc..7b99bd98de75 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -48,6 +48,7 @@ enum cachefiles_object_state {
CACHEFILES_ONDEMAND_OBJSTATE_CLOSE, /* Anonymous fd closed by daemon or initial state */
CACHEFILES_ONDEMAND_OBJSTATE_OPEN, /* Anonymous fd associated with object is available */
CACHEFILES_ONDEMAND_OBJSTATE_REOPENING, /* Object that was closed and is being reopened. */
+ CACHEFILES_ONDEMAND_OBJSTATE_DROPPING, /* Object is being dropped. */
};
struct cachefiles_ondemand_info {
@@ -128,6 +129,7 @@ struct cachefiles_cache {
unsigned long req_id_next;
struct xarray ondemand_ids; /* xarray for ondemand_id allocation */
u32 ondemand_id_next;
+ u32 msg_id_next;
};
static inline bool cachefiles_in_ondemand_mode(struct cachefiles_cache *cache)
@@ -335,6 +337,7 @@ cachefiles_ondemand_set_object_##_state(struct cachefiles_object *object) \
CACHEFILES_OBJECT_STATE_FUNCS(open, OPEN);
CACHEFILES_OBJECT_STATE_FUNCS(close, CLOSE);
CACHEFILES_OBJECT_STATE_FUNCS(reopening, REOPENING);
+CACHEFILES_OBJECT_STATE_FUNCS(dropping, DROPPING);
static inline bool cachefiles_ondemand_is_reopening_read(struct cachefiles_req *req)
{
diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
index bce005f2b456..470c96658385 100644
--- a/fs/cachefiles/ondemand.c
+++ b/fs/cachefiles/ondemand.c
@@ -517,7 +517,8 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,
*/
xas_lock(&xas);
- if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
+ if (test_bit(CACHEFILES_DEAD, &cache->flags) ||
+ cachefiles_ondemand_object_is_dropping(object)) {
xas_unlock(&xas);
ret = -EIO;
goto out;
@@ -527,20 +528,32 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,
smp_mb();
if (opcode == CACHEFILES_OP_CLOSE &&
- !cachefiles_ondemand_object_is_open(object)) {
+ !cachefiles_ondemand_object_is_open(object)) {
WARN_ON_ONCE(object->ondemand->ondemand_id == 0);
xas_unlock(&xas);
ret = -EIO;
goto out;
}
- xas.xa_index = 0;
+ /*
+ * Cyclically find a free xas to avoid msg_id reuse that would
+ * cause the daemon to successfully copen a stale msg_id.
+ */
+ xas.xa_index = cache->msg_id_next;
xas_find_marked(&xas, UINT_MAX, XA_FREE_MARK);
+ if (xas.xa_node == XAS_RESTART) {
+ xas.xa_index = 0;
+ xas_find_marked(&xas, cache->msg_id_next - 1, XA_FREE_MARK);
+ }
if (xas.xa_node == XAS_RESTART)
xas_set_err(&xas, -EBUSY);
+
xas_store(&xas, req);
- xas_clear_mark(&xas, XA_FREE_MARK);
- xas_set_mark(&xas, CACHEFILES_REQ_NEW);
+ if (xas_valid(&xas)) {
+ cache->msg_id_next = xas.xa_index + 1;
+ xas_clear_mark(&xas, XA_FREE_MARK);
+ xas_set_mark(&xas, CACHEFILES_REQ_NEW);
+ }
xas_unlock(&xas);
} while (xas_nomem(&xas, GFP_KERNEL));
@@ -568,7 +581,8 @@ out:
* If error occurs after creating the anonymous fd,
* cachefiles_ondemand_fd_release() will set object to close.
*/
- if (opcode == CACHEFILES_OP_OPEN)
+ if (opcode == CACHEFILES_OP_OPEN &&
+ !cachefiles_ondemand_object_is_dropping(object))
cachefiles_ondemand_set_object_close(object);
kfree(req);
return ret;
@@ -667,8 +681,34 @@ int cachefiles_ondemand_init_object(struct cachefiles_object *object)
void cachefiles_ondemand_clean_object(struct cachefiles_object *object)
{
+ unsigned long index;
+ struct cachefiles_req *req;
+ struct cachefiles_cache *cache;
+
+ if (!object->ondemand)
+ return;
+
cachefiles_ondemand_send_req(object, CACHEFILES_OP_CLOSE, 0,
cachefiles_ondemand_init_close_req, NULL);
+
+ if (!object->ondemand->ondemand_id)
+ return;
+
+ /* Cancel all requests for the object that is being dropped. */
+ cache = object->volume->cache;
+ xa_lock(&cache->reqs);
+ cachefiles_ondemand_set_object_dropping(object);
+ xa_for_each(&cache->reqs, index, req) {
+ if (req->object == object) {
+ req->error = -EIO;
+ complete(&req->done);
+ __xa_erase(&cache->reqs, index);
+ }
+ }
+ xa_unlock(&cache->reqs);
+
+ /* Wait for ondemand_object_worker() to finish to avoid UAF. */
+ cancel_work_sync(&object->ondemand->ondemand_work);
}
int cachefiles_ondemand_init_obj_info(struct cachefiles_object *object,
diff --git a/fs/cachefiles/volume.c b/fs/cachefiles/volume.c
index 89df0ba8ba5e..781aac4ef274 100644
--- a/fs/cachefiles/volume.c
+++ b/fs/cachefiles/volume.c
@@ -133,7 +133,6 @@ void cachefiles_free_volume(struct fscache_volume *vcookie)
void cachefiles_withdraw_volume(struct cachefiles_volume *volume)
{
- fscache_withdraw_volume(volume->vcookie);
cachefiles_set_volume_xattr(volume);
__cachefiles_free_volume(volume);
}
diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c
index bcb6173943ee..4dd8a993c60a 100644
--- a/fs/cachefiles/xattr.c
+++ b/fs/cachefiles/xattr.c
@@ -110,9 +110,11 @@ int cachefiles_check_auxdata(struct cachefiles_object *object, struct file *file
if (xlen == 0)
xlen = vfs_getxattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache, buf, tlen);
if (xlen != tlen) {
- if (xlen < 0)
+ if (xlen < 0) {
+ ret = xlen;
trace_cachefiles_vfs_error(object, file_inode(file), xlen,
cachefiles_trace_getxattr_error);
+ }
if (xlen == -EIO)
cachefiles_io_error_obj(
object,
@@ -252,6 +254,7 @@ int cachefiles_check_volume_xattr(struct cachefiles_volume *volume)
xlen = vfs_getxattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache, buf, len);
if (xlen != len) {
if (xlen < 0) {
+ ret = xlen;
trace_cachefiles_vfs_error(NULL, d_inode(dentry), xlen,
cachefiles_trace_getxattr_error);
if (xlen == -EIO)
diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c
index ccdbec388091..40f84d014524 100644
--- a/fs/coda/symlink.c
+++ b/fs/coda/symlink.c
@@ -31,15 +31,7 @@ static int coda_symlink_filler(struct file *file, struct folio *folio)
cii = ITOC(inode);
error = venus_readlink(inode->i_sb, &cii->c_fid, p, &len);
- if (error)
- goto fail;
- folio_mark_uptodate(folio);
- folio_unlock(folio);
- return 0;
-
-fail:
- folio_set_error(folio);
- folio_unlock(folio);
+ folio_end_read(folio, error == 0);
return error;
}
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 18677cd4e62f..43d6bde1adcc 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -580,6 +580,7 @@ static void detach_attrs(struct config_item * item)
static int populate_attrs(struct config_item *item)
{
const struct config_item_type *t = item->ci_type;
+ struct configfs_group_operations *ops;
struct configfs_attribute *attr;
struct configfs_bin_attribute *bin_attr;
int error = 0;
@@ -587,14 +588,23 @@ static int populate_attrs(struct config_item *item)
if (!t)
return -EINVAL;
+
+ ops = t->ct_group_ops;
+
if (t->ct_attrs) {
for (i = 0; (attr = t->ct_attrs[i]) != NULL; i++) {
+ if (ops && ops->is_visible && !ops->is_visible(item, attr, i))
+ continue;
+
if ((error = configfs_create_file(item, attr)))
break;
}
}
if (t->ct_bin_attrs) {
for (i = 0; (bin_attr = t->ct_bin_attrs[i]) != NULL; i++) {
+ if (ops && ops->is_bin_visible && !ops->is_bin_visible(item, bin_attr, i))
+ continue;
+
error = configfs_create_bin_file(item, bin_attr);
if (error)
break;
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 460690ca0174..b84d1747a020 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -811,19 +811,19 @@ out:
static int cramfs_read_folio(struct file *file, struct folio *folio)
{
- struct page *page = &folio->page;
- struct inode *inode = page->mapping->host;
+ struct inode *inode = folio->mapping->host;
u32 maxblock;
int bytes_filled;
void *pgdata;
+ bool success = false;
maxblock = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
bytes_filled = 0;
- pgdata = kmap_local_page(page);
+ pgdata = kmap_local_folio(folio, 0);
- if (page->index < maxblock) {
+ if (folio->index < maxblock) {
struct super_block *sb = inode->i_sb;
- u32 blkptr_offset = OFFSET(inode) + page->index * 4;
+ u32 blkptr_offset = OFFSET(inode) + folio->index * 4;
u32 block_ptr, block_start, block_len;
bool uncompressed, direct;
@@ -844,7 +844,7 @@ static int cramfs_read_folio(struct file *file, struct folio *folio)
if (uncompressed) {
block_len = PAGE_SIZE;
/* if last block: cap to file length */
- if (page->index == maxblock - 1)
+ if (folio->index == maxblock - 1)
block_len =
offset_in_page(inode->i_size);
} else {
@@ -861,7 +861,7 @@ static int cramfs_read_folio(struct file *file, struct folio *folio)
* from the previous block's pointer.
*/
block_start = OFFSET(inode) + maxblock * 4;
- if (page->index)
+ if (folio->index)
block_start = *(u32 *)
cramfs_read(sb, blkptr_offset - 4, 4);
/* Beware... previous ptr might be a direct ptr */
@@ -906,17 +906,12 @@ static int cramfs_read_folio(struct file *file, struct folio *folio)
}
memset(pgdata + bytes_filled, 0, PAGE_SIZE - bytes_filled);
- flush_dcache_page(page);
- kunmap_local(pgdata);
- SetPageUptodate(page);
- unlock_page(page);
- return 0;
+ flush_dcache_folio(folio);
+ success = true;
err:
kunmap_local(pgdata);
- ClearPageUptodate(page);
- SetPageError(page);
- unlock_page(page);
+ folio_end_read(folio, success);
return 0;
}
@@ -1003,4 +998,5 @@ static void __exit exit_cramfs_fs(void)
module_init(init_cramfs_fs)
module_exit(exit_cramfs_fs)
+MODULE_DESCRIPTION("Compressed ROM file system support");
MODULE_LICENSE("GPL");
diff --git a/fs/dcache.c b/fs/dcache.c
index 407095188f83..8bdc278a0205 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -35,6 +35,8 @@
#include "internal.h"
#include "mount.h"
+#include <asm/runtime-const.h>
+
/*
* Usage:
* dcache->d_inode->i_lock protects:
@@ -100,9 +102,10 @@ static unsigned int d_hash_shift __ro_after_init;
static struct hlist_bl_head *dentry_hashtable __ro_after_init;
-static inline struct hlist_bl_head *d_hash(unsigned int hash)
+static inline struct hlist_bl_head *d_hash(unsigned long hashlen)
{
- return dentry_hashtable + (hash >> d_hash_shift);
+ return runtime_const_ptr(dentry_hashtable) +
+ runtime_const_shift_right_32(hashlen, d_hash_shift);
}
#define IN_LOOKUP_SHIFT 10
@@ -355,7 +358,11 @@ static inline void __d_clear_type_and_inode(struct dentry *dentry)
flags &= ~DCACHE_ENTRY_TYPE;
WRITE_ONCE(dentry->d_flags, flags);
dentry->d_inode = NULL;
- if (flags & DCACHE_LRU_LIST)
+ /*
+ * The negative counter only tracks dentries on the LRU. Don't inc if
+ * d_lru is on another list.
+ */
+ if ((flags & (DCACHE_LRU_LIST|DCACHE_SHRINK_LIST)) == DCACHE_LRU_LIST)
this_cpu_inc(nr_dentry_negative);
}
@@ -1548,7 +1555,7 @@ void shrink_dcache_for_umount(struct super_block *sb)
{
struct dentry *dentry;
- WARN(down_read_trylock(&sb->s_umount), "s_umount should've been locked");
+ rwsem_assert_held_write(&sb->s_umount);
dentry = sb->s_root;
sb->s_root = NULL;
@@ -1844,9 +1851,11 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
spin_lock(&dentry->d_lock);
/*
- * Decrement negative dentry count if it was in the LRU list.
+ * The negative counter only tracks dentries on the LRU. Don't dec if
+ * d_lru is on another list.
*/
- if (dentry->d_flags & DCACHE_LRU_LIST)
+ if ((dentry->d_flags &
+ (DCACHE_LRU_LIST|DCACHE_SHRINK_LIST)) == DCACHE_LRU_LIST)
this_cpu_dec(nr_dentry_negative);
hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
raw_write_seqcount_begin(&dentry->d_seq);
@@ -2104,7 +2113,7 @@ static noinline struct dentry *__d_lookup_rcu_op_compare(
unsigned *seqp)
{
u64 hashlen = name->hash_len;
- struct hlist_bl_head *b = d_hash(hashlen_hash(hashlen));
+ struct hlist_bl_head *b = d_hash(hashlen);
struct hlist_bl_node *node;
struct dentry *dentry;
@@ -2171,7 +2180,7 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,
{
u64 hashlen = name->hash_len;
const unsigned char *str = name->name;
- struct hlist_bl_head *b = d_hash(hashlen_hash(hashlen));
+ struct hlist_bl_head *b = d_hash(hashlen);
struct hlist_bl_node *node;
struct dentry *dentry;
@@ -3029,28 +3038,25 @@ EXPORT_SYMBOL(d_splice_alias);
bool is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
{
- bool result;
+ bool subdir;
unsigned seq;
if (new_dentry == old_dentry)
return true;
- do {
- /* for restarting inner loop in case of seq retry */
- seq = read_seqbegin(&rename_lock);
- /*
- * Need rcu_readlock to protect against the d_parent trashing
- * due to d_move
- */
- rcu_read_lock();
- if (d_ancestor(old_dentry, new_dentry))
- result = true;
- else
- result = false;
- rcu_read_unlock();
- } while (read_seqretry(&rename_lock, seq));
-
- return result;
+ /* Access d_parent under rcu as d_move() may change it. */
+ rcu_read_lock();
+ seq = read_seqbegin(&rename_lock);
+ subdir = d_ancestor(old_dentry, new_dentry);
+ /* Try lockless once... */
+ if (read_seqretry(&rename_lock, seq)) {
+ /* ...else acquire lock for progress even on deep chains. */
+ read_seqlock_excl(&rename_lock);
+ subdir = d_ancestor(old_dentry, new_dentry);
+ read_sequnlock_excl(&rename_lock);
+ }
+ rcu_read_unlock();
+ return subdir;
}
EXPORT_SYMBOL(is_subdir);
@@ -3100,6 +3106,34 @@ void d_tmpfile(struct file *file, struct inode *inode)
}
EXPORT_SYMBOL(d_tmpfile);
+/*
+ * Obtain inode number of the parent dentry.
+ */
+ino_t d_parent_ino(struct dentry *dentry)
+{
+ struct dentry *parent;
+ struct inode *iparent;
+ unsigned seq;
+ ino_t ret;
+
+ scoped_guard(rcu) {
+ seq = raw_seqcount_begin(&dentry->d_seq);
+ parent = READ_ONCE(dentry->d_parent);
+ iparent = d_inode_rcu(parent);
+ if (likely(iparent)) {
+ ret = iparent->i_ino;
+ if (!read_seqcount_retry(&dentry->d_seq, seq))
+ return ret;
+ }
+ }
+
+ spin_lock(&dentry->d_lock);
+ ret = dentry->d_parent->d_inode->i_ino;
+ spin_unlock(&dentry->d_lock);
+ return ret;
+}
+EXPORT_SYMBOL(d_parent_ino);
+
static __initdata unsigned long dhash_entries;
static int __init set_dhash_entries(char *str)
{
@@ -3129,6 +3163,9 @@ static void __init dcache_init_early(void)
0,
0);
d_hash_shift = 32 - d_hash_shift;
+
+ runtime_const_init(shift, d_hash_shift);
+ runtime_const_init(ptr, dentry_hashtable);
}
static void __init dcache_init(void)
@@ -3157,6 +3194,9 @@ static void __init dcache_init(void)
0,
0);
d_hash_shift = 32 - d_hash_shift;
+
+ runtime_const_init(shift, d_hash_shift);
+ runtime_const_init(ptr, dentry_hashtable);
}
/* SLAB cache for __getname() consumers */
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 8fd928899a59..91521576f500 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -92,9 +92,9 @@ enum {
};
static const struct fs_parameter_spec debugfs_param_specs[] = {
- fsparam_u32 ("gid", Opt_gid),
+ fsparam_gid ("gid", Opt_gid),
fsparam_u32oct ("mode", Opt_mode),
- fsparam_u32 ("uid", Opt_uid),
+ fsparam_uid ("uid", Opt_uid),
{}
};
@@ -102,8 +102,6 @@ static int debugfs_parse_param(struct fs_context *fc, struct fs_parameter *param
{
struct debugfs_fs_info *opts = fc->s_fs_info;
struct fs_parse_result result;
- kuid_t uid;
- kgid_t gid;
int opt;
opt = fs_parse(fc, debugfs_param_specs, param, &result);
@@ -120,16 +118,10 @@ static int debugfs_parse_param(struct fs_context *fc, struct fs_parameter *param
switch (opt) {
case Opt_uid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- return invalf(fc, "Unknown uid");
- opts->uid = uid;
+ opts->uid = result.uid;
break;
case Opt_gid:
- gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(gid))
- return invalf(fc, "Unknown gid");
- opts->gid = gid;
+ opts->gid = result.gid;
break;
case Opt_mode:
opts->mode = result.uint_32 & S_IALLUGO;
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
index bb14462f6d99..a929f1b613be 100644
--- a/fs/efivarfs/super.c
+++ b/fs/efivarfs/super.c
@@ -275,8 +275,8 @@ enum {
};
static const struct fs_parameter_spec efivarfs_parameters[] = {
- fsparam_u32("uid", Opt_uid),
- fsparam_u32("gid", Opt_gid),
+ fsparam_uid("uid", Opt_uid),
+ fsparam_gid("gid", Opt_gid),
{},
};
@@ -293,14 +293,10 @@ static int efivarfs_parse_param(struct fs_context *fc, struct fs_parameter *para
switch (opt) {
case Opt_uid:
- opts->uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(opts->uid))
- return -EINVAL;
+ opts->uid = result.uid;
break;
case Opt_gid:
- opts->gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(opts->gid))
- return -EINVAL;
+ opts->gid = result.gid;
break;
default:
return -EINVAL;
diff --git a/fs/efs/inode.c b/fs/efs/inode.c
index 7844ab24b813..462619e59766 100644
--- a/fs/efs/inode.c
+++ b/fs/efs/inode.c
@@ -311,4 +311,5 @@ efs_block_t efs_map_block(struct inode *inode, efs_block_t block) {
return 0;
}
+MODULE_DESCRIPTION("Extent File System (efs)");
MODULE_LICENSE("GPL");
diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c
index 3b03a573cb1a..7749feded722 100644
--- a/fs/efs/symlink.c
+++ b/fs/efs/symlink.c
@@ -14,10 +14,9 @@
static int efs_symlink_read_folio(struct file *file, struct folio *folio)
{
- struct page *page = &folio->page;
- char *link = page_address(page);
- struct buffer_head * bh;
- struct inode * inode = page->mapping->host;
+ char *link = folio_address(folio);
+ struct buffer_head *bh;
+ struct inode *inode = folio->mapping->host;
efs_block_t size = inode->i_size;
int err;
@@ -40,12 +39,9 @@ static int efs_symlink_read_folio(struct file *file, struct folio *folio)
brelse(bh);
}
link[size] = '\0';
- SetPageUptodate(page);
- unlock_page(page);
- return 0;
+ err = 0;
fail:
- SetPageError(page);
- unlock_page(page);
+ folio_end_read(folio, err == 0);
return err;
}
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index c93bd24d2771..1b91d9513013 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -343,7 +343,7 @@ static int erofs_read_superblock(struct super_block *sb)
sbi->build_time = le64_to_cpu(dsb->build_time);
sbi->build_time_nsec = le32_to_cpu(dsb->build_time_nsec);
- memcpy(&sb->s_uuid, dsb->uuid, sizeof(dsb->uuid));
+ super_set_uuid(sb, (void *)dsb->uuid, sizeof(dsb->uuid));
ret = strscpy(sbi->volume_name, dsb->volume_name,
sizeof(dsb->volume_name));
diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c
index 9b248ee5fef2..74d3d7bffcf3 100644
--- a/fs/erofs/zmap.c
+++ b/fs/erofs/zmap.c
@@ -711,6 +711,8 @@ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map,
err = z_erofs_do_map_blocks(inode, map, flags);
out:
+ if (err)
+ map->m_llen = 0;
trace_z_erofs_map_blocks_iter_exit(inode, map, flags, err);
return err;
}
diff --git a/fs/erofs/zutil.c b/fs/erofs/zutil.c
index 036024bce9f7..b80f612867c2 100644
--- a/fs/erofs/zutil.c
+++ b/fs/erofs/zutil.c
@@ -148,7 +148,7 @@ int __init z_erofs_gbuf_init(void)
void z_erofs_gbuf_exit(void)
{
- int i;
+ int i, j;
for (i = 0; i < z_erofs_gbuf_count + (!!z_erofs_rsvbuf); ++i) {
struct z_erofs_gbuf *gbuf = &z_erofs_gbufpool[i];
@@ -161,9 +161,9 @@ void z_erofs_gbuf_exit(void)
if (!gbuf->pages)
continue;
- for (i = 0; i < gbuf->nrpages; ++i)
- if (gbuf->pages[i])
- put_page(gbuf->pages[i]);
+ for (j = 0; j < gbuf->nrpages; ++j)
+ if (gbuf->pages[j])
+ put_page(gbuf->pages[j]);
kfree(gbuf->pages);
gbuf->pages = NULL;
}
diff --git a/fs/exec.c b/fs/exec.c
index 40073142288f..4dee205452e2 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -952,10 +952,6 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
path_noexec(&file->f_path)))
goto exit;
- err = deny_write_access(file);
- if (err)
- goto exit;
-
out:
return file;
@@ -971,8 +967,7 @@ exit:
*
* Returns ERR_PTR on failure or allocated struct file on success.
*
- * As this is a wrapper for the internal do_open_execat(), callers
- * must call allow_write_access() before fput() on release. Also see
+ * As this is a wrapper for the internal do_open_execat(). Also see
* do_close_execat().
*/
struct file *open_exec(const char *name)
@@ -1524,10 +1519,8 @@ static int prepare_bprm_creds(struct linux_binprm *bprm)
/* Matches do_open_execat() */
static void do_close_execat(struct file *file)
{
- if (!file)
- return;
- allow_write_access(file);
- fput(file);
+ if (file)
+ fput(file);
}
static void free_bprm(struct linux_binprm *bprm)
@@ -1846,7 +1839,6 @@ static int exec_binprm(struct linux_binprm *bprm)
bprm->file = bprm->interpreter;
bprm->interpreter = NULL;
- allow_write_access(exec);
if (unlikely(bprm->have_execfd)) {
if (bprm->executable) {
fput(exec);
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
index 3d5ea2cfad66..a3c7173ef693 100644
--- a/fs/exfat/super.c
+++ b/fs/exfat/super.c
@@ -225,8 +225,8 @@ static const struct constant_table exfat_param_enums[] = {
};
static const struct fs_parameter_spec exfat_parameters[] = {
- fsparam_u32("uid", Opt_uid),
- fsparam_u32("gid", Opt_gid),
+ fsparam_uid("uid", Opt_uid),
+ fsparam_gid("gid", Opt_gid),
fsparam_u32oct("umask", Opt_umask),
fsparam_u32oct("dmask", Opt_dmask),
fsparam_u32oct("fmask", Opt_fmask),
@@ -262,10 +262,10 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
switch (opt) {
case Opt_uid:
- opts->fs_uid = make_kuid(current_user_ns(), result.uint_32);
+ opts->fs_uid = result.uid;
break;
case Opt_gid:
- opts->fs_gid = make_kgid(current_user_ns(), result.uint_32);
+ opts->fs_gid = result.gid;
break;
case Opt_umask:
opts->fs_fmask = result.uint_32;
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 07ea3d62b298..4f2dd4ab4486 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -427,7 +427,7 @@ EXPORT_SYMBOL_GPL(exportfs_encode_fh);
struct dentry *
exportfs_decode_fh_raw(struct vfsmount *mnt, struct fid *fid, int fh_len,
- int fileid_type,
+ int fileid_type, unsigned int flags,
int (*acceptable)(void *, struct dentry *),
void *context)
{
@@ -445,6 +445,11 @@ exportfs_decode_fh_raw(struct vfsmount *mnt, struct fid *fid, int fh_len,
if (IS_ERR_OR_NULL(result))
return result;
+ if ((flags & EXPORT_FH_DIR_ONLY) && !d_is_dir(result)) {
+ err = -ENOTDIR;
+ goto err_result;
+ }
+
/*
* If no acceptance criteria was specified by caller, a disconnected
* dentry is also accepatable. Callers may use this mode to query if
@@ -581,7 +586,7 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
{
struct dentry *ret;
- ret = exportfs_decode_fh_raw(mnt, fid, fh_len, fileid_type,
+ ret = exportfs_decode_fh_raw(mnt, fid, fh_len, fileid_type, 0,
acceptable, context);
if (IS_ERR_OR_NULL(ret)) {
if (ret == ERR_PTR(-ENOMEM))
diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
index 7ae0b61258a7..0a056d97e640 100644
--- a/fs/ext4/crypto.c
+++ b/fs/ext4/crypto.c
@@ -31,11 +31,10 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
ext4_fname_from_fscrypt_name(fname, &name);
-#if IS_ENABLED(CONFIG_UNICODE)
err = ext4_fname_setup_ci_filename(dir, iname, fname);
if (err)
ext4_fname_free_filename(fname);
-#endif
+
return err;
}
@@ -51,11 +50,9 @@ int ext4_fname_prepare_lookup(struct inode *dir, struct dentry *dentry,
ext4_fname_from_fscrypt_name(fname, &name);
-#if IS_ENABLED(CONFIG_UNICODE)
err = ext4_fname_setup_ci_filename(dir, &dentry->d_name, fname);
if (err)
ext4_fname_free_filename(fname);
-#endif
return err;
}
@@ -70,10 +67,7 @@ void ext4_fname_free_filename(struct ext4_filename *fname)
fname->usr_fname = NULL;
fname->disk_name.name = NULL;
-#if IS_ENABLED(CONFIG_UNICODE)
- kfree(fname->cf_name.name);
- fname->cf_name.name = NULL;
-#endif
+ ext4_fname_free_ci_filename(fname);
}
static bool uuid_is_zero(__u8 u[16])
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 983dad8c07ec..8007abd4972d 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2511,7 +2511,7 @@ struct ext4_filename {
struct fscrypt_str crypto_buf;
#endif
#if IS_ENABLED(CONFIG_UNICODE)
- struct fscrypt_str cf_name;
+ struct qstr cf_name;
#endif
};
@@ -2745,8 +2745,25 @@ ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
#if IS_ENABLED(CONFIG_UNICODE)
extern int ext4_fname_setup_ci_filename(struct inode *dir,
- const struct qstr *iname,
- struct ext4_filename *fname);
+ const struct qstr *iname,
+ struct ext4_filename *fname);
+
+static inline void ext4_fname_free_ci_filename(struct ext4_filename *fname)
+{
+ kfree(fname->cf_name.name);
+ fname->cf_name.name = NULL;
+}
+#else
+static inline int ext4_fname_setup_ci_filename(struct inode *dir,
+ const struct qstr *iname,
+ struct ext4_filename *fname)
+{
+ return 0;
+}
+
+static inline void ext4_fname_free_ci_filename(struct ext4_filename *fname)
+{
+}
#endif
/* ext4 encryption related stuff goes here crypto.c */
@@ -2769,16 +2786,11 @@ static inline int ext4_fname_setup_filename(struct inode *dir,
int lookup,
struct ext4_filename *fname)
{
- int err = 0;
fname->usr_fname = iname;
fname->disk_name.name = (unsigned char *) iname->name;
fname->disk_name.len = iname->len;
-#if IS_ENABLED(CONFIG_UNICODE)
- err = ext4_fname_setup_ci_filename(dir, iname, fname);
-#endif
-
- return err;
+ return ext4_fname_setup_ci_filename(dir, iname, fname);
}
static inline int ext4_fname_prepare_lookup(struct inode *dir,
@@ -2790,10 +2802,7 @@ static inline int ext4_fname_prepare_lookup(struct inode *dir,
static inline void ext4_fname_free_filename(struct ext4_filename *fname)
{
-#if IS_ENABLED(CONFIG_UNICODE)
- kfree(fname->cf_name.name);
- fname->cf_name.name = NULL;
-#endif
+ ext4_fname_free_ci_filename(fname);
}
static inline int ext4_ioctl_get_encryption_pwsalt(struct file *filp,
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index a630b27a4cc6..e6769b97a970 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1390,62 +1390,11 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)
}
#if IS_ENABLED(CONFIG_UNICODE)
-/*
- * Test whether a case-insensitive directory entry matches the filename
- * being searched for. If quick is set, assume the name being looked up
- * is already in the casefolded form.
- *
- * Returns: 0 if the directory entry matches, more than 0 if it
- * doesn't match or less than zero on error.
- */
-static int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
- u8 *de_name, size_t de_name_len, bool quick)
-{
- const struct super_block *sb = parent->i_sb;
- const struct unicode_map *um = sb->s_encoding;
- struct fscrypt_str decrypted_name = FSTR_INIT(NULL, de_name_len);
- struct qstr entry = QSTR_INIT(de_name, de_name_len);
- int ret;
-
- if (IS_ENCRYPTED(parent)) {
- const struct fscrypt_str encrypted_name =
- FSTR_INIT(de_name, de_name_len);
-
- decrypted_name.name = kmalloc(de_name_len, GFP_KERNEL);
- if (!decrypted_name.name)
- return -ENOMEM;
- ret = fscrypt_fname_disk_to_usr(parent, 0, 0, &encrypted_name,
- &decrypted_name);
- if (ret < 0)
- goto out;
- entry.name = decrypted_name.name;
- entry.len = decrypted_name.len;
- }
-
- if (quick)
- ret = utf8_strncasecmp_folded(um, name, &entry);
- else
- ret = utf8_strncasecmp(um, name, &entry);
- if (ret < 0) {
- /* Handle invalid character sequence as either an error
- * or as an opaque byte sequence.
- */
- if (sb_has_strict_encoding(sb))
- ret = -EINVAL;
- else if (name->len != entry.len)
- ret = 1;
- else
- ret = !!memcmp(name->name, entry.name, entry.len);
- }
-out:
- kfree(decrypted_name.name);
- return ret;
-}
-
int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
struct ext4_filename *name)
{
- struct fscrypt_str *cf_name = &name->cf_name;
+ struct qstr *cf_name = &name->cf_name;
+ unsigned char *buf;
struct dx_hash_info *hinfo = &name->hinfo;
int len;
@@ -1455,18 +1404,18 @@ int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
return 0;
}
- cf_name->name = kmalloc(EXT4_NAME_LEN, GFP_NOFS);
- if (!cf_name->name)
+ buf = kmalloc(EXT4_NAME_LEN, GFP_NOFS);
+ if (!buf)
return -ENOMEM;
- len = utf8_casefold(dir->i_sb->s_encoding,
- iname, cf_name->name,
- EXT4_NAME_LEN);
+ len = utf8_casefold(dir->i_sb->s_encoding, iname, buf, EXT4_NAME_LEN);
if (len <= 0) {
- kfree(cf_name->name);
- cf_name->name = NULL;
+ kfree(buf);
+ buf = NULL;
}
+ cf_name->name = buf;
cf_name->len = (unsigned) len;
+
if (!IS_ENCRYPTED(dir))
return 0;
@@ -1502,22 +1451,29 @@ static bool ext4_match(struct inode *parent,
#if IS_ENABLED(CONFIG_UNICODE)
if (IS_CASEFOLDED(parent) &&
(!IS_ENCRYPTED(parent) || fscrypt_has_encryption_key(parent))) {
- if (fname->cf_name.name) {
- struct qstr cf = {.name = fname->cf_name.name,
- .len = fname->cf_name.len};
- if (IS_ENCRYPTED(parent)) {
- if (fname->hinfo.hash != EXT4_DIRENT_HASH(de) ||
- fname->hinfo.minor_hash !=
- EXT4_DIRENT_MINOR_HASH(de)) {
-
- return false;
- }
- }
- return !ext4_ci_compare(parent, &cf, de->name,
- de->name_len, true);
- }
- return !ext4_ci_compare(parent, fname->usr_fname, de->name,
- de->name_len, false);
+ /*
+ * Just checking IS_ENCRYPTED(parent) below is not
+ * sufficient to decide whether one can use the hash for
+ * skipping the string comparison, because the key might
+ * have been added right after
+ * ext4_fname_setup_ci_filename(). In this case, a hash
+ * mismatch will be a false negative. Therefore, make
+ * sure cf_name was properly initialized before
+ * considering the calculated hash.
+ */
+ if (IS_ENCRYPTED(parent) && fname->cf_name.name &&
+ (fname->hinfo.hash != EXT4_DIRENT_HASH(de) ||
+ fname->hinfo.minor_hash != EXT4_DIRENT_MINOR_HASH(de)))
+ return false;
+ /*
+ * Treat comparison errors as not a match. The
+ * only case where it happens is on a disk
+ * corruption or ENOMEM.
+ */
+
+ return generic_ci_match(parent, fname->usr_fname,
+ &fname->cf_name, de->name,
+ de->name_len) > 0;
}
#endif
@@ -1869,8 +1825,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
}
}
-#if IS_ENABLED(CONFIG_UNICODE)
- if (!inode && IS_CASEFOLDED(dir)) {
+ if (IS_ENABLED(CONFIG_UNICODE) && !inode && IS_CASEFOLDED(dir)) {
/* Eventually we want to call d_add_ci(dentry, NULL)
* for negative dentries in the encoding case as
* well. For now, prevent the negative dentry
@@ -1878,7 +1833,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
*/
return NULL;
}
-#endif
+
return d_splice_alias(inode, dentry);
}
@@ -3208,16 +3163,14 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
ext4_fc_track_unlink(handle, dentry);
retval = ext4_mark_inode_dirty(handle, dir);
-#if IS_ENABLED(CONFIG_UNICODE)
/* VFS negative dentries are incompatible with Encoding and
* Case-insensitiveness. Eventually we'll want avoid
* invalidating the dentries here, alongside with returning the
* negative dentries at ext4_lookup(), when it is better
* supported by the VFS for the CI case.
*/
- if (IS_CASEFOLDED(dir))
+ if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
d_invalidate(dentry);
-#endif
end_rmdir:
brelse(bh);
@@ -3319,16 +3272,15 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
goto out_trace;
retval = __ext4_unlink(dir, &dentry->d_name, d_inode(dentry), dentry);
-#if IS_ENABLED(CONFIG_UNICODE)
+
/* VFS negative dentries are incompatible with Encoding and
* Case-insensitiveness. Eventually we'll want avoid
* invalidating the dentries here, alongside with returning the
* negative dentries at ext4_lookup(), when it is better
* supported by the VFS for the CI case.
*/
- if (IS_CASEFOLDED(dir))
+ if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
d_invalidate(dentry);
-#endif
out_trace:
trace_ext4_unlink_exit(dentry, retval);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index c682fb927b64..eb899628e121 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1721,8 +1721,8 @@ static const struct fs_parameter_spec ext4_param_specs[] = {
fsparam_flag ("bsdgroups", Opt_grpid),
fsparam_flag ("nogrpid", Opt_nogrpid),
fsparam_flag ("sysvgroups", Opt_nogrpid),
- fsparam_u32 ("resgid", Opt_resgid),
- fsparam_u32 ("resuid", Opt_resuid),
+ fsparam_gid ("resgid", Opt_resgid),
+ fsparam_uid ("resuid", Opt_resuid),
fsparam_u32 ("sb", Opt_sb),
fsparam_enum ("errors", Opt_errors, ext4_param_errors),
fsparam_flag ("nouid32", Opt_nouid32),
@@ -2127,8 +2127,6 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param)
struct fs_parse_result result;
const struct mount_opts *m;
int is_remount;
- kuid_t uid;
- kgid_t gid;
int token;
token = fs_parse(fc, ext4_param_specs, param, &result);
@@ -2270,23 +2268,11 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param)
ctx->spec |= EXT4_SPEC_s_stripe;
return 0;
case Opt_resuid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid)) {
- ext4_msg(NULL, KERN_ERR, "Invalid uid value %d",
- result.uint_32);
- return -EINVAL;
- }
- ctx->s_resuid = uid;
+ ctx->s_resuid = result.uid;
ctx->spec |= EXT4_SPEC_s_resuid;
return 0;
case Opt_resgid:
- gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(gid)) {
- ext4_msg(NULL, KERN_ERR, "Invalid gid value %d",
- result.uint_32);
- return -EINVAL;
- }
- ctx->s_resgid = gid;
+ ctx->s_resgid = result.gid;
ctx->spec |= EXT4_SPEC_s_resgid;
return 0;
case Opt_journal_dev:
@@ -3586,14 +3572,12 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly)
return 0;
}
-#if !IS_ENABLED(CONFIG_UNICODE)
- if (ext4_has_feature_casefold(sb)) {
+ if (!IS_ENABLED(CONFIG_UNICODE) && ext4_has_feature_casefold(sb)) {
ext4_msg(sb, KERN_ERR,
"Filesystem with casefold feature cannot be "
"mounted without CONFIG_UNICODE");
return 0;
}
-#endif
if (readonly)
return 1;
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index ec2aeccb69a3..8bffdeccdbc3 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -219,8 +219,7 @@ static int f2fs_acl_update_mode(struct mnt_idmap *idmap,
return error;
if (error == 0)
*acl = NULL;
- if (!vfsgid_in_group_p(i_gid_into_vfsgid(idmap, inode)) &&
- !capable_wrt_inode_uidgid(idmap, inode, CAP_FSETID))
+ if (!in_group_or_capable(idmap, inode, i_gid_into_vfsgid(idmap, inode)))
mode &= ~S_ISGID;
*mode_p = mode;
return 0;
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 02c9355176d3..cbd7a5e96a37 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -42,35 +42,49 @@ static unsigned int bucket_blocks(unsigned int level)
return 4;
}
+#if IS_ENABLED(CONFIG_UNICODE)
/* If @dir is casefolded, initialize @fname->cf_name from @fname->usr_fname. */
int f2fs_init_casefolded_name(const struct inode *dir,
struct f2fs_filename *fname)
{
-#if IS_ENABLED(CONFIG_UNICODE)
struct super_block *sb = dir->i_sb;
+ unsigned char *buf;
+ int len;
if (IS_CASEFOLDED(dir) &&
!is_dot_dotdot(fname->usr_fname->name, fname->usr_fname->len)) {
- fname->cf_name.name = f2fs_kmem_cache_alloc(f2fs_cf_name_slab,
- GFP_NOFS, false, F2FS_SB(sb));
- if (!fname->cf_name.name)
+ buf = f2fs_kmem_cache_alloc(f2fs_cf_name_slab,
+ GFP_NOFS, false, F2FS_SB(sb));
+ if (!buf)
return -ENOMEM;
- fname->cf_name.len = utf8_casefold(sb->s_encoding,
- fname->usr_fname,
- fname->cf_name.name,
- F2FS_NAME_LEN);
- if ((int)fname->cf_name.len <= 0) {
- kmem_cache_free(f2fs_cf_name_slab, fname->cf_name.name);
- fname->cf_name.name = NULL;
+
+ len = utf8_casefold(sb->s_encoding, fname->usr_fname,
+ buf, F2FS_NAME_LEN);
+ if (len <= 0) {
+ kmem_cache_free(f2fs_cf_name_slab, buf);
if (sb_has_strict_encoding(sb))
return -EINVAL;
/* fall back to treating name as opaque byte sequence */
+ return 0;
}
+ fname->cf_name.name = buf;
+ fname->cf_name.len = len;
}
-#endif
+
return 0;
}
+void f2fs_free_casefolded_name(struct f2fs_filename *fname)
+{
+ unsigned char *buf = (unsigned char *)fname->cf_name.name;
+
+ if (buf) {
+ kmem_cache_free(f2fs_cf_name_slab, buf);
+ fname->cf_name.name = NULL;
+ }
+}
+#endif /* CONFIG_UNICODE */
+
static int __f2fs_setup_filename(const struct inode *dir,
const struct fscrypt_name *crypt_name,
struct f2fs_filename *fname)
@@ -142,12 +156,7 @@ void f2fs_free_filename(struct f2fs_filename *fname)
kfree(fname->crypto_buf.name);
fname->crypto_buf.name = NULL;
#endif
-#if IS_ENABLED(CONFIG_UNICODE)
- if (fname->cf_name.name) {
- kmem_cache_free(f2fs_cf_name_slab, fname->cf_name.name);
- fname->cf_name.name = NULL;
- }
-#endif
+ f2fs_free_casefolded_name(fname);
}
static unsigned long dir_block_index(unsigned int level,
@@ -176,58 +185,6 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir,
return f2fs_find_target_dentry(&d, fname, max_slots);
}
-#if IS_ENABLED(CONFIG_UNICODE)
-/*
- * Test whether a case-insensitive directory entry matches the filename
- * being searched for.
- *
- * Returns 1 for a match, 0 for no match, and -errno on an error.
- */
-static int f2fs_match_ci_name(const struct inode *dir, const struct qstr *name,
- const u8 *de_name, u32 de_name_len)
-{
- const struct super_block *sb = dir->i_sb;
- const struct unicode_map *um = sb->s_encoding;
- struct fscrypt_str decrypted_name = FSTR_INIT(NULL, de_name_len);
- struct qstr entry = QSTR_INIT(de_name, de_name_len);
- int res;
-
- if (IS_ENCRYPTED(dir)) {
- const struct fscrypt_str encrypted_name =
- FSTR_INIT((u8 *)de_name, de_name_len);
-
- if (WARN_ON_ONCE(!fscrypt_has_encryption_key(dir)))
- return -EINVAL;
-
- decrypted_name.name = kmalloc(de_name_len, GFP_KERNEL);
- if (!decrypted_name.name)
- return -ENOMEM;
- res = fscrypt_fname_disk_to_usr(dir, 0, 0, &encrypted_name,
- &decrypted_name);
- if (res < 0)
- goto out;
- entry.name = decrypted_name.name;
- entry.len = decrypted_name.len;
- }
-
- res = utf8_strncasecmp_folded(um, name, &entry);
- /*
- * In strict mode, ignore invalid names. In non-strict mode,
- * fall back to treating them as opaque byte sequences.
- */
- if (res < 0 && !sb_has_strict_encoding(sb)) {
- res = name->len == entry.len &&
- memcmp(name->name, entry.name, name->len) == 0;
- } else {
- /* utf8_strncasecmp_folded returns 0 on match */
- res = (res == 0);
- }
-out:
- kfree(decrypted_name.name);
- return res;
-}
-#endif /* CONFIG_UNICODE */
-
static inline int f2fs_match_name(const struct inode *dir,
const struct f2fs_filename *fname,
const u8 *de_name, u32 de_name_len)
@@ -235,11 +192,11 @@ static inline int f2fs_match_name(const struct inode *dir,
struct fscrypt_name f;
#if IS_ENABLED(CONFIG_UNICODE)
- if (fname->cf_name.name) {
- struct qstr cf = FSTR_TO_QSTR(&fname->cf_name);
+ if (fname->cf_name.name)
+ return generic_ci_match(dir, fname->usr_fname,
+ &fname->cf_name,
+ de_name, de_name_len);
- return f2fs_match_ci_name(dir, &cf, de_name, de_name_len);
- }
#endif
f.usr_fname = fname->usr_fname;
f.disk_name = fname->disk_name;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 1974b6aff397..8a9d910aa552 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -531,7 +531,7 @@ struct f2fs_filename {
* internal operation where usr_fname is also NULL. In all these cases
* we fall back to treating the name as an opaque byte sequence.
*/
- struct fscrypt_str cf_name;
+ struct qstr cf_name;
#endif
};
@@ -3533,8 +3533,22 @@ int f2fs_get_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
/*
* dir.c
*/
+#if IS_ENABLED(CONFIG_UNICODE)
int f2fs_init_casefolded_name(const struct inode *dir,
struct f2fs_filename *fname);
+void f2fs_free_casefolded_name(struct f2fs_filename *fname);
+#else
+static inline int f2fs_init_casefolded_name(const struct inode *dir,
+ struct f2fs_filename *fname)
+{
+ return 0;
+}
+
+static inline void f2fs_free_casefolded_name(struct f2fs_filename *fname)
+{
+}
+#endif /* CONFIG_UNICODE */
+
int f2fs_setup_filename(struct inode *dir, const struct qstr *iname,
int lookup, struct f2fs_filename *fname);
int f2fs_prepare_lookup(struct inode *dir, struct dentry *dentry,
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 5c0b281a70f3..c1ad9b278c47 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -185,7 +185,7 @@ static int get_parent_ino(struct inode *inode, nid_t *pino)
if (!dentry)
return 0;
- *pino = parent_ino(dentry);
+ *pino = d_parent_ino(dentry);
dput(dentry);
return 1;
}
@@ -923,10 +923,8 @@ static void __setattr_copy(struct mnt_idmap *idmap,
inode_set_ctime_to_ts(inode, attr->ia_ctime);
if (ia_valid & ATTR_MODE) {
umode_t mode = attr->ia_mode;
- vfsgid_t vfsgid = i_gid_into_vfsgid(idmap, inode);
- if (!vfsgid_in_group_p(vfsgid) &&
- !capable_wrt_inode_uidgid(idmap, inode, CAP_FSETID))
+ if (!in_group_or_capable(idmap, inode, i_gid_into_vfsgid(idmap, inode)))
mode &= ~S_ISGID;
set_acl_inode(inode, mode);
}
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index e54f8c08bda8..1ecde2b45e99 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -576,8 +576,7 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
goto out_iput;
}
out_splice:
-#if IS_ENABLED(CONFIG_UNICODE)
- if (!inode && IS_CASEFOLDED(dir)) {
+ if (IS_ENABLED(CONFIG_UNICODE) && !inode && IS_CASEFOLDED(dir)) {
/* Eventually we want to call d_add_ci(dentry, NULL)
* for negative dentries in the encoding case as
* well. For now, prevent the negative dentry
@@ -586,7 +585,7 @@ out_splice:
trace_f2fs_lookup_end(dir, dentry, ino, err);
return NULL;
}
-#endif
+
new = d_splice_alias(inode, dentry);
trace_f2fs_lookup_end(dir, !IS_ERR_OR_NULL(new) ? new : dentry,
ino, IS_ERR(new) ? PTR_ERR(new) : err);
@@ -639,16 +638,15 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
f2fs_delete_entry(de, page, dir, inode);
f2fs_unlock_op(sbi);
-#if IS_ENABLED(CONFIG_UNICODE)
/* VFS negative dentries are incompatible with Encoding and
* Case-insensitiveness. Eventually we'll want avoid
* invalidating the dentries here, alongside with returning the
* negative dentries at f2fs_lookup(), when it is better
* supported by the VFS for the CI case.
*/
- if (IS_CASEFOLDED(dir))
+ if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
d_invalidate(dentry);
-#endif
+
if (IS_DIRSYNC(dir))
f2fs_sync_fs(sbi->sb, 1);
fail:
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 496aee53c38a..8712e264071f 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -46,10 +46,6 @@
static struct kmem_cache *fsync_entry_slab;
-#if IS_ENABLED(CONFIG_UNICODE)
-extern struct kmem_cache *f2fs_cf_name_slab;
-#endif
-
bool f2fs_space_for_roll_forward(struct f2fs_sb_info *sbi)
{
s64 nalloc = percpu_counter_sum_positive(&sbi->alloc_valid_block_count);
@@ -153,11 +149,8 @@ static int init_recovered_filename(const struct inode *dir,
if (err)
return err;
f2fs_hash_filename(dir, fname);
-#if IS_ENABLED(CONFIG_UNICODE)
/* Case-sensitive match is fine for recovery */
- kmem_cache_free(f2fs_cf_name_slab, fname->cf_name.name);
- fname->cf_name.name = NULL;
-#endif
+ f2fs_free_casefolded_name(fname);
} else {
f2fs_hash_filename(dir, fname);
}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 1f1b3647a998..df4cf31f93df 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -321,7 +321,7 @@ struct kmem_cache *f2fs_cf_name_slab;
static int __init f2fs_create_casefold_cache(void)
{
f2fs_cf_name_slab = f2fs_kmem_cache_create("f2fs_casefolded_name",
- F2FS_NAME_LEN);
+ F2FS_NAME_LEN);
return f2fs_cf_name_slab ? 0 : -ENOMEM;
}
@@ -1326,13 +1326,13 @@ default_check:
return -EINVAL;
}
#endif
-#if !IS_ENABLED(CONFIG_UNICODE)
- if (f2fs_sb_has_casefold(sbi)) {
+
+ if (!IS_ENABLED(CONFIG_UNICODE) && f2fs_sb_has_casefold(sbi)) {
f2fs_err(sbi,
"Filesystem with casefold feature cannot be mounted without CONFIG_UNICODE");
return -EINVAL;
}
-#endif
+
/*
* The BLKZONED feature indicates that the drive was formatted with
* zone alignment optimization. This is optional for host-aware
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 66cf4778cf3b..d3e426de5f01 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -7,6 +7,8 @@
#include <linux/hash.h>
#include <linux/ratelimit.h>
#include <linux/msdos_fs.h>
+#include <linux/fs_context.h>
+#include <linux/fs_parser.h>
/*
* vfat shortname flags
@@ -51,7 +53,8 @@ struct fat_mount_options {
tz_set:1, /* Filesystem timestamps' offset set */
rodir:1, /* allow ATTR_RO for directory */
discard:1, /* Issue discard requests on deletions */
- dos1xfloppy:1; /* Assume default BPB for DOS 1.x floppies */
+ dos1xfloppy:1, /* Assume default BPB for DOS 1.x floppies */
+ debug:1; /* Not currently used */
};
#define FAT_HASH_BITS 8
@@ -415,12 +418,21 @@ extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos);
extern struct inode *fat_build_inode(struct super_block *sb,
struct msdos_dir_entry *de, loff_t i_pos);
extern int fat_sync_inode(struct inode *inode);
-extern int fat_fill_super(struct super_block *sb, void *data, int silent,
- int isvfat, void (*setup)(struct super_block *));
+extern int fat_fill_super(struct super_block *sb, struct fs_context *fc,
+ void (*setup)(struct super_block *));
extern int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de);
extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
struct inode *i2);
+
+extern const struct fs_parameter_spec fat_param_spec[];
+int fat_init_fs_context(struct fs_context *fc, bool is_vfat);
+void fat_free_fc(struct fs_context *fc);
+
+int fat_parse_param(struct fs_context *fc, struct fs_parameter *param,
+ bool is_vfat);
+int fat_reconfigure(struct fs_context *fc);
+
static inline unsigned long fat_dir_hash(int logstart)
{
return hash_32(logstart, FAT_HASH_BITS);
diff --git a/fs/fat/fat_test.c b/fs/fat/fat_test.c
index 2dab4ca1d0d8..1f0062659067 100644
--- a/fs/fat/fat_test.c
+++ b/fs/fat/fat_test.c
@@ -193,4 +193,5 @@ static struct kunit_suite fat_test_suite = {
kunit_test_suites(&fat_test_suite);
+MODULE_DESCRIPTION("KUnit tests for FAT filesystems");
MODULE_LICENSE("GPL v2");
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index d9e6fbb6f246..19115fd2d2a4 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -16,7 +16,6 @@
#include <linux/mpage.h>
#include <linux/vfs.h>
#include <linux/seq_file.h>
-#include <linux/parser.h>
#include <linux/uio.h>
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
@@ -804,16 +803,17 @@ static void __exit fat_destroy_inodecache(void)
kmem_cache_destroy(fat_inode_cachep);
}
-static int fat_remount(struct super_block *sb, int *flags, char *data)
+int fat_reconfigure(struct fs_context *fc)
{
bool new_rdonly;
+ struct super_block *sb = fc->root->d_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
- *flags |= SB_NODIRATIME | (sbi->options.isvfat ? 0 : SB_NOATIME);
+ fc->sb_flags |= SB_NODIRATIME | (sbi->options.isvfat ? 0 : SB_NOATIME);
sync_filesystem(sb);
/* make sure we update state on remount. */
- new_rdonly = *flags & SB_RDONLY;
+ new_rdonly = fc->sb_flags & SB_RDONLY;
if (new_rdonly != sb_rdonly(sb)) {
if (new_rdonly)
fat_set_state(sb, 0, 0);
@@ -822,6 +822,7 @@ static int fat_remount(struct super_block *sb, int *flags, char *data)
}
return 0;
}
+EXPORT_SYMBOL_GPL(fat_reconfigure);
static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
{
@@ -939,8 +940,6 @@ static const struct super_operations fat_sops = {
.evict_inode = fat_evict_inode,
.put_super = fat_put_super,
.statfs = fat_statfs,
- .remount_fs = fat_remount,
-
.show_options = fat_show_options,
};
@@ -1037,355 +1036,282 @@ static int fat_show_options(struct seq_file *m, struct dentry *root)
}
enum {
- Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,
- Opt_umask, Opt_dmask, Opt_fmask, Opt_allow_utime, Opt_codepage,
- Opt_usefree, Opt_nocase, Opt_quiet, Opt_showexec, Opt_debug,
- Opt_immutable, Opt_dots, Opt_nodots,
- Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
- Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
- Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
- Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
- Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset,
- Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err, Opt_dos1xfloppy,
+ Opt_check, Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask,
+ Opt_allow_utime, Opt_codepage, Opt_usefree, Opt_nocase, Opt_quiet,
+ Opt_showexec, Opt_debug, Opt_immutable, Opt_dots, Opt_dotsOK,
+ Opt_charset, Opt_shortname, Opt_utf8, Opt_utf8_bool,
+ Opt_uni_xl, Opt_uni_xl_bool, Opt_nonumtail, Opt_nonumtail_bool,
+ Opt_obsolete, Opt_flush, Opt_tz, Opt_rodir, Opt_errors, Opt_discard,
+ Opt_nfs, Opt_nfs_enum, Opt_time_offset, Opt_dos1xfloppy,
};
-static const match_table_t fat_tokens = {
- {Opt_check_r, "check=relaxed"},
- {Opt_check_s, "check=strict"},
- {Opt_check_n, "check=normal"},
- {Opt_check_r, "check=r"},
- {Opt_check_s, "check=s"},
- {Opt_check_n, "check=n"},
- {Opt_uid, "uid=%u"},
- {Opt_gid, "gid=%u"},
- {Opt_umask, "umask=%o"},
- {Opt_dmask, "dmask=%o"},
- {Opt_fmask, "fmask=%o"},
- {Opt_allow_utime, "allow_utime=%o"},
- {Opt_codepage, "codepage=%u"},
- {Opt_usefree, "usefree"},
- {Opt_nocase, "nocase"},
- {Opt_quiet, "quiet"},
- {Opt_showexec, "showexec"},
- {Opt_debug, "debug"},
- {Opt_immutable, "sys_immutable"},
- {Opt_flush, "flush"},
- {Opt_tz_utc, "tz=UTC"},
- {Opt_time_offset, "time_offset=%d"},
- {Opt_err_cont, "errors=continue"},
- {Opt_err_panic, "errors=panic"},
- {Opt_err_ro, "errors=remount-ro"},
- {Opt_discard, "discard"},
- {Opt_nfs_stale_rw, "nfs"},
- {Opt_nfs_stale_rw, "nfs=stale_rw"},
- {Opt_nfs_nostale_ro, "nfs=nostale_ro"},
- {Opt_dos1xfloppy, "dos1xfloppy"},
- {Opt_obsolete, "conv=binary"},
- {Opt_obsolete, "conv=text"},
- {Opt_obsolete, "conv=auto"},
- {Opt_obsolete, "conv=b"},
- {Opt_obsolete, "conv=t"},
- {Opt_obsolete, "conv=a"},
- {Opt_obsolete, "fat=%u"},
- {Opt_obsolete, "blocksize=%u"},
- {Opt_obsolete, "cvf_format=%20s"},
- {Opt_obsolete, "cvf_options=%100s"},
- {Opt_obsolete, "posix"},
- {Opt_err, NULL},
-};
-static const match_table_t msdos_tokens = {
- {Opt_nodots, "nodots"},
- {Opt_nodots, "dotsOK=no"},
- {Opt_dots, "dots"},
- {Opt_dots, "dotsOK=yes"},
- {Opt_err, NULL}
+static const struct constant_table fat_param_check[] = {
+ {"relaxed", 'r'},
+ {"r", 'r'},
+ {"strict", 's'},
+ {"s", 's'},
+ {"normal", 'n'},
+ {"n", 'n'},
+ {}
};
-static const match_table_t vfat_tokens = {
- {Opt_charset, "iocharset=%s"},
- {Opt_shortname_lower, "shortname=lower"},
- {Opt_shortname_win95, "shortname=win95"},
- {Opt_shortname_winnt, "shortname=winnt"},
- {Opt_shortname_mixed, "shortname=mixed"},
- {Opt_utf8_no, "utf8=0"}, /* 0 or no or false */
- {Opt_utf8_no, "utf8=no"},
- {Opt_utf8_no, "utf8=false"},
- {Opt_utf8_yes, "utf8=1"}, /* empty or 1 or yes or true */
- {Opt_utf8_yes, "utf8=yes"},
- {Opt_utf8_yes, "utf8=true"},
- {Opt_utf8_yes, "utf8"},
- {Opt_uni_xl_no, "uni_xlate=0"}, /* 0 or no or false */
- {Opt_uni_xl_no, "uni_xlate=no"},
- {Opt_uni_xl_no, "uni_xlate=false"},
- {Opt_uni_xl_yes, "uni_xlate=1"}, /* empty or 1 or yes or true */
- {Opt_uni_xl_yes, "uni_xlate=yes"},
- {Opt_uni_xl_yes, "uni_xlate=true"},
- {Opt_uni_xl_yes, "uni_xlate"},
- {Opt_nonumtail_no, "nonumtail=0"}, /* 0 or no or false */
- {Opt_nonumtail_no, "nonumtail=no"},
- {Opt_nonumtail_no, "nonumtail=false"},
- {Opt_nonumtail_yes, "nonumtail=1"}, /* empty or 1 or yes or true */
- {Opt_nonumtail_yes, "nonumtail=yes"},
- {Opt_nonumtail_yes, "nonumtail=true"},
- {Opt_nonumtail_yes, "nonumtail"},
- {Opt_rodir, "rodir"},
- {Opt_err, NULL}
+
+static const struct constant_table fat_param_tz[] = {
+ {"UTC", 0},
+ {}
};
-static int parse_options(struct super_block *sb, char *options, int is_vfat,
- int silent, int *debug, struct fat_mount_options *opts)
-{
- char *p;
- substring_t args[MAX_OPT_ARGS];
- int option;
- char *iocharset;
+static const struct constant_table fat_param_errors[] = {
+ {"continue", FAT_ERRORS_CONT},
+ {"panic", FAT_ERRORS_PANIC},
+ {"remount-ro", FAT_ERRORS_RO},
+ {}
+};
- opts->isvfat = is_vfat;
- opts->fs_uid = current_uid();
- opts->fs_gid = current_gid();
- opts->fs_fmask = opts->fs_dmask = current_umask();
- opts->allow_utime = -1;
- opts->codepage = fat_default_codepage;
- fat_reset_iocharset(opts);
- if (is_vfat) {
- opts->shortname = VFAT_SFN_DISPLAY_WINNT|VFAT_SFN_CREATE_WIN95;
- opts->rodir = 0;
- } else {
- opts->shortname = 0;
- opts->rodir = 1;
- }
- opts->name_check = 'n';
- opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0;
- opts->unicode_xlate = 0;
- opts->numtail = 1;
- opts->usefree = opts->nocase = 0;
- opts->tz_set = 0;
- opts->nfs = 0;
- opts->errors = FAT_ERRORS_RO;
- *debug = 0;
+static const struct constant_table fat_param_nfs[] = {
+ {"stale_rw", FAT_NFS_STALE_RW},
+ {"nostale_ro", FAT_NFS_NOSTALE_RO},
+ {}
+};
- opts->utf8 = IS_ENABLED(CONFIG_FAT_DEFAULT_UTF8) && is_vfat;
+/*
+ * These are all obsolete but we still reject invalid options.
+ * The corresponding values are therefore meaningless.
+ */
+static const struct constant_table fat_param_conv[] = {
+ {"binary", 0},
+ {"text", 0},
+ {"auto", 0},
+ {"b", 0},
+ {"t", 0},
+ {"a", 0},
+ {}
+};
- if (!options)
- goto out;
+/* Core options. See below for vfat and msdos extras */
+const struct fs_parameter_spec fat_param_spec[] = {
+ fsparam_enum ("check", Opt_check, fat_param_check),
+ fsparam_uid ("uid", Opt_uid),
+ fsparam_gid ("gid", Opt_gid),
+ fsparam_u32oct ("umask", Opt_umask),
+ fsparam_u32oct ("dmask", Opt_dmask),
+ fsparam_u32oct ("fmask", Opt_fmask),
+ fsparam_u32oct ("allow_utime", Opt_allow_utime),
+ fsparam_u32 ("codepage", Opt_codepage),
+ fsparam_flag ("usefree", Opt_usefree),
+ fsparam_flag ("nocase", Opt_nocase),
+ fsparam_flag ("quiet", Opt_quiet),
+ fsparam_flag ("showexec", Opt_showexec),
+ fsparam_flag ("debug", Opt_debug),
+ fsparam_flag ("sys_immutable", Opt_immutable),
+ fsparam_flag ("flush", Opt_flush),
+ fsparam_enum ("tz", Opt_tz, fat_param_tz),
+ fsparam_s32 ("time_offset", Opt_time_offset),
+ fsparam_enum ("errors", Opt_errors, fat_param_errors),
+ fsparam_flag ("discard", Opt_discard),
+ fsparam_flag ("nfs", Opt_nfs),
+ fsparam_enum ("nfs", Opt_nfs_enum, fat_param_nfs),
+ fsparam_flag ("dos1xfloppy", Opt_dos1xfloppy),
+ __fsparam(fs_param_is_enum, "conv",
+ Opt_obsolete, fs_param_deprecated, fat_param_conv),
+ __fsparam(fs_param_is_u32, "fat",
+ Opt_obsolete, fs_param_deprecated, NULL),
+ __fsparam(fs_param_is_u32, "blocksize",
+ Opt_obsolete, fs_param_deprecated, NULL),
+ __fsparam(fs_param_is_string, "cvf_format",
+ Opt_obsolete, fs_param_deprecated, NULL),
+ __fsparam(fs_param_is_string, "cvf_options",
+ Opt_obsolete, fs_param_deprecated, NULL),
+ __fsparam(NULL, "posix",
+ Opt_obsolete, fs_param_deprecated, NULL),
+ {}
+};
+EXPORT_SYMBOL_GPL(fat_param_spec);
- while ((p = strsep(&options, ",")) != NULL) {
- int token;
- if (!*p)
- continue;
+static const struct fs_parameter_spec msdos_param_spec[] = {
+ fsparam_flag_no ("dots", Opt_dots),
+ fsparam_bool ("dotsOK", Opt_dotsOK),
+ {}
+};
- token = match_token(p, fat_tokens, args);
- if (token == Opt_err) {
- if (is_vfat)
- token = match_token(p, vfat_tokens, args);
- else
- token = match_token(p, msdos_tokens, args);
- }
- switch (token) {
- case Opt_check_s:
- opts->name_check = 's';
- break;
- case Opt_check_r:
- opts->name_check = 'r';
- break;
- case Opt_check_n:
- opts->name_check = 'n';
- break;
- case Opt_usefree:
- opts->usefree = 1;
- break;
- case Opt_nocase:
- if (!is_vfat)
- opts->nocase = 1;
- else {
- /* for backward compatibility */
- opts->shortname = VFAT_SFN_DISPLAY_WIN95
- | VFAT_SFN_CREATE_WIN95;
- }
- break;
- case Opt_quiet:
- opts->quiet = 1;
- break;
- case Opt_showexec:
- opts->showexec = 1;
- break;
- case Opt_debug:
- *debug = 1;
- break;
- case Opt_immutable:
- opts->sys_immutable = 1;
- break;
- case Opt_uid:
- if (match_int(&args[0], &option))
- return -EINVAL;
- opts->fs_uid = make_kuid(current_user_ns(), option);
- if (!uid_valid(opts->fs_uid))
- return -EINVAL;
- break;
- case Opt_gid:
- if (match_int(&args[0], &option))
- return -EINVAL;
- opts->fs_gid = make_kgid(current_user_ns(), option);
- if (!gid_valid(opts->fs_gid))
- return -EINVAL;
- break;
- case Opt_umask:
- if (match_octal(&args[0], &option))
- return -EINVAL;
- opts->fs_fmask = opts->fs_dmask = option;
- break;
- case Opt_dmask:
- if (match_octal(&args[0], &option))
- return -EINVAL;
- opts->fs_dmask = option;
- break;
- case Opt_fmask:
- if (match_octal(&args[0], &option))
- return -EINVAL;
- opts->fs_fmask = option;
- break;
- case Opt_allow_utime:
- if (match_octal(&args[0], &option))
- return -EINVAL;
- opts->allow_utime = option & (S_IWGRP | S_IWOTH);
- break;
- case Opt_codepage:
- if (match_int(&args[0], &option))
- return -EINVAL;
- opts->codepage = option;
- break;
- case Opt_flush:
- opts->flush = 1;
- break;
- case Opt_time_offset:
- if (match_int(&args[0], &option))
- return -EINVAL;
- /*
- * GMT+-12 zones may have DST corrections so at least
- * 13 hours difference is needed. Make the limit 24
- * just in case someone invents something unusual.
- */
- if (option < -24 * 60 || option > 24 * 60)
- return -EINVAL;
- opts->tz_set = 1;
- opts->time_offset = option;
- break;
- case Opt_tz_utc:
- opts->tz_set = 1;
- opts->time_offset = 0;
- break;
- case Opt_err_cont:
- opts->errors = FAT_ERRORS_CONT;
- break;
- case Opt_err_panic:
- opts->errors = FAT_ERRORS_PANIC;
- break;
- case Opt_err_ro:
- opts->errors = FAT_ERRORS_RO;
- break;
- case Opt_nfs_stale_rw:
- opts->nfs = FAT_NFS_STALE_RW;
- break;
- case Opt_nfs_nostale_ro:
- opts->nfs = FAT_NFS_NOSTALE_RO;
- break;
- case Opt_dos1xfloppy:
- opts->dos1xfloppy = 1;
- break;
+static const struct constant_table fat_param_shortname[] = {
+ {"lower", VFAT_SFN_DISPLAY_LOWER | VFAT_SFN_CREATE_WIN95},
+ {"win95", VFAT_SFN_DISPLAY_WIN95 | VFAT_SFN_CREATE_WIN95},
+ {"winnt", VFAT_SFN_DISPLAY_WINNT | VFAT_SFN_CREATE_WINNT},
+ {"mixed", VFAT_SFN_DISPLAY_WINNT | VFAT_SFN_CREATE_WIN95},
+ {}
+};
- /* msdos specific */
- case Opt_dots:
- opts->dotsOK = 1;
- break;
- case Opt_nodots:
- opts->dotsOK = 0;
- break;
+static const struct fs_parameter_spec vfat_param_spec[] = {
+ fsparam_string ("iocharset", Opt_charset),
+ fsparam_enum ("shortname", Opt_shortname, fat_param_shortname),
+ fsparam_flag ("utf8", Opt_utf8),
+ fsparam_bool ("utf8", Opt_utf8_bool),
+ fsparam_flag ("uni_xlate", Opt_uni_xl),
+ fsparam_bool ("uni_xlate", Opt_uni_xl_bool),
+ fsparam_flag ("nonumtail", Opt_nonumtail),
+ fsparam_bool ("nonumtail", Opt_nonumtail_bool),
+ fsparam_flag ("rodir", Opt_rodir),
+ {}
+};
- /* vfat specific */
- case Opt_charset:
- fat_reset_iocharset(opts);
- iocharset = match_strdup(&args[0]);
- if (!iocharset)
- return -ENOMEM;
- opts->iocharset = iocharset;
- break;
- case Opt_shortname_lower:
- opts->shortname = VFAT_SFN_DISPLAY_LOWER
- | VFAT_SFN_CREATE_WIN95;
- break;
- case Opt_shortname_win95:
- opts->shortname = VFAT_SFN_DISPLAY_WIN95
- | VFAT_SFN_CREATE_WIN95;
- break;
- case Opt_shortname_winnt:
- opts->shortname = VFAT_SFN_DISPLAY_WINNT
- | VFAT_SFN_CREATE_WINNT;
- break;
- case Opt_shortname_mixed:
- opts->shortname = VFAT_SFN_DISPLAY_WINNT
- | VFAT_SFN_CREATE_WIN95;
- break;
- case Opt_utf8_no: /* 0 or no or false */
- opts->utf8 = 0;
- break;
- case Opt_utf8_yes: /* empty or 1 or yes or true */
- opts->utf8 = 1;
- break;
- case Opt_uni_xl_no: /* 0 or no or false */
- opts->unicode_xlate = 0;
- break;
- case Opt_uni_xl_yes: /* empty or 1 or yes or true */
- opts->unicode_xlate = 1;
- break;
- case Opt_nonumtail_no: /* 0 or no or false */
- opts->numtail = 1; /* negated option */
- break;
- case Opt_nonumtail_yes: /* empty or 1 or yes or true */
- opts->numtail = 0; /* negated option */
- break;
- case Opt_rodir:
- opts->rodir = 1;
- break;
- case Opt_discard:
- opts->discard = 1;
- break;
+int fat_parse_param(struct fs_context *fc, struct fs_parameter *param,
+ bool is_vfat)
+{
+ struct fat_mount_options *opts = fc->fs_private;
+ struct fs_parse_result result;
+ int opt;
- /* obsolete mount options */
- case Opt_obsolete:
- fat_msg(sb, KERN_INFO, "\"%s\" option is obsolete, "
- "not supported now", p);
- break;
- /* unknown option */
- default:
- if (!silent) {
- fat_msg(sb, KERN_ERR,
- "Unrecognized mount option \"%s\" "
- "or missing value", p);
- }
- return -EINVAL;
- }
- }
+ /* remount options have traditionally been ignored */
+ if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE)
+ return 0;
-out:
- /* UTF-8 doesn't provide FAT semantics */
- if (!strcmp(opts->iocharset, "utf8")) {
- fat_msg(sb, KERN_WARNING, "utf8 is not a recommended IO charset"
- " for FAT filesystems, filesystem will be "
- "case sensitive!");
+ opt = fs_parse(fc, fat_param_spec, param, &result);
+ /* If option not found in fat_param_spec, try vfat/msdos options */
+ if (opt == -ENOPARAM) {
+ if (is_vfat)
+ opt = fs_parse(fc, vfat_param_spec, param, &result);
+ else
+ opt = fs_parse(fc, msdos_param_spec, param, &result);
}
- /* If user doesn't specify allow_utime, it's initialized from dmask. */
- if (opts->allow_utime == (unsigned short)-1)
- opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH);
- if (opts->unicode_xlate)
- opts->utf8 = 0;
- if (opts->nfs == FAT_NFS_NOSTALE_RO) {
- sb->s_flags |= SB_RDONLY;
- sb->s_export_op = &fat_export_ops_nostale;
+ if (opt < 0)
+ return opt;
+
+ switch (opt) {
+ case Opt_check:
+ opts->name_check = result.uint_32;
+ break;
+ case Opt_usefree:
+ opts->usefree = 1;
+ break;
+ case Opt_nocase:
+ if (!is_vfat)
+ opts->nocase = 1;
+ else {
+ /* for backward compatibility */
+ opts->shortname = VFAT_SFN_DISPLAY_WIN95
+ | VFAT_SFN_CREATE_WIN95;
+ }
+ break;
+ case Opt_quiet:
+ opts->quiet = 1;
+ break;
+ case Opt_showexec:
+ opts->showexec = 1;
+ break;
+ case Opt_debug:
+ opts->debug = 1;
+ break;
+ case Opt_immutable:
+ opts->sys_immutable = 1;
+ break;
+ case Opt_uid:
+ opts->fs_uid = result.uid;
+ break;
+ case Opt_gid:
+ opts->fs_gid = result.gid;
+ break;
+ case Opt_umask:
+ opts->fs_fmask = opts->fs_dmask = result.uint_32;
+ break;
+ case Opt_dmask:
+ opts->fs_dmask = result.uint_32;
+ break;
+ case Opt_fmask:
+ opts->fs_fmask = result.uint_32;
+ break;
+ case Opt_allow_utime:
+ opts->allow_utime = result.uint_32 & (S_IWGRP | S_IWOTH);
+ break;
+ case Opt_codepage:
+ opts->codepage = result.uint_32;
+ break;
+ case Opt_flush:
+ opts->flush = 1;
+ break;
+ case Opt_time_offset:
+ /*
+ * GMT+-12 zones may have DST corrections so at least
+ * 13 hours difference is needed. Make the limit 24
+ * just in case someone invents something unusual.
+ */
+ if (result.int_32 < -24 * 60 || result.int_32 > 24 * 60)
+ return -EINVAL;
+ opts->tz_set = 1;
+ opts->time_offset = result.int_32;
+ break;
+ case Opt_tz:
+ opts->tz_set = 1;
+ opts->time_offset = result.uint_32;
+ break;
+ case Opt_errors:
+ opts->errors = result.uint_32;
+ break;
+ case Opt_nfs:
+ opts->nfs = FAT_NFS_STALE_RW;
+ break;
+ case Opt_nfs_enum:
+ opts->nfs = result.uint_32;
+ break;
+ case Opt_dos1xfloppy:
+ opts->dos1xfloppy = 1;
+ break;
+
+ /* msdos specific */
+ case Opt_dots: /* dots / nodots */
+ opts->dotsOK = !result.negated;
+ break;
+ case Opt_dotsOK: /* dotsOK = yes/no */
+ opts->dotsOK = result.boolean;
+ break;
+
+ /* vfat specific */
+ case Opt_charset:
+ fat_reset_iocharset(opts);
+ opts->iocharset = param->string;
+ param->string = NULL; /* Steal string */
+ break;
+ case Opt_shortname:
+ opts->shortname = result.uint_32;
+ break;
+ case Opt_utf8:
+ opts->utf8 = 1;
+ break;
+ case Opt_utf8_bool:
+ opts->utf8 = result.boolean;
+ break;
+ case Opt_uni_xl:
+ opts->unicode_xlate = 1;
+ break;
+ case Opt_uni_xl_bool:
+ opts->unicode_xlate = result.boolean;
+ break;
+ case Opt_nonumtail:
+ opts->numtail = 0; /* negated option */
+ break;
+ case Opt_nonumtail_bool:
+ opts->numtail = !result.boolean; /* negated option */
+ break;
+ case Opt_rodir:
+ opts->rodir = 1;
+ break;
+ case Opt_discard:
+ opts->discard = 1;
+ break;
+
+ /* obsolete mount options */
+ case Opt_obsolete:
+ printk(KERN_INFO "FAT-fs: \"%s\" option is obsolete, "
+ "not supported now", param->key);
+ break;
+ default:
+ return -EINVAL;
}
return 0;
}
+EXPORT_SYMBOL_GPL(fat_parse_param);
static int fat_read_root(struct inode *inode)
{
@@ -1604,9 +1530,11 @@ out:
/*
* Read the super block of an MS-DOS FS.
*/
-int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
+int fat_fill_super(struct super_block *sb, struct fs_context *fc,
void (*setup)(struct super_block *))
{
+ struct fat_mount_options *opts = fc->fs_private;
+ int silent = fc->sb_flags & SB_SILENT;
struct inode *root_inode = NULL, *fat_inode = NULL;
struct inode *fsinfo_inode = NULL;
struct buffer_head *bh;
@@ -1614,7 +1542,6 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
struct msdos_sb_info *sbi;
u16 logical_sector_size;
u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors;
- int debug;
long error;
char buf[50];
struct timespec64 ts;
@@ -1643,9 +1570,27 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
- error = parse_options(sb, data, isvfat, silent, &debug, &sbi->options);
- if (error)
- goto out_fail;
+ /* UTF-8 doesn't provide FAT semantics */
+ if (!strcmp(opts->iocharset, "utf8")) {
+ fat_msg(sb, KERN_WARNING, "utf8 is not a recommended IO charset"
+ " for FAT filesystems, filesystem will be"
+ " case sensitive!");
+ }
+
+ /* If user doesn't specify allow_utime, it's initialized from dmask. */
+ if (opts->allow_utime == (unsigned short)-1)
+ opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH);
+ if (opts->unicode_xlate)
+ opts->utf8 = 0;
+ if (opts->nfs == FAT_NFS_NOSTALE_RO) {
+ sb->s_flags |= SB_RDONLY;
+ sb->s_export_op = &fat_export_ops_nostale;
+ }
+
+ /* Apply parsed options to sbi (structure copy) */
+ sbi->options = *opts;
+ /* Transfer ownership of iocharset to sbi->options */
+ opts->iocharset = NULL;
setup(sb); /* flavour-specific stuff that needs options */
@@ -1950,6 +1895,57 @@ int fat_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2)
}
EXPORT_SYMBOL_GPL(fat_flush_inodes);
+int fat_init_fs_context(struct fs_context *fc, bool is_vfat)
+{
+ struct fat_mount_options *opts;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return -ENOMEM;
+
+ opts->isvfat = is_vfat;
+ opts->fs_uid = current_uid();
+ opts->fs_gid = current_gid();
+ opts->fs_fmask = opts->fs_dmask = current_umask();
+ opts->allow_utime = -1;
+ opts->codepage = fat_default_codepage;
+ fat_reset_iocharset(opts);
+ if (is_vfat) {
+ opts->shortname = VFAT_SFN_DISPLAY_WINNT|VFAT_SFN_CREATE_WIN95;
+ opts->rodir = 0;
+ } else {
+ opts->shortname = 0;
+ opts->rodir = 1;
+ }
+ opts->name_check = 'n';
+ opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0;
+ opts->unicode_xlate = 0;
+ opts->numtail = 1;
+ opts->usefree = opts->nocase = 0;
+ opts->tz_set = 0;
+ opts->nfs = 0;
+ opts->errors = FAT_ERRORS_RO;
+ opts->debug = 0;
+
+ opts->utf8 = IS_ENABLED(CONFIG_FAT_DEFAULT_UTF8) && is_vfat;
+
+ fc->fs_private = opts;
+ /* fc->ops assigned by caller */
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fat_init_fs_context);
+
+void fat_free_fc(struct fs_context *fc)
+{
+ struct fat_mount_options *opts = fc->fs_private;
+
+ if (opts->iocharset != fat_default_iocharset)
+ kfree(opts->iocharset);
+ kfree(fc->fs_private);
+}
+EXPORT_SYMBOL_GPL(fat_free_fc);
+
static int __init init_fat_fs(void)
{
int err;
@@ -1978,4 +1974,5 @@ static void __exit exit_fat_fs(void)
module_init(init_fat_fs)
module_exit(exit_fat_fs)
+MODULE_DESCRIPTION("Core FAT filesystem support");
MODULE_LICENSE("GPL");
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 2116c486843b..f06f6ba643cc 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -650,24 +650,48 @@ static void setup(struct super_block *sb)
sb->s_flags |= SB_NOATIME;
}
-static int msdos_fill_super(struct super_block *sb, void *data, int silent)
+static int msdos_fill_super(struct super_block *sb, struct fs_context *fc)
{
- return fat_fill_super(sb, data, silent, 0, setup);
+ return fat_fill_super(sb, fc, setup);
}
-static struct dentry *msdos_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name,
- void *data)
+static int msdos_get_tree(struct fs_context *fc)
{
- return mount_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
+ return get_tree_bdev(fc, msdos_fill_super);
+}
+
+static int msdos_parse_param(struct fs_context *fc, struct fs_parameter *param)
+{
+ return fat_parse_param(fc, param, false);
+}
+
+static const struct fs_context_operations msdos_context_ops = {
+ .parse_param = msdos_parse_param,
+ .get_tree = msdos_get_tree,
+ .reconfigure = fat_reconfigure,
+ .free = fat_free_fc,
+};
+
+static int msdos_init_fs_context(struct fs_context *fc)
+{
+ int err;
+
+ /* Initialize with is_vfat == false */
+ err = fat_init_fs_context(fc, false);
+ if (err)
+ return err;
+
+ fc->ops = &msdos_context_ops;
+ return 0;
}
static struct file_system_type msdos_fs_type = {
.owner = THIS_MODULE,
.name = "msdos",
- .mount = msdos_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
+ .init_fs_context = msdos_init_fs_context,
+ .parameters = fat_param_spec,
};
MODULE_ALIAS_FS("msdos");
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index c4d00999a433..6423e1dedf14 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -1195,24 +1195,48 @@ static void setup(struct super_block *sb)
sb->s_d_op = &vfat_dentry_ops;
}
-static int vfat_fill_super(struct super_block *sb, void *data, int silent)
+static int vfat_fill_super(struct super_block *sb, struct fs_context *fc)
{
- return fat_fill_super(sb, data, silent, 1, setup);
+ return fat_fill_super(sb, fc, setup);
}
-static struct dentry *vfat_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name,
- void *data)
+static int vfat_get_tree(struct fs_context *fc)
{
- return mount_bdev(fs_type, flags, dev_name, data, vfat_fill_super);
+ return get_tree_bdev(fc, vfat_fill_super);
+}
+
+static int vfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
+{
+ return fat_parse_param(fc, param, true);
+}
+
+static const struct fs_context_operations vfat_context_ops = {
+ .parse_param = vfat_parse_param,
+ .get_tree = vfat_get_tree,
+ .reconfigure = fat_reconfigure,
+ .free = fat_free_fc,
+};
+
+static int vfat_init_fs_context(struct fs_context *fc)
+{
+ int err;
+
+ /* Initialize with is_vfat == true */
+ err = fat_init_fs_context(fc, true);
+ if (err)
+ return err;
+
+ fc->ops = &vfat_context_ops;
+ return 0;
}
static struct file_system_type vfat_fs_type = {
.owner = THIS_MODULE,
.name = "vfat",
- .mount = vfat_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
+ .init_fs_context = vfat_init_fs_context,
+ .parameters = fat_param_spec,
};
MODULE_ALIAS_FS("vfat");
diff --git a/fs/fhandle.c b/fs/fhandle.c
index 8a7f86c2139a..6e8cea16790e 100644
--- a/fs/fhandle.c
+++ b/fs/fhandle.c
@@ -115,88 +115,188 @@ SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
return err;
}
-static struct vfsmount *get_vfsmount_from_fd(int fd)
+static int get_path_from_fd(int fd, struct path *root)
{
- struct vfsmount *mnt;
-
if (fd == AT_FDCWD) {
struct fs_struct *fs = current->fs;
spin_lock(&fs->lock);
- mnt = mntget(fs->pwd.mnt);
+ *root = fs->pwd;
+ path_get(root);
spin_unlock(&fs->lock);
} else {
struct fd f = fdget(fd);
if (!f.file)
- return ERR_PTR(-EBADF);
- mnt = mntget(f.file->f_path.mnt);
+ return -EBADF;
+ *root = f.file->f_path;
+ path_get(root);
fdput(f);
}
- return mnt;
+
+ return 0;
}
+enum handle_to_path_flags {
+ HANDLE_CHECK_PERMS = (1 << 0),
+ HANDLE_CHECK_SUBTREE = (1 << 1),
+};
+
+struct handle_to_path_ctx {
+ struct path root;
+ enum handle_to_path_flags flags;
+ unsigned int fh_flags;
+};
+
static int vfs_dentry_acceptable(void *context, struct dentry *dentry)
{
- return 1;
+ struct handle_to_path_ctx *ctx = context;
+ struct user_namespace *user_ns = current_user_ns();
+ struct dentry *d, *root = ctx->root.dentry;
+ struct mnt_idmap *idmap = mnt_idmap(ctx->root.mnt);
+ int retval = 0;
+
+ if (!root)
+ return 1;
+
+ /* Old permission model with global CAP_DAC_READ_SEARCH. */
+ if (!ctx->flags)
+ return 1;
+
+ /*
+ * It's racy as we're not taking rename_lock but we're able to ignore
+ * permissions and we just need an approximation whether we were able
+ * to follow a path to the file.
+ *
+ * It's also potentially expensive on some filesystems especially if
+ * there is a deep path.
+ */
+ d = dget(dentry);
+ while (d != root && !IS_ROOT(d)) {
+ struct dentry *parent = dget_parent(d);
+
+ /*
+ * We know that we have the ability to override DAC permissions
+ * as we've verified this earlier via CAP_DAC_READ_SEARCH. But
+ * we also need to make sure that there aren't any unmapped
+ * inodes in the path that would prevent us from reaching the
+ * file.
+ */
+ if (!privileged_wrt_inode_uidgid(user_ns, idmap,
+ d_inode(parent))) {
+ dput(d);
+ dput(parent);
+ return retval;
+ }
+
+ dput(d);
+ d = parent;
+ }
+
+ if (!(ctx->flags & HANDLE_CHECK_SUBTREE) || d == root)
+ retval = 1;
+ WARN_ON_ONCE(d != root && d != root->d_sb->s_root);
+ dput(d);
+ return retval;
}
-static int do_handle_to_path(int mountdirfd, struct file_handle *handle,
- struct path *path)
+static int do_handle_to_path(struct file_handle *handle, struct path *path,
+ struct handle_to_path_ctx *ctx)
{
- int retval = 0;
int handle_dwords;
+ struct vfsmount *mnt = ctx->root.mnt;
- path->mnt = get_vfsmount_from_fd(mountdirfd);
- if (IS_ERR(path->mnt)) {
- retval = PTR_ERR(path->mnt);
- goto out_err;
- }
/* change the handle size to multiple of sizeof(u32) */
handle_dwords = handle->handle_bytes >> 2;
- path->dentry = exportfs_decode_fh(path->mnt,
+ path->dentry = exportfs_decode_fh_raw(mnt,
(struct fid *)handle->f_handle,
handle_dwords, handle->handle_type,
- vfs_dentry_acceptable, NULL);
- if (IS_ERR(path->dentry)) {
- retval = PTR_ERR(path->dentry);
- goto out_mnt;
+ ctx->fh_flags,
+ vfs_dentry_acceptable, ctx);
+ if (IS_ERR_OR_NULL(path->dentry)) {
+ if (path->dentry == ERR_PTR(-ENOMEM))
+ return -ENOMEM;
+ return -ESTALE;
}
+ path->mnt = mntget(mnt);
return 0;
-out_mnt:
- mntput(path->mnt);
-out_err:
- return retval;
+}
+
+/*
+ * Allow relaxed permissions of file handles if the caller has the
+ * ability to mount the filesystem or create a bind-mount of the
+ * provided @mountdirfd.
+ *
+ * In both cases the caller may be able to get an unobstructed way to
+ * the encoded file handle. If the caller is only able to create a
+ * bind-mount we need to verify that there are no locked mounts on top
+ * of it that could prevent us from getting to the encoded file.
+ *
+ * In principle, locked mounts can prevent the caller from mounting the
+ * filesystem but that only applies to procfs and sysfs neither of which
+ * support decoding file handles.
+ */
+static inline bool may_decode_fh(struct handle_to_path_ctx *ctx,
+ unsigned int o_flags)
+{
+ struct path *root = &ctx->root;
+
+ /*
+ * Restrict to O_DIRECTORY to provide a deterministic API that avoids a
+ * confusing api in the face of disconnected non-dir dentries.
+ *
+ * There's only one dentry for each directory inode (VFS rule)...
+ */
+ if (!(o_flags & O_DIRECTORY))
+ return false;
+
+ if (ns_capable(root->mnt->mnt_sb->s_user_ns, CAP_SYS_ADMIN))
+ ctx->flags = HANDLE_CHECK_PERMS;
+ else if (is_mounted(root->mnt) &&
+ ns_capable(real_mount(root->mnt)->mnt_ns->user_ns,
+ CAP_SYS_ADMIN) &&
+ !has_locked_children(real_mount(root->mnt), root->dentry))
+ ctx->flags = HANDLE_CHECK_PERMS | HANDLE_CHECK_SUBTREE;
+ else
+ return false;
+
+ /* Are we able to override DAC permissions? */
+ if (!ns_capable(current_user_ns(), CAP_DAC_READ_SEARCH))
+ return false;
+
+ ctx->fh_flags = EXPORT_FH_DIR_ONLY;
+ return true;
}
static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
- struct path *path)
+ struct path *path, unsigned int o_flags)
{
int retval = 0;
struct file_handle f_handle;
struct file_handle *handle = NULL;
+ struct handle_to_path_ctx ctx = {};
- /*
- * With handle we don't look at the execute bit on the
- * directory. Ideally we would like CAP_DAC_SEARCH.
- * But we don't have that
- */
- if (!capable(CAP_DAC_READ_SEARCH)) {
- retval = -EPERM;
+ retval = get_path_from_fd(mountdirfd, &ctx.root);
+ if (retval)
goto out_err;
+
+ if (!capable(CAP_DAC_READ_SEARCH) && !may_decode_fh(&ctx, o_flags)) {
+ retval = -EPERM;
+ goto out_path;
}
+
if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) {
retval = -EFAULT;
- goto out_err;
+ goto out_path;
}
if ((f_handle.handle_bytes > MAX_HANDLE_SZ) ||
(f_handle.handle_bytes == 0)) {
retval = -EINVAL;
- goto out_err;
+ goto out_path;
}
handle = kmalloc(struct_size(handle, f_handle, f_handle.handle_bytes),
GFP_KERNEL);
if (!handle) {
retval = -ENOMEM;
- goto out_err;
+ goto out_path;
}
/* copy the full handle */
*handle = f_handle;
@@ -207,10 +307,12 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
goto out_handle;
}
- retval = do_handle_to_path(mountdirfd, handle, path);
+ retval = do_handle_to_path(handle, path, &ctx);
out_handle:
kfree(handle);
+out_path:
+ path_put(&ctx.root);
out_err:
return retval;
}
@@ -223,7 +325,7 @@ static long do_handle_open(int mountdirfd, struct file_handle __user *ufh,
struct file *file;
int fd;
- retval = handle_to_path(mountdirfd, ufh, &path);
+ retval = handle_to_path(mountdirfd, ufh, &path, open_flag);
if (retval)
return retval;
diff --git a/fs/fs_parser.c b/fs/fs_parser.c
index a4d6ca0b8971..24727ec34e5a 100644
--- a/fs/fs_parser.c
+++ b/fs/fs_parser.c
@@ -308,6 +308,40 @@ int fs_param_is_fd(struct p_log *log, const struct fs_parameter_spec *p,
}
EXPORT_SYMBOL(fs_param_is_fd);
+int fs_param_is_uid(struct p_log *log, const struct fs_parameter_spec *p,
+ struct fs_parameter *param, struct fs_parse_result *result)
+{
+ kuid_t uid;
+
+ if (fs_param_is_u32(log, p, param, result) != 0)
+ return fs_param_bad_value(log, param);
+
+ uid = make_kuid(current_user_ns(), result->uint_32);
+ if (!uid_valid(uid))
+ return inval_plog(log, "Invalid uid '%s'", param->string);
+
+ result->uid = uid;
+ return 0;
+}
+EXPORT_SYMBOL(fs_param_is_uid);
+
+int fs_param_is_gid(struct p_log *log, const struct fs_parameter_spec *p,
+ struct fs_parameter *param, struct fs_parse_result *result)
+{
+ kgid_t gid;
+
+ if (fs_param_is_u32(log, p, param, result) != 0)
+ return fs_param_bad_value(log, param);
+
+ gid = make_kgid(current_user_ns(), result->uint_32);
+ if (!gid_valid(gid))
+ return inval_plog(log, "Invalid gid '%s'", param->string);
+
+ result->gid = gid;
+ return 0;
+}
+EXPORT_SYMBOL(fs_param_is_gid);
+
int fs_param_is_blockdev(struct p_log *log, const struct fs_parameter_spec *p,
struct fs_parameter *param, struct fs_parse_result *result)
{
diff --git a/fs/fsopen.c b/fs/fsopen.c
index 6593ae518115..ed2dd000622e 100644
--- a/fs/fsopen.c
+++ b/fs/fsopen.c
@@ -220,10 +220,6 @@ static int vfs_cmd_create(struct fs_context *fc, bool exclusive)
if (!mount_capable(fc))
return -EPERM;
- /* require the new mount api */
- if (exclusive && fc->ops == &legacy_fs_context_ops)
- return -EOPNOTSUPP;
-
fc->phase = FS_CONTEXT_CREATING;
fc->exclusive = exclusive;
@@ -411,6 +407,7 @@ SYSCALL_DEFINE5(fsconfig,
case FSCONFIG_SET_PATH:
case FSCONFIG_SET_PATH_EMPTY:
case FSCONFIG_SET_FD:
+ case FSCONFIG_CMD_CREATE_EXCL:
ret = -EOPNOTSUPP;
goto out_f;
}
@@ -451,7 +448,7 @@ SYSCALL_DEFINE5(fsconfig,
fallthrough;
case FSCONFIG_SET_PATH:
param.type = fs_value_is_filename;
- param.name = getname_flags(_value, lookup_flags, NULL);
+ param.name = getname_flags(_value, lookup_flags);
if (IS_ERR(param.name)) {
ret = PTR_ERR(param.name);
goto out_key;
diff --git a/fs/fuse/acl.c b/fs/fuse/acl.c
index 3d192b80a561..04cfd8fee992 100644
--- a/fs/fuse/acl.c
+++ b/fs/fuse/acl.c
@@ -146,8 +146,8 @@ int fuse_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
* be stripped.
*/
if (fc->posix_acl &&
- !vfsgid_in_group_p(i_gid_into_vfsgid(&nop_mnt_idmap, inode)) &&
- !capable_wrt_inode_uidgid(&nop_mnt_idmap, inode, CAP_FSETID))
+ !in_group_or_capable(&nop_mnt_idmap, inode,
+ i_gid_into_vfsgid(&nop_mnt_idmap, inode)))
extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID;
ret = fuse_setxattr(inode, name, value, size, 0, extra_flags);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 99e44ea7d875..d8ab4e93916f 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -740,8 +740,8 @@ static const struct fs_parameter_spec fuse_fs_parameters[] = {
fsparam_string ("source", OPT_SOURCE),
fsparam_u32 ("fd", OPT_FD),
fsparam_u32oct ("rootmode", OPT_ROOTMODE),
- fsparam_u32 ("user_id", OPT_USER_ID),
- fsparam_u32 ("group_id", OPT_GROUP_ID),
+ fsparam_uid ("user_id", OPT_USER_ID),
+ fsparam_gid ("group_id", OPT_GROUP_ID),
fsparam_flag ("default_permissions", OPT_DEFAULT_PERMISSIONS),
fsparam_flag ("allow_other", OPT_ALLOW_OTHER),
fsparam_u32 ("max_read", OPT_MAX_READ),
@@ -755,6 +755,8 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
struct fs_parse_result result;
struct fuse_fs_context *ctx = fsc->fs_private;
int opt;
+ kuid_t kuid;
+ kgid_t kgid;
if (fsc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
/*
@@ -799,16 +801,26 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
break;
case OPT_USER_ID:
- ctx->user_id = make_kuid(fsc->user_ns, result.uint_32);
- if (!uid_valid(ctx->user_id))
+ kuid = result.uid;
+ /*
+ * The requested uid must be representable in the
+ * filesystem's idmapping.
+ */
+ if (!kuid_has_mapping(fsc->user_ns, kuid))
return invalfc(fsc, "Invalid user_id");
+ ctx->user_id = kuid;
ctx->user_id_present = true;
break;
case OPT_GROUP_ID:
- ctx->group_id = make_kgid(fsc->user_ns, result.uint_32);
- if (!gid_valid(ctx->group_id))
+ kgid = result.gid;
+ /*
+ * The requested gid must be representable in the
+ * filesystem's idmapping.
+ */
+ if (!kgid_has_mapping(fsc->user_ns, kgid))
return invalfc(fsc, "Invalid group_id");
+ ctx->group_id = kgid;
ctx->group_id_present = true;
break;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 8c34798a0715..744e10b46904 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -200,6 +200,7 @@ struct inode *hfs_new_inode(struct inode *dir, const struct qstr *name, umode_t
HFS_I(inode)->flags = 0;
HFS_I(inode)->rsrc_inode = NULL;
HFS_I(inode)->fs_blocks = 0;
+ HFS_I(inode)->tz_secondswest = sys_tz.tz_minuteswest * 60;
if (S_ISDIR(mode)) {
inode->i_size = 2;
HFS_SB(sb)->folder_count++;
@@ -275,6 +276,8 @@ void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
for (count = 0, i = 0; i < 3; i++)
count += be16_to_cpu(ext[i].count);
HFS_I(inode)->first_blocks = count;
+ HFS_I(inode)->cached_start = 0;
+ HFS_I(inode)->cached_blocks = 0;
inode->i_size = HFS_I(inode)->phys_size = log_size;
HFS_I(inode)->fs_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 6764afa98a6f..eeac99765f0d 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -28,6 +28,7 @@
static struct kmem_cache *hfs_inode_cachep;
+MODULE_DESCRIPTION("Apple Macintosh file system support");
MODULE_LICENSE("GPL");
static int hfs_sync_fs(struct super_block *sb, int wait)
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index ca2ba8c9f82e..901e83d65d20 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -25,19 +25,8 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd)
fd->key = ptr + tree->max_key_len + 2;
hfs_dbg(BNODE_REFS, "find_init: %d (%p)\n",
tree->cnid, __builtin_return_address(0));
- switch (tree->cnid) {
- case HFSPLUS_CAT_CNID:
- mutex_lock_nested(&tree->tree_lock, CATALOG_BTREE_MUTEX);
- break;
- case HFSPLUS_EXT_CNID:
- mutex_lock_nested(&tree->tree_lock, EXTENTS_BTREE_MUTEX);
- break;
- case HFSPLUS_ATTR_CNID:
- mutex_lock_nested(&tree->tree_lock, ATTR_BTREE_MUTEX);
- break;
- default:
- BUG();
- }
+ mutex_lock_nested(&tree->tree_lock,
+ hfsplus_btree_lock_class(tree));
return 0;
}
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 3c572e44f2ad..9c51867dddc5 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -430,7 +430,8 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid,
hfsplus_free_extents(sb, ext_entry, total_blocks - start,
total_blocks);
total_blocks = start;
- mutex_lock(&fd.tree->tree_lock);
+ mutex_lock_nested(&fd.tree->tree_lock,
+ hfsplus_btree_lock_class(fd.tree));
} while (total_blocks > blocks);
hfs_find_exit(&fd);
@@ -592,7 +593,8 @@ void hfsplus_file_truncate(struct inode *inode)
alloc_cnt, alloc_cnt - blk_cnt);
hfsplus_dump_extent(hip->first_extents);
hip->first_blocks = blk_cnt;
- mutex_lock(&fd.tree->tree_lock);
+ mutex_lock_nested(&fd.tree->tree_lock,
+ hfsplus_btree_lock_class(fd.tree));
break;
}
res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt);
@@ -606,7 +608,8 @@ void hfsplus_file_truncate(struct inode *inode)
hfsplus_free_extents(sb, hip->cached_extents,
alloc_cnt - start, alloc_cnt - blk_cnt);
hfsplus_dump_extent(hip->cached_extents);
- mutex_lock(&fd.tree->tree_lock);
+ mutex_lock_nested(&fd.tree->tree_lock,
+ hfsplus_btree_lock_class(fd.tree));
if (blk_cnt > start) {
hip->extent_state |= HFSPLUS_EXT_DIRTY;
break;
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 012a3d003fbe..9e78f181c24f 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -553,6 +553,27 @@ static inline __be32 __hfsp_ut2mt(time64_t ut)
return cpu_to_be32(lower_32_bits(ut) + HFSPLUS_UTC_OFFSET);
}
+static inline enum hfsplus_btree_mutex_classes
+hfsplus_btree_lock_class(struct hfs_btree *tree)
+{
+ enum hfsplus_btree_mutex_classes class;
+
+ switch (tree->cnid) {
+ case HFSPLUS_CAT_CNID:
+ class = CATALOG_BTREE_MUTEX;
+ break;
+ case HFSPLUS_EXT_CNID:
+ class = EXTENTS_BTREE_MUTEX;
+ break;
+ case HFSPLUS_ATTR_CNID:
+ class = ATTR_BTREE_MUTEX;
+ break;
+ default:
+ BUG();
+ }
+ return class;
+}
+
/* compatibility */
#define hfsp_mt2ut(t) (struct timespec64){ .tv_sec = __hfsp_mt2ut(t) }
#define hfsp_ut2mt(t) __hfsp_ut2mt((t).tv_sec)
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
index 5661a2e24d03..40d04dba13ac 100644
--- a/fs/hfsplus/ioctl.c
+++ b/fs/hfsplus/ioctl.c
@@ -40,7 +40,7 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
/* Directory containing the bootable system */
vh->finder_info[0] = bvh->finder_info[0] =
- cpu_to_be32(parent_ino(dentry));
+ cpu_to_be32(d_parent_ino(dentry));
/*
* Bootloader. Just using the inode here breaks in the case of
@@ -51,7 +51,7 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
/* Per spec, the OS X system folder - same as finder_info[0] here */
vh->finder_info[5] = bvh->finder_info[5] =
- cpu_to_be32(parent_ino(dentry));
+ cpu_to_be32(d_parent_ino(dentry));
mutex_unlock(&sbi->vh_mutex);
return 0;
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index 5a400259ae74..9a1a93e3888b 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -696,7 +696,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
return err;
}
- strbuf = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN +
+ strbuf = kzalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN +
XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL);
if (!strbuf) {
res = -ENOMEM;
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index a73d27c4dd58..3eb747d26924 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -16,11 +16,16 @@
#include <linux/seq_file.h>
#include <linux/writeback.h>
#include <linux/mount.h>
+#include <linux/fs_context.h>
#include <linux/namei.h>
#include "hostfs.h"
#include <init.h>
#include <kern.h>
+struct hostfs_fs_info {
+ char *host_root_path;
+};
+
struct hostfs_inode_info {
int fd;
fmode_t mode;
@@ -90,8 +95,10 @@ static char *__dentry_name(struct dentry *dentry, char *name)
char *p = dentry_path_raw(dentry, name, PATH_MAX);
char *root;
size_t len;
+ struct hostfs_fs_info *fsi;
- root = dentry->d_sb->s_fs_info;
+ fsi = dentry->d_sb->s_fs_info;
+ root = fsi->host_root_path;
len = strlen(root);
if (IS_ERR(p)) {
__putname(name);
@@ -196,8 +203,10 @@ static int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
long long f_bavail;
long long f_files;
long long f_ffree;
+ struct hostfs_fs_info *fsi;
- err = do_statfs(dentry->d_sb->s_fs_info,
+ fsi = dentry->d_sb->s_fs_info;
+ err = do_statfs(fsi->host_root_path,
&sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
&f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
&sf->f_namelen);
@@ -245,7 +254,11 @@ static void hostfs_free_inode(struct inode *inode)
static int hostfs_show_options(struct seq_file *seq, struct dentry *root)
{
- const char *root_path = root->d_sb->s_fs_info;
+ struct hostfs_fs_info *fsi;
+ const char *root_path;
+
+ fsi = root->d_sb->s_fs_info;
+ root_path = fsi->host_root_path;
size_t offset = strlen(root_ino) + 1;
if (strlen(root_path) > offset)
@@ -432,31 +445,20 @@ static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
static int hostfs_read_folio(struct file *file, struct folio *folio)
{
- struct page *page = &folio->page;
char *buffer;
- loff_t start = page_offset(page);
+ loff_t start = folio_pos(folio);
int bytes_read, ret = 0;
- buffer = kmap_local_page(page);
+ buffer = kmap_local_folio(folio, 0);
bytes_read = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
PAGE_SIZE);
- if (bytes_read < 0) {
- ClearPageUptodate(page);
- SetPageError(page);
+ if (bytes_read < 0)
ret = bytes_read;
- goto out;
- }
-
- memset(buffer + bytes_read, 0, PAGE_SIZE - bytes_read);
-
- ClearPageError(page);
- SetPageUptodate(page);
-
- out:
- flush_dcache_page(page);
+ else
+ buffer = folio_zero_tail(folio, bytes_read, buffer);
kunmap_local(buffer);
- unlock_page(page);
+ folio_end_read(folio, ret == 0);
return ret;
}
@@ -922,10 +924,11 @@ static const struct inode_operations hostfs_link_iops = {
.get_link = hostfs_get_link,
};
-static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
+static int hostfs_fill_super(struct super_block *sb, struct fs_context *fc)
{
+ struct hostfs_fs_info *fsi = sb->s_fs_info;
+ const char *host_root = fc->source;
struct inode *root_inode;
- char *host_root_path, *req_root = d;
int err;
sb->s_blocksize = 1024;
@@ -939,15 +942,15 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
return err;
/* NULL is printed as '(null)' by printf(): avoid that. */
- if (req_root == NULL)
- req_root = "";
+ if (fc->source == NULL)
+ host_root = "";
- sb->s_fs_info = host_root_path =
- kasprintf(GFP_KERNEL, "%s/%s", root_ino, req_root);
- if (host_root_path == NULL)
+ fsi->host_root_path =
+ kasprintf(GFP_KERNEL, "%s/%s", root_ino, host_root);
+ if (fsi->host_root_path == NULL)
return -ENOMEM;
- root_inode = hostfs_iget(sb, host_root_path);
+ root_inode = hostfs_iget(sb, fsi->host_root_path);
if (IS_ERR(root_inode))
return PTR_ERR(root_inode);
@@ -955,7 +958,7 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
char *name;
iput(root_inode);
- name = follow_link(host_root_path);
+ name = follow_link(fsi->host_root_path);
if (IS_ERR(name))
return PTR_ERR(name);
@@ -972,11 +975,38 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
return 0;
}
-static struct dentry *hostfs_read_sb(struct file_system_type *type,
- int flags, const char *dev_name,
- void *data)
+static int hostfs_fc_get_tree(struct fs_context *fc)
+{
+ return get_tree_nodev(fc, hostfs_fill_super);
+}
+
+static void hostfs_fc_free(struct fs_context *fc)
{
- return mount_nodev(type, flags, data, hostfs_fill_sb_common);
+ struct hostfs_fs_info *fsi = fc->s_fs_info;
+
+ if (!fsi)
+ return;
+
+ kfree(fsi->host_root_path);
+ kfree(fsi);
+}
+
+static const struct fs_context_operations hostfs_context_ops = {
+ .get_tree = hostfs_fc_get_tree,
+ .free = hostfs_fc_free,
+};
+
+static int hostfs_init_fs_context(struct fs_context *fc)
+{
+ struct hostfs_fs_info *fsi;
+
+ fsi = kzalloc(sizeof(*fsi), GFP_KERNEL);
+ if (!fsi)
+ return -ENOMEM;
+
+ fc->s_fs_info = fsi;
+ fc->ops = &hostfs_context_ops;
+ return 0;
}
static void hostfs_kill_sb(struct super_block *s)
@@ -986,11 +1016,11 @@ static void hostfs_kill_sb(struct super_block *s)
}
static struct file_system_type hostfs_type = {
- .owner = THIS_MODULE,
- .name = "hostfs",
- .mount = hostfs_read_sb,
- .kill_sb = hostfs_kill_sb,
- .fs_flags = 0,
+ .owner = THIS_MODULE,
+ .name = "hostfs",
+ .init_fs_context = hostfs_init_fs_context,
+ .kill_sb = hostfs_kill_sb,
+ .fs_flags = 0,
};
MODULE_ALIAS_FS("hostfs");
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 9184b4584b01..d0edf9ed33b6 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -472,9 +472,8 @@ out:
static int hpfs_symlink_read_folio(struct file *file, struct folio *folio)
{
- struct page *page = &folio->page;
- char *link = page_address(page);
- struct inode *i = page->mapping->host;
+ char *link = folio_address(folio);
+ struct inode *i = folio->mapping->host;
struct fnode *fnode;
struct buffer_head *bh;
int err;
@@ -485,17 +484,9 @@ static int hpfs_symlink_read_folio(struct file *file, struct folio *folio)
goto fail;
err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);
brelse(bh);
- if (err)
- goto fail;
- hpfs_unlock(i->i_sb);
- SetPageUptodate(page);
- unlock_page(page);
- return 0;
-
fail:
hpfs_unlock(i->i_sb);
- SetPageError(page);
- unlock_page(page);
+ folio_end_read(folio, err == 0);
return err;
}
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 314834a078e9..e73717daa5f9 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -793,4 +793,5 @@ static void __exit exit_hpfs_fs(void)
module_init(init_hpfs_fs)
module_exit(exit_hpfs_fs)
+MODULE_DESCRIPTION("OS/2 HPFS file system support");
MODULE_LICENSE("GPL");
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 412f295acebe..81dab95f67ed 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -73,13 +73,13 @@ enum hugetlb_param {
};
static const struct fs_parameter_spec hugetlb_fs_parameters[] = {
- fsparam_u32 ("gid", Opt_gid),
+ fsparam_gid ("gid", Opt_gid),
fsparam_string("min_size", Opt_min_size),
fsparam_u32oct("mode", Opt_mode),
fsparam_string("nr_inodes", Opt_nr_inodes),
fsparam_string("pagesize", Opt_pagesize),
fsparam_string("size", Opt_size),
- fsparam_u32 ("uid", Opt_uid),
+ fsparam_uid ("uid", Opt_uid),
{}
};
@@ -1376,15 +1376,11 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par
switch (opt) {
case Opt_uid:
- ctx->uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(ctx->uid))
- goto bad_val;
+ ctx->uid = result.uid;
return 0;
case Opt_gid:
- ctx->gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(ctx->gid))
- goto bad_val;
+ ctx->gid = result.gid;
return 0;
case Opt_mode:
diff --git a/fs/inode.c b/fs/inode.c
index 3a41f83a4ba5..f356fe2ec2b6 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -162,6 +162,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
inode->i_sb = sb;
inode->i_blkbits = sb->s_blocksize_bits;
inode->i_flags = 0;
+ inode->i_state = 0;
atomic64_set(&inode->i_sequence, 0);
atomic_set(&inode->i_count, 1);
inode->i_op = &empty_iops;
@@ -231,6 +232,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
if (unlikely(security_inode_alloc(inode)))
return -ENOMEM;
+
this_cpu_inc(nr_inodes);
return 0;
@@ -886,36 +888,45 @@ long prune_icache_sb(struct super_block *sb, struct shrink_control *sc)
return freed;
}
-static void __wait_on_freeing_inode(struct inode *inode);
+static void __wait_on_freeing_inode(struct inode *inode, bool locked);
/*
* Called with the inode lock held.
*/
static struct inode *find_inode(struct super_block *sb,
struct hlist_head *head,
int (*test)(struct inode *, void *),
- void *data)
+ void *data, bool locked)
{
struct inode *inode = NULL;
+ if (locked)
+ lockdep_assert_held(&inode_hash_lock);
+ else
+ lockdep_assert_not_held(&inode_hash_lock);
+
+ rcu_read_lock();
repeat:
- hlist_for_each_entry(inode, head, i_hash) {
+ hlist_for_each_entry_rcu(inode, head, i_hash) {
if (inode->i_sb != sb)
continue;
if (!test(inode, data))
continue;
spin_lock(&inode->i_lock);
if (inode->i_state & (I_FREEING|I_WILL_FREE)) {
- __wait_on_freeing_inode(inode);
+ __wait_on_freeing_inode(inode, locked);
goto repeat;
}
if (unlikely(inode->i_state & I_CREATING)) {
spin_unlock(&inode->i_lock);
+ rcu_read_unlock();
return ERR_PTR(-ESTALE);
}
__iget(inode);
spin_unlock(&inode->i_lock);
+ rcu_read_unlock();
return inode;
}
+ rcu_read_unlock();
return NULL;
}
@@ -924,29 +935,39 @@ repeat:
* iget_locked for details.
*/
static struct inode *find_inode_fast(struct super_block *sb,
- struct hlist_head *head, unsigned long ino)
+ struct hlist_head *head, unsigned long ino,
+ bool locked)
{
struct inode *inode = NULL;
+ if (locked)
+ lockdep_assert_held(&inode_hash_lock);
+ else
+ lockdep_assert_not_held(&inode_hash_lock);
+
+ rcu_read_lock();
repeat:
- hlist_for_each_entry(inode, head, i_hash) {
+ hlist_for_each_entry_rcu(inode, head, i_hash) {
if (inode->i_ino != ino)
continue;
if (inode->i_sb != sb)
continue;
spin_lock(&inode->i_lock);
if (inode->i_state & (I_FREEING|I_WILL_FREE)) {
- __wait_on_freeing_inode(inode);
+ __wait_on_freeing_inode(inode, locked);
goto repeat;
}
if (unlikely(inode->i_state & I_CREATING)) {
spin_unlock(&inode->i_lock);
+ rcu_read_unlock();
return ERR_PTR(-ESTALE);
}
__iget(inode);
spin_unlock(&inode->i_lock);
+ rcu_read_unlock();
return inode;
}
+ rcu_read_unlock();
return NULL;
}
@@ -1004,14 +1025,7 @@ EXPORT_SYMBOL(get_next_ino);
*/
struct inode *new_inode_pseudo(struct super_block *sb)
{
- struct inode *inode = alloc_inode(sb);
-
- if (inode) {
- spin_lock(&inode->i_lock);
- inode->i_state = 0;
- spin_unlock(&inode->i_lock);
- }
- return inode;
+ return alloc_inode(sb);
}
/**
@@ -1161,7 +1175,7 @@ struct inode *inode_insert5(struct inode *inode, unsigned long hashval,
again:
spin_lock(&inode_hash_lock);
- old = find_inode(inode->i_sb, head, test, data);
+ old = find_inode(inode->i_sb, head, test, data, true);
if (unlikely(old)) {
/*
* Uhhuh, somebody else created the same inode under us.
@@ -1235,7 +1249,6 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
struct inode *new = alloc_inode(sb);
if (new) {
- new->i_state = 0;
inode = inode_insert5(new, hashval, test, set, data);
if (unlikely(inode != new))
destroy_inode(new);
@@ -1246,6 +1259,47 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
EXPORT_SYMBOL(iget5_locked);
/**
+ * iget5_locked_rcu - obtain an inode from a mounted file system
+ * @sb: super block of file system
+ * @hashval: hash value (usually inode number) to get
+ * @test: callback used for comparisons between inodes
+ * @set: callback used to initialize a new struct inode
+ * @data: opaque data pointer to pass to @test and @set
+ *
+ * This is equivalent to iget5_locked, except the @test callback must
+ * tolerate the inode not being stable, including being mid-teardown.
+ */
+struct inode *iget5_locked_rcu(struct super_block *sb, unsigned long hashval,
+ int (*test)(struct inode *, void *),
+ int (*set)(struct inode *, void *), void *data)
+{
+ struct hlist_head *head = inode_hashtable + hash(sb, hashval);
+ struct inode *inode, *new;
+
+again:
+ inode = find_inode(sb, head, test, data, false);
+ if (inode) {
+ if (IS_ERR(inode))
+ return NULL;
+ wait_on_inode(inode);
+ if (unlikely(inode_unhashed(inode))) {
+ iput(inode);
+ goto again;
+ }
+ return inode;
+ }
+
+ new = alloc_inode(sb);
+ if (new) {
+ inode = inode_insert5(new, hashval, test, set, data);
+ if (unlikely(inode != new))
+ destroy_inode(new);
+ }
+ return inode;
+}
+EXPORT_SYMBOL_GPL(iget5_locked_rcu);
+
+/**
* iget_locked - obtain an inode from a mounted file system
* @sb: super block of file system
* @ino: inode number to get
@@ -1263,9 +1317,7 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino)
struct hlist_head *head = inode_hashtable + hash(sb, ino);
struct inode *inode;
again:
- spin_lock(&inode_hash_lock);
- inode = find_inode_fast(sb, head, ino);
- spin_unlock(&inode_hash_lock);
+ inode = find_inode_fast(sb, head, ino, false);
if (inode) {
if (IS_ERR(inode))
return NULL;
@@ -1283,7 +1335,7 @@ again:
spin_lock(&inode_hash_lock);
/* We released the lock, so.. */
- old = find_inode_fast(sb, head, ino);
+ old = find_inode_fast(sb, head, ino, true);
if (!old) {
inode->i_ino = ino;
spin_lock(&inode->i_lock);
@@ -1419,7 +1471,7 @@ struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval,
struct inode *inode;
spin_lock(&inode_hash_lock);
- inode = find_inode(sb, head, test, data);
+ inode = find_inode(sb, head, test, data, true);
spin_unlock(&inode_hash_lock);
return IS_ERR(inode) ? NULL : inode;
@@ -1474,7 +1526,7 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
struct inode *inode;
again:
spin_lock(&inode_hash_lock);
- inode = find_inode_fast(sb, head, ino);
+ inode = find_inode_fast(sb, head, ino, true);
spin_unlock(&inode_hash_lock);
if (inode) {
@@ -2235,17 +2287,21 @@ EXPORT_SYMBOL(inode_needs_sync);
* wake_up_bit(&inode->i_state, __I_NEW) after removing from the hash list
* will DTRT.
*/
-static void __wait_on_freeing_inode(struct inode *inode)
+static void __wait_on_freeing_inode(struct inode *inode, bool locked)
{
wait_queue_head_t *wq;
DEFINE_WAIT_BIT(wait, &inode->i_state, __I_NEW);
wq = bit_waitqueue(&inode->i_state, __I_NEW);
prepare_to_wait(wq, &wait.wq_entry, TASK_UNINTERRUPTIBLE);
spin_unlock(&inode->i_lock);
- spin_unlock(&inode_hash_lock);
+ rcu_read_unlock();
+ if (locked)
+ spin_unlock(&inode_hash_lock);
schedule();
finish_wait(wq, &wait.wq_entry);
- spin_lock(&inode_hash_lock);
+ if (locked)
+ spin_lock(&inode_hash_lock);
+ rcu_read_lock();
}
static __initdata unsigned long ihash_entries;
@@ -2538,6 +2594,7 @@ bool in_group_or_capable(struct mnt_idmap *idmap,
return true;
return false;
}
+EXPORT_SYMBOL(in_group_or_capable);
/**
* mode_strip_sgid - handle the sgid bit for non-directories
diff --git a/fs/internal.h b/fs/internal.h
index ab2225136f60..cdd73209eecb 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -17,6 +17,7 @@ struct fs_context;
struct pipe_inode_info;
struct iov_iter;
struct mnt_idmap;
+struct ns_common;
/*
* block/bdev.c
@@ -239,6 +240,7 @@ extern void mnt_pin_kill(struct mount *m);
* fs/nsfs.c
*/
extern const struct dentry_operations ns_dentry_operations;
+int open_namespace(struct ns_common *ns);
/*
* fs/stat.c:
@@ -247,6 +249,8 @@ extern const struct dentry_operations ns_dentry_operations;
int getname_statx_lookup_flags(int flags);
int do_statx(int dfd, struct filename *filename, unsigned int flags,
unsigned int mask, struct statx __user *buffer);
+int do_statx_fd(int fd, unsigned int flags, unsigned int mask,
+ struct statx __user *buffer);
/*
* fs/splice.c:
@@ -321,3 +325,15 @@ struct stashed_operations {
int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data,
struct path *path);
void stashed_dentry_prune(struct dentry *dentry);
+/**
+ * path_mounted - check whether path is mounted
+ * @path: path to check
+ *
+ * Determine whether @path refers to the root of a mount.
+ *
+ * Return: true if @path is the root of a mount, false if not.
+ */
+static inline bool path_mounted(const struct path *path)
+{
+ return path->mnt->mnt_root == path->dentry;
+}
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index d46558990279..f420c53d86ac 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -307,8 +307,6 @@ static void iomap_finish_folio_read(struct folio *folio, size_t off,
spin_unlock_irqrestore(&ifs->state_lock, flags);
}
- if (error)
- folio_set_error(folio);
if (finished)
folio_end_read(folio, uptodate);
}
@@ -444,6 +442,24 @@ done:
return pos - orig_pos + plen;
}
+static loff_t iomap_read_folio_iter(const struct iomap_iter *iter,
+ struct iomap_readpage_ctx *ctx)
+{
+ struct folio *folio = ctx->cur_folio;
+ size_t offset = offset_in_folio(folio, iter->pos);
+ loff_t length = min_t(loff_t, folio_size(folio) - offset,
+ iomap_length(iter));
+ loff_t done, ret;
+
+ for (done = 0; done < length; done += ret) {
+ ret = iomap_readpage_iter(iter, ctx, done);
+ if (ret <= 0)
+ return ret;
+ }
+
+ return done;
+}
+
int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops)
{
struct iomap_iter iter = {
@@ -459,10 +475,7 @@ int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops)
trace_iomap_readpage(iter.inode, 1);
while ((ret = iomap_iter(&iter, ops)) > 0)
- iter.processed = iomap_readpage_iter(&iter, &ctx, 0);
-
- if (ret < 0)
- folio_set_error(folio);
+ iter.processed = iomap_read_folio_iter(&iter, &ctx);
if (ctx.bio) {
submit_bio(ctx.bio);
@@ -698,7 +711,6 @@ static int __iomap_write_begin(const struct iomap_iter *iter, loff_t pos,
if (folio_test_uptodate(folio))
return 0;
- folio_clear_error(folio);
do {
iomap_adjust_read_range(iter->inode, folio, &block_start,
@@ -878,37 +890,22 @@ static bool iomap_write_end(struct iomap_iter *iter, loff_t pos, size_t len,
size_t copied, struct folio *folio)
{
const struct iomap *srcmap = iomap_iter_srcmap(iter);
- loff_t old_size = iter->inode->i_size;
- size_t written;
if (srcmap->type == IOMAP_INLINE) {
iomap_write_end_inline(iter, folio, pos, copied);
- written = copied;
- } else if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
- written = block_write_end(NULL, iter->inode->i_mapping, pos,
- len, copied, &folio->page, NULL);
- WARN_ON_ONCE(written != copied && written != 0);
- } else {
- written = __iomap_write_end(iter->inode, pos, len, copied,
- folio) ? copied : 0;
+ return true;
}
- /*
- * Update the in-memory inode size after copying the data into the page
- * cache. It's up to the file system to write the updated size to disk,
- * preferably after I/O completion so that no stale data is exposed.
- * Only once that's done can we unlock and release the folio.
- */
- if (pos + written > old_size) {
- i_size_write(iter->inode, pos + written);
- iter->iomap.flags |= IOMAP_F_SIZE_CHANGED;
- }
- __iomap_put_folio(iter, pos, written, folio);
+ if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
+ size_t bh_written;
- if (old_size < pos)
- pagecache_isize_extended(iter->inode, old_size, pos);
+ bh_written = block_write_end(NULL, iter->inode->i_mapping, pos,
+ len, copied, &folio->page, NULL);
+ WARN_ON_ONCE(bh_written != copied && bh_written != 0);
+ return bh_written == copied;
+ }
- return written == copied;
+ return __iomap_write_end(iter->inode, pos, len, copied, folio);
}
static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
@@ -923,6 +920,7 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
do {
struct folio *folio;
+ loff_t old_size;
size_t offset; /* Offset into folio */
size_t bytes; /* Bytes to write to folio */
size_t copied; /* Bytes copied from user */
@@ -974,6 +972,23 @@ retry:
written = iomap_write_end(iter, pos, bytes, copied, folio) ?
copied : 0;
+ /*
+ * Update the in-memory inode size after copying the data into
+ * the page cache. It's up to the file system to write the
+ * updated size to disk, preferably after I/O completion so that
+ * no stale data is exposed. Only once that's done can we
+ * unlock and release the folio.
+ */
+ old_size = iter->inode->i_size;
+ if (pos + written > old_size) {
+ i_size_write(iter->inode, pos + written);
+ iter->iomap.flags |= IOMAP_F_SIZE_CHANGED;
+ }
+ __iomap_put_folio(iter, pos, written, folio);
+
+ if (old_size < pos)
+ pagecache_isize_extended(iter->inode, old_size, pos);
+
cond_resched();
if (unlikely(written == 0)) {
/*
@@ -1344,6 +1359,7 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter)
bytes = folio_size(folio) - offset;
ret = iomap_write_end(iter, pos, bytes, bytes, folio);
+ __iomap_put_folio(iter, pos, bytes, folio);
if (WARN_ON_ONCE(!ret))
return -EIO;
@@ -1409,6 +1425,7 @@ static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero)
folio_mark_accessed(folio);
ret = iomap_write_end(iter, pos, bytes, bytes, folio);
+ __iomap_put_folio(iter, pos, bytes, folio);
if (WARN_ON_ONCE(!ret))
return -EIO;
@@ -1539,8 +1556,6 @@ iomap_finish_ioend(struct iomap_ioend *ioend, int error)
/* walk all folios in bio, ending page IO on them */
bio_for_each_folio_all(fi, bio) {
- if (error)
- folio_set_error(fi.folio);
iomap_finish_folio_write(inode, fi.folio, fi.length);
folio_count++;
}
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 93b1077a380a..ed548efdd9bb 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -326,8 +326,8 @@ static const struct fs_parameter_spec isofs_param_spec[] = {
fsparam_u32 ("session", Opt_session),
fsparam_u32 ("sbsector", Opt_sb),
fsparam_enum ("check", Opt_check, isofs_param_check),
- fsparam_u32 ("uid", Opt_uid),
- fsparam_u32 ("gid", Opt_gid),
+ fsparam_uid ("uid", Opt_uid),
+ fsparam_gid ("gid", Opt_gid),
/* Note: mode/dmode historically accepted %u not strictly %o */
fsparam_u32 ("mode", Opt_mode),
fsparam_u32 ("dmode", Opt_dmode),
@@ -344,8 +344,6 @@ static int isofs_parse_param(struct fs_context *fc,
struct isofs_options *popt = fc->fs_private;
struct fs_parse_result result;
int opt;
- kuid_t uid;
- kgid_t gid;
unsigned int n;
/* There are no remountable options */
@@ -409,17 +407,11 @@ static int isofs_parse_param(struct fs_context *fc,
case Opt_ignore:
break;
case Opt_uid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- return -EINVAL;
- popt->uid = uid;
+ popt->uid = result.uid;
popt->uid_set = 1;
break;
case Opt_gid:
- gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(gid))
- return -EINVAL;
- popt->gid = gid;
+ popt->gid = result.gid;
popt->gid_set = 1;
break;
case Opt_mode:
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index d6c17ad69dee..dbf911126e61 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -688,11 +688,10 @@ int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode,
*/
static int rock_ridge_symlink_read_folio(struct file *file, struct folio *folio)
{
- struct page *page = &folio->page;
- struct inode *inode = page->mapping->host;
+ struct inode *inode = folio->mapping->host;
struct iso_inode_info *ei = ISOFS_I(inode);
struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
- char *link = page_address(page);
+ char *link = folio_address(folio);
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
struct buffer_head *bh;
char *rpnt = link;
@@ -779,9 +778,10 @@ repeat:
goto fail;
brelse(bh);
*rpnt = '\0';
- SetPageUptodate(page);
- unlock_page(page);
- return 0;
+ ret = 0;
+end:
+ folio_end_read(folio, ret == 0);
+ return ret;
/* error exit from macro */
out:
@@ -795,9 +795,8 @@ out_bad_span:
fail:
brelse(bh);
error:
- SetPageError(page);
- unlock_page(page);
- return -EIO;
+ ret = -EIO;
+ goto end;
}
const struct address_space_operations isofs_symlink_aops = {
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 62ea76da7fdf..e12cb145147e 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -95,13 +95,8 @@ static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
ret = jffs2_read_inode_range(c, f, pg_buf, pg->index << PAGE_SHIFT,
PAGE_SIZE);
- if (ret) {
- ClearPageUptodate(pg);
- SetPageError(pg);
- } else {
+ if (!ret)
SetPageUptodate(pg);
- ClearPageError(pg);
- }
flush_dcache_page(pg);
kunmap(pg);
@@ -304,10 +299,8 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
kunmap(pg);
- if (ret) {
- /* There was an error writing. */
- SetPageError(pg);
- }
+ if (ret)
+ mapping_set_error(mapping, ret);
/* Adjust writtenlen for the padding we did, so we don't confuse our caller */
writtenlen -= min(writtenlen, (start - aligned_start));
@@ -330,7 +323,6 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
it gets reread */
jffs2_dbg(1, "%s(): Not all bytes written. Marking page !uptodate\n",
__func__);
- SetPageError(pg);
ClearPageUptodate(pg);
}
diff --git a/fs/libfs.c b/fs/libfs.c
index b635ee5adbcc..8aa34870449f 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -1854,6 +1854,80 @@ static const struct dentry_operations generic_ci_dentry_ops = {
.d_revalidate = fscrypt_d_revalidate,
#endif
};
+
+/**
+ * generic_ci_match() - Match a name (case-insensitively) with a dirent.
+ * This is a filesystem helper for comparison with directory entries.
+ * generic_ci_d_compare should be used in VFS' ->d_compare instead.
+ *
+ * @parent: Inode of the parent of the dirent under comparison
+ * @name: name under lookup.
+ * @folded_name: Optional pre-folded name under lookup
+ * @de_name: Dirent name.
+ * @de_name_len: dirent name length.
+ *
+ * Test whether a case-insensitive directory entry matches the filename
+ * being searched. If @folded_name is provided, it is used instead of
+ * recalculating the casefold of @name.
+ *
+ * Return: > 0 if the directory entry matches, 0 if it doesn't match, or
+ * < 0 on error.
+ */
+int generic_ci_match(const struct inode *parent,
+ const struct qstr *name,
+ const struct qstr *folded_name,
+ const u8 *de_name, u32 de_name_len)
+{
+ const struct super_block *sb = parent->i_sb;
+ const struct unicode_map *um = sb->s_encoding;
+ struct fscrypt_str decrypted_name = FSTR_INIT(NULL, de_name_len);
+ struct qstr dirent = QSTR_INIT(de_name, de_name_len);
+ int res = 0;
+
+ if (IS_ENCRYPTED(parent)) {
+ const struct fscrypt_str encrypted_name =
+ FSTR_INIT((u8 *) de_name, de_name_len);
+
+ if (WARN_ON_ONCE(!fscrypt_has_encryption_key(parent)))
+ return -EINVAL;
+
+ decrypted_name.name = kmalloc(de_name_len, GFP_KERNEL);
+ if (!decrypted_name.name)
+ return -ENOMEM;
+ res = fscrypt_fname_disk_to_usr(parent, 0, 0, &encrypted_name,
+ &decrypted_name);
+ if (res < 0) {
+ kfree(decrypted_name.name);
+ return res;
+ }
+ dirent.name = decrypted_name.name;
+ dirent.len = decrypted_name.len;
+ }
+
+ /*
+ * Attempt a case-sensitive match first. It is cheaper and
+ * should cover most lookups, including all the sane
+ * applications that expect a case-sensitive filesystem.
+ */
+
+ if (dirent.len == name->len &&
+ !memcmp(name->name, dirent.name, dirent.len))
+ goto out;
+
+ if (folded_name->name)
+ res = utf8_strncasecmp_folded(um, folded_name, &dirent);
+ else
+ res = utf8_strncasecmp(um, name, &dirent);
+
+out:
+ kfree(decrypted_name.name);
+ if (res < 0 && sb_has_strict_encoding(sb)) {
+ pr_err_ratelimited("Directory contains filename that is invalid UTF-8");
+ return 0;
+ }
+ return !res;
+}
+EXPORT_SYMBOL(generic_ci_match);
#endif
#ifdef CONFIG_FS_ENCRYPTION
diff --git a/fs/locks.c b/fs/locks.c
index 90c8746874de..bdd94c32256f 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1367,9 +1367,9 @@ retry:
locks_wake_up_blocks(&left->c);
}
out:
+ trace_posix_lock_inode(inode, request, error);
spin_unlock(&ctx->flc_lock);
percpu_up_read(&file_rwsem);
- trace_posix_lock_inode(inode, request, error);
/*
* Free any unused locks.
*/
@@ -2448,8 +2448,9 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
error = do_lock_file_wait(filp, cmd, file_lock);
/*
- * Attempt to detect a close/fcntl race and recover by releasing the
- * lock that was just acquired. There is no need to do that when we're
+ * Detect close/fcntl races and recover by zapping all POSIX locks
+ * associated with this file and our files_struct, just like on
+ * filp_flush(). There is no need to do that when we're
* unlocking though, or for OFD locks.
*/
if (!error && file_lock->c.flc_type != F_UNLCK &&
@@ -2464,9 +2465,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
f = files_lookup_fd_locked(files, fd);
spin_unlock(&files->file_lock);
if (f != filp) {
- file_lock->c.flc_type = F_UNLCK;
- error = do_lock_file_wait(filp, cmd, file_lock);
- WARN_ON_ONCE(error);
+ locks_remove_posix(filp, files);
error = -EBADF;
}
}
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 7f9a2d8aa420..1c3df63162ef 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -730,5 +730,6 @@ static void __exit exit_minix_fs(void)
module_init(init_minix_fs)
module_exit(exit_minix_fs)
+MODULE_DESCRIPTION("Minix file system");
MODULE_LICENSE("GPL");
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index d6031acc34f0..a944a0f17b53 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -213,8 +213,7 @@ static int minix_rename(struct mnt_idmap *idmap,
if (!new_de)
goto out_dir;
err = minix_set_link(new_de, new_page, old_inode);
- kunmap(new_page);
- put_page(new_page);
+ unmap_and_put_page(new_page, new_de);
if (err)
goto out_dir;
inode_set_ctime_current(new_inode);
diff --git a/fs/mount.h b/fs/mount.h
index 4a42fc68f4cc..ad4b1ddebb54 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -16,6 +16,8 @@ struct mnt_namespace {
u64 event;
unsigned int nr_mounts; /* # of mounts in the namespace */
unsigned int pending_mounts;
+ struct rb_node mnt_ns_tree_node; /* node in the mnt_ns_tree */
+ refcount_t passive; /* number references not pinning @mounts */
} __randomize_layout;
struct mnt_pcp {
@@ -152,3 +154,4 @@ static inline void move_from_ns(struct mount *mnt, struct list_head *dt_list)
}
extern void mnt_cursor_del(struct mnt_namespace *ns, struct mount *cursor);
+bool has_locked_children(struct mount *mnt, struct dentry *dentry);
diff --git a/fs/mpage.c b/fs/mpage.c
index fa8b99a199fa..b5b5ddf9d513 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -48,13 +48,8 @@ static void mpage_read_end_io(struct bio *bio)
struct folio_iter fi;
int err = blk_status_to_errno(bio->bi_status);
- bio_for_each_folio_all(fi, bio) {
- if (err)
- folio_set_error(fi.folio);
- else
- folio_mark_uptodate(fi.folio);
- folio_unlock(fi.folio);
- }
+ bio_for_each_folio_all(fi, bio)
+ folio_end_read(fi.folio, err == 0);
bio_put(bio);
}
@@ -65,10 +60,8 @@ static void mpage_write_end_io(struct bio *bio)
int err = blk_status_to_errno(bio->bi_status);
bio_for_each_folio_all(fi, bio) {
- if (err) {
- folio_set_error(fi.folio);
+ if (err)
mapping_set_error(fi.folio->mapping, err);
- }
folio_end_writeback(fi.folio);
}
diff --git a/fs/namei.c b/fs/namei.c
index 37fb0a8aa09a..3a4c40e12f78 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -126,7 +126,7 @@
#define EMBEDDED_NAME_MAX (PATH_MAX - offsetof(struct filename, iname))
struct filename *
-getname_flags(const char __user *filename, int flags, int *empty)
+getname_flags(const char __user *filename, int flags)
{
struct filename *result;
char *kname;
@@ -148,9 +148,20 @@ getname_flags(const char __user *filename, int flags, int *empty)
result->name = kname;
len = strncpy_from_user(kname, filename, EMBEDDED_NAME_MAX);
- if (unlikely(len < 0)) {
- __putname(result);
- return ERR_PTR(len);
+ /*
+ * Handle both empty path and copy failure in one go.
+ */
+ if (unlikely(len <= 0)) {
+ if (unlikely(len < 0)) {
+ __putname(result);
+ return ERR_PTR(len);
+ }
+
+ /* The empty path is special. */
+ if (!(flags & LOOKUP_EMPTY)) {
+ __putname(result);
+ return ERR_PTR(-ENOENT);
+ }
}
/*
@@ -180,6 +191,12 @@ getname_flags(const char __user *filename, int flags, int *empty)
kfree(result);
return ERR_PTR(len);
}
+ /* The empty path is special. */
+ if (unlikely(!len) && !(flags & LOOKUP_EMPTY)) {
+ __putname(kname);
+ kfree(result);
+ return ERR_PTR(-ENOENT);
+ }
if (unlikely(len == PATH_MAX)) {
__putname(kname);
kfree(result);
@@ -188,16 +205,6 @@ getname_flags(const char __user *filename, int flags, int *empty)
}
atomic_set(&result->refcnt, 1);
- /* The empty path is special. */
- if (unlikely(!len)) {
- if (empty)
- *empty = 1;
- if (!(flags & LOOKUP_EMPTY)) {
- putname(result);
- return ERR_PTR(-ENOENT);
- }
- }
-
result->uptr = filename;
result->aname = NULL;
audit_getname(result);
@@ -209,13 +216,13 @@ getname_uflags(const char __user *filename, int uflags)
{
int flags = (uflags & AT_EMPTY_PATH) ? LOOKUP_EMPTY : 0;
- return getname_flags(filename, flags, NULL);
+ return getname_flags(filename, flags);
}
struct filename *
getname(const char __user * filename)
{
- return getname_flags(filename, 0, NULL);
+ return getname_flags(filename, 0);
}
struct filename *
@@ -1233,29 +1240,48 @@ int may_linkat(struct mnt_idmap *idmap, const struct path *link)
*
* Returns 0 if the open is allowed, -ve on error.
*/
-static int may_create_in_sticky(struct mnt_idmap *idmap,
- struct nameidata *nd, struct inode *const inode)
+static int may_create_in_sticky(struct mnt_idmap *idmap, struct nameidata *nd,
+ struct inode *const inode)
{
umode_t dir_mode = nd->dir_mode;
- vfsuid_t dir_vfsuid = nd->dir_vfsuid;
+ vfsuid_t dir_vfsuid = nd->dir_vfsuid, i_vfsuid;
- if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
- (!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
- likely(!(dir_mode & S_ISVTX)) ||
- vfsuid_eq(i_uid_into_vfsuid(idmap, inode), dir_vfsuid) ||
- vfsuid_eq_kuid(i_uid_into_vfsuid(idmap, inode), current_fsuid()))
+ if (likely(!(dir_mode & S_ISVTX)))
return 0;
- if (likely(dir_mode & 0002) ||
- (dir_mode & 0020 &&
- ((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) ||
- (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) {
- const char *operation = S_ISFIFO(inode->i_mode) ?
- "sticky_create_fifo" :
- "sticky_create_regular";
- audit_log_path_denied(AUDIT_ANOM_CREAT, operation);
+ if (S_ISREG(inode->i_mode) && !sysctl_protected_regular)
+ return 0;
+
+ if (S_ISFIFO(inode->i_mode) && !sysctl_protected_fifos)
+ return 0;
+
+ i_vfsuid = i_uid_into_vfsuid(idmap, inode);
+
+ if (vfsuid_eq(i_vfsuid, dir_vfsuid))
+ return 0;
+
+ if (vfsuid_eq_kuid(i_vfsuid, current_fsuid()))
+ return 0;
+
+ if (likely(dir_mode & 0002)) {
+ audit_log_path_denied(AUDIT_ANOM_CREAT, "sticky_create");
return -EACCES;
}
+
+ if (dir_mode & 0020) {
+ if (sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) {
+ audit_log_path_denied(AUDIT_ANOM_CREAT,
+ "sticky_create_fifo");
+ return -EACCES;
+ }
+
+ if (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode)) {
+ audit_log_path_denied(AUDIT_ANOM_CREAT,
+ "sticky_create_regular");
+ return -EACCES;
+ }
+ }
+
return 0;
}
@@ -1712,17 +1738,26 @@ static struct dentry *lookup_slow(const struct qstr *name,
}
static inline int may_lookup(struct mnt_idmap *idmap,
- struct nameidata *nd)
+ struct nameidata *restrict nd)
{
- if (nd->flags & LOOKUP_RCU) {
- int err = inode_permission(idmap, nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
- if (!err) // success, keep going
- return 0;
- if (!try_to_unlazy(nd))
- return -ECHILD; // redo it all non-lazy
- if (err != -ECHILD) // hard error
- return err;
- }
+ int err, mask;
+
+ mask = nd->flags & LOOKUP_RCU ? MAY_NOT_BLOCK : 0;
+ err = inode_permission(idmap, nd->inode, mask | MAY_EXEC);
+ if (likely(!err))
+ return 0;
+
+ // If we failed, and we weren't in LOOKUP_RCU, it's final
+ if (!(nd->flags & LOOKUP_RCU))
+ return err;
+
+ // Drop out of RCU mode to make sure it wasn't transient
+ if (!try_to_unlazy(nd))
+ return -ECHILD; // redo it all non-lazy
+
+ if (err != -ECHILD) // hard error
+ return err;
+
return inode_permission(idmap, nd->inode, MAY_EXEC);
}
@@ -2163,21 +2198,39 @@ EXPORT_SYMBOL(hashlen_string);
/*
* Calculate the length and hash of the path component, and
- * return the "hash_len" as the result.
+ * return the length as the result.
*/
-static inline u64 hash_name(const void *salt, const char *name)
+static inline const char *hash_name(struct nameidata *nd,
+ const char *name,
+ unsigned long *lastword)
{
- unsigned long a = 0, b, x = 0, y = (unsigned long)salt;
+ unsigned long a, b, x, y = (unsigned long)nd->path.dentry;
unsigned long adata, bdata, mask, len;
const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
- len = 0;
- goto inside;
+ /*
+ * The first iteration is special, because it can result in
+ * '.' and '..' and has no mixing other than the final fold.
+ */
+ a = load_unaligned_zeropad(name);
+ b = a ^ REPEAT_BYTE('/');
+ if (has_zero(a, &adata, &constants) | has_zero(b, &bdata, &constants)) {
+ adata = prep_zero_mask(a, adata, &constants);
+ bdata = prep_zero_mask(b, bdata, &constants);
+ mask = create_zero_mask(adata | bdata);
+ a &= zero_bytemask(mask);
+ *lastword = a;
+ len = find_zero(mask);
+ nd->last.hash = fold_hash(a, y);
+ nd->last.len = len;
+ return name + len;
+ }
+ len = 0;
+ x = 0;
do {
HASH_MIX(x, y, a);
len += sizeof(unsigned long);
-inside:
a = load_unaligned_zeropad(name+len);
b = a ^ REPEAT_BYTE('/');
} while (!(has_zero(a, &adata, &constants) | has_zero(b, &bdata, &constants)));
@@ -2185,11 +2238,25 @@ inside:
adata = prep_zero_mask(a, adata, &constants);
bdata = prep_zero_mask(b, bdata, &constants);
mask = create_zero_mask(adata | bdata);
- x ^= a & zero_bytemask(mask);
+ a &= zero_bytemask(mask);
+ x ^= a;
+ len += find_zero(mask);
+ *lastword = 0; // Multi-word components cannot be DOT or DOTDOT
- return hashlen_create(fold_hash(x, y), len + find_zero(mask));
+ nd->last.hash = fold_hash(x, y);
+ nd->last.len = len;
+ return name + len;
}
+/*
+ * Note that the 'last' word is always zero-masked, but
+ * was loaded as a possibly big-endian word.
+ */
+#ifdef __BIG_ENDIAN
+ #define LAST_WORD_IS_DOT (0x2eul << (BITS_PER_LONG-8))
+ #define LAST_WORD_IS_DOTDOT (0x2e2eul << (BITS_PER_LONG-16))
+#endif
+
#else /* !CONFIG_DCACHE_WORD_ACCESS: Slow, byte-at-a-time version */
/* Return the hash of a string of known length */
@@ -2222,22 +2289,35 @@ EXPORT_SYMBOL(hashlen_string);
* We know there's a real path component here of at least
* one character.
*/
-static inline u64 hash_name(const void *salt, const char *name)
+static inline const char *hash_name(struct nameidata *nd, const char *name, unsigned long *lastword)
{
- unsigned long hash = init_name_hash(salt);
- unsigned long len = 0, c;
+ unsigned long hash = init_name_hash(nd->path.dentry);
+ unsigned long len = 0, c, last = 0;
c = (unsigned char)*name;
do {
+ last = (last << 8) + c;
len++;
hash = partial_name_hash(c, hash);
c = (unsigned char)name[len];
} while (c && c != '/');
- return hashlen_create(end_name_hash(hash), len);
+
+ // This is reliable for DOT or DOTDOT, since the component
+ // cannot contain NUL characters - top bits being zero means
+ // we cannot have had any other pathnames.
+ *lastword = last;
+ nd->last.hash = end_name_hash(hash);
+ nd->last.len = len;
+ return name + len;
}
#endif
+#ifndef LAST_WORD_IS_DOT
+ #define LAST_WORD_IS_DOT 0x2e
+ #define LAST_WORD_IS_DOTDOT 0x2e2e
+#endif
+
/*
* Name resolution.
* This is the basic name resolution function, turning a pathname into
@@ -2266,45 +2346,38 @@ static int link_path_walk(const char *name, struct nameidata *nd)
for(;;) {
struct mnt_idmap *idmap;
const char *link;
- u64 hash_len;
- int type;
+ unsigned long lastword;
idmap = mnt_idmap(nd->path.mnt);
err = may_lookup(idmap, nd);
if (err)
return err;
- hash_len = hash_name(nd->path.dentry, name);
+ nd->last.name = name;
+ name = hash_name(nd, name, &lastword);
- type = LAST_NORM;
- if (name[0] == '.') switch (hashlen_len(hash_len)) {
- case 2:
- if (name[1] == '.') {
- type = LAST_DOTDOT;
- nd->state |= ND_JUMPED;
- }
- break;
- case 1:
- type = LAST_DOT;
- }
- if (likely(type == LAST_NORM)) {
- struct dentry *parent = nd->path.dentry;
+ switch(lastword) {
+ case LAST_WORD_IS_DOTDOT:
+ nd->last_type = LAST_DOTDOT;
+ nd->state |= ND_JUMPED;
+ break;
+
+ case LAST_WORD_IS_DOT:
+ nd->last_type = LAST_DOT;
+ break;
+
+ default:
+ nd->last_type = LAST_NORM;
nd->state &= ~ND_JUMPED;
+
+ struct dentry *parent = nd->path.dentry;
if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
- struct qstr this = { { .hash_len = hash_len }, .name = name };
- err = parent->d_op->d_hash(parent, &this);
+ err = parent->d_op->d_hash(parent, &nd->last);
if (err < 0)
return err;
- hash_len = this.hash_len;
- name = this.name;
}
}
- nd->last.hash_len = hash_len;
- nd->last.name = name;
- nd->last_type = type;
-
- name += hashlen_len(hash_len);
if (!*name)
goto OK;
/*
@@ -2922,16 +2995,16 @@ int path_pts(struct path *path)
}
#endif
-int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
- struct path *path, int *empty)
+int user_path_at(int dfd, const char __user *name, unsigned flags,
+ struct path *path)
{
- struct filename *filename = getname_flags(name, flags, empty);
+ struct filename *filename = getname_flags(name, flags);
int ret = filename_lookup(dfd, filename, flags, path, NULL);
putname(filename);
return ret;
}
-EXPORT_SYMBOL(user_path_at_empty);
+EXPORT_SYMBOL(user_path_at);
int __check_sticky(struct mnt_idmap *idmap, struct inode *dir,
struct inode *inode)
@@ -3572,8 +3645,12 @@ static const char *open_last_lookups(struct nameidata *nd,
else
inode_lock_shared(dir->d_inode);
dentry = lookup_open(nd, file, op, got_write);
- if (!IS_ERR(dentry) && (file->f_mode & FMODE_CREATED))
- fsnotify_create(dir->d_inode, dentry);
+ if (!IS_ERR(dentry)) {
+ if (file->f_mode & FMODE_CREATED)
+ fsnotify_create(dir->d_inode, dentry);
+ if (file->f_mode & FMODE_OPENED)
+ fsnotify_open(file);
+ }
if (open_flag & O_CREAT)
inode_unlock(dir->d_inode);
else
@@ -3700,6 +3777,8 @@ int vfs_tmpfile(struct mnt_idmap *idmap,
mode = vfs_prepare_mode(idmap, dir, mode, mode, mode);
error = dir->i_op->tmpfile(idmap, dir, file, mode);
dput(child);
+ if (file->f_mode & FMODE_OPENED)
+ fsnotify_open(file);
if (error)
return error;
/* Don't check for other permissions, the inode was just created */
diff --git a/fs/namespace.c b/fs/namespace.c
index 5a51315c6678..221db9de4729 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -70,7 +70,8 @@ static DEFINE_IDA(mnt_id_ida);
static DEFINE_IDA(mnt_group_ida);
/* Don't allow confusion with old 32bit mount ID */
-static atomic64_t mnt_id_ctr = ATOMIC64_INIT(1ULL << 32);
+#define MNT_UNIQUE_ID_OFFSET (1ULL << 32)
+static atomic64_t mnt_id_ctr = ATOMIC64_INIT(MNT_UNIQUE_ID_OFFSET);
static struct hlist_head *mount_hashtable __ro_after_init;
static struct hlist_head *mountpoint_hashtable __ro_after_init;
@@ -78,6 +79,8 @@ static struct kmem_cache *mnt_cache __ro_after_init;
static DECLARE_RWSEM(namespace_sem);
static HLIST_HEAD(unmounted); /* protected by namespace_sem */
static LIST_HEAD(ex_mountpoints); /* protected by namespace_sem */
+static DEFINE_RWLOCK(mnt_ns_tree_lock);
+static struct rb_root mnt_ns_tree = RB_ROOT; /* protected by mnt_ns_tree_lock */
struct mount_kattr {
unsigned int attr_set;
@@ -103,6 +106,109 @@ EXPORT_SYMBOL_GPL(fs_kobj);
*/
__cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
+static int mnt_ns_cmp(u64 seq, const struct mnt_namespace *ns)
+{
+ u64 seq_b = ns->seq;
+
+ if (seq < seq_b)
+ return -1;
+ if (seq > seq_b)
+ return 1;
+ return 0;
+}
+
+static inline struct mnt_namespace *node_to_mnt_ns(const struct rb_node *node)
+{
+ if (!node)
+ return NULL;
+ return rb_entry(node, struct mnt_namespace, mnt_ns_tree_node);
+}
+
+static bool mnt_ns_less(struct rb_node *a, const struct rb_node *b)
+{
+ struct mnt_namespace *ns_a = node_to_mnt_ns(a);
+ struct mnt_namespace *ns_b = node_to_mnt_ns(b);
+ u64 seq_a = ns_a->seq;
+
+ return mnt_ns_cmp(seq_a, ns_b) < 0;
+}
+
+static void mnt_ns_tree_add(struct mnt_namespace *ns)
+{
+ guard(write_lock)(&mnt_ns_tree_lock);
+ rb_add(&ns->mnt_ns_tree_node, &mnt_ns_tree, mnt_ns_less);
+}
+
+static void mnt_ns_release(struct mnt_namespace *ns)
+{
+ lockdep_assert_not_held(&mnt_ns_tree_lock);
+
+ /* keep alive for {list,stat}mount() */
+ if (refcount_dec_and_test(&ns->passive)) {
+ put_user_ns(ns->user_ns);
+ kfree(ns);
+ }
+}
+DEFINE_FREE(mnt_ns_release, struct mnt_namespace *, if (_T) mnt_ns_release(_T))
+
+static void mnt_ns_tree_remove(struct mnt_namespace *ns)
+{
+ /* remove from global mount namespace list */
+ if (!is_anon_ns(ns)) {
+ guard(write_lock)(&mnt_ns_tree_lock);
+ rb_erase(&ns->mnt_ns_tree_node, &mnt_ns_tree);
+ }
+
+ mnt_ns_release(ns);
+}
+
+/*
+ * Returns the mount namespace which either has the specified id, or has the
+ * next smallest id afer the specified one.
+ */
+static struct mnt_namespace *mnt_ns_find_id_at(u64 mnt_ns_id)
+{
+ struct rb_node *node = mnt_ns_tree.rb_node;
+ struct mnt_namespace *ret = NULL;
+
+ lockdep_assert_held(&mnt_ns_tree_lock);
+
+ while (node) {
+ struct mnt_namespace *n = node_to_mnt_ns(node);
+
+ if (mnt_ns_id <= n->seq) {
+ ret = node_to_mnt_ns(node);
+ if (mnt_ns_id == n->seq)
+ break;
+ node = node->rb_left;
+ } else {
+ node = node->rb_right;
+ }
+ }
+ return ret;
+}
+
+/*
+ * Lookup a mount namespace by id and take a passive reference count. Taking a
+ * passive reference means the mount namespace can be emptied if e.g., the last
+ * task holding an active reference exits. To access the mounts of the
+ * namespace the @namespace_sem must first be acquired. If the namespace has
+ * already shut down before acquiring @namespace_sem, {list,stat}mount() will
+ * see that the mount rbtree of the namespace is empty.
+ */
+static struct mnt_namespace *lookup_mnt_ns(u64 mnt_ns_id)
+{
+ struct mnt_namespace *ns;
+
+ guard(read_lock)(&mnt_ns_tree_lock);
+ ns = mnt_ns_find_id_at(mnt_ns_id);
+ if (!ns || ns->seq != mnt_ns_id)
+ return NULL;
+
+ refcount_inc(&ns->passive);
+ return ns;
+}
+
static inline void lock_mount_hash(void)
{
write_seqlock(&mount_lock);
@@ -1448,6 +1554,30 @@ static struct mount *mnt_find_id_at(struct mnt_namespace *ns, u64 mnt_id)
return ret;
}
+/*
+ * Returns the mount which either has the specified mnt_id, or has the next
+ * greater id before the specified one.
+ */
+static struct mount *mnt_find_id_at_reverse(struct mnt_namespace *ns, u64 mnt_id)
+{
+ struct rb_node *node = ns->mounts.rb_node;
+ struct mount *ret = NULL;
+
+ while (node) {
+ struct mount *m = node_to_mount(node);
+
+ if (mnt_id >= m->mnt_id_unique) {
+ ret = node_to_mount(node);
+ if (mnt_id == m->mnt_id_unique)
+ break;
+ node = node->rb_right;
+ } else {
+ node = node->rb_left;
+ }
+ }
+ return ret;
+}
+
#ifdef CONFIG_PROC_FS
/* iterator; we want it to have access to namespace_sem, thus here... */
@@ -1846,19 +1976,6 @@ bool may_mount(void)
return ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN);
}
-/**
- * path_mounted - check whether path is mounted
- * @path: path to check
- *
- * Determine whether @path refers to the root of a mount.
- *
- * Return: true if @path is the root of a mount, false if not.
- */
-static inline bool path_mounted(const struct path *path)
-{
- return path->mnt->mnt_root == path->dentry;
-}
-
static void warn_mandlock(void)
{
pr_warn_once("=======================================================\n"
@@ -1966,69 +2083,72 @@ static bool mnt_ns_loop(struct dentry *dentry)
return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
}
-struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
+struct mount *copy_tree(struct mount *src_root, struct dentry *dentry,
int flag)
{
- struct mount *res, *p, *q, *r, *parent;
+ struct mount *res, *src_parent, *src_root_child, *src_mnt,
+ *dst_parent, *dst_mnt;
- if (!(flag & CL_COPY_UNBINDABLE) && IS_MNT_UNBINDABLE(mnt))
+ if (!(flag & CL_COPY_UNBINDABLE) && IS_MNT_UNBINDABLE(src_root))
return ERR_PTR(-EINVAL);
if (!(flag & CL_COPY_MNT_NS_FILE) && is_mnt_ns_file(dentry))
return ERR_PTR(-EINVAL);
- res = q = clone_mnt(mnt, dentry, flag);
- if (IS_ERR(q))
- return q;
+ res = dst_mnt = clone_mnt(src_root, dentry, flag);
+ if (IS_ERR(dst_mnt))
+ return dst_mnt;
- q->mnt_mountpoint = mnt->mnt_mountpoint;
+ src_parent = src_root;
+ dst_mnt->mnt_mountpoint = src_root->mnt_mountpoint;
- p = mnt;
- list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
- struct mount *s;
- if (!is_subdir(r->mnt_mountpoint, dentry))
+ list_for_each_entry(src_root_child, &src_root->mnt_mounts, mnt_child) {
+ if (!is_subdir(src_root_child->mnt_mountpoint, dentry))
continue;
- for (s = r; s; s = next_mnt(s, r)) {
+ for (src_mnt = src_root_child; src_mnt;
+ src_mnt = next_mnt(src_mnt, src_root_child)) {
if (!(flag & CL_COPY_UNBINDABLE) &&
- IS_MNT_UNBINDABLE(s)) {
- if (s->mnt.mnt_flags & MNT_LOCKED) {
+ IS_MNT_UNBINDABLE(src_mnt)) {
+ if (src_mnt->mnt.mnt_flags & MNT_LOCKED) {
/* Both unbindable and locked. */
- q = ERR_PTR(-EPERM);
+ dst_mnt = ERR_PTR(-EPERM);
goto out;
} else {
- s = skip_mnt_tree(s);
+ src_mnt = skip_mnt_tree(src_mnt);
continue;
}
}
if (!(flag & CL_COPY_MNT_NS_FILE) &&
- is_mnt_ns_file(s->mnt.mnt_root)) {
- s = skip_mnt_tree(s);
+ is_mnt_ns_file(src_mnt->mnt.mnt_root)) {
+ src_mnt = skip_mnt_tree(src_mnt);
continue;
}
- while (p != s->mnt_parent) {
- p = p->mnt_parent;
- q = q->mnt_parent;
+ while (src_parent != src_mnt->mnt_parent) {
+ src_parent = src_parent->mnt_parent;
+ dst_mnt = dst_mnt->mnt_parent;
}
- p = s;
- parent = q;
- q = clone_mnt(p, p->mnt.mnt_root, flag);
- if (IS_ERR(q))
+
+ src_parent = src_mnt;
+ dst_parent = dst_mnt;
+ dst_mnt = clone_mnt(src_mnt, src_mnt->mnt.mnt_root, flag);
+ if (IS_ERR(dst_mnt))
goto out;
lock_mount_hash();
- list_add_tail(&q->mnt_list, &res->mnt_list);
- attach_mnt(q, parent, p->mnt_mp, false);
+ list_add_tail(&dst_mnt->mnt_list, &res->mnt_list);
+ attach_mnt(dst_mnt, dst_parent, src_parent->mnt_mp, false);
unlock_mount_hash();
}
}
return res;
+
out:
if (res) {
lock_mount_hash();
umount_tree(res, UMOUNT_SYNC);
unlock_mount_hash();
}
- return q;
+ return dst_mnt;
}
/* Caller should check returned pointer for errors */
@@ -2078,7 +2198,7 @@ void drop_collected_mounts(struct vfsmount *mnt)
namespace_unlock();
}
-static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
+bool has_locked_children(struct mount *mnt, struct dentry *dentry)
{
struct mount *child;
@@ -3709,8 +3829,7 @@ static void free_mnt_ns(struct mnt_namespace *ns)
if (!is_anon_ns(ns))
ns_free_inum(&ns->ns);
dec_mnt_namespaces(ns->ucounts);
- put_user_ns(ns->user_ns);
- kfree(ns);
+ mnt_ns_tree_remove(ns);
}
/*
@@ -3749,7 +3868,9 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns, bool a
if (!anon)
new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
refcount_set(&new_ns->ns.count, 1);
+ refcount_set(&new_ns->passive, 1);
new_ns->mounts = RB_ROOT;
+ RB_CLEAR_NODE(&new_ns->mnt_ns_tree_node);
init_waitqueue_head(&new_ns->poll);
new_ns->user_ns = get_user_ns(user_ns);
new_ns->ucounts = ucounts;
@@ -3826,6 +3947,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
while (p->mnt.mnt_root != q->mnt.mnt_root)
p = next_mnt(skip_mnt_tree(p), old);
}
+ mnt_ns_tree_add(new_ns);
namespace_unlock();
if (rootmnt)
@@ -4843,6 +4965,40 @@ static int statmount_fs_type(struct kstatmount *s, struct seq_file *seq)
return 0;
}
+static void statmount_mnt_ns_id(struct kstatmount *s, struct mnt_namespace *ns)
+{
+ s->sm.mask |= STATMOUNT_MNT_NS_ID;
+ s->sm.mnt_ns_id = ns->seq;
+}
+
+static int statmount_mnt_opts(struct kstatmount *s, struct seq_file *seq)
+{
+ struct vfsmount *mnt = s->mnt;
+ struct super_block *sb = mnt->mnt_sb;
+ int err;
+
+ if (sb->s_op->show_options) {
+ size_t start = seq->count;
+
+ err = sb->s_op->show_options(seq, mnt->mnt_root);
+ if (err)
+ return err;
+
+ if (unlikely(seq_has_overflowed(seq)))
+ return -EAGAIN;
+
+ if (seq->count == start)
+ return 0;
+
+ /* skip leading comma */
+ memmove(seq->buf + start, seq->buf + start + 1,
+ seq->count - start - 1);
+ seq->count--;
+ }
+
+ return 0;
+}
+
static int statmount_string(struct kstatmount *s, u64 flag)
{
int ret;
@@ -4863,6 +5019,10 @@ static int statmount_string(struct kstatmount *s, u64 flag)
sm->mnt_point = seq->count;
ret = statmount_mnt_point(s, seq);
break;
+ case STATMOUNT_MNT_OPTS:
+ sm->mnt_opts = seq->count;
+ ret = statmount_mnt_opts(s, seq);
+ break;
default:
WARN_ON_ONCE(true);
return -EINVAL;
@@ -4903,23 +5063,84 @@ static int copy_statmount_to_user(struct kstatmount *s)
return 0;
}
-static int do_statmount(struct kstatmount *s)
+static struct mount *listmnt_next(struct mount *curr, bool reverse)
{
- struct mount *m = real_mount(s->mnt);
+ struct rb_node *node;
+
+ if (reverse)
+ node = rb_prev(&curr->mnt_node);
+ else
+ node = rb_next(&curr->mnt_node);
+
+ return node_to_mount(node);
+}
+
+static int grab_requested_root(struct mnt_namespace *ns, struct path *root)
+{
+ struct mount *first, *child;
+
+ rwsem_assert_held(&namespace_sem);
+
+ /* We're looking at our own ns, just use get_fs_root. */
+ if (ns == current->nsproxy->mnt_ns) {
+ get_fs_root(current->fs, root);
+ return 0;
+ }
+
+ /*
+ * We have to find the first mount in our ns and use that, however it
+ * may not exist, so handle that properly.
+ */
+ if (RB_EMPTY_ROOT(&ns->mounts))
+ return -ENOENT;
+
+ first = child = ns->root;
+ for (;;) {
+ child = listmnt_next(child, false);
+ if (!child)
+ return -ENOENT;
+ if (child->mnt_parent == first)
+ break;
+ }
+
+ root->mnt = mntget(&child->mnt);
+ root->dentry = dget(root->mnt->mnt_root);
+ return 0;
+}
+
+static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
+ struct mnt_namespace *ns)
+{
+ struct path root __free(path_put) = {};
+ struct mount *m;
int err;
+ /* Has the namespace already been emptied? */
+ if (mnt_ns_id && RB_EMPTY_ROOT(&ns->mounts))
+ return -ENOENT;
+
+ s->mnt = lookup_mnt_in_ns(mnt_id, ns);
+ if (!s->mnt)
+ return -ENOENT;
+
+ err = grab_requested_root(ns, &root);
+ if (err)
+ return err;
+
/*
* Don't trigger audit denials. We just want to determine what
* mounts to show users.
*/
- if (!is_path_reachable(m, m->mnt.mnt_root, &s->root) &&
- !ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN))
+ m = real_mount(s->mnt);
+ if (!is_path_reachable(m, m->mnt.mnt_root, &root) &&
+ !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
return -EPERM;
err = security_sb_statfs(s->mnt->mnt_root);
if (err)
return err;
+ s->root = root;
if (s->mask & STATMOUNT_SB_BASIC)
statmount_sb_basic(s);
@@ -4938,6 +5159,12 @@ static int do_statmount(struct kstatmount *s)
if (!err && s->mask & STATMOUNT_MNT_POINT)
err = statmount_string(s, STATMOUNT_MNT_POINT);
+ if (!err && s->mask & STATMOUNT_MNT_OPTS)
+ err = statmount_string(s, STATMOUNT_MNT_OPTS);
+
+ if (!err && s->mask & STATMOUNT_MNT_NS_ID)
+ statmount_mnt_ns_id(s, ns);
+
if (err)
return err;
@@ -4955,6 +5182,9 @@ static inline bool retry_statmount(const long ret, size_t *seq_size)
return true;
}
+#define STATMOUNT_STRING_REQ (STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT | \
+ STATMOUNT_FS_TYPE | STATMOUNT_MNT_OPTS)
+
static int prepare_kstatmount(struct kstatmount *ks, struct mnt_id_req *kreq,
struct statmount __user *buf, size_t bufsize,
size_t seq_size)
@@ -4966,10 +5196,18 @@ static int prepare_kstatmount(struct kstatmount *ks, struct mnt_id_req *kreq,
ks->mask = kreq->param;
ks->buf = buf;
ks->bufsize = bufsize;
- ks->seq.size = seq_size;
- ks->seq.buf = kvmalloc(seq_size, GFP_KERNEL_ACCOUNT);
- if (!ks->seq.buf)
- return -ENOMEM;
+
+ if (ks->mask & STATMOUNT_STRING_REQ) {
+ if (bufsize == sizeof(ks->sm))
+ return -EOVERFLOW;
+
+ ks->seq.buf = kvmalloc(seq_size, GFP_KERNEL_ACCOUNT);
+ if (!ks->seq.buf)
+ return -ENOMEM;
+
+ ks->seq.size = seq_size;
+ }
+
return 0;
}
@@ -4979,7 +5217,7 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req,
int ret;
size_t usize;
- BUILD_BUG_ON(sizeof(struct mnt_id_req) != MNT_ID_REQ_SIZE_VER0);
+ BUILD_BUG_ON(sizeof(struct mnt_id_req) != MNT_ID_REQ_SIZE_VER1);
ret = get_user(usize, &req->size);
if (ret)
@@ -4994,16 +5232,32 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req,
return ret;
if (kreq->spare != 0)
return -EINVAL;
+ /* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
+ if (kreq->mnt_id <= MNT_UNIQUE_ID_OFFSET)
+ return -EINVAL;
return 0;
}
+/*
+ * If the user requested a specific mount namespace id, look that up and return
+ * that, or if not simply grab a passive reference on our mount namespace and
+ * return that.
+ */
+static struct mnt_namespace *grab_requested_mnt_ns(u64 mnt_ns_id)
+{
+ if (mnt_ns_id)
+ return lookup_mnt_ns(mnt_ns_id);
+ refcount_inc(&current->nsproxy->mnt_ns->passive);
+ return current->nsproxy->mnt_ns;
+}
+
SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
struct statmount __user *, buf, size_t, bufsize,
unsigned int, flags)
{
- struct vfsmount *mnt;
+ struct mnt_namespace *ns __free(mnt_ns_release) = NULL;
+ struct kstatmount *ks __free(kfree) = NULL;
struct mnt_id_req kreq;
- struct kstatmount ks;
/* We currently support retrieval of 3 strings. */
size_t seq_size = 3 * PATH_MAX;
int ret;
@@ -5015,64 +5269,88 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
if (ret)
return ret;
+ ns = grab_requested_mnt_ns(kreq.mnt_ns_id);
+ if (!ns)
+ return -ENOENT;
+
+ if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) &&
+ !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
+ return -ENOENT;
+
+ ks = kmalloc(sizeof(*ks), GFP_KERNEL_ACCOUNT);
+ if (!ks)
+ return -ENOMEM;
+
retry:
- ret = prepare_kstatmount(&ks, &kreq, buf, bufsize, seq_size);
+ ret = prepare_kstatmount(ks, &kreq, buf, bufsize, seq_size);
if (ret)
return ret;
- down_read(&namespace_sem);
- mnt = lookup_mnt_in_ns(kreq.mnt_id, current->nsproxy->mnt_ns);
- if (!mnt) {
- up_read(&namespace_sem);
- kvfree(ks.seq.buf);
- return -ENOENT;
- }
-
- ks.mnt = mnt;
- get_fs_root(current->fs, &ks.root);
- ret = do_statmount(&ks);
- path_put(&ks.root);
- up_read(&namespace_sem);
+ scoped_guard(rwsem_read, &namespace_sem)
+ ret = do_statmount(ks, kreq.mnt_id, kreq.mnt_ns_id, ns);
if (!ret)
- ret = copy_statmount_to_user(&ks);
- kvfree(ks.seq.buf);
+ ret = copy_statmount_to_user(ks);
+ kvfree(ks->seq.buf);
if (retry_statmount(ret, &seq_size))
goto retry;
return ret;
}
-static struct mount *listmnt_next(struct mount *curr)
+static ssize_t do_listmount(struct mnt_namespace *ns, u64 mnt_parent_id,
+ u64 last_mnt_id, u64 *mnt_ids, size_t nr_mnt_ids,
+ bool reverse)
{
- return node_to_mount(rb_next(&curr->mnt_node));
-}
-
-static ssize_t do_listmount(struct mount *first, struct path *orig,
- u64 mnt_parent_id, u64 __user *mnt_ids,
- size_t nr_mnt_ids, const struct path *root)
-{
- struct mount *r;
+ struct path root __free(path_put) = {};
+ struct path orig;
+ struct mount *r, *first;
ssize_t ret;
+ rwsem_assert_held(&namespace_sem);
+
+ ret = grab_requested_root(ns, &root);
+ if (ret)
+ return ret;
+
+ if (mnt_parent_id == LSMT_ROOT) {
+ orig = root;
+ } else {
+ orig.mnt = lookup_mnt_in_ns(mnt_parent_id, ns);
+ if (!orig.mnt)
+ return -ENOENT;
+ orig.dentry = orig.mnt->mnt_root;
+ }
+
/*
* Don't trigger audit denials. We just want to determine what
* mounts to show users.
*/
- if (!is_path_reachable(real_mount(orig->mnt), orig->dentry, root) &&
- !ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN))
+ if (!is_path_reachable(real_mount(orig.mnt), orig.dentry, &root) &&
+ !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
return -EPERM;
- ret = security_sb_statfs(orig->dentry);
+ ret = security_sb_statfs(orig.dentry);
if (ret)
return ret;
- for (ret = 0, r = first; r && nr_mnt_ids; r = listmnt_next(r)) {
+ if (!last_mnt_id) {
+ if (reverse)
+ first = node_to_mount(rb_last(&ns->mounts));
+ else
+ first = node_to_mount(rb_first(&ns->mounts));
+ } else {
+ if (reverse)
+ first = mnt_find_id_at_reverse(ns, last_mnt_id - 1);
+ else
+ first = mnt_find_id_at(ns, last_mnt_id + 1);
+ }
+
+ for (ret = 0, r = first; r && nr_mnt_ids; r = listmnt_next(r, reverse)) {
if (r->mnt_id_unique == mnt_parent_id)
continue;
- if (!is_path_reachable(r, r->mnt.mnt_root, orig))
+ if (!is_path_reachable(r, r->mnt.mnt_root, &orig))
continue;
- if (put_user(r->mnt_id_unique, mnt_ids))
- return -EFAULT;
+ *mnt_ids = r->mnt_id_unique;
mnt_ids++;
nr_mnt_ids--;
ret++;
@@ -5080,22 +5358,26 @@ static ssize_t do_listmount(struct mount *first, struct path *orig,
return ret;
}
-SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req, u64 __user *,
- mnt_ids, size_t, nr_mnt_ids, unsigned int, flags)
+SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req,
+ u64 __user *, mnt_ids, size_t, nr_mnt_ids, unsigned int, flags)
{
- struct mnt_namespace *ns = current->nsproxy->mnt_ns;
+ u64 *kmnt_ids __free(kvfree) = NULL;
+ const size_t maxcount = 1000000;
+ struct mnt_namespace *ns __free(mnt_ns_release) = NULL;
struct mnt_id_req kreq;
- struct mount *first;
- struct path root, orig;
- u64 mnt_parent_id, last_mnt_id;
- const size_t maxcount = (size_t)-1 >> 3;
+ u64 last_mnt_id;
ssize_t ret;
- if (flags)
+ if (flags & ~LISTMOUNT_REVERSE)
return -EINVAL;
+ /*
+ * If the mount namespace really has more than 1 million mounts the
+ * caller must iterate over the mount namespace (and reconsider their
+ * system design...).
+ */
if (unlikely(nr_mnt_ids > maxcount))
- return -EFAULT;
+ return -EOVERFLOW;
if (!access_ok(mnt_ids, nr_mnt_ids * sizeof(*mnt_ids)))
return -EFAULT;
@@ -5103,33 +5385,37 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req, u64 __user *,
ret = copy_mnt_id_req(req, &kreq);
if (ret)
return ret;
- mnt_parent_id = kreq.mnt_id;
+
last_mnt_id = kreq.param;
+ /* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
+ if (last_mnt_id != 0 && last_mnt_id <= MNT_UNIQUE_ID_OFFSET)
+ return -EINVAL;
- down_read(&namespace_sem);
- get_fs_root(current->fs, &root);
- if (mnt_parent_id == LSMT_ROOT) {
- orig = root;
- } else {
- ret = -ENOENT;
- orig.mnt = lookup_mnt_in_ns(mnt_parent_id, ns);
- if (!orig.mnt)
- goto err;
- orig.dentry = orig.mnt->mnt_root;
- }
- if (!last_mnt_id)
- first = node_to_mount(rb_first(&ns->mounts));
- else
- first = mnt_find_id_at(ns, last_mnt_id + 1);
+ kmnt_ids = kvmalloc_array(nr_mnt_ids, sizeof(*kmnt_ids),
+ GFP_KERNEL_ACCOUNT);
+ if (!kmnt_ids)
+ return -ENOMEM;
+
+ ns = grab_requested_mnt_ns(kreq.mnt_ns_id);
+ if (!ns)
+ return -ENOENT;
+
+ if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) &&
+ !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
+ return -ENOENT;
+
+ scoped_guard(rwsem_read, &namespace_sem)
+ ret = do_listmount(ns, kreq.mnt_id, last_mnt_id, kmnt_ids,
+ nr_mnt_ids, (flags & LISTMOUNT_REVERSE));
+ if (ret <= 0)
+ return ret;
+
+ if (copy_to_user(mnt_ids, kmnt_ids, ret * sizeof(*mnt_ids)))
+ return -EFAULT;
- ret = do_listmount(first, &orig, mnt_parent_id, mnt_ids, nr_mnt_ids, &root);
-err:
- path_put(&root);
- up_read(&namespace_sem);
return ret;
}
-
static void __init init_mount_tree(void)
{
struct vfsmount *mnt;
@@ -5157,6 +5443,8 @@ static void __init init_mount_tree(void)
set_fs_pwd(current->fs, &root);
set_fs_root(current->fs, &root);
+
+ mnt_ns_tree_add(ns);
}
void __init mnt_init(void)
diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c
index a6bb03bea920..4c0401dbbfcf 100644
--- a/fs/netfs/buffered_read.c
+++ b/fs/netfs/buffered_read.c
@@ -117,7 +117,7 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq)
if (!test_bit(NETFS_RREQ_DONT_UNLOCK_FOLIOS, &rreq->flags)) {
if (folio->index == rreq->no_unlock_folio &&
test_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags))
- _debug("no unlock");
+ kdebug("no unlock");
else
folio_unlock(folio);
}
@@ -204,7 +204,7 @@ void netfs_readahead(struct readahead_control *ractl)
struct netfs_inode *ctx = netfs_inode(ractl->mapping->host);
int ret;
- _enter("%lx,%x", readahead_index(ractl), readahead_count(ractl));
+ kenter("%lx,%x", readahead_index(ractl), readahead_count(ractl));
if (readahead_count(ractl) == 0)
return;
@@ -268,7 +268,7 @@ int netfs_read_folio(struct file *file, struct folio *folio)
struct folio *sink = NULL;
int ret;
- _enter("%lx", folio->index);
+ kenter("%lx", folio->index);
rreq = netfs_alloc_request(mapping, file,
folio_file_pos(folio), folio_size(folio),
@@ -508,7 +508,7 @@ retry:
have_folio:
*_folio = folio;
- _leave(" = 0");
+ kleave(" = 0");
return 0;
error_put:
@@ -518,7 +518,7 @@ error:
folio_unlock(folio);
folio_put(folio);
}
- _leave(" = %d", ret);
+ kleave(" = %d", ret);
return ret;
}
EXPORT_SYMBOL(netfs_write_begin);
@@ -536,7 +536,7 @@ int netfs_prefetch_for_write(struct file *file, struct folio *folio,
size_t flen = folio_size(folio);
int ret;
- _enter("%zx @%llx", flen, start);
+ kenter("%zx @%llx", flen, start);
ret = -ENOMEM;
@@ -567,7 +567,7 @@ int netfs_prefetch_for_write(struct file *file, struct folio *folio,
error_put:
netfs_put_request(rreq, false, netfs_rreq_trace_put_discard);
error:
- _leave(" = %d", ret);
+ kleave(" = %d", ret);
return ret;
}
diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c
index 07bc1fd43530..ecbc99ec7d36 100644
--- a/fs/netfs/buffered_write.c
+++ b/fs/netfs/buffered_write.c
@@ -56,7 +56,7 @@ static enum netfs_how_to_modify netfs_how_to_modify(struct netfs_inode *ctx,
struct netfs_group *group = netfs_folio_group(folio);
loff_t pos = folio_file_pos(folio);
- _enter("");
+ kenter("");
if (group != netfs_group && group != NETFS_FOLIO_COPY_TO_CACHE)
return NETFS_FLUSH_CONTENT;
@@ -272,12 +272,12 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
*/
howto = netfs_how_to_modify(ctx, file, folio, netfs_group,
flen, offset, part, maybe_trouble);
- _debug("howto %u", howto);
+ kdebug("howto %u", howto);
switch (howto) {
case NETFS_JUST_PREFETCH:
ret = netfs_prefetch_for_write(file, folio, offset, part);
if (ret < 0) {
- _debug("prefetch = %zd", ret);
+ kdebug("prefetch = %zd", ret);
goto error_folio_unlock;
}
break;
@@ -418,7 +418,7 @@ out:
}
iocb->ki_pos += written;
- _leave(" = %zd [%zd]", written, ret);
+ kleave(" = %zd [%zd]", written, ret);
return written ? written : ret;
error_folio_unlock:
@@ -491,7 +491,7 @@ ssize_t netfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct netfs_inode *ictx = netfs_inode(inode);
ssize_t ret;
- _enter("%llx,%zx,%llx", iocb->ki_pos, iov_iter_count(from), i_size_read(inode));
+ kenter("%llx,%zx,%llx", iocb->ki_pos, iov_iter_count(from), i_size_read(inode));
if (!iov_iter_count(from))
return 0;
@@ -523,17 +523,23 @@ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_gr
struct netfs_group *group;
struct folio *folio = page_folio(vmf->page);
struct file *file = vmf->vma->vm_file;
+ struct address_space *mapping = file->f_mapping;
struct inode *inode = file_inode(file);
struct netfs_inode *ictx = netfs_inode(inode);
vm_fault_t ret = VM_FAULT_RETRY;
int err;
- _enter("%lx", folio->index);
+ kenter("%lx", folio->index);
sb_start_pagefault(inode->i_sb);
if (folio_lock_killable(folio) < 0)
goto out;
+ if (folio->mapping != mapping) {
+ folio_unlock(folio);
+ ret = VM_FAULT_NOPAGE;
+ goto out;
+ }
if (folio_wait_writeback_killable(folio)) {
ret = VM_FAULT_LOCKED;
@@ -549,9 +555,9 @@ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_gr
group = netfs_folio_group(folio);
if (group != netfs_group && group != NETFS_FOLIO_COPY_TO_CACHE) {
folio_unlock(folio);
- err = filemap_fdatawait_range(inode->i_mapping,
- folio_pos(folio),
- folio_pos(folio) + folio_size(folio));
+ err = filemap_fdatawrite_range(mapping,
+ folio_pos(folio),
+ folio_pos(folio) + folio_size(folio));
switch (err) {
case 0:
ret = VM_FAULT_RETRY;
diff --git a/fs/netfs/direct_read.c b/fs/netfs/direct_read.c
index 10a1e4da6bda..b6debac6205f 100644
--- a/fs/netfs/direct_read.c
+++ b/fs/netfs/direct_read.c
@@ -33,7 +33,7 @@ ssize_t netfs_unbuffered_read_iter_locked(struct kiocb *iocb, struct iov_iter *i
size_t orig_count = iov_iter_count(iter);
bool async = !is_sync_kiocb(iocb);
- _enter("");
+ kenter("");
if (!orig_count)
return 0; /* Don't update atime */
diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c
index e14cd53ac9fd..792ef17bae21 100644
--- a/fs/netfs/direct_write.c
+++ b/fs/netfs/direct_write.c
@@ -37,7 +37,7 @@ ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *
size_t len = iov_iter_count(iter);
bool async = !is_sync_kiocb(iocb);
- _enter("");
+ kenter("");
/* We're going to need a bounce buffer if what we transmit is going to
* be different in some way to the source buffer, e.g. because it gets
@@ -45,7 +45,7 @@ ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *
*/
// TODO
- _debug("uw %llx-%llx", start, end);
+ kdebug("uw %llx-%llx", start, end);
wreq = netfs_create_write_req(iocb->ki_filp->f_mapping, iocb->ki_filp, start,
iocb->ki_flags & IOCB_DIRECT ?
@@ -92,10 +92,11 @@ ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *
__set_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags);
if (async)
wreq->iocb = iocb;
+ wreq->len = iov_iter_count(&wreq->io_iter);
wreq->cleanup = netfs_cleanup_dio_write;
- ret = netfs_unbuffered_write(wreq, is_sync_kiocb(iocb), iov_iter_count(&wreq->io_iter));
+ ret = netfs_unbuffered_write(wreq, is_sync_kiocb(iocb), wreq->len);
if (ret < 0) {
- _debug("begin = %zd", ret);
+ kdebug("begin = %zd", ret);
goto out;
}
@@ -142,7 +143,7 @@ ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb, struct iov_iter *from)
loff_t pos = iocb->ki_pos;
unsigned long long end = pos + iov_iter_count(from) - 1;
- _enter("%llx,%zx,%llx", pos, iov_iter_count(from), i_size_read(inode));
+ kenter("%llx,%zx,%llx", pos, iov_iter_count(from), i_size_read(inode));
if (!iov_iter_count(from))
return 0;
diff --git a/fs/netfs/fscache_cache.c b/fs/netfs/fscache_cache.c
index 9397ed39b0b4..288a73c3072d 100644
--- a/fs/netfs/fscache_cache.c
+++ b/fs/netfs/fscache_cache.c
@@ -237,7 +237,7 @@ int fscache_add_cache(struct fscache_cache *cache,
{
int n_accesses;
- _enter("{%s,%s}", ops->name, cache->name);
+ kenter("{%s,%s}", ops->name, cache->name);
BUG_ON(fscache_cache_state(cache) != FSCACHE_CACHE_IS_PREPARING);
@@ -257,7 +257,7 @@ int fscache_add_cache(struct fscache_cache *cache,
up_write(&fscache_addremove_sem);
pr_notice("Cache \"%s\" added (type %s)\n", cache->name, ops->name);
- _leave(" = 0 [%s]", cache->name);
+ kleave(" = 0 [%s]", cache->name);
return 0;
}
EXPORT_SYMBOL(fscache_add_cache);
diff --git a/fs/netfs/fscache_cookie.c b/fs/netfs/fscache_cookie.c
index bce2492186d0..4d1e8bf4c615 100644
--- a/fs/netfs/fscache_cookie.c
+++ b/fs/netfs/fscache_cookie.c
@@ -456,7 +456,7 @@ struct fscache_cookie *__fscache_acquire_cookie(
{
struct fscache_cookie *cookie;
- _enter("V=%x", volume->debug_id);
+ kenter("V=%x", volume->debug_id);
if (!index_key || !index_key_len || index_key_len > 255 || aux_data_len > 255)
return NULL;
@@ -484,7 +484,7 @@ struct fscache_cookie *__fscache_acquire_cookie(
trace_fscache_acquire(cookie);
fscache_stat(&fscache_n_acquires_ok);
- _leave(" = c=%08x", cookie->debug_id);
+ kleave(" = c=%08x", cookie->debug_id);
return cookie;
}
EXPORT_SYMBOL(__fscache_acquire_cookie);
@@ -505,7 +505,7 @@ static void fscache_perform_lookup(struct fscache_cookie *cookie)
enum fscache_access_trace trace = fscache_access_lookup_cookie_end_failed;
bool need_withdraw = false;
- _enter("");
+ kenter("");
if (!cookie->volume->cache_priv) {
fscache_create_volume(cookie->volume, true);
@@ -519,7 +519,7 @@ static void fscache_perform_lookup(struct fscache_cookie *cookie)
if (cookie->state != FSCACHE_COOKIE_STATE_FAILED)
fscache_set_cookie_state(cookie, FSCACHE_COOKIE_STATE_QUIESCENT);
need_withdraw = true;
- _leave(" [fail]");
+ kleave(" [fail]");
goto out;
}
@@ -572,7 +572,7 @@ void __fscache_use_cookie(struct fscache_cookie *cookie, bool will_modify)
bool queue = false;
int n_active;
- _enter("c=%08x", cookie->debug_id);
+ kenter("c=%08x", cookie->debug_id);
if (WARN(test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags),
"Trying to use relinquished cookie\n"))
@@ -636,7 +636,7 @@ again:
spin_unlock(&cookie->lock);
if (queue)
fscache_queue_cookie(cookie, fscache_cookie_get_use_work);
- _leave("");
+ kleave("");
}
EXPORT_SYMBOL(__fscache_use_cookie);
@@ -702,7 +702,7 @@ static void fscache_cookie_state_machine(struct fscache_cookie *cookie)
enum fscache_cookie_state state;
bool wake = false;
- _enter("c=%x", cookie->debug_id);
+ kenter("c=%x", cookie->debug_id);
again:
spin_lock(&cookie->lock);
@@ -820,7 +820,7 @@ out:
spin_unlock(&cookie->lock);
if (wake)
wake_up_cookie_state(cookie);
- _leave("");
+ kleave("");
}
static void fscache_cookie_worker(struct work_struct *work)
@@ -867,7 +867,7 @@ static void fscache_cookie_lru_do_one(struct fscache_cookie *cookie)
set_bit(FSCACHE_COOKIE_DO_LRU_DISCARD, &cookie->flags);
spin_unlock(&cookie->lock);
fscache_stat(&fscache_n_cookies_lru_expired);
- _debug("lru c=%x", cookie->debug_id);
+ kdebug("lru c=%x", cookie->debug_id);
__fscache_withdraw_cookie(cookie);
}
@@ -971,7 +971,7 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire)
if (retire)
fscache_stat(&fscache_n_relinquishes_retire);
- _enter("c=%08x{%d},%d",
+ kenter("c=%08x{%d},%d",
cookie->debug_id, atomic_read(&cookie->n_active), retire);
if (WARN(test_and_set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags),
@@ -1050,7 +1050,7 @@ void __fscache_invalidate(struct fscache_cookie *cookie,
{
bool is_caching;
- _enter("c=%x", cookie->debug_id);
+ kenter("c=%x", cookie->debug_id);
fscache_stat(&fscache_n_invalidates);
@@ -1072,7 +1072,7 @@ void __fscache_invalidate(struct fscache_cookie *cookie,
case FSCACHE_COOKIE_STATE_INVALIDATING: /* is_still_valid will catch it */
default:
spin_unlock(&cookie->lock);
- _leave(" [no %u]", cookie->state);
+ kleave(" [no %u]", cookie->state);
return;
case FSCACHE_COOKIE_STATE_LOOKING_UP:
@@ -1081,7 +1081,7 @@ void __fscache_invalidate(struct fscache_cookie *cookie,
fallthrough;
case FSCACHE_COOKIE_STATE_CREATING:
spin_unlock(&cookie->lock);
- _leave(" [look %x]", cookie->inval_counter);
+ kleave(" [look %x]", cookie->inval_counter);
return;
case FSCACHE_COOKIE_STATE_ACTIVE:
@@ -1094,7 +1094,7 @@ void __fscache_invalidate(struct fscache_cookie *cookie,
if (is_caching)
fscache_queue_cookie(cookie, fscache_cookie_get_inval_work);
- _leave(" [inv]");
+ kleave(" [inv]");
return;
}
}
diff --git a/fs/netfs/fscache_io.c b/fs/netfs/fscache_io.c
index 38637e5c9b57..bf4eaeec44fb 100644
--- a/fs/netfs/fscache_io.c
+++ b/fs/netfs/fscache_io.c
@@ -28,12 +28,12 @@ bool fscache_wait_for_operation(struct netfs_cache_resources *cres,
again:
if (!fscache_cache_is_live(cookie->volume->cache)) {
- _leave(" [broken]");
+ kleave(" [broken]");
return false;
}
state = fscache_cookie_state(cookie);
- _enter("c=%08x{%u},%x", cookie->debug_id, state, want_state);
+ kenter("c=%08x{%u},%x", cookie->debug_id, state, want_state);
switch (state) {
case FSCACHE_COOKIE_STATE_CREATING:
@@ -52,7 +52,7 @@ again:
case FSCACHE_COOKIE_STATE_DROPPED:
case FSCACHE_COOKIE_STATE_RELINQUISHING:
default:
- _leave(" [not live]");
+ kleave(" [not live]");
return false;
}
@@ -92,7 +92,7 @@ again:
spin_lock(&cookie->lock);
state = fscache_cookie_state(cookie);
- _enter("c=%08x{%u},%x", cookie->debug_id, state, want_state);
+ kenter("c=%08x{%u},%x", cookie->debug_id, state, want_state);
switch (state) {
case FSCACHE_COOKIE_STATE_LOOKING_UP:
@@ -140,7 +140,7 @@ failed:
cres->cache_priv = NULL;
cres->ops = NULL;
fscache_end_cookie_access(cookie, fscache_access_io_not_live);
- _leave(" = -ENOBUFS");
+ kleave(" = -ENOBUFS");
return -ENOBUFS;
}
@@ -224,7 +224,7 @@ void __fscache_write_to_cache(struct fscache_cookie *cookie,
if (len == 0)
goto abandon;
- _enter("%llx,%zx", start, len);
+ kenter("%llx,%zx", start, len);
wreq = kzalloc(sizeof(struct fscache_write_request), GFP_NOFS);
if (!wreq)
diff --git a/fs/netfs/fscache_main.c b/fs/netfs/fscache_main.c
index 42e98bb523e3..bf9b33d26e31 100644
--- a/fs/netfs/fscache_main.c
+++ b/fs/netfs/fscache_main.c
@@ -99,7 +99,7 @@ error_wq:
*/
void __exit fscache_exit(void)
{
- _enter("");
+ kenter("");
kmem_cache_destroy(fscache_cookie_jar);
fscache_proc_cleanup();
diff --git a/fs/netfs/fscache_volume.c b/fs/netfs/fscache_volume.c
index cdf991bdd9de..2e2a405ca9b0 100644
--- a/fs/netfs/fscache_volume.c
+++ b/fs/netfs/fscache_volume.c
@@ -27,6 +27,19 @@ struct fscache_volume *fscache_get_volume(struct fscache_volume *volume,
return volume;
}
+struct fscache_volume *fscache_try_get_volume(struct fscache_volume *volume,
+ enum fscache_volume_trace where)
+{
+ int ref;
+
+ if (!__refcount_inc_not_zero(&volume->ref, &ref))
+ return NULL;
+
+ trace_fscache_volume(volume->debug_id, ref + 1, where);
+ return volume;
+}
+EXPORT_SYMBOL(fscache_try_get_volume);
+
static void fscache_see_volume(struct fscache_volume *volume,
enum fscache_volume_trace where)
{
@@ -251,7 +264,7 @@ static struct fscache_volume *fscache_alloc_volume(const char *volume_key,
fscache_see_volume(volume, fscache_volume_new_acquire);
fscache_stat(&fscache_n_volumes);
up_write(&fscache_addremove_sem);
- _leave(" = v=%x", volume->debug_id);
+ kleave(" = v=%x", volume->debug_id);
return volume;
err_vol:
@@ -420,6 +433,7 @@ void fscache_put_volume(struct fscache_volume *volume,
fscache_free_volume(volume);
}
}
+EXPORT_SYMBOL(fscache_put_volume);
/*
* Relinquish a volume representation cookie.
@@ -452,7 +466,7 @@ void fscache_withdraw_volume(struct fscache_volume *volume)
{
int n_accesses;
- _debug("withdraw V=%x", volume->debug_id);
+ kdebug("withdraw V=%x", volume->debug_id);
/* Allow wakeups on dec-to-0 */
n_accesses = atomic_dec_return(&volume->n_accesses);
diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h
index 95e281a8af78..21e46bc9aa49 100644
--- a/fs/netfs/internal.h
+++ b/fs/netfs/internal.h
@@ -34,7 +34,6 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync);
/*
* main.c
*/
-extern unsigned int netfs_debug;
extern struct list_head netfs_io_requests;
extern spinlock_t netfs_proc_lock;
extern mempool_t netfs_request_pool;
@@ -63,15 +62,6 @@ static inline void netfs_proc_del_rreq(struct netfs_io_request *rreq) {}
/*
* misc.c
*/
-#define NETFS_FLAG_PUT_MARK BIT(0)
-#define NETFS_FLAG_PAGECACHE_MARK BIT(1)
-int netfs_xa_store_and_mark(struct xarray *xa, unsigned long index,
- struct folio *folio, unsigned int flags,
- gfp_t gfp_mask);
-int netfs_add_folios_to_buffer(struct xarray *buffer,
- struct address_space *mapping,
- pgoff_t index, pgoff_t to, gfp_t gfp_mask);
-void netfs_clear_buffer(struct xarray *buffer);
/*
* objects.c
@@ -353,8 +343,6 @@ extern const struct seq_operations fscache_volumes_seq_ops;
struct fscache_volume *fscache_get_volume(struct fscache_volume *volume,
enum fscache_volume_trace where);
-void fscache_put_volume(struct fscache_volume *volume,
- enum fscache_volume_trace where);
bool fscache_begin_volume_access(struct fscache_volume *volume,
struct fscache_cookie *cookie,
enum fscache_access_trace why);
@@ -365,42 +353,12 @@ void fscache_create_volume(struct fscache_volume *volume, bool wait);
* debug tracing
*/
#define dbgprintk(FMT, ...) \
- printk("[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__)
+ pr_debug("[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__)
#define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__)
#define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
#define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__)
-#ifdef __KDEBUG
-#define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__)
-#define _leave(FMT, ...) kleave(FMT, ##__VA_ARGS__)
-#define _debug(FMT, ...) kdebug(FMT, ##__VA_ARGS__)
-
-#elif defined(CONFIG_NETFS_DEBUG)
-#define _enter(FMT, ...) \
-do { \
- if (netfs_debug) \
- kenter(FMT, ##__VA_ARGS__); \
-} while (0)
-
-#define _leave(FMT, ...) \
-do { \
- if (netfs_debug) \
- kleave(FMT, ##__VA_ARGS__); \
-} while (0)
-
-#define _debug(FMT, ...) \
-do { \
- if (netfs_debug) \
- kdebug(FMT, ##__VA_ARGS__); \
-} while (0)
-
-#else
-#define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__)
-#define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
-#define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
-#endif
-
/*
* assertions
*/
diff --git a/fs/netfs/io.c b/fs/netfs/io.c
index c93851b98368..c7576481c321 100644
--- a/fs/netfs/io.c
+++ b/fs/netfs/io.c
@@ -130,7 +130,7 @@ static void netfs_reset_subreq_iter(struct netfs_io_request *rreq,
if (count == remaining)
return;
- _debug("R=%08x[%u] ITER RESUB-MISMATCH %zx != %zx-%zx-%llx %x\n",
+ kdebug("R=%08x[%u] ITER RESUB-MISMATCH %zx != %zx-%zx-%llx %x\n",
rreq->debug_id, subreq->debug_index,
iov_iter_count(&subreq->io_iter), subreq->transferred,
subreq->len, rreq->i_size,
@@ -326,7 +326,7 @@ void netfs_subreq_terminated(struct netfs_io_subrequest *subreq,
struct netfs_io_request *rreq = subreq->rreq;
int u;
- _enter("R=%x[%x]{%llx,%lx},%zd",
+ kenter("R=%x[%x]{%llx,%lx},%zd",
rreq->debug_id, subreq->debug_index,
subreq->start, subreq->flags, transferred_or_error);
@@ -435,7 +435,7 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq,
struct netfs_inode *ictx = netfs_inode(rreq->inode);
size_t lsize;
- _enter("%llx-%llx,%llx", subreq->start, subreq->start + subreq->len, rreq->i_size);
+ kenter("%llx-%llx,%llx", subreq->start, subreq->start + subreq->len, rreq->i_size);
if (rreq->origin != NETFS_DIO_READ) {
source = netfs_cache_prepare_read(subreq, rreq->i_size);
@@ -518,7 +518,7 @@ static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq,
subreq->start = rreq->start + rreq->submitted;
subreq->len = io_iter->count;
- _debug("slice %llx,%zx,%llx", subreq->start, subreq->len, rreq->submitted);
+ kdebug("slice %llx,%zx,%llx", subreq->start, subreq->len, rreq->submitted);
list_add_tail(&subreq->rreq_link, &rreq->subrequests);
/* Call out to the cache to find out what it can do with the remaining
@@ -570,7 +570,7 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync)
struct iov_iter io_iter;
int ret;
- _enter("R=%x %llx-%llx",
+ kenter("R=%x %llx-%llx",
rreq->debug_id, rreq->start, rreq->start + rreq->len - 1);
if (rreq->len == 0) {
@@ -593,7 +593,7 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync)
atomic_set(&rreq->nr_outstanding, 1);
io_iter = rreq->io_iter;
do {
- _debug("submit %llx + %llx >= %llx",
+ kdebug("submit %llx + %llx >= %llx",
rreq->start, rreq->submitted, rreq->i_size);
if (rreq->origin == NETFS_DIO_READ &&
rreq->start + rreq->submitted >= rreq->i_size)
diff --git a/fs/netfs/main.c b/fs/netfs/main.c
index 5f0f438e5d21..db824c372842 100644
--- a/fs/netfs/main.c
+++ b/fs/netfs/main.c
@@ -20,10 +20,6 @@ MODULE_LICENSE("GPL");
EXPORT_TRACEPOINT_SYMBOL(netfs_sreq);
-unsigned netfs_debug;
-module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO);
-MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask");
-
static struct kmem_cache *netfs_request_slab;
static struct kmem_cache *netfs_subrequest_slab;
mempool_t netfs_request_pool;
diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c
index bc1fc54fb724..172808e83ca8 100644
--- a/fs/netfs/misc.c
+++ b/fs/netfs/misc.c
@@ -8,87 +8,6 @@
#include <linux/swap.h>
#include "internal.h"
-/*
- * Attach a folio to the buffer and maybe set marks on it to say that we need
- * to put the folio later and twiddle the pagecache flags.
- */
-int netfs_xa_store_and_mark(struct xarray *xa, unsigned long index,
- struct folio *folio, unsigned int flags,
- gfp_t gfp_mask)
-{
- XA_STATE_ORDER(xas, xa, index, folio_order(folio));
-
-retry:
- xas_lock(&xas);
- for (;;) {
- xas_store(&xas, folio);
- if (!xas_error(&xas))
- break;
- xas_unlock(&xas);
- if (!xas_nomem(&xas, gfp_mask))
- return xas_error(&xas);
- goto retry;
- }
-
- if (flags & NETFS_FLAG_PUT_MARK)
- xas_set_mark(&xas, NETFS_BUF_PUT_MARK);
- if (flags & NETFS_FLAG_PAGECACHE_MARK)
- xas_set_mark(&xas, NETFS_BUF_PAGECACHE_MARK);
- xas_unlock(&xas);
- return xas_error(&xas);
-}
-
-/*
- * Create the specified range of folios in the buffer attached to the read
- * request. The folios are marked with NETFS_BUF_PUT_MARK so that we know that
- * these need freeing later.
- */
-int netfs_add_folios_to_buffer(struct xarray *buffer,
- struct address_space *mapping,
- pgoff_t index, pgoff_t to, gfp_t gfp_mask)
-{
- struct folio *folio;
- int ret;
-
- if (to + 1 == index) /* Page range is inclusive */
- return 0;
-
- do {
- /* TODO: Figure out what order folio can be allocated here */
- folio = filemap_alloc_folio(readahead_gfp_mask(mapping), 0);
- if (!folio)
- return -ENOMEM;
- folio->index = index;
- ret = netfs_xa_store_and_mark(buffer, index, folio,
- NETFS_FLAG_PUT_MARK, gfp_mask);
- if (ret < 0) {
- folio_put(folio);
- return ret;
- }
-
- index += folio_nr_pages(folio);
- } while (index <= to && index != 0);
-
- return 0;
-}
-
-/*
- * Clear an xarray buffer, putting a ref on the folios that have
- * NETFS_BUF_PUT_MARK set.
- */
-void netfs_clear_buffer(struct xarray *buffer)
-{
- struct folio *folio;
- XA_STATE(xas, buffer, 0);
-
- rcu_read_lock();
- xas_for_each_marked(&xas, folio, ULONG_MAX, NETFS_BUF_PUT_MARK) {
- folio_put(folio);
- }
- rcu_read_unlock();
- xa_destroy(buffer);
-}
-
/**
* netfs_dirty_folio - Mark folio dirty and pin a cache object for writeback
* @mapping: The mapping the folio belongs to.
@@ -107,7 +26,7 @@ bool netfs_dirty_folio(struct address_space *mapping, struct folio *folio)
struct fscache_cookie *cookie = netfs_i_cookie(ictx);
bool need_use = false;
- _enter("");
+ kenter("");
if (!filemap_dirty_folio(mapping, folio))
return false;
@@ -180,7 +99,7 @@ void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length)
struct netfs_folio *finfo;
size_t flen = folio_size(folio);
- _enter("{%lx},%zx,%zx", folio->index, offset, length);
+ kenter("{%lx},%zx,%zx", folio->index, offset, length);
if (!folio_test_private(folio))
return;
diff --git a/fs/netfs/write_collect.c b/fs/netfs/write_collect.c
index 426cf87aaf2e..488147439fe0 100644
--- a/fs/netfs/write_collect.c
+++ b/fs/netfs/write_collect.c
@@ -161,7 +161,7 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
{
struct list_head *next;
- _enter("R=%x[%x:]", wreq->debug_id, stream->stream_nr);
+ kenter("R=%x[%x:]", wreq->debug_id, stream->stream_nr);
if (list_empty(&stream->subrequests))
return;
@@ -374,7 +374,7 @@ static void netfs_collect_write_results(struct netfs_io_request *wreq)
unsigned int notes;
int s;
- _enter("%llx-%llx", wreq->start, wreq->start + wreq->len);
+ kenter("%llx-%llx", wreq->start, wreq->start + wreq->len);
trace_netfs_collect(wreq);
trace_netfs_rreq(wreq, netfs_rreq_trace_collect);
@@ -409,7 +409,7 @@ reassess_streams:
front = stream->front;
while (front) {
trace_netfs_collect_sreq(wreq, front);
- //_debug("sreq [%x] %llx %zx/%zx",
+ //kdebug("sreq [%x] %llx %zx/%zx",
// front->debug_index, front->start, front->transferred, front->len);
/* Stall if there may be a discontinuity. */
@@ -598,7 +598,7 @@ reassess_streams:
out:
netfs_put_group_many(wreq->group, wreq->nr_group_rel);
wreq->nr_group_rel = 0;
- _leave(" = %x", notes);
+ kleave(" = %x", notes);
return;
need_retry:
@@ -606,7 +606,7 @@ need_retry:
* that any partially completed op will have had any wholly transferred
* folios removed from it.
*/
- _debug("retry");
+ kdebug("retry");
netfs_retry_writes(wreq);
goto out;
}
@@ -621,7 +621,7 @@ void netfs_write_collection_worker(struct work_struct *work)
size_t transferred;
int s;
- _enter("R=%x", wreq->debug_id);
+ kenter("R=%x", wreq->debug_id);
netfs_see_request(wreq, netfs_rreq_trace_see_work);
if (!test_bit(NETFS_RREQ_IN_PROGRESS, &wreq->flags)) {
@@ -684,7 +684,7 @@ void netfs_write_collection_worker(struct work_struct *work)
if (wreq->origin == NETFS_DIO_WRITE)
inode_dio_end(wreq->inode);
- _debug("finished");
+ kdebug("finished");
trace_netfs_rreq(wreq, netfs_rreq_trace_wake_ip);
clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &wreq->flags);
wake_up_bit(&wreq->flags, NETFS_RREQ_IN_PROGRESS);
@@ -744,7 +744,7 @@ void netfs_write_subrequest_terminated(void *_op, ssize_t transferred_or_error,
struct netfs_io_request *wreq = subreq->rreq;
struct netfs_io_stream *stream = &wreq->io_streams[subreq->stream_nr];
- _enter("%x[%x] %zd", wreq->debug_id, subreq->debug_index, transferred_or_error);
+ kenter("%x[%x] %zd", wreq->debug_id, subreq->debug_index, transferred_or_error);
switch (subreq->source) {
case NETFS_UPLOAD_TO_SERVER:
diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c
index 3aa86e268f40..d7c971df8866 100644
--- a/fs/netfs/write_issue.c
+++ b/fs/netfs/write_issue.c
@@ -99,7 +99,7 @@ struct netfs_io_request *netfs_create_write_req(struct address_space *mapping,
if (IS_ERR(wreq))
return wreq;
- _enter("R=%x", wreq->debug_id);
+ kenter("R=%x", wreq->debug_id);
ictx = netfs_inode(wreq->inode);
if (test_bit(NETFS_RREQ_WRITE_TO_CACHE, &wreq->flags))
@@ -159,7 +159,7 @@ static void netfs_prepare_write(struct netfs_io_request *wreq,
subreq->max_nr_segs = INT_MAX;
subreq->stream_nr = stream->stream_nr;
- _enter("R=%x[%x]", wreq->debug_id, subreq->debug_index);
+ kenter("R=%x[%x]", wreq->debug_id, subreq->debug_index);
trace_netfs_sreq_ref(wreq->debug_id, subreq->debug_index,
refcount_read(&subreq->ref),
@@ -215,7 +215,7 @@ static void netfs_do_issue_write(struct netfs_io_stream *stream,
{
struct netfs_io_request *wreq = subreq->rreq;
- _enter("R=%x[%x],%zx", wreq->debug_id, subreq->debug_index, subreq->len);
+ kenter("R=%x[%x],%zx", wreq->debug_id, subreq->debug_index, subreq->len);
if (test_bit(NETFS_SREQ_FAILED, &subreq->flags))
return netfs_write_subrequest_terminated(subreq, subreq->error, false);
@@ -272,11 +272,11 @@ int netfs_advance_write(struct netfs_io_request *wreq,
size_t part;
if (!stream->avail) {
- _leave("no write");
+ kleave("no write");
return len;
}
- _enter("R=%x[%x]", wreq->debug_id, subreq ? subreq->debug_index : 0);
+ kenter("R=%x[%x]", wreq->debug_id, subreq ? subreq->debug_index : 0);
if (subreq && start != subreq->start + subreq->len) {
netfs_issue_write(wreq, stream);
@@ -288,7 +288,7 @@ int netfs_advance_write(struct netfs_io_request *wreq,
subreq = stream->construct;
part = min(subreq->max_len - subreq->len, len);
- _debug("part %zx/%zx %zx/%zx", subreq->len, subreq->max_len, part, len);
+ kdebug("part %zx/%zx %zx/%zx", subreq->len, subreq->max_len, part, len);
subreq->len += part;
subreq->nr_segs++;
@@ -319,7 +319,7 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
bool to_eof = false, streamw = false;
bool debug = false;
- _enter("");
+ kenter("");
/* netfs_perform_write() may shift i_size around the page or from out
* of the page to beyond it, but cannot move i_size into or through the
@@ -329,7 +329,7 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
if (fpos >= i_size) {
/* mmap beyond eof. */
- _debug("beyond eof");
+ kdebug("beyond eof");
folio_start_writeback(folio);
folio_unlock(folio);
wreq->nr_group_rel += netfs_folio_written_back(folio);
@@ -363,7 +363,7 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
}
flen -= foff;
- _debug("folio %zx %zx %zx", foff, flen, fsize);
+ kdebug("folio %zx %zx %zx", foff, flen, fsize);
/* Deal with discontinuities in the stream of dirty pages. These can
* arise from a number of sources:
@@ -483,11 +483,11 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
if (!debug)
kdebug("R=%x: No submit", wreq->debug_id);
- if (flen < fsize)
+ if (foff + flen < fsize)
for (int s = 0; s < NR_IO_STREAMS; s++)
netfs_issue_write(wreq, &wreq->io_streams[s]);
- _leave(" = 0");
+ kleave(" = 0");
return 0;
}
@@ -522,7 +522,7 @@ int netfs_writepages(struct address_space *mapping,
netfs_stat(&netfs_n_wh_writepages);
do {
- _debug("wbiter %lx %llx", folio->index, wreq->start + wreq->submitted);
+ kdebug("wbiter %lx %llx", folio->index, wreq->start + wreq->submitted);
/* It appears we don't have to handle cyclic writeback wrapping. */
WARN_ON_ONCE(wreq && folio_pos(folio) < wreq->start + wreq->submitted);
@@ -546,14 +546,14 @@ int netfs_writepages(struct address_space *mapping,
mutex_unlock(&ictx->wb_lock);
netfs_put_request(wreq, false, netfs_rreq_trace_put_return);
- _leave(" = %d", error);
+ kleave(" = %d", error);
return error;
couldnt_start:
netfs_kill_dirty_pages(mapping, wbc, folio);
out:
mutex_unlock(&ictx->wb_lock);
- _leave(" = %d", error);
+ kleave(" = %d", error);
return error;
}
EXPORT_SYMBOL(netfs_writepages);
@@ -590,7 +590,7 @@ int netfs_advance_writethrough(struct netfs_io_request *wreq, struct writeback_c
struct folio *folio, size_t copied, bool to_page_end,
struct folio **writethrough_cache)
{
- _enter("R=%x ic=%zu ws=%u cp=%zu tp=%u",
+ kenter("R=%x ic=%zu ws=%u cp=%zu tp=%u",
wreq->debug_id, wreq->iter.count, wreq->wsize, copied, to_page_end);
if (!*writethrough_cache) {
@@ -624,7 +624,7 @@ int netfs_end_writethrough(struct netfs_io_request *wreq, struct writeback_contr
struct netfs_inode *ictx = netfs_inode(wreq->inode);
int ret;
- _enter("R=%x", wreq->debug_id);
+ kenter("R=%x", wreq->debug_id);
if (writethrough_cache)
netfs_write_folio(wreq, wbc, writethrough_cache);
@@ -657,7 +657,7 @@ int netfs_unbuffered_write(struct netfs_io_request *wreq, bool may_wait, size_t
loff_t start = wreq->start;
int error = 0;
- _enter("%zx", len);
+ kenter("%zx", len);
if (wreq->origin == NETFS_DIO_WRITE)
inode_dio_begin(wreq->inode);
@@ -665,7 +665,7 @@ int netfs_unbuffered_write(struct netfs_io_request *wreq, bool may_wait, size_t
while (len) {
// TODO: Prepare content encryption
- _debug("unbuffered %zx", len);
+ kdebug("unbuffered %zx", len);
part = netfs_advance_write(wreq, upload, start, len, false);
start += part;
len -= part;
@@ -684,6 +684,6 @@ int netfs_unbuffered_write(struct netfs_io_request *wreq, bool may_wait, size_t
if (list_empty(&upload->subrequests))
netfs_wake_write_collector(wreq, false);
- _leave(" = %d", error);
+ kleave(" = %d", error);
return error;
}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index a142287d86f6..cca80b5f54e0 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -122,8 +122,6 @@ static void nfs_readpage_release(struct nfs_page *req, int error)
{
struct folio *folio = nfs_page_to_folio(req);
- if (nfs_error_is_fatal_on_server(error) && error != -ETIMEDOUT)
- folio_set_error(folio);
if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE))
if (nfs_netfs_folio_unlock(folio))
folio_unlock(folio);
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 13818129d268..1c62a5a9f51d 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -32,15 +32,7 @@ static int nfs_symlink_filler(struct file *file, struct folio *folio)
int error;
error = NFS_PROTO(inode)->readlink(inode, &folio->page, 0, PAGE_SIZE);
- if (error < 0)
- goto error;
- folio_mark_uptodate(folio);
- folio_unlock(folio);
- return 0;
-
-error:
- folio_set_error(folio);
- folio_unlock(folio);
+ folio_end_read(folio, error == 0);
return error;
}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 2329cbb0e446..a91463ab87a0 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -311,7 +311,6 @@ static void nfs_mapping_set_error(struct folio *folio, int error)
{
struct address_space *mapping = folio_file_mapping(folio);
- folio_set_error(folio);
filemap_set_wb_err(mapping, error);
if (mapping->host)
errseq_set(&mapping->host->i_sb->s_wb_err,
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 0b75305fb5f5..dd4e11a703aa 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -247,7 +247,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
dentry = dget(exp->ex_path.dentry);
else {
dentry = exportfs_decode_fh_raw(exp->ex_path.mnt, fid,
- data_left, fileid_type,
+ data_left, fileid_type, 0,
nfsd_acceptable, exp);
if (IS_ERR_OR_NULL(dentry)) {
trace_nfsd_set_fh_dentry_badhandle(rqstp, fhp,
diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c
index 89caef7513db..ba50388ee4bf 100644
--- a/fs/nilfs2/alloc.c
+++ b/fs/nilfs2/alloc.c
@@ -377,11 +377,12 @@ void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr,
* @target: offset number of an entry in the group (start point)
* @bsize: size in bits
* @lock: spin lock protecting @bitmap
+ * @wrap: whether to wrap around
*/
static int nilfs_palloc_find_available_slot(unsigned char *bitmap,
unsigned long target,
unsigned int bsize,
- spinlock_t *lock)
+ spinlock_t *lock, bool wrap)
{
int pos, end = bsize;
@@ -397,6 +398,8 @@ static int nilfs_palloc_find_available_slot(unsigned char *bitmap,
end = target;
}
+ if (!wrap)
+ return -ENOSPC;
/* wrap around */
for (pos = 0; pos < end; pos++) {
@@ -495,9 +498,10 @@ int nilfs_palloc_count_max_entries(struct inode *inode, u64 nused, u64 *nmaxp)
* nilfs_palloc_prepare_alloc_entry - prepare to allocate a persistent object
* @inode: inode of metadata file using this allocator
* @req: nilfs_palloc_req structure exchanged for the allocation
+ * @wrap: whether to wrap around
*/
int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
- struct nilfs_palloc_req *req)
+ struct nilfs_palloc_req *req, bool wrap)
{
struct buffer_head *desc_bh, *bitmap_bh;
struct nilfs_palloc_group_desc *desc;
@@ -516,7 +520,7 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
entries_per_group = nilfs_palloc_entries_per_group(inode);
for (i = 0; i < ngroups; i += n) {
- if (group >= ngroups) {
+ if (group >= ngroups && wrap) {
/* wrap around */
group = 0;
maxgroup = nilfs_palloc_group(inode, req->pr_entry_nr,
@@ -550,7 +554,14 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
bitmap_kaddr = kmap_local_page(bitmap_bh->b_page);
bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
pos = nilfs_palloc_find_available_slot(
- bitmap, group_offset, entries_per_group, lock);
+ bitmap, group_offset, entries_per_group, lock,
+ wrap);
+ /*
+ * Since the search for a free slot in the second and
+ * subsequent bitmap blocks always starts from the
+ * beginning, the wrap flag only has an effect on the
+ * first search.
+ */
kunmap_local(bitmap_kaddr);
if (pos >= 0)
goto found;
diff --git a/fs/nilfs2/alloc.h b/fs/nilfs2/alloc.h
index b667e869ac07..d825a9faca6d 100644
--- a/fs/nilfs2/alloc.h
+++ b/fs/nilfs2/alloc.h
@@ -50,8 +50,8 @@ struct nilfs_palloc_req {
struct buffer_head *pr_entry_bh;
};
-int nilfs_palloc_prepare_alloc_entry(struct inode *,
- struct nilfs_palloc_req *);
+int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
+ struct nilfs_palloc_req *req, bool wrap);
void nilfs_palloc_commit_alloc_entry(struct inode *,
struct nilfs_palloc_req *);
void nilfs_palloc_abort_alloc_entry(struct inode *, struct nilfs_palloc_req *);
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index 180fc8d36213..fc1caf63a42a 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -75,7 +75,7 @@ int nilfs_dat_prepare_alloc(struct inode *dat, struct nilfs_palloc_req *req)
{
int ret;
- ret = nilfs_palloc_prepare_alloc_entry(dat, req);
+ ret = nilfs_palloc_prepare_alloc_entry(dat, req, true);
if (ret < 0)
return ret;
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 52e50b1b7f22..4a29b0138d75 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -135,6 +135,9 @@ static bool nilfs_check_folio(struct folio *folio, char *kaddr)
goto Enamelen;
if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1))
goto Espan;
+ if (unlikely(p->inode &&
+ NILFS_PRIVATE_INODE(le64_to_cpu(p->inode))))
+ goto Einumber;
}
if (offs != limit)
goto Eend;
@@ -160,6 +163,9 @@ Enamelen:
goto bad_entry;
Espan:
error = "directory entry across blocks";
+ goto bad_entry;
+Einumber:
+ error = "disallowed inode number";
bad_entry:
nilfs_error(sb,
"bad entry in directory #%lu: %s - offset=%lu, inode=%lu, rec_len=%zd, name_len=%d",
@@ -377,11 +383,39 @@ found:
struct nilfs_dir_entry *nilfs_dotdot(struct inode *dir, struct folio **foliop)
{
- struct nilfs_dir_entry *de = nilfs_get_folio(dir, 0, foliop);
+ struct folio *folio;
+ struct nilfs_dir_entry *de, *next_de;
+ size_t limit;
+ char *msg;
+ de = nilfs_get_folio(dir, 0, &folio);
if (IS_ERR(de))
return NULL;
- return nilfs_next_entry(de);
+
+ limit = nilfs_last_byte(dir, 0); /* is a multiple of chunk size */
+ if (unlikely(!limit || le64_to_cpu(de->inode) != dir->i_ino ||
+ !nilfs_match(1, ".", de))) {
+ msg = "missing '.'";
+ goto fail;
+ }
+
+ next_de = nilfs_next_entry(de);
+ /*
+ * If "next_de" has not reached the end of the chunk, there is
+ * at least one more record. Check whether it matches "..".
+ */
+ if (unlikely((char *)next_de == (char *)de + nilfs_chunk_size(dir) ||
+ !nilfs_match(2, "..", next_de))) {
+ msg = "missing '..'";
+ goto fail;
+ }
+ *foliop = folio;
+ return next_de;
+
+fail:
+ nilfs_error(dir->i_sb, "directory #%lu %s", dir->i_ino, msg);
+ folio_release_kmap(folio, de);
+ return NULL;
}
ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr)
diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c
index 612e609158b5..1e86b9303b7c 100644
--- a/fs/nilfs2/ifile.c
+++ b/fs/nilfs2/ifile.c
@@ -56,13 +56,10 @@ int nilfs_ifile_create_inode(struct inode *ifile, ino_t *out_ino,
struct nilfs_palloc_req req;
int ret;
- req.pr_entry_nr = 0; /*
- * 0 says find free inode from beginning
- * of a group. dull code!!
- */
+ req.pr_entry_nr = NILFS_FIRST_INO(ifile->i_sb);
req.pr_entry_bh = NULL;
- ret = nilfs_palloc_prepare_alloc_entry(ifile, &req);
+ ret = nilfs_palloc_prepare_alloc_entry(ifile, &req, false);
if (!ret) {
ret = nilfs_palloc_get_entry_block(ifile, req.pr_entry_nr, 1,
&req.pr_entry_bh);
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 728e90be3570..4017f7856440 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -116,9 +116,15 @@ enum {
#define NILFS_FIRST_INO(sb) (((struct the_nilfs *)sb->s_fs_info)->ns_first_ino)
#define NILFS_MDT_INODE(sb, ino) \
- ((ino) < NILFS_FIRST_INO(sb) && (NILFS_MDT_INO_BITS & BIT(ino)))
+ ((ino) < NILFS_USER_INO && (NILFS_MDT_INO_BITS & BIT(ino)))
#define NILFS_VALID_INODE(sb, ino) \
- ((ino) >= NILFS_FIRST_INO(sb) || (NILFS_SYS_INO_BITS & BIT(ino)))
+ ((ino) >= NILFS_FIRST_INO(sb) || \
+ ((ino) < NILFS_USER_INO && (NILFS_SYS_INO_BITS & BIT(ino))))
+
+#define NILFS_PRIVATE_INODE(ino) ({ \
+ ino_t __ino = (ino); \
+ ((__ino) < NILFS_USER_INO && (__ino) != NILFS_ROOT_INO && \
+ (__ino) != NILFS_SKETCH_INO); })
/**
* struct nilfs_transaction_info: context information for synchronization
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index f41d7b6d432c..e44dde57ab65 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -452,6 +452,12 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
}
nilfs->ns_first_ino = le32_to_cpu(sbp->s_first_ino);
+ if (nilfs->ns_first_ino < NILFS_USER_INO) {
+ nilfs_err(nilfs->ns_sb,
+ "too small lower limit for non-reserved inode numbers: %u",
+ nilfs->ns_first_ino);
+ return -EINVAL;
+ }
nilfs->ns_blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment);
if (nilfs->ns_blocks_per_segment < NILFS_SEG_MIN_BLOCKS) {
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index 85da0629415d..1e829ed7b0ef 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -182,7 +182,7 @@ struct the_nilfs {
unsigned long ns_nrsvsegs;
unsigned long ns_first_data_block;
int ns_inode_size;
- int ns_first_ino;
+ unsigned int ns_first_ino;
u32 ns_crc_seed;
/* /sys/fs/<nilfs>/<device> */
diff --git a/fs/nls/mac-celtic.c b/fs/nls/mac-celtic.c
index 266c2d7d50bd..2963f3299d7e 100644
--- a/fs/nls/mac-celtic.c
+++ b/fs/nls/mac-celtic.c
@@ -598,4 +598,5 @@ static void __exit exit_nls_macceltic(void)
module_init(init_nls_macceltic)
module_exit(exit_nls_macceltic)
+MODULE_DESCRIPTION("NLS Codepage macceltic");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/mac-centeuro.c b/fs/nls/mac-centeuro.c
index 9789c6057551..43b20f4bdb67 100644
--- a/fs/nls/mac-centeuro.c
+++ b/fs/nls/mac-centeuro.c
@@ -528,4 +528,5 @@ static void __exit exit_nls_maccenteuro(void)
module_init(init_nls_maccenteuro)
module_exit(exit_nls_maccenteuro)
+MODULE_DESCRIPTION("NLS Codepage maccenteuro");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/mac-croatian.c b/fs/nls/mac-croatian.c
index bb19e7a07d43..62730d6a64e5 100644
--- a/fs/nls/mac-croatian.c
+++ b/fs/nls/mac-croatian.c
@@ -598,4 +598,5 @@ static void __exit exit_nls_maccroatian(void)
module_init(init_nls_maccroatian)
module_exit(exit_nls_maccroatian)
+MODULE_DESCRIPTION("NLS Codepage maccroatian");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/mac-cyrillic.c b/fs/nls/mac-cyrillic.c
index 2a7dea36acba..7a5c4d16aac8 100644
--- a/fs/nls/mac-cyrillic.c
+++ b/fs/nls/mac-cyrillic.c
@@ -493,4 +493,5 @@ static void __exit exit_nls_maccyrillic(void)
module_init(init_nls_maccyrillic)
module_exit(exit_nls_maccyrillic)
+MODULE_DESCRIPTION("NLS Codepage maccyrillic");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/mac-gaelic.c b/fs/nls/mac-gaelic.c
index 77b001653588..3d22f03a90b6 100644
--- a/fs/nls/mac-gaelic.c
+++ b/fs/nls/mac-gaelic.c
@@ -563,4 +563,5 @@ static void __exit exit_nls_macgaelic(void)
module_init(init_nls_macgaelic)
module_exit(exit_nls_macgaelic)
+MODULE_DESCRIPTION("NLS Codepage macgaelic");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/mac-greek.c b/fs/nls/mac-greek.c
index 1eccf499e2eb..de3aa9ddb5b1 100644
--- a/fs/nls/mac-greek.c
+++ b/fs/nls/mac-greek.c
@@ -493,4 +493,5 @@ static void __exit exit_nls_macgreek(void)
module_init(init_nls_macgreek)
module_exit(exit_nls_macgreek)
+MODULE_DESCRIPTION("NLS Codepage macgreek");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/mac-iceland.c b/fs/nls/mac-iceland.c
index cbd0875c6d69..0bba83f9d415 100644
--- a/fs/nls/mac-iceland.c
+++ b/fs/nls/mac-iceland.c
@@ -598,4 +598,5 @@ static void __exit exit_nls_maciceland(void)
module_init(init_nls_maciceland)
module_exit(exit_nls_maciceland)
+MODULE_DESCRIPTION("NLS Codepage maciceland");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/mac-inuit.c b/fs/nls/mac-inuit.c
index fba8357aaf03..493386832dfd 100644
--- a/fs/nls/mac-inuit.c
+++ b/fs/nls/mac-inuit.c
@@ -528,4 +528,5 @@ static void __exit exit_nls_macinuit(void)
module_init(init_nls_macinuit)
module_exit(exit_nls_macinuit)
+MODULE_DESCRIPTION("NLS Codepage macinuit");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/mac-roman.c b/fs/nls/mac-roman.c
index b6a98a5208cd..d3c082173c20 100644
--- a/fs/nls/mac-roman.c
+++ b/fs/nls/mac-roman.c
@@ -633,4 +633,5 @@ static void __exit exit_nls_macroman(void)
module_init(init_nls_macroman)
module_exit(exit_nls_macroman)
+MODULE_DESCRIPTION("NLS Codepage macroman");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/mac-romanian.c b/fs/nls/mac-romanian.c
index 25547f023638..a7735852f2d5 100644
--- a/fs/nls/mac-romanian.c
+++ b/fs/nls/mac-romanian.c
@@ -598,4 +598,5 @@ static void __exit exit_nls_macromanian(void)
module_init(init_nls_macromanian)
module_exit(exit_nls_macromanian)
+MODULE_DESCRIPTION("NLS Codepage macromanian");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/mac-turkish.c b/fs/nls/mac-turkish.c
index b5454bc7b7fa..d77e9b6b7d7c 100644
--- a/fs/nls/mac-turkish.c
+++ b/fs/nls/mac-turkish.c
@@ -598,4 +598,5 @@ static void __exit exit_nls_macturkish(void)
module_init(init_nls_macturkish)
module_exit(exit_nls_macturkish)
+MODULE_DESCRIPTION("NLS Codepage macturkish");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_ascii.c b/fs/nls/nls_ascii.c
index a2620650d5e4..068143d71284 100644
--- a/fs/nls/nls_ascii.c
+++ b/fs/nls/nls_ascii.c
@@ -163,4 +163,5 @@ static void __exit exit_nls_ascii(void)
module_init(init_nls_ascii)
module_exit(exit_nls_ascii)
+MODULE_DESCRIPTION("NLS ASCII (United States)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
index a026dbd3593f..18d597e49a19 100644
--- a/fs/nls/nls_base.c
+++ b/fs/nls/nls_base.c
@@ -545,4 +545,5 @@ EXPORT_SYMBOL(unload_nls);
EXPORT_SYMBOL(load_nls);
EXPORT_SYMBOL(load_nls_default);
+MODULE_DESCRIPTION("Base file system native language support");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp1250.c b/fs/nls/nls_cp1250.c
index ace3e19d3407..e22a57a4b828 100644
--- a/fs/nls/nls_cp1250.c
+++ b/fs/nls/nls_cp1250.c
@@ -343,4 +343,5 @@ static void __exit exit_nls_cp1250(void)
module_init(init_nls_cp1250)
module_exit(exit_nls_cp1250)
+MODULE_DESCRIPTION("NLS Windows CP1250 (Slavic/Central European Languages)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp1251.c b/fs/nls/nls_cp1251.c
index 9273ddfd08a1..6f46d339f23c 100644
--- a/fs/nls/nls_cp1251.c
+++ b/fs/nls/nls_cp1251.c
@@ -298,4 +298,5 @@ static void __exit exit_nls_cp1251(void)
module_init(init_nls_cp1251)
module_exit(exit_nls_cp1251)
+MODULE_DESCRIPTION("NLS Windows CP1251 (Bulgarian, Belarusian)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp1255.c b/fs/nls/nls_cp1255.c
index 1caf5dfed85b..299e089d4301 100644
--- a/fs/nls/nls_cp1255.c
+++ b/fs/nls/nls_cp1255.c
@@ -380,5 +380,6 @@ static void __exit exit_nls_cp1255(void)
module_init(init_nls_cp1255)
module_exit(exit_nls_cp1255)
+MODULE_DESCRIPTION("NLS Hebrew charsets (ISO-8859-8, CP1255)");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS_NLS(iso8859-8);
diff --git a/fs/nls/nls_cp437.c b/fs/nls/nls_cp437.c
index 7ddb830da3fd..ab880499ea32 100644
--- a/fs/nls/nls_cp437.c
+++ b/fs/nls/nls_cp437.c
@@ -384,4 +384,5 @@ static void __exit exit_nls_cp437(void)
module_init(init_nls_cp437)
module_exit(exit_nls_cp437)
+MODULE_DESCRIPTION("NLS Codepage 437 (United States, Canada)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp737.c b/fs/nls/nls_cp737.c
index c593f683a0cd..5c37618296e9 100644
--- a/fs/nls/nls_cp737.c
+++ b/fs/nls/nls_cp737.c
@@ -347,4 +347,5 @@ static void __exit exit_nls_cp737(void)
module_init(init_nls_cp737)
module_exit(exit_nls_cp737)
+MODULE_DESCRIPTION("NLS Codepage 737 (Greek)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp775.c b/fs/nls/nls_cp775.c
index 554c863745f2..51ccc908901f 100644
--- a/fs/nls/nls_cp775.c
+++ b/fs/nls/nls_cp775.c
@@ -316,4 +316,5 @@ static void __exit exit_nls_cp775(void)
module_init(init_nls_cp775)
module_exit(exit_nls_cp775)
+MODULE_DESCRIPTION("NLS Codepage 775 (Baltic Rim)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp850.c b/fs/nls/nls_cp850.c
index 56cccd14b40b..5f9b9507a8b6 100644
--- a/fs/nls/nls_cp850.c
+++ b/fs/nls/nls_cp850.c
@@ -312,4 +312,5 @@ static void __exit exit_nls_cp850(void)
module_init(init_nls_cp850)
module_exit(exit_nls_cp850)
+MODULE_DESCRIPTION("NLS Codepage 850 (Europe)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp852.c b/fs/nls/nls_cp852.c
index 7cdc05ac1d40..fc513a5e8358 100644
--- a/fs/nls/nls_cp852.c
+++ b/fs/nls/nls_cp852.c
@@ -334,4 +334,5 @@ static void __exit exit_nls_cp852(void)
module_init(init_nls_cp852)
module_exit(exit_nls_cp852)
+MODULE_DESCRIPTION("NLS Codepage 852 (Central/Eastern Europe)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp855.c b/fs/nls/nls_cp855.c
index 7426eea05663..a43be58adb36 100644
--- a/fs/nls/nls_cp855.c
+++ b/fs/nls/nls_cp855.c
@@ -296,4 +296,5 @@ static void __exit exit_nls_cp855(void)
module_init(init_nls_cp855)
module_exit(exit_nls_cp855)
+MODULE_DESCRIPTION("NLS Codepage 855 (Cyrillic)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp857.c b/fs/nls/nls_cp857.c
index 098309733ebd..772cd4195bad 100644
--- a/fs/nls/nls_cp857.c
+++ b/fs/nls/nls_cp857.c
@@ -298,4 +298,5 @@ static void __exit exit_nls_cp857(void)
module_init(init_nls_cp857)
module_exit(exit_nls_cp857)
+MODULE_DESCRIPTION("NLS Codepage 857 (Turkish)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp860.c b/fs/nls/nls_cp860.c
index 84224478e731..36cf4ca11966 100644
--- a/fs/nls/nls_cp860.c
+++ b/fs/nls/nls_cp860.c
@@ -361,4 +361,5 @@ static void __exit exit_nls_cp860(void)
module_init(init_nls_cp860)
module_exit(exit_nls_cp860)
+MODULE_DESCRIPTION("NLS Codepage 860 (Portuguese)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp861.c b/fs/nls/nls_cp861.c
index dc873e4be092..b7397d079f8f 100644
--- a/fs/nls/nls_cp861.c
+++ b/fs/nls/nls_cp861.c
@@ -384,4 +384,5 @@ static void __exit exit_nls_cp861(void)
module_init(init_nls_cp861)
module_exit(exit_nls_cp861)
+MODULE_DESCRIPTION("NLS Codepage 861 (Icelandic)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp862.c b/fs/nls/nls_cp862.c
index d5263e3c5566..fd3b95d1e95d 100644
--- a/fs/nls/nls_cp862.c
+++ b/fs/nls/nls_cp862.c
@@ -418,4 +418,5 @@ static void __exit exit_nls_cp862(void)
module_init(init_nls_cp862)
module_exit(exit_nls_cp862)
+MODULE_DESCRIPTION("NLS Codepage 862 (Hebrew)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp863.c b/fs/nls/nls_cp863.c
index 051c9832e36a..813ae7944249 100644
--- a/fs/nls/nls_cp863.c
+++ b/fs/nls/nls_cp863.c
@@ -378,4 +378,5 @@ static void __exit exit_nls_cp863(void)
module_init(init_nls_cp863)
module_exit(exit_nls_cp863)
+MODULE_DESCRIPTION("NLS Codepage 863 (Canadian French)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp864.c b/fs/nls/nls_cp864.c
index 97eb1273b2f7..d9eb6d5cd47a 100644
--- a/fs/nls/nls_cp864.c
+++ b/fs/nls/nls_cp864.c
@@ -404,4 +404,5 @@ static void __exit exit_nls_cp864(void)
module_init(init_nls_cp864)
module_exit(exit_nls_cp864)
+MODULE_DESCRIPTION("NLS Codepage 864 (Arabic)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp865.c b/fs/nls/nls_cp865.c
index 111214228525..2678ffd98bb6 100644
--- a/fs/nls/nls_cp865.c
+++ b/fs/nls/nls_cp865.c
@@ -384,4 +384,5 @@ static void __exit exit_nls_cp865(void)
module_init(init_nls_cp865)
module_exit(exit_nls_cp865)
+MODULE_DESCRIPTION("NLS Codepage 865 (Norwegian, Danish)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp866.c b/fs/nls/nls_cp866.c
index ffdcbc3fc38d..7e93d0a3802a 100644
--- a/fs/nls/nls_cp866.c
+++ b/fs/nls/nls_cp866.c
@@ -302,4 +302,5 @@ static void __exit exit_nls_cp866(void)
module_init(init_nls_cp866)
module_exit(exit_nls_cp866)
+MODULE_DESCRIPTION("NLS Codepage 866 (Cyrillic/Russian)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp869.c b/fs/nls/nls_cp869.c
index 3b5a34589354..4491737dd5cb 100644
--- a/fs/nls/nls_cp869.c
+++ b/fs/nls/nls_cp869.c
@@ -312,4 +312,5 @@ static void __exit exit_nls_cp869(void)
module_init(init_nls_cp869)
module_exit(exit_nls_cp869)
+MODULE_DESCRIPTION("NLS Codepage 869 (Greek)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp874.c b/fs/nls/nls_cp874.c
index 8dfaa10710fa..4fcfbf8ca72c 100644
--- a/fs/nls/nls_cp874.c
+++ b/fs/nls/nls_cp874.c
@@ -271,5 +271,6 @@ static void __exit exit_nls_cp874(void)
module_init(init_nls_cp874)
module_exit(exit_nls_cp874)
+MODULE_DESCRIPTION("NLS Thai charset (CP874, TIS-620)");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS_NLS(tis-620);
diff --git a/fs/nls/nls_cp932.c b/fs/nls/nls_cp932.c
index 67b7398e8483..e5e6270fcca6 100644
--- a/fs/nls/nls_cp932.c
+++ b/fs/nls/nls_cp932.c
@@ -7929,5 +7929,6 @@ static void __exit exit_nls_cp932(void)
module_init(init_nls_cp932)
module_exit(exit_nls_cp932)
+MODULE_DESCRIPTION("NLS Japanese charset (Shift-JIS)");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS_NLS(sjis);
diff --git a/fs/nls/nls_cp936.c b/fs/nls/nls_cp936.c
index c96546cfec9f..91d0a15fd7f9 100644
--- a/fs/nls/nls_cp936.c
+++ b/fs/nls/nls_cp936.c
@@ -11107,5 +11107,6 @@ static void __exit exit_nls_cp936(void)
module_init(init_nls_cp936)
module_exit(exit_nls_cp936)
+MODULE_DESCRIPTION("NLS Simplified Chinese charset (CP936, GB2312)");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS_NLS(gb2312);
diff --git a/fs/nls/nls_cp949.c b/fs/nls/nls_cp949.c
index 199171e97aa4..3ae03c76d59c 100644
--- a/fs/nls/nls_cp949.c
+++ b/fs/nls/nls_cp949.c
@@ -13942,5 +13942,6 @@ static void __exit exit_nls_cp949(void)
module_init(init_nls_cp949)
module_exit(exit_nls_cp949)
+MODULE_DESCRIPTION("NLS Korean charset (CP949, EUC-KR)");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS_NLS(euc-kr);
diff --git a/fs/nls/nls_cp950.c b/fs/nls/nls_cp950.c
index 8e1418708209..e968aa80198d 100644
--- a/fs/nls/nls_cp950.c
+++ b/fs/nls/nls_cp950.c
@@ -9478,5 +9478,6 @@ static void __exit exit_nls_cp950(void)
module_init(init_nls_cp950)
module_exit(exit_nls_cp950)
+MODULE_DESCRIPTION("NLS Traditional Chinese charset (Big5)");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS_NLS(big5);
diff --git a/fs/nls/nls_euc-jp.c b/fs/nls/nls_euc-jp.c
index 162b3f160353..0191cc9d955e 100644
--- a/fs/nls/nls_euc-jp.c
+++ b/fs/nls/nls_euc-jp.c
@@ -577,4 +577,5 @@ static void __exit exit_nls_euc_jp(void)
module_init(init_nls_euc_jp)
module_exit(exit_nls_euc_jp)
+MODULE_DESCRIPTION("NLS Japanese charset (EUC-JP)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-1.c b/fs/nls/nls_iso8859-1.c
index 69ac020d43b1..a181be488f7d 100644
--- a/fs/nls/nls_iso8859-1.c
+++ b/fs/nls/nls_iso8859-1.c
@@ -254,4 +254,5 @@ static void __exit exit_nls_iso8859_1(void)
module_init(init_nls_iso8859_1)
module_exit(exit_nls_iso8859_1)
+MODULE_DESCRIPTION("NLS ISO 8859-1 (Latin 1; Western European Languages)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-13.c b/fs/nls/nls_iso8859-13.c
index afb3f8f275f0..8e2be5bfeaf1 100644
--- a/fs/nls/nls_iso8859-13.c
+++ b/fs/nls/nls_iso8859-13.c
@@ -282,4 +282,5 @@ static void __exit exit_nls_iso8859_13(void)
module_init(init_nls_iso8859_13)
module_exit(exit_nls_iso8859_13)
+MODULE_DESCRIPTION("NLS ISO 8859-13 (Latin 7; Baltic)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-14.c b/fs/nls/nls_iso8859-14.c
index 046370f0b6f0..c789eccb8a69 100644
--- a/fs/nls/nls_iso8859-14.c
+++ b/fs/nls/nls_iso8859-14.c
@@ -338,4 +338,5 @@ static void __exit exit_nls_iso8859_14(void)
module_init(init_nls_iso8859_14)
module_exit(exit_nls_iso8859_14)
+MODULE_DESCRIPTION("NLS ISO 8859-14 (Latin 8; Celtic)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-15.c b/fs/nls/nls_iso8859-15.c
index 7e34a841a056..ffec649176fb 100644
--- a/fs/nls/nls_iso8859-15.c
+++ b/fs/nls/nls_iso8859-15.c
@@ -304,4 +304,5 @@ static void __exit exit_nls_iso8859_15(void)
module_init(init_nls_iso8859_15)
module_exit(exit_nls_iso8859_15)
+MODULE_DESCRIPTION("NLS ISO 8859-15 (Latin 9; Western European Languages with Euro)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-2.c b/fs/nls/nls_iso8859-2.c
index 7dd571181741..d352334d0314 100644
--- a/fs/nls/nls_iso8859-2.c
+++ b/fs/nls/nls_iso8859-2.c
@@ -305,4 +305,5 @@ static void __exit exit_nls_iso8859_2(void)
module_init(init_nls_iso8859_2)
module_exit(exit_nls_iso8859_2)
+MODULE_DESCRIPTION("NLS ISO 8859-2 (Latin 2; Slavic/Central European Languages)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-3.c b/fs/nls/nls_iso8859-3.c
index 740b75ec4493..09990e6634d2 100644
--- a/fs/nls/nls_iso8859-3.c
+++ b/fs/nls/nls_iso8859-3.c
@@ -305,4 +305,5 @@ static void __exit exit_nls_iso8859_3(void)
module_init(init_nls_iso8859_3)
module_exit(exit_nls_iso8859_3)
+MODULE_DESCRIPTION("NLS ISO 8859-3 (Latin 3; Esperanto, Galician, Maltese, Turkish)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-4.c b/fs/nls/nls_iso8859-4.c
index 8826021e32f5..92795224912e 100644
--- a/fs/nls/nls_iso8859-4.c
+++ b/fs/nls/nls_iso8859-4.c
@@ -305,4 +305,5 @@ static void __exit exit_nls_iso8859_4(void)
module_init(init_nls_iso8859_4)
module_exit(exit_nls_iso8859_4)
+MODULE_DESCRIPTION("NLS ISO 8859-4 (Latin 4; old Baltic charset)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-5.c b/fs/nls/nls_iso8859-5.c
index 7c04057a1ad8..32309315307a 100644
--- a/fs/nls/nls_iso8859-5.c
+++ b/fs/nls/nls_iso8859-5.c
@@ -269,4 +269,5 @@ static void __exit exit_nls_iso8859_5(void)
module_init(init_nls_iso8859_5)
module_exit(exit_nls_iso8859_5)
+MODULE_DESCRIPTION("NLS ISO 8859-5 (Cyrillic)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-6.c b/fs/nls/nls_iso8859-6.c
index d4a881400d74..c18183469d2a 100644
--- a/fs/nls/nls_iso8859-6.c
+++ b/fs/nls/nls_iso8859-6.c
@@ -260,4 +260,5 @@ static void __exit exit_nls_iso8859_6(void)
module_init(init_nls_iso8859_6)
module_exit(exit_nls_iso8859_6)
+MODULE_DESCRIPTION("NLS ISO 8859-6 (Arabic)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-7.c b/fs/nls/nls_iso8859-7.c
index 37b75d825a75..3652d6832864 100644
--- a/fs/nls/nls_iso8859-7.c
+++ b/fs/nls/nls_iso8859-7.c
@@ -314,4 +314,5 @@ static void __exit exit_nls_iso8859_7(void)
module_init(init_nls_iso8859_7)
module_exit(exit_nls_iso8859_7)
+MODULE_DESCRIPTION("NLS ISO 8859-7 (Modern Greek)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_iso8859-9.c b/fs/nls/nls_iso8859-9.c
index 557b98250d37..11a67834b855 100644
--- a/fs/nls/nls_iso8859-9.c
+++ b/fs/nls/nls_iso8859-9.c
@@ -269,4 +269,5 @@ static void __exit exit_nls_iso8859_9(void)
module_init(init_nls_iso8859_9)
module_exit(exit_nls_iso8859_9)
+MODULE_DESCRIPTION("NLS ISO 8859-9 (Latin 5; Turkish)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_koi8-r.c b/fs/nls/nls_koi8-r.c
index 811f232fccfb..e3dca27a3803 100644
--- a/fs/nls/nls_koi8-r.c
+++ b/fs/nls/nls_koi8-r.c
@@ -320,4 +320,5 @@ static void __exit exit_nls_koi8_r(void)
module_init(init_nls_koi8_r)
module_exit(exit_nls_koi8_r)
+MODULE_DESCRIPTION("NLS KOI8-R (Russian)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_koi8-ru.c b/fs/nls/nls_koi8-ru.c
index a80a741a8676..07afcd9e58c0 100644
--- a/fs/nls/nls_koi8-ru.c
+++ b/fs/nls/nls_koi8-ru.c
@@ -79,4 +79,5 @@ static void __exit exit_nls_koi8_ru(void)
module_init(init_nls_koi8_ru)
module_exit(exit_nls_koi8_ru)
+MODULE_DESCRIPTION("NLS KOI8-RU (Belarusian)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_koi8-u.c b/fs/nls/nls_koi8-u.c
index 7e029e4c188a..f60645758c1a 100644
--- a/fs/nls/nls_koi8-u.c
+++ b/fs/nls/nls_koi8-u.c
@@ -327,4 +327,5 @@ static void __exit exit_nls_koi8_u(void)
module_init(init_nls_koi8_u)
module_exit(exit_nls_koi8_u)
+MODULE_DESCRIPTION("NLS KOI8-U (Ukrainian)");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_ucs2_utils.c b/fs/nls/nls_ucs2_utils.c
index a69781c54dd8..d4564b79d7bf 100644
--- a/fs/nls/nls_ucs2_utils.c
+++ b/fs/nls/nls_ucs2_utils.c
@@ -16,6 +16,7 @@
#include <asm/unaligned.h>
#include "nls_ucs2_utils.h"
+MODULE_DESCRIPTION("NLS UCS-2");
MODULE_LICENSE("GPL");
/*
diff --git a/fs/nls/nls_utf8.c b/fs/nls/nls_utf8.c
index afcfbc4a14db..a0fa0610eaac 100644
--- a/fs/nls/nls_utf8.c
+++ b/fs/nls/nls_utf8.c
@@ -64,4 +64,5 @@ static void __exit exit_nls_utf8(void)
module_init(init_nls_utf8)
module_exit(exit_nls_utf8)
+MODULE_DESCRIPTION("NLS UTF-8");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nsfs.c b/fs/nsfs.c
index 07e22a15ef02..a4a925dce331 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -8,10 +8,12 @@
#include <linux/magic.h>
#include <linux/ktime.h>
#include <linux/seq_file.h>
+#include <linux/pid_namespace.h>
#include <linux/user_namespace.h>
#include <linux/nsfs.h>
#include <linux/uaccess.h>
+#include "mount.h"
#include "internal.h"
static struct vfsmount *nsfs_mnt;
@@ -82,40 +84,47 @@ int ns_get_path(struct path *path, struct task_struct *task,
return ns_get_path_cb(path, ns_get_path_task, &args);
}
-int open_related_ns(struct ns_common *ns,
- struct ns_common *(*get_ns)(struct ns_common *ns))
+/**
+ * open_namespace - open a namespace
+ * @ns: the namespace to open
+ *
+ * This will consume a reference to @ns indendent of success or failure.
+ *
+ * Return: A file descriptor on success or a negative error code on failure.
+ */
+int open_namespace(struct ns_common *ns)
{
- struct path path = {};
- struct ns_common *relative;
+ struct path path __free(path_put) = {};
struct file *f;
int err;
- int fd;
- fd = get_unused_fd_flags(O_CLOEXEC);
+ /* call first to consume reference */
+ err = path_from_stashed(&ns->stashed, nsfs_mnt, ns, &path);
+ if (err < 0)
+ return err;
+
+ CLASS(get_unused_fd, fd)(O_CLOEXEC);
if (fd < 0)
return fd;
- relative = get_ns(ns);
- if (IS_ERR(relative)) {
- put_unused_fd(fd);
- return PTR_ERR(relative);
- }
+ f = dentry_open(&path, O_RDONLY, current_cred());
+ if (IS_ERR(f))
+ return PTR_ERR(f);
- err = path_from_stashed(&relative->stashed, nsfs_mnt, relative, &path);
- if (err < 0) {
- put_unused_fd(fd);
- return err;
- }
+ fd_install(fd, f);
+ return take_fd(fd);
+}
- f = dentry_open(&path, O_RDONLY, current_cred());
- path_put(&path);
- if (IS_ERR(f)) {
- put_unused_fd(fd);
- fd = PTR_ERR(f);
- } else
- fd_install(fd, f);
+int open_related_ns(struct ns_common *ns,
+ struct ns_common *(*get_ns)(struct ns_common *ns))
+{
+ struct ns_common *relative;
+
+ relative = get_ns(ns);
+ if (IS_ERR(relative))
+ return PTR_ERR(relative);
- return fd;
+ return open_namespace(relative);
}
EXPORT_SYMBOL_GPL(open_related_ns);
@@ -123,9 +132,12 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl,
unsigned long arg)
{
struct user_namespace *user_ns;
+ struct pid_namespace *pid_ns;
+ struct task_struct *tsk;
struct ns_common *ns = get_proc_ns(file_inode(filp));
uid_t __user *argp;
uid_t uid;
+ int ret;
switch (ioctl) {
case NS_GET_USERNS:
@@ -143,9 +155,69 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl,
argp = (uid_t __user *) arg;
uid = from_kuid_munged(current_user_ns(), user_ns->owner);
return put_user(uid, argp);
+ case NS_GET_MNTNS_ID: {
+ struct mnt_namespace *mnt_ns;
+ __u64 __user *idp;
+ __u64 id;
+
+ if (ns->ops->type != CLONE_NEWNS)
+ return -EINVAL;
+
+ mnt_ns = container_of(ns, struct mnt_namespace, ns);
+ idp = (__u64 __user *)arg;
+ id = mnt_ns->seq;
+ return put_user(id, idp);
+ }
+ case NS_GET_PID_FROM_PIDNS:
+ fallthrough;
+ case NS_GET_TGID_FROM_PIDNS:
+ fallthrough;
+ case NS_GET_PID_IN_PIDNS:
+ fallthrough;
+ case NS_GET_TGID_IN_PIDNS:
+ if (ns->ops->type != CLONE_NEWPID)
+ return -EINVAL;
+
+ ret = -ESRCH;
+ pid_ns = container_of(ns, struct pid_namespace, ns);
+
+ rcu_read_lock();
+
+ if (ioctl == NS_GET_PID_IN_PIDNS ||
+ ioctl == NS_GET_TGID_IN_PIDNS)
+ tsk = find_task_by_vpid(arg);
+ else
+ tsk = find_task_by_pid_ns(arg, pid_ns);
+ if (!tsk)
+ break;
+
+ switch (ioctl) {
+ case NS_GET_PID_FROM_PIDNS:
+ ret = task_pid_vnr(tsk);
+ break;
+ case NS_GET_TGID_FROM_PIDNS:
+ ret = task_tgid_vnr(tsk);
+ break;
+ case NS_GET_PID_IN_PIDNS:
+ ret = task_pid_nr_ns(tsk, pid_ns);
+ break;
+ case NS_GET_TGID_IN_PIDNS:
+ ret = task_tgid_nr_ns(tsk, pid_ns);
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+ rcu_read_unlock();
+
+ if (!ret)
+ ret = -ESRCH;
+ break;
default:
- return -ENOTTY;
+ ret = -ENOTTY;
}
+
+ return ret;
}
int ns_get_name(char *buf, size_t size, struct task_struct *task,
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index 27fbde2701b6..c5b688c5f984 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -259,8 +259,8 @@ enum Opt {
// clang-format off
static const struct fs_parameter_spec ntfs_fs_parameters[] = {
- fsparam_u32("uid", Opt_uid),
- fsparam_u32("gid", Opt_gid),
+ fsparam_uid("uid", Opt_uid),
+ fsparam_gid("gid", Opt_gid),
fsparam_u32oct("umask", Opt_umask),
fsparam_u32oct("dmask", Opt_dmask),
fsparam_u32oct("fmask", Opt_fmask),
@@ -319,14 +319,10 @@ static int ntfs_fs_parse_param(struct fs_context *fc,
switch (opt) {
case Opt_uid:
- opts->fs_uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(opts->fs_uid))
- return invalf(fc, "ntfs3: Invalid value for uid.");
+ opts->fs_uid = result.uid;
break;
case Opt_gid:
- opts->fs_gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(opts->fs_gid))
- return invalf(fc, "ntfs3: Invalid value for gid.");
+ opts->fs_gid = result.gid;
break;
case Opt_umask:
if (result.uint_32 & ~07777)
diff --git a/fs/open.c b/fs/open.c
index 50e45bc7c4d8..22adbef7ecc2 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -247,6 +247,7 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
{
struct inode *inode = file_inode(file);
long ret;
+ loff_t sum;
if (offset < 0 || len <= 0)
return -EINVAL;
@@ -319,8 +320,11 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
return -ENODEV;
- /* Check for wrap through zero too */
- if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
+ /* Check for wraparound */
+ if (check_add_overflow(offset, len, &sum))
+ return -EFBIG;
+
+ if (sum > inode->i_sb->s_maxbytes)
return -EFBIG;
if (!file->f_op->fallocate)
@@ -982,12 +986,11 @@ static int do_dentry_open(struct file *f,
*/
if (f->f_mode & FMODE_WRITE) {
/*
- * Paired with smp_mb() in collapse_file() to ensure nr_thps
- * is up to date and the update to i_writecount by
- * get_write_access() is visible. Ensures subsequent insertion
- * of THPs into the page cache will fail.
+ * Depends on full fence from get_write_access() to synchronize
+ * against collapse_file() regarding i_writecount and nr_thps
+ * updates. Ensures subsequent insertion of THPs into the page
+ * cache will fail.
*/
- smp_mb();
if (filemap_nr_thps(inode->i_mapping)) {
struct address_space *mapping = inode->i_mapping;
@@ -1004,11 +1007,6 @@ static int do_dentry_open(struct file *f,
}
}
- /*
- * Once we return a file with FMODE_OPENED, __fput() will call
- * fsnotify_close(), so we need fsnotify_open() here for symmetry.
- */
- fsnotify_open(f);
return 0;
cleanup_all:
@@ -1085,8 +1083,19 @@ EXPORT_SYMBOL(file_path);
*/
int vfs_open(const struct path *path, struct file *file)
{
+ int ret;
+
file->f_path = *path;
- return do_dentry_open(file, NULL);
+ ret = do_dentry_open(file, NULL);
+ if (!ret) {
+ /*
+ * Once we return a file with FMODE_OPENED, __fput() will call
+ * fsnotify_close(), so we need fsnotify_open() here for
+ * symmetry.
+ */
+ fsnotify_open(file);
+ }
+ return ret;
}
struct file *dentry_open(const struct path *path, int flags,
@@ -1177,8 +1186,10 @@ struct file *kernel_file_open(const struct path *path, int flags,
error = do_dentry_open(f, NULL);
if (error) {
fput(f);
- f = ERR_PTR(error);
+ return ERR_PTR(error);
}
+
+ fsnotify_open(f);
return f;
}
EXPORT_SYMBOL_GPL(kernel_file_open);
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index a7b527ea50d3..26ecda0e4d19 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -471,4 +471,5 @@ static void __exit exit_openprom_fs(void)
module_init(init_openprom_fs)
module_exit(exit_openprom_fs)
+MODULE_DESCRIPTION("OpenPROM filesystem support");
MODULE_LICENSE("GPL");
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 085912268442..fdb9b65db1de 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -56,7 +56,6 @@ static int orangefs_writepage_locked(struct page *page,
ret = wait_for_direct_io(ORANGEFS_IO_WRITE, inode, &off, &iter, wlen,
len, wr, NULL, NULL);
if (ret < 0) {
- SetPageError(page);
mapping_set_error(page->mapping, ret);
} else {
ret = 0;
@@ -119,7 +118,6 @@ static int orangefs_writepages_work(struct orangefs_writepages *ow,
0, &wr, NULL, NULL);
if (ret < 0) {
for (i = 0; i < ow->npages; i++) {
- SetPageError(ow->pages[i]);
mapping_set_error(ow->pages[i]->mapping, ret);
if (PagePrivate(ow->pages[i])) {
wrp = (struct orangefs_write_range *)
@@ -303,15 +301,10 @@ static int orangefs_read_folio(struct file *file, struct folio *folio)
iov_iter_zero(~0U, &iter);
/* takes care of potential aliasing */
flush_dcache_folio(folio);
- if (ret < 0) {
- folio_set_error(folio);
- } else {
- folio_mark_uptodate(folio);
+ if (ret > 0)
ret = 0;
- }
- /* unlock the folio after the ->read_folio() routine completes */
- folio_unlock(folio);
- return ret;
+ folio_end_read(folio, ret == 0);
+ return ret;
}
static int orangefs_write_begin(struct file *file,
diff --git a/fs/orangefs/orangefs-bufmap.c b/fs/orangefs/orangefs-bufmap.c
index b501dc07f922..edcca4beb765 100644
--- a/fs/orangefs/orangefs-bufmap.c
+++ b/fs/orangefs/orangefs-bufmap.c
@@ -274,10 +274,8 @@ orangefs_bufmap_map(struct orangefs_bufmap *bufmap,
gossip_err("orangefs error: asked for %d pages, only got %d.\n",
bufmap->page_count, ret);
- for (i = 0; i < ret; i++) {
- SetPageError(bufmap->page_array[i]);
+ for (i = 0; i < ret; i++)
unpin_user_page(bufmap->page_array[i]);
- }
return -ENOMEM;
}
diff --git a/fs/pidfs.c b/fs/pidfs.c
index dbb9d854d1c5..c9cb14181def 100644
--- a/fs/pidfs.c
+++ b/fs/pidfs.c
@@ -11,10 +11,16 @@
#include <linux/proc_fs.h>
#include <linux/proc_ns.h>
#include <linux/pseudo_fs.h>
+#include <linux/ptrace.h>
#include <linux/seq_file.h>
#include <uapi/linux/pidfd.h>
+#include <linux/ipc_namespace.h>
+#include <linux/time_namespace.h>
+#include <linux/utsname.h>
+#include <net/net_namespace.h>
#include "internal.h"
+#include "mount.h"
#ifdef CONFIG_PROC_FS
/**
@@ -108,11 +114,95 @@ static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts)
return poll_flags;
}
+static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct task_struct *task __free(put_task) = NULL;
+ struct nsproxy *nsp __free(put_nsproxy) = NULL;
+ struct pid *pid = pidfd_pid(file);
+ struct ns_common *ns_common;
+
+ if (arg)
+ return -EINVAL;
+
+ task = get_pid_task(pid, PIDTYPE_PID);
+ if (!task)
+ return -ESRCH;
+
+ scoped_guard(task_lock, task) {
+ nsp = task->nsproxy;
+ if (nsp)
+ get_nsproxy(nsp);
+ }
+ if (!nsp)
+ return -ESRCH; /* just pretend it didn't exist */
+
+ /*
+ * We're trying to open a file descriptor to the namespace so perform a
+ * filesystem cred ptrace check. Also, we mirror nsfs behavior.
+ */
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
+ return -EACCES;
+
+ switch (cmd) {
+ /* Namespaces that hang of nsproxy. */
+ case PIDFD_GET_CGROUP_NAMESPACE:
+ get_cgroup_ns(nsp->cgroup_ns);
+ ns_common = to_ns_common(nsp->cgroup_ns);
+ break;
+ case PIDFD_GET_IPC_NAMESPACE:
+ get_ipc_ns(nsp->ipc_ns);
+ ns_common = to_ns_common(nsp->ipc_ns);
+ break;
+ case PIDFD_GET_MNT_NAMESPACE:
+ get_mnt_ns(nsp->mnt_ns);
+ ns_common = to_ns_common(nsp->mnt_ns);
+ break;
+ case PIDFD_GET_NET_NAMESPACE:
+ ns_common = to_ns_common(nsp->net_ns);
+ get_net_ns(ns_common);
+ break;
+ case PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE:
+ get_pid_ns(nsp->pid_ns_for_children);
+ ns_common = to_ns_common(nsp->pid_ns_for_children);
+ break;
+ case PIDFD_GET_TIME_NAMESPACE:
+ get_time_ns(nsp->time_ns);
+ ns_common = to_ns_common(nsp->time_ns);
+ break;
+ case PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE:
+ get_time_ns(nsp->time_ns_for_children);
+ ns_common = to_ns_common(nsp->time_ns_for_children);
+ break;
+ case PIDFD_GET_UTS_NAMESPACE:
+ get_uts_ns(nsp->uts_ns);
+ ns_common = to_ns_common(nsp->uts_ns);
+ break;
+ /* Namespaces that don't hang of nsproxy. */
+ case PIDFD_GET_USER_NAMESPACE:
+ rcu_read_lock();
+ ns_common = to_ns_common(get_user_ns(task_cred_xxx(task, user_ns)));
+ rcu_read_unlock();
+ break;
+ case PIDFD_GET_PID_NAMESPACE:
+ rcu_read_lock();
+ ns_common = to_ns_common(get_pid_ns(task_active_pid_ns(task)));
+ rcu_read_unlock();
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ /* open_namespace() unconditionally consumes the reference */
+ return open_namespace(ns_common);
+}
+
static const struct file_operations pidfs_file_operations = {
.poll = pidfd_poll,
#ifdef CONFIG_PROC_FS
.show_fdinfo = pidfd_show_fdinfo,
#endif
+ .unlocked_ioctl = pidfd_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
};
struct pid *pidfd_pid(const struct file *file)
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 775ce0bcf08c..c02f1e63f82d 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -202,8 +202,8 @@ int proc_alloc_inum(unsigned int *inum)
{
int i;
- i = ida_simple_get(&proc_inum_ida, 0, UINT_MAX - PROC_DYNAMIC_FIRST + 1,
- GFP_KERNEL);
+ i = ida_alloc_max(&proc_inum_ida, UINT_MAX - PROC_DYNAMIC_FIRST,
+ GFP_KERNEL);
if (i < 0)
return i;
@@ -213,7 +213,7 @@ int proc_alloc_inum(unsigned int *inum)
void proc_free_inum(unsigned int inum)
{
- ida_simple_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
+ ida_free(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
}
static int proc_misc_d_revalidate(struct dentry *dentry, unsigned int flags)
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
index 0a808951b7d3..e133b507ddf3 100644
--- a/fs/proc_namespace.c
+++ b/fs/proc_namespace.c
@@ -61,7 +61,7 @@ static int show_sb_opts(struct seq_file *m, struct super_block *sb)
return security_sb_show_options(m, sb);
}
-static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt)
+static void show_vfsmnt_opts(struct seq_file *m, struct vfsmount *mnt)
{
static const struct proc_fs_opts mnt_opts[] = {
{ MNT_NOSUID, ",nosuid" },
@@ -124,7 +124,7 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
err = show_sb_opts(m, sb);
if (err)
goto out;
- show_mnt_opts(m, mnt);
+ show_vfsmnt_opts(m, mnt);
if (sb->s_op->show_options)
err = sb->s_op->show_options(m, mnt_path.dentry);
seq_puts(m, " 0 0\n");
@@ -153,7 +153,7 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
goto out;
seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw");
- show_mnt_opts(m, mnt);
+ show_vfsmnt_opts(m, mnt);
/* Tagged fields ("foo:X" or "bar") */
if (IS_MNT_SHARED(r))
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index d79841e94428..e399e2dd3a12 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -430,5 +430,6 @@ static void __exit exit_qnx4_fs(void)
module_init(init_qnx4_fs)
module_exit(exit_qnx4_fs)
+MODULE_DESCRIPTION("QNX4 file system");
MODULE_LICENSE("GPL");
diff --git a/fs/qnx6/inode.c b/fs/qnx6/inode.c
index d62fbef838b6..4f1735b882b1 100644
--- a/fs/qnx6/inode.c
+++ b/fs/qnx6/inode.c
@@ -694,4 +694,5 @@ static void __exit exit_qnx6_fs(void)
module_init(init_qnx6_fs)
module_exit(exit_qnx6_fs)
+MODULE_DESCRIPTION("QNX6 file system");
MODULE_LICENSE("GPL");
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 627eb2f72ef3..a2b256dac36e 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2246,9 +2246,7 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
int cnt;
struct quota_info *dqopt = sb_dqopt(sb);
- /* s_umount should be held in exclusive mode */
- if (WARN_ON_ONCE(down_read_trylock(&sb->s_umount)))
- up_read(&sb->s_umount);
+ rwsem_assert_held_write(&sb->s_umount);
/* Cannot turn off usage accounting without turning off limits, or
* suspend quotas and simultaneously turn quotas off. */
@@ -2510,9 +2508,7 @@ int dquot_resume(struct super_block *sb, int type)
int ret = 0, cnt;
unsigned int flags;
- /* s_umount should be held in exclusive mode */
- if (WARN_ON_ONCE(down_read_trylock(&sb->s_umount)))
- up_read(&sb->s_umount);
+ rwsem_assert_held_write(&sb->s_umount);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (type != -1 && cnt != type)
diff --git a/fs/read_write.c b/fs/read_write.c
index ef6339391351..90e283b31ca1 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -730,7 +730,7 @@ static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
ssize_t ret;
init_sync_kiocb(&kiocb, filp);
- ret = kiocb_set_rw_flags(&kiocb, flags);
+ ret = kiocb_set_rw_flags(&kiocb, flags, type);
if (ret)
return ret;
kiocb.ki_pos = (ppos ? *ppos : 0);
@@ -1736,3 +1736,19 @@ int generic_file_rw_checks(struct file *file_in, struct file *file_out)
return 0;
}
+
+bool generic_atomic_write_valid(struct iov_iter *iter, loff_t pos)
+{
+ size_t len = iov_iter_count(iter);
+
+ if (!iter_is_ubuf(iter))
+ return false;
+
+ if (!is_power_of_2(len))
+ return false;
+
+ if (!IS_ALIGNED(pos, len))
+ return false;
+
+ return true;
+}
diff --git a/fs/readdir.c b/fs/readdir.c
index 278bc0254732..d6c82421902a 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -22,8 +22,6 @@
#include <linux/compat.h>
#include <linux/uaccess.h>
-#include <asm/unaligned.h>
-
/*
* Some filesystems were never converted to '->iterate_shared()'
* and their directory iterators want the inode lock held for
@@ -72,7 +70,7 @@ int wrap_directory_iterator(struct file *file,
EXPORT_SYMBOL(wrap_directory_iterator);
/*
- * Note the "unsafe_put_user() semantics: we goto a
+ * Note the "unsafe_put_user()" semantics: we goto a
* label for errors.
*/
#define unsafe_copy_dirent_name(_dst, _src, _len, label) do { \
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index c1daedc50f4c..9b43a81a6488 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2699,7 +2699,6 @@ fail:
}
bh = bh->b_this_page;
} while (bh != head);
- folio_set_error(folio);
BUG_ON(folio_test_writeback(folio));
folio_start_writeback(folio);
folio_unlock(folio);
diff --git a/fs/romfs/super.c b/fs/romfs/super.c
index 2cbb92462074..68758b6fed94 100644
--- a/fs/romfs/super.c
+++ b/fs/romfs/super.c
@@ -101,19 +101,15 @@ static struct inode *romfs_iget(struct super_block *sb, unsigned long pos);
*/
static int romfs_read_folio(struct file *file, struct folio *folio)
{
- struct page *page = &folio->page;
- struct inode *inode = page->mapping->host;
+ struct inode *inode = folio->mapping->host;
loff_t offset, size;
unsigned long fillsize, pos;
void *buf;
int ret;
- buf = kmap(page);
- if (!buf)
- return -ENOMEM;
+ buf = kmap_local_folio(folio, 0);
- /* 32 bit warning -- but not for us :) */
- offset = page_offset(page);
+ offset = folio_pos(folio);
size = i_size_read(inode);
fillsize = 0;
ret = 0;
@@ -125,20 +121,14 @@ static int romfs_read_folio(struct file *file, struct folio *folio)
ret = romfs_dev_read(inode->i_sb, pos, buf, fillsize);
if (ret < 0) {
- SetPageError(page);
fillsize = 0;
ret = -EIO;
}
}
- if (fillsize < PAGE_SIZE)
- memset(buf + fillsize, 0, PAGE_SIZE - fillsize);
- if (ret == 0)
- SetPageUptodate(page);
-
- flush_dcache_page(page);
- kunmap(page);
- unlock_page(page);
+ buf = folio_zero_tail(folio, fillsize, buf);
+ kunmap_local(buf);
+ folio_end_read(folio, ret == 0);
return ret;
}
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 557b68e99d0a..a865941724c0 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -1918,8 +1918,8 @@ require use of the stronger protocol */
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
#define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */
-#define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_NTLMSSP)
-#define CIFSSEC_MAX (CIFSSEC_MUST_NTLMV2)
+#define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_NTLMSSP | CIFSSEC_MAY_SEAL)
+#define CIFSSEC_MAX (CIFSSEC_MAY_SIGN | CIFSSEC_MUST_KRB5 | CIFSSEC_MAY_SEAL)
#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)
/*
*****************************************************************
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index f1f2573bb18d..1374635e89fa 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -246,35 +246,6 @@ static int cifs_init_request(struct netfs_io_request *rreq, struct file *file)
}
/*
- * Expand the size of a readahead to the size of the rsize, if at least as
- * large as a page, allowing for the possibility that rsize is not pow-2
- * aligned.
- */
-static void cifs_expand_readahead(struct netfs_io_request *rreq)
-{
- unsigned int rsize = rreq->rsize;
- loff_t misalignment, i_size = i_size_read(rreq->inode);
-
- if (rsize < PAGE_SIZE)
- return;
-
- if (rsize < INT_MAX)
- rsize = roundup_pow_of_two(rsize);
- else
- rsize = ((unsigned int)INT_MAX + 1) / 2;
-
- misalignment = rreq->start & (rsize - 1);
- if (misalignment) {
- rreq->start -= misalignment;
- rreq->len += misalignment;
- }
-
- rreq->len = round_up(rreq->len, rsize);
- if (rreq->start < i_size && rreq->len > i_size - rreq->start)
- rreq->len = i_size - rreq->start;
-}
-
-/*
* Completion of a request operation.
*/
static void cifs_rreq_done(struct netfs_io_request *rreq)
@@ -329,7 +300,6 @@ const struct netfs_request_ops cifs_req_ops = {
.init_request = cifs_init_request,
.free_request = cifs_free_request,
.free_subrequest = cifs_free_subrequest,
- .expand_readahead = cifs_expand_readahead,
.clamp_length = cifs_clamp_length,
.issue_read = cifs_req_issue_read,
.done = cifs_rreq_done,
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index 3bbac925d076..bc926ab2555b 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -128,12 +128,14 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
fsparam_flag("compress", Opt_compress),
fsparam_flag("witness", Opt_witness),
+ /* Mount options which take uid or gid */
+ fsparam_uid("backupuid", Opt_backupuid),
+ fsparam_gid("backupgid", Opt_backupgid),
+ fsparam_uid("uid", Opt_uid),
+ fsparam_uid("cruid", Opt_cruid),
+ fsparam_gid("gid", Opt_gid),
+
/* Mount options which take numeric value */
- fsparam_u32("backupuid", Opt_backupuid),
- fsparam_u32("backupgid", Opt_backupgid),
- fsparam_u32("uid", Opt_uid),
- fsparam_u32("cruid", Opt_cruid),
- fsparam_u32("gid", Opt_gid),
fsparam_u32("file_mode", Opt_file_mode),
fsparam_u32("dirmode", Opt_dirmode),
fsparam_u32("dir_mode", Opt_dirmode),
@@ -951,8 +953,6 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
int i, opt;
bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
bool skip_parsing = false;
- kuid_t uid;
- kgid_t gid;
cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
@@ -1083,38 +1083,23 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
}
break;
case Opt_uid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- goto cifs_parse_mount_err;
- ctx->linux_uid = uid;
+ ctx->linux_uid = result.uid;
ctx->uid_specified = true;
break;
case Opt_cruid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- goto cifs_parse_mount_err;
- ctx->cred_uid = uid;
+ ctx->cred_uid = result.uid;
ctx->cruid_specified = true;
break;
case Opt_backupuid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- goto cifs_parse_mount_err;
- ctx->backupuid = uid;
+ ctx->backupuid = result.uid;
ctx->backupuid_specified = true;
break;
case Opt_backupgid:
- gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(gid))
- goto cifs_parse_mount_err;
- ctx->backupgid = gid;
+ ctx->backupgid = result.gid;
ctx->backupgid_specified = true;
break;
case Opt_gid:
- gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(gid))
- goto cifs_parse_mount_err;
- ctx->linux_gid = gid;
+ ctx->linux_gid = result.gid;
ctx->gid_specified = true;
break;
case Opt_port:
diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h
index 8d10be1fe18a..c3ee42188d25 100644
--- a/fs/smb/common/smb2pdu.h
+++ b/fs/smb/common/smb2pdu.h
@@ -917,6 +917,40 @@ struct smb2_query_directory_rsp {
__u8 Buffer[];
} __packed;
+/* DeviceType Flags */
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+
+/* Device Characteristics */
+#define FILE_REMOVABLE_MEDIA 0x00000001
+#define FILE_READ_ONLY_DEVICE 0x00000002
+#define FILE_FLOPPY_DISKETTE 0x00000004
+#define FILE_WRITE_ONCE_MEDIA 0x00000008
+#define FILE_REMOTE_DEVICE 0x00000010
+#define FILE_DEVICE_IS_MOUNTED 0x00000020
+#define FILE_VIRTUAL_VOLUME 0x00000040
+#define FILE_DEVICE_SECURE_OPEN 0x00000100
+#define FILE_CHARACTERISTIC_TS_DEVICE 0x00001000
+#define FILE_CHARACTERISTIC_WEBDAV_DEVICE 0x00002000
+#define FILE_PORTABLE_DEVICE 0x00004000
+#define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000
+
/*
* Maximum number of iovs we need for a set-info request.
* The largest one is rename/hardlink
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index e7e07891781b..840c71c66b30 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -2051,15 +2051,22 @@ out_err1:
* @access: file access flags
* @disposition: file disposition flags
* @may_flags: set with MAY_ flags
+ * @is_dir: is creating open flags for directory
*
* Return: file open flags
*/
static int smb2_create_open_flags(bool file_present, __le32 access,
__le32 disposition,
- int *may_flags)
+ int *may_flags,
+ bool is_dir)
{
int oflags = O_NONBLOCK | O_LARGEFILE;
+ if (is_dir) {
+ access &= ~FILE_WRITE_DESIRE_ACCESS_LE;
+ ksmbd_debug(SMB, "Discard write access to a directory\n");
+ }
+
if (access & FILE_READ_DESIRED_ACCESS_LE &&
access & FILE_WRITE_DESIRE_ACCESS_LE) {
oflags |= O_RDWR;
@@ -3167,7 +3174,9 @@ int smb2_open(struct ksmbd_work *work)
open_flags = smb2_create_open_flags(file_present, daccess,
req->CreateDisposition,
- &may_flags);
+ &may_flags,
+ req->CreateOptions & FILE_DIRECTORY_FILE_LE ||
+ (file_present && S_ISDIR(d_inode(path.dentry)->i_mode)));
if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
if (open_flags & (O_CREAT | O_TRUNC)) {
@@ -5314,8 +5323,13 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info = (struct filesystem_device_info *)rsp->Buffer;
- info->DeviceType = cpu_to_le32(stfs.f_type);
- info->DeviceCharacteristics = cpu_to_le32(0x00000020);
+ info->DeviceType = cpu_to_le32(FILE_DEVICE_DISK);
+ info->DeviceCharacteristics =
+ cpu_to_le32(FILE_DEVICE_IS_MOUNTED);
+ if (!test_tree_conn_flag(work->tcon,
+ KSMBD_TREE_CONN_FLAG_WRITABLE))
+ info->DeviceCharacteristics |=
+ cpu_to_le32(FILE_READ_ONLY_DEVICE);
rsp->OutputBufferLength = cpu_to_le32(8);
break;
}
diff --git a/fs/stat.c b/fs/stat.c
index 70bd3e888cfa..89ce1be56310 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -90,6 +90,37 @@ void generic_fill_statx_attr(struct inode *inode, struct kstat *stat)
EXPORT_SYMBOL(generic_fill_statx_attr);
/**
+ * generic_fill_statx_atomic_writes - Fill in atomic writes statx attributes
+ * @stat: Where to fill in the attribute flags
+ * @unit_min: Minimum supported atomic write length in bytes
+ * @unit_max: Maximum supported atomic write length in bytes
+ *
+ * Fill in the STATX{_ATTR}_WRITE_ATOMIC flags in the kstat structure from
+ * atomic write unit_min and unit_max values.
+ */
+void generic_fill_statx_atomic_writes(struct kstat *stat,
+ unsigned int unit_min,
+ unsigned int unit_max)
+{
+ /* Confirm that the request type is known */
+ stat->result_mask |= STATX_WRITE_ATOMIC;
+
+ /* Confirm that the file attribute type is known */
+ stat->attributes_mask |= STATX_ATTR_WRITE_ATOMIC;
+
+ if (unit_min) {
+ stat->atomic_write_unit_min = unit_min;
+ stat->atomic_write_unit_max = unit_max;
+ /* Initially only allow 1x segment */
+ stat->atomic_write_segments_max = 1;
+
+ /* Confirm atomic writes are actually supported */
+ stat->attributes |= STATX_ATTR_WRITE_ATOMIC;
+ }
+}
+EXPORT_SYMBOL_GPL(generic_fill_statx_atomic_writes);
+
+/**
* vfs_getattr_nosec - getattr without security checks
* @path: file to get attributes from
* @stat: structure to return attributes in
@@ -214,6 +245,43 @@ int getname_statx_lookup_flags(int flags)
return lookup_flags;
}
+static int vfs_statx_path(struct path *path, int flags, struct kstat *stat,
+ u32 request_mask)
+{
+ int error = vfs_getattr(path, stat, request_mask, flags);
+
+ if (request_mask & STATX_MNT_ID_UNIQUE) {
+ stat->mnt_id = real_mount(path->mnt)->mnt_id_unique;
+ stat->result_mask |= STATX_MNT_ID_UNIQUE;
+ } else {
+ stat->mnt_id = real_mount(path->mnt)->mnt_id;
+ stat->result_mask |= STATX_MNT_ID;
+ }
+
+ if (path_mounted(path))
+ stat->attributes |= STATX_ATTR_MOUNT_ROOT;
+ stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
+
+ /*
+ * If this is a block device inode, override the filesystem
+ * attributes with the block device specific parameters that need to be
+ * obtained from the bdev backing inode.
+ */
+ if (S_ISBLK(stat->mode))
+ bdev_statx(path, stat, request_mask);
+
+ return error;
+}
+
+static int vfs_statx_fd(int fd, int flags, struct kstat *stat,
+ u32 request_mask)
+{
+ CLASS(fd_raw, f)(fd);
+ if (!f.file)
+ return -EBADF;
+ return vfs_statx_path(&f.file->f_path, flags, stat, request_mask);
+}
+
/**
* vfs_statx - Get basic and extra attributes by filename
* @dfd: A file descriptor representing the base dir for a relative filename
@@ -243,36 +311,13 @@ static int vfs_statx(int dfd, struct filename *filename, int flags,
retry:
error = filename_lookup(dfd, filename, lookup_flags, &path, NULL);
if (error)
- goto out;
-
- error = vfs_getattr(&path, stat, request_mask, flags);
-
- if (request_mask & STATX_MNT_ID_UNIQUE) {
- stat->mnt_id = real_mount(path.mnt)->mnt_id_unique;
- stat->result_mask |= STATX_MNT_ID_UNIQUE;
- } else {
- stat->mnt_id = real_mount(path.mnt)->mnt_id;
- stat->result_mask |= STATX_MNT_ID;
- }
-
- if (path.mnt->mnt_root == path.dentry)
- stat->attributes |= STATX_ATTR_MOUNT_ROOT;
- stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
-
- /* Handle STATX_DIOALIGN for block devices. */
- if (request_mask & STATX_DIOALIGN) {
- struct inode *inode = d_backing_inode(path.dentry);
-
- if (S_ISBLK(inode->i_mode))
- bdev_statx_dioalign(inode, stat);
- }
-
+ return error;
+ error = vfs_statx_path(&path, flags, stat, request_mask);
path_put(&path);
if (retry_estale(error, lookup_flags)) {
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
-out:
return error;
}
@@ -289,18 +334,10 @@ int vfs_fstatat(int dfd, const char __user *filename,
* If AT_EMPTY_PATH is set, we expect the common case to be that
* empty path, and avoid doing all the extra pathname work.
*/
- if (dfd >= 0 && flags == AT_EMPTY_PATH) {
- char c;
-
- ret = get_user(c, filename);
- if (unlikely(ret))
- return ret;
+ if (flags == AT_EMPTY_PATH && vfs_empty_path(dfd, filename))
+ return vfs_fstat(dfd, stat);
- if (likely(!c))
- return vfs_fstat(dfd, stat);
- }
-
- name = getname_flags(filename, getname_statx_lookup_flags(statx_flags), NULL);
+ name = getname_flags(filename, getname_statx_lookup_flags(statx_flags));
ret = vfs_statx(dfd, name, statx_flags, stat, STATX_BASIC_STATS);
putname(name);
@@ -488,34 +525,39 @@ static int do_readlinkat(int dfd, const char __user *pathname,
char __user *buf, int bufsiz)
{
struct path path;
+ struct filename *name;
int error;
- int empty = 0;
unsigned int lookup_flags = LOOKUP_EMPTY;
if (bufsiz <= 0)
return -EINVAL;
retry:
- error = user_path_at_empty(dfd, pathname, lookup_flags, &path, &empty);
- if (!error) {
- struct inode *inode = d_backing_inode(path.dentry);
-
- error = empty ? -ENOENT : -EINVAL;
- /*
- * AFS mountpoints allow readlink(2) but are not symlinks
- */
- if (d_is_symlink(path.dentry) || inode->i_op->readlink) {
- error = security_inode_readlink(path.dentry);
- if (!error) {
- touch_atime(&path);
- error = vfs_readlink(path.dentry, buf, bufsiz);
- }
- }
- path_put(&path);
- if (retry_estale(error, lookup_flags)) {
- lookup_flags |= LOOKUP_REVAL;
- goto retry;
+ name = getname_flags(pathname, lookup_flags);
+ error = filename_lookup(dfd, name, lookup_flags, &path, NULL);
+ if (unlikely(error)) {
+ putname(name);
+ return error;
+ }
+
+ /*
+ * AFS mountpoints allow readlink(2) but are not symlinks
+ */
+ if (d_is_symlink(path.dentry) ||
+ d_backing_inode(path.dentry)->i_op->readlink) {
+ error = security_inode_readlink(path.dentry);
+ if (!error) {
+ touch_atime(&path);
+ error = vfs_readlink(path.dentry, buf, bufsiz);
}
+ } else {
+ error = (name->name[0] == '\0') ? -ENOENT : -EINVAL;
+ }
+ path_put(&path);
+ putname(name);
+ if (retry_estale(error, lookup_flags)) {
+ lookup_flags |= LOOKUP_REVAL;
+ goto retry;
}
return error;
}
@@ -659,6 +701,9 @@ cp_statx(const struct kstat *stat, struct statx __user *buffer)
tmp.stx_dio_mem_align = stat->dio_mem_align;
tmp.stx_dio_offset_align = stat->dio_offset_align;
tmp.stx_subvol = stat->subvol;
+ tmp.stx_atomic_write_unit_min = stat->atomic_write_unit_min;
+ tmp.stx_atomic_write_unit_max = stat->atomic_write_unit_max;
+ tmp.stx_atomic_write_segments_max = stat->atomic_write_segments_max;
return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0;
}
@@ -674,7 +719,8 @@ int do_statx(int dfd, struct filename *filename, unsigned int flags,
if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
return -EINVAL;
- /* STATX_CHANGE_COOKIE is kernel-only for now. Ignore requests
+ /*
+ * STATX_CHANGE_COOKIE is kernel-only for now. Ignore requests
* from userland.
*/
mask &= ~STATX_CHANGE_COOKIE;
@@ -686,16 +732,41 @@ int do_statx(int dfd, struct filename *filename, unsigned int flags,
return cp_statx(&stat, buffer);
}
+int do_statx_fd(int fd, unsigned int flags, unsigned int mask,
+ struct statx __user *buffer)
+{
+ struct kstat stat;
+ int error;
+
+ if (mask & STATX__RESERVED)
+ return -EINVAL;
+ if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
+ return -EINVAL;
+
+ /*
+ * STATX_CHANGE_COOKIE is kernel-only for now. Ignore requests
+ * from userland.
+ */
+ mask &= ~STATX_CHANGE_COOKIE;
+
+ error = vfs_statx_fd(fd, flags, &stat, mask);
+ if (error)
+ return error;
+
+ return cp_statx(&stat, buffer);
+}
+
/**
* sys_statx - System call to get enhanced stats
* @dfd: Base directory to pathwalk from *or* fd to stat.
- * @filename: File to stat or "" with AT_EMPTY_PATH
+ * @filename: File to stat or either NULL or "" with AT_EMPTY_PATH
* @flags: AT_* flags to control pathwalk.
* @mask: Parts of statx struct actually required.
* @buffer: Result buffer.
*
* Note that fstat() can be emulated by setting dfd to the fd of interest,
- * supplying "" as the filename and setting AT_EMPTY_PATH in the flags.
+ * supplying "" (or preferably NULL) as the filename and setting AT_EMPTY_PATH
+ * in the flags.
*/
SYSCALL_DEFINE5(statx,
int, dfd, const char __user *, filename, unsigned, flags,
@@ -703,9 +774,24 @@ SYSCALL_DEFINE5(statx,
struct statx __user *, buffer)
{
int ret;
+ unsigned lflags;
struct filename *name;
- name = getname_flags(filename, getname_statx_lookup_flags(flags), NULL);
+ /*
+ * Short-circuit handling of NULL and "" paths.
+ *
+ * For a NULL path we require and accept only the AT_EMPTY_PATH flag
+ * (possibly |'d with AT_STATX flags).
+ *
+ * However, glibc on 32-bit architectures implements fstatat as statx
+ * with the "" pathname and AT_NO_AUTOMOUNT | AT_EMPTY_PATH flags.
+ * Supporting this results in the uglification below.
+ */
+ lflags = flags & ~(AT_NO_AUTOMOUNT | AT_STATX_SYNC_TYPE);
+ if (lflags == AT_EMPTY_PATH && vfs_empty_path(dfd, filename))
+ return do_statx_fd(dfd, flags & ~AT_NO_AUTOMOUNT, mask, buffer);
+
+ name = getname_flags(filename, getname_statx_lookup_flags(flags));
ret = do_statx(dfd, name, flags, mask, buffer);
putname(name);
diff --git a/fs/super.c b/fs/super.c
index b72f1d288e95..095ba793e10c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1502,8 +1502,17 @@ static int fs_bdev_thaw(struct block_device *bdev)
lockdep_assert_held(&bdev->bd_fsfreeze_mutex);
+ /*
+ * The block device may have been frozen before it was claimed by a
+ * filesystem. Concurrently another process might try to mount that
+ * frozen block device and has temporarily claimed the block device for
+ * that purpose causing a concurrent fs_bdev_thaw() to end up here. The
+ * mounter is already about to abort mounting because they still saw an
+ * elevanted bdev->bd_fsfreeze_count so get_bdev_super() will return
+ * NULL in that case.
+ */
sb = get_bdev_super(bdev);
- if (WARN_ON_ONCE(!sb))
+ if (!sb)
return -EINVAL;
if (sb->s_op->thaw_super)
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index 3365a30dc1e0..5c0d07ddbda2 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -591,4 +591,5 @@ static void __exit exit_sysv_fs(void)
module_init(init_sysv_fs)
module_exit(exit_sysv_fs)
+MODULE_DESCRIPTION("SystemV Filesystem");
MODULE_LICENSE("GPL");
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index 7c29f4afc23d..1028ab6d9a74 100644
--- a/fs/tracefs/inode.c
+++ b/fs/tracefs/inode.c
@@ -296,9 +296,9 @@ enum {
};
static const struct fs_parameter_spec tracefs_param_specs[] = {
- fsparam_u32 ("gid", Opt_gid),
+ fsparam_gid ("gid", Opt_gid),
fsparam_u32oct ("mode", Opt_mode),
- fsparam_u32 ("uid", Opt_uid),
+ fsparam_uid ("uid", Opt_uid),
{}
};
@@ -306,8 +306,6 @@ static int tracefs_parse_param(struct fs_context *fc, struct fs_parameter *param
{
struct tracefs_fs_info *opts = fc->s_fs_info;
struct fs_parse_result result;
- kuid_t uid;
- kgid_t gid;
int opt;
opt = fs_parse(fc, tracefs_param_specs, param, &result);
@@ -316,16 +314,10 @@ static int tracefs_parse_param(struct fs_context *fc, struct fs_parameter *param
switch (opt) {
case Opt_uid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- return invalf(fc, "Unknown uid");
- opts->uid = uid;
+ opts->uid = result.uid;
break;
case Opt_gid:
- gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(gid))
- return invalf(fc, "Unknown gid");
- opts->gid = gid;
+ opts->gid = result.gid;
break;
case Opt_mode:
opts->mode = result.uint_32 & S_IALLUGO;
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 27c85d92d1dc..61f25d3cf3f7 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -188,7 +188,6 @@ Eend:
"offset=%lu",
dir->i_ino, (page->index<<PAGE_SHIFT)+offs);
fail:
- SetPageError(page);
return false;
}
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index eee7320ab0b0..17e409ceaa33 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -2057,7 +2057,7 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
goto out;
features = uffdio_api.features;
ret = -EINVAL;
- if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES))
+ if (uffdio_api.api != UFFD_API)
goto err_out;
ret = -EPERM;
if ((features & UFFD_FEATURE_EVENT_FORK) && !capable(CAP_SYS_PTRACE))
@@ -2081,6 +2081,11 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
uffdio_api.features &= ~UFFD_FEATURE_WP_UNPOPULATED;
uffdio_api.features &= ~UFFD_FEATURE_WP_ASYNC;
#endif
+
+ ret = -EINVAL;
+ if (features & ~uffdio_api.features)
+ goto err_out;
+
uffdio_api.ioctls = UFFD_API_IOCTLS;
ret = -EFAULT;
if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api)))
diff --git a/fs/vboxsf/file.c b/fs/vboxsf/file.c
index 118dedef8ebe..fdb4da24d662 100644
--- a/fs/vboxsf/file.c
+++ b/fs/vboxsf/file.c
@@ -228,26 +228,19 @@ const struct inode_operations vboxsf_reg_iops = {
static int vboxsf_read_folio(struct file *file, struct folio *folio)
{
- struct page *page = &folio->page;
struct vboxsf_handle *sf_handle = file->private_data;
- loff_t off = page_offset(page);
+ loff_t off = folio_pos(folio);
u32 nread = PAGE_SIZE;
u8 *buf;
int err;
- buf = kmap(page);
+ buf = kmap_local_folio(folio, 0);
err = vboxsf_read(sf_handle->root, sf_handle->handle, off, &nread, buf);
- if (err == 0) {
- memset(&buf[nread], 0, PAGE_SIZE - nread);
- flush_dcache_page(page);
- SetPageUptodate(page);
- } else {
- SetPageError(page);
- }
+ buf = folio_zero_tail(folio, nread, buf + nread);
- kunmap(page);
- unlock_page(page);
+ kunmap_local(buf);
+ folio_end_read(folio, err == 0);
return err;
}
@@ -295,7 +288,6 @@ static int vboxsf_writepage(struct page *page, struct writeback_control *wbc)
kref_put(&sf_handle->refcount, vboxsf_handle_release);
if (err == 0) {
- ClearPageError(page);
/* mtime changed */
sf_i->force_restat = 1;
} else {
diff --git a/fs/vboxsf/super.c b/fs/vboxsf/super.c
index ffb1d565da39..e95b8a48d8a0 100644
--- a/fs/vboxsf/super.c
+++ b/fs/vboxsf/super.c
@@ -41,8 +41,8 @@ enum { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode,
static const struct fs_parameter_spec vboxsf_fs_parameters[] = {
fsparam_string ("nls", opt_nls),
- fsparam_u32 ("uid", opt_uid),
- fsparam_u32 ("gid", opt_gid),
+ fsparam_uid ("uid", opt_uid),
+ fsparam_gid ("gid", opt_gid),
fsparam_u32 ("ttl", opt_ttl),
fsparam_u32oct ("dmode", opt_dmode),
fsparam_u32oct ("fmode", opt_fmode),
@@ -55,8 +55,6 @@ static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
struct vboxsf_fs_context *ctx = fc->fs_private;
struct fs_parse_result result;
- kuid_t uid;
- kgid_t gid;
int opt;
opt = fs_parse(fc, vboxsf_fs_parameters, param, &result);
@@ -73,16 +71,10 @@ static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param)
param->string = NULL;
break;
case opt_uid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- return -EINVAL;
- ctx->o.uid = uid;
+ ctx->o.uid = result.uid;
break;
case opt_gid:
- gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(gid))
- return -EINVAL;
- ctx->o.gid = gid;
+ ctx->o.gid = result.gid;
break;
case opt_ttl:
ctx->o.ttl = msecs_to_jiffies(result.uint_32);
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 9967334ea99f..cf629302d48e 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -86,9 +86,8 @@ xfs_inode_alloc(
return NULL;
}
- /* VFS doesn't initialise i_mode or i_state! */
+ /* VFS doesn't initialise i_mode! */
VFS_I(ip)->i_mode = 0;
- VFS_I(ip)->i_state = 0;
mapping_set_large_folios(VFS_I(ip)->i_mapping);
XFS_STATS_INC(mp, vn_active);
@@ -314,6 +313,7 @@ xfs_reinit_inode(
dev_t dev = inode->i_rdev;
kuid_t uid = inode->i_uid;
kgid_t gid = inode->i_gid;
+ unsigned long state = inode->i_state;
error = inode_init_always(mp->m_super, inode);
@@ -324,6 +324,7 @@ xfs_reinit_inode(
inode->i_rdev = dev;
inode->i_uid = uid;
inode->i_gid = gid;
+ inode->i_state = state;
mapping_set_large_folios(inode->i_mapping);
return error;
}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index ff222827e550..a00dcbc77e12 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -17,6 +17,8 @@
#include "xfs_da_btree.h"
#include "xfs_attr.h"
#include "xfs_trans.h"
+#include "xfs_trans_space.h"
+#include "xfs_bmap_btree.h"
#include "xfs_trace.h"
#include "xfs_icache.h"
#include "xfs_symlink.h"
@@ -811,6 +813,7 @@ xfs_setattr_size(
struct xfs_trans *tp;
int error;
uint lock_flags = 0;
+ uint resblks = 0;
bool did_zeroing = false;
xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL);
@@ -917,7 +920,17 @@ xfs_setattr_size(
return error;
}
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
+ /*
+ * For realtime inode with more than one block rtextsize, we need the
+ * block reservation for bmap btree block allocations/splits that can
+ * happen since it could split the tail written extent and convert the
+ * right beyond EOF one to unwritten.
+ */
+ if (xfs_inode_has_bigrtalloc(ip))
+ resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+
+ error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, resblks,
+ 0, 0, &tp);
if (error)
return error;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 1a4dfd7a1c4a..05ca49478537 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -134,6 +134,7 @@ struct acpi_scan_handler {
bool (*match)(const char *idstr, const struct acpi_device_id **matchid);
int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
void (*detach)(struct acpi_device *dev);
+ void (*post_eject)(struct acpi_device *dev);
void (*bind)(struct device *phys_dev);
void (*unbind)(struct device *phys_dev);
struct acpi_hotplug_profile hotplug;
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index ae747c89d92c..e27958ef8264 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -1194,11 +1194,23 @@ struct acpi_madt_generic_translator {
struct acpi_madt_multiproc_wakeup {
struct acpi_subtable_header header;
- u16 mailbox_version;
+ u16 version;
u32 reserved; /* reserved - must be zero */
- u64 base_address;
+ u64 mailbox_address;
+ u64 reset_vector;
};
+/* Values for Version field above */
+
+enum acpi_madt_multiproc_wakeup_version {
+ ACPI_MADT_MP_WAKEUP_VERSION_NONE = 0,
+ ACPI_MADT_MP_WAKEUP_VERSION_V1 = 1,
+ ACPI_MADT_MP_WAKEUP_VERSION_RESERVED = 2, /* 2 and greater are reserved */
+};
+
+#define ACPI_MADT_MP_WAKEUP_SIZE_V0 16
+#define ACPI_MADT_MP_WAKEUP_SIZE_V1 24
+
#define ACPI_MULTIPROC_WAKEUP_MB_OS_SIZE 2032
#define ACPI_MULTIPROC_WAKEUP_MB_FIRMWARE_SIZE 2048
@@ -1211,7 +1223,8 @@ struct acpi_madt_multiproc_wakeup_mailbox {
u8 reserved_firmware[ACPI_MULTIPROC_WAKEUP_MB_FIRMWARE_SIZE]; /* reserved for firmware use */
};
-#define ACPI_MP_WAKE_COMMAND_WAKEUP 1
+#define ACPI_MP_WAKE_COMMAND_WAKEUP 1
+#define ACPI_MP_WAKE_COMMAND_TEST 2
/* 17: CPU Core Interrupt Controller (ACPI 6.5) */
diff --git a/include/acpi/battery.h b/include/acpi/battery.h
index 611a2561a014..c93f16dfb944 100644
--- a/include/acpi/battery.h
+++ b/include/acpi/battery.h
@@ -2,6 +2,7 @@
#ifndef __ACPI_BATTERY_H
#define __ACPI_BATTERY_H
+#include <linux/device.h>
#include <linux/power_supply.h>
#define ACPI_BATTERY_CLASS "battery"
@@ -19,5 +20,6 @@ struct acpi_battery_hook {
void battery_hook_register(struct acpi_battery_hook *hook);
void battery_hook_unregister(struct acpi_battery_hook *hook);
+int devm_battery_hook_register(struct device *dev, struct acpi_battery_hook *hook);
#endif
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 3f34ebb27525..e6f6074eadbf 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -217,7 +217,7 @@ struct acpi_processor_flags {
u8 has_lpi:1;
u8 power_setup_done:1;
u8 bm_rld_set:1;
- u8 need_hotplug_init:1;
+ u8 previously_online:1;
};
struct acpi_processor {
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
index b20fa25a7e8d..620b6da429d4 100644
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -9,7 +9,6 @@ mandatory-y += archrandom.h
mandatory-y += barrier.h
mandatory-y += bitops.h
mandatory-y += bug.h
-mandatory-y += bugs.h
mandatory-y += cacheflush.h
mandatory-y += cfi.h
mandatory-y += checksum.h
@@ -46,6 +45,7 @@ mandatory-y += pci.h
mandatory-y += percpu.h
mandatory-y += pgalloc.h
mandatory-y += preempt.h
+mandatory-y += runtime-const.h
mandatory-y += rwonce.h
mandatory-y += sections.h
mandatory-y += serial.h
diff --git a/include/asm-generic/fixmap.h b/include/asm-generic/fixmap.h
index 8cc7b09c1bc7..29cab7947980 100644
--- a/include/asm-generic/fixmap.h
+++ b/include/asm-generic/fixmap.h
@@ -97,8 +97,5 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr)
#define set_fixmap_io(idx, phys) \
__set_fixmap(idx, phys, FIXMAP_PAGE_IO)
-#define set_fixmap_offset_io(idx, phys) \
- __set_fixmap_offset(idx, phys, FIXMAP_PAGE_IO)
-
#endif /* __ASSEMBLY__ */
#endif /* __ASM_GENERIC_FIXMAP_H */
diff --git a/include/asm-generic/runtime-const.h b/include/asm-generic/runtime-const.h
new file mode 100644
index 000000000000..670499459514
--- /dev/null
+++ b/include/asm-generic/runtime-const.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RUNTIME_CONST_H
+#define _ASM_RUNTIME_CONST_H
+
+/*
+ * This is the fallback for when the architecture doesn't
+ * support the runtime const operations.
+ *
+ * We just use the actual symbols as-is.
+ */
+#define runtime_const_ptr(sym) (sym)
+#define runtime_const_shift_right_32(val, sym) ((u32)(val)>>(sym))
+#define runtime_const_init(type,sym) do { } while (0)
+
+#endif
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 5703526d6ebf..35245e9225a5 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -103,7 +103,7 @@
#define DATA_MAIN .data .data.[0-9a-zA-Z_]* .data..L* .data..compoundliteral* .data.$__unnamed_* .data.$L*
#define SDATA_MAIN .sdata .sdata.[0-9a-zA-Z_]*
#define RODATA_MAIN .rodata .rodata.[0-9a-zA-Z_]* .rodata..L*
-#define BSS_MAIN .bss .bss.[0-9a-zA-Z_]* .bss..compoundliteral*
+#define BSS_MAIN .bss .bss.[0-9a-zA-Z_]* .bss..L* .bss..compoundliteral*
#define SBSS_MAIN .sbss .sbss.[0-9a-zA-Z_]*
#else
#define TEXT_MAIN .text
@@ -944,6 +944,14 @@
#define CON_INITCALL \
BOUNDED_SECTION_POST_LABEL(.con_initcall.init, __con_initcall, _start, _end)
+#define RUNTIME_NAME(t,x) runtime_##t##_##x
+
+#define RUNTIME_CONST(t,x) \
+ . = ALIGN(8); \
+ RUNTIME_NAME(t,x) : AT(ADDR(RUNTIME_NAME(t,x)) - LOAD_OFFSET) { \
+ *(RUNTIME_NAME(t,x)); \
+ }
+
/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */
#define KUNIT_TABLE() \
. = ALIGN(8); \
diff --git a/include/clocksource/timer-xilinx.h b/include/clocksource/timer-xilinx.h
index c0f56fe6d22a..d116f18de899 100644
--- a/include/clocksource/timer-xilinx.h
+++ b/include/clocksource/timer-xilinx.h
@@ -41,7 +41,7 @@ struct regmap;
struct xilinx_timer_priv {
struct regmap *map;
struct clk *clk;
- u32 max;
+ u64 max;
};
/**
diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h
index d040033dc8ee..d6c9e9472121 100644
--- a/include/dt-bindings/arm/qcom,ids.h
+++ b/include/dt-bindings/arm/qcom,ids.h
@@ -175,6 +175,7 @@
#define QCOM_ID_SDA630 327
#define QCOM_ID_MSM8905 331
#define QCOM_ID_SDX202 333
+#define QCOM_ID_SDM670 336
#define QCOM_ID_SDM450 338
#define QCOM_ID_SM8150 339
#define QCOM_ID_SDA845 341
@@ -272,6 +273,7 @@
#define QCOM_ID_QCS8550 603
#define QCOM_ID_QCM8550 604
#define QCOM_ID_IPQ5300 624
+#define QCOM_ID_IPQ5321 650
/*
* The board type and revision information, used by Qualcomm bootloaders and
diff --git a/include/dt-bindings/clock/qcom,qcm2290-gpucc.h b/include/dt-bindings/clock/qcom,qcm2290-gpucc.h
new file mode 100644
index 000000000000..7c76dd05278f
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,qcm2290-gpucc.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_QCM2290_H
+#define _DT_BINDINGS_CLK_QCOM_GPU_CC_QCM2290_H
+
+/* GPU_CC clocks */
+#define GPU_CC_AHB_CLK 0
+#define GPU_CC_CRC_AHB_CLK 1
+#define GPU_CC_CX_GFX3D_CLK 2
+#define GPU_CC_CX_GMU_CLK 3
+#define GPU_CC_CX_SNOC_DVM_CLK 4
+#define GPU_CC_CXO_AON_CLK 5
+#define GPU_CC_CXO_CLK 6
+#define GPU_CC_GMU_CLK_SRC 7
+#define GPU_CC_GX_GFX3D_CLK 8
+#define GPU_CC_GX_GFX3D_CLK_SRC 9
+#define GPU_CC_PLL0 10
+#define GPU_CC_SLEEP_CLK 11
+#define GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK 12
+
+/* Resets */
+#define GPU_GX_BCR 0
+
+/* GDSCs */
+#define GPU_CX_GDSC 0
+#define GPU_GX_GDSC 1
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,sm8650-camcc.h b/include/dt-bindings/clock/qcom,sm8650-camcc.h
new file mode 100644
index 000000000000..df73bf35f4bf
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,sm8650-camcc.h
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_SM8650_H
+#define _DT_BINDINGS_CLK_QCOM_CAM_CC_SM8650_H
+
+/* CAM_CC clocks */
+#define CAM_CC_BPS_AHB_CLK 0
+#define CAM_CC_BPS_CLK 1
+#define CAM_CC_BPS_CLK_SRC 2
+#define CAM_CC_BPS_FAST_AHB_CLK 3
+#define CAM_CC_BPS_SHIFT_CLK 4
+#define CAM_CC_CAMNOC_AXI_NRT_CLK 5
+#define CAM_CC_CAMNOC_AXI_RT_CLK 6
+#define CAM_CC_CAMNOC_AXI_RT_CLK_SRC 7
+#define CAM_CC_CAMNOC_DCD_XO_CLK 8
+#define CAM_CC_CAMNOC_XO_CLK 9
+#define CAM_CC_CCI_0_CLK 10
+#define CAM_CC_CCI_0_CLK_SRC 11
+#define CAM_CC_CCI_1_CLK 12
+#define CAM_CC_CCI_1_CLK_SRC 13
+#define CAM_CC_CCI_2_CLK 14
+#define CAM_CC_CCI_2_CLK_SRC 15
+#define CAM_CC_CORE_AHB_CLK 16
+#define CAM_CC_CPAS_AHB_CLK 17
+#define CAM_CC_CPAS_BPS_CLK 18
+#define CAM_CC_CPAS_CRE_CLK 19
+#define CAM_CC_CPAS_FAST_AHB_CLK 20
+#define CAM_CC_CPAS_IFE_0_CLK 21
+#define CAM_CC_CPAS_IFE_1_CLK 22
+#define CAM_CC_CPAS_IFE_2_CLK 23
+#define CAM_CC_CPAS_IFE_LITE_CLK 24
+#define CAM_CC_CPAS_IPE_NPS_CLK 25
+#define CAM_CC_CPAS_SBI_CLK 26
+#define CAM_CC_CPAS_SFE_0_CLK 27
+#define CAM_CC_CPAS_SFE_1_CLK 28
+#define CAM_CC_CPAS_SFE_2_CLK 29
+#define CAM_CC_CPHY_RX_CLK_SRC 30
+#define CAM_CC_CRE_AHB_CLK 31
+#define CAM_CC_CRE_CLK 32
+#define CAM_CC_CRE_CLK_SRC 33
+#define CAM_CC_CSI0PHYTIMER_CLK 34
+#define CAM_CC_CSI0PHYTIMER_CLK_SRC 35
+#define CAM_CC_CSI1PHYTIMER_CLK 36
+#define CAM_CC_CSI1PHYTIMER_CLK_SRC 37
+#define CAM_CC_CSI2PHYTIMER_CLK 38
+#define CAM_CC_CSI2PHYTIMER_CLK_SRC 39
+#define CAM_CC_CSI3PHYTIMER_CLK 40
+#define CAM_CC_CSI3PHYTIMER_CLK_SRC 41
+#define CAM_CC_CSI4PHYTIMER_CLK 42
+#define CAM_CC_CSI4PHYTIMER_CLK_SRC 43
+#define CAM_CC_CSI5PHYTIMER_CLK 44
+#define CAM_CC_CSI5PHYTIMER_CLK_SRC 45
+#define CAM_CC_CSI6PHYTIMER_CLK 46
+#define CAM_CC_CSI6PHYTIMER_CLK_SRC 47
+#define CAM_CC_CSI7PHYTIMER_CLK 48
+#define CAM_CC_CSI7PHYTIMER_CLK_SRC 49
+#define CAM_CC_CSID_CLK 50
+#define CAM_CC_CSID_CLK_SRC 51
+#define CAM_CC_CSID_CSIPHY_RX_CLK 52
+#define CAM_CC_CSIPHY0_CLK 53
+#define CAM_CC_CSIPHY1_CLK 54
+#define CAM_CC_CSIPHY2_CLK 55
+#define CAM_CC_CSIPHY3_CLK 56
+#define CAM_CC_CSIPHY4_CLK 57
+#define CAM_CC_CSIPHY5_CLK 58
+#define CAM_CC_CSIPHY6_CLK 59
+#define CAM_CC_CSIPHY7_CLK 60
+#define CAM_CC_DRV_AHB_CLK 61
+#define CAM_CC_DRV_XO_CLK 62
+#define CAM_CC_FAST_AHB_CLK_SRC 63
+#define CAM_CC_GDSC_CLK 64
+#define CAM_CC_ICP_AHB_CLK 65
+#define CAM_CC_ICP_CLK 66
+#define CAM_CC_ICP_CLK_SRC 67
+#define CAM_CC_IFE_0_CLK 68
+#define CAM_CC_IFE_0_CLK_SRC 69
+#define CAM_CC_IFE_0_FAST_AHB_CLK 70
+#define CAM_CC_IFE_0_SHIFT_CLK 71
+#define CAM_CC_IFE_1_CLK 72
+#define CAM_CC_IFE_1_CLK_SRC 73
+#define CAM_CC_IFE_1_FAST_AHB_CLK 74
+#define CAM_CC_IFE_1_SHIFT_CLK 75
+#define CAM_CC_IFE_2_CLK 76
+#define CAM_CC_IFE_2_CLK_SRC 77
+#define CAM_CC_IFE_2_FAST_AHB_CLK 78
+#define CAM_CC_IFE_2_SHIFT_CLK 79
+#define CAM_CC_IFE_LITE_AHB_CLK 80
+#define CAM_CC_IFE_LITE_CLK 81
+#define CAM_CC_IFE_LITE_CLK_SRC 82
+#define CAM_CC_IFE_LITE_CPHY_RX_CLK 83
+#define CAM_CC_IFE_LITE_CSID_CLK 84
+#define CAM_CC_IFE_LITE_CSID_CLK_SRC 85
+#define CAM_CC_IPE_NPS_AHB_CLK 86
+#define CAM_CC_IPE_NPS_CLK 87
+#define CAM_CC_IPE_NPS_CLK_SRC 88
+#define CAM_CC_IPE_NPS_FAST_AHB_CLK 89
+#define CAM_CC_IPE_PPS_CLK 90
+#define CAM_CC_IPE_PPS_FAST_AHB_CLK 91
+#define CAM_CC_IPE_SHIFT_CLK 92
+#define CAM_CC_JPEG_1_CLK 93
+#define CAM_CC_JPEG_CLK 94
+#define CAM_CC_JPEG_CLK_SRC 95
+#define CAM_CC_MCLK0_CLK 96
+#define CAM_CC_MCLK0_CLK_SRC 97
+#define CAM_CC_MCLK1_CLK 98
+#define CAM_CC_MCLK1_CLK_SRC 99
+#define CAM_CC_MCLK2_CLK 100
+#define CAM_CC_MCLK2_CLK_SRC 101
+#define CAM_CC_MCLK3_CLK 102
+#define CAM_CC_MCLK3_CLK_SRC 103
+#define CAM_CC_MCLK4_CLK 104
+#define CAM_CC_MCLK4_CLK_SRC 105
+#define CAM_CC_MCLK5_CLK 106
+#define CAM_CC_MCLK5_CLK_SRC 107
+#define CAM_CC_MCLK6_CLK 108
+#define CAM_CC_MCLK6_CLK_SRC 109
+#define CAM_CC_MCLK7_CLK 110
+#define CAM_CC_MCLK7_CLK_SRC 111
+#define CAM_CC_PLL0 112
+#define CAM_CC_PLL0_OUT_EVEN 113
+#define CAM_CC_PLL0_OUT_ODD 114
+#define CAM_CC_PLL1 115
+#define CAM_CC_PLL1_OUT_EVEN 116
+#define CAM_CC_PLL2 117
+#define CAM_CC_PLL3 118
+#define CAM_CC_PLL3_OUT_EVEN 119
+#define CAM_CC_PLL4 120
+#define CAM_CC_PLL4_OUT_EVEN 121
+#define CAM_CC_PLL5 122
+#define CAM_CC_PLL5_OUT_EVEN 123
+#define CAM_CC_PLL6 124
+#define CAM_CC_PLL6_OUT_EVEN 125
+#define CAM_CC_PLL7 126
+#define CAM_CC_PLL7_OUT_EVEN 127
+#define CAM_CC_PLL8 128
+#define CAM_CC_PLL8_OUT_EVEN 129
+#define CAM_CC_PLL9 130
+#define CAM_CC_PLL9_OUT_EVEN 131
+#define CAM_CC_PLL9_OUT_ODD 132
+#define CAM_CC_PLL10 133
+#define CAM_CC_PLL10_OUT_EVEN 134
+#define CAM_CC_QDSS_DEBUG_CLK 135
+#define CAM_CC_QDSS_DEBUG_CLK_SRC 136
+#define CAM_CC_QDSS_DEBUG_XO_CLK 137
+#define CAM_CC_SBI_CLK 138
+#define CAM_CC_SBI_FAST_AHB_CLK 139
+#define CAM_CC_SBI_SHIFT_CLK 140
+#define CAM_CC_SFE_0_CLK 141
+#define CAM_CC_SFE_0_CLK_SRC 142
+#define CAM_CC_SFE_0_FAST_AHB_CLK 143
+#define CAM_CC_SFE_0_SHIFT_CLK 144
+#define CAM_CC_SFE_1_CLK 145
+#define CAM_CC_SFE_1_CLK_SRC 146
+#define CAM_CC_SFE_1_FAST_AHB_CLK 147
+#define CAM_CC_SFE_1_SHIFT_CLK 148
+#define CAM_CC_SFE_2_CLK 149
+#define CAM_CC_SFE_2_CLK_SRC 150
+#define CAM_CC_SFE_2_FAST_AHB_CLK 151
+#define CAM_CC_SFE_2_SHIFT_CLK 152
+#define CAM_CC_SLEEP_CLK 153
+#define CAM_CC_SLEEP_CLK_SRC 154
+#define CAM_CC_SLOW_AHB_CLK_SRC 155
+#define CAM_CC_TITAN_TOP_SHIFT_CLK 156
+#define CAM_CC_XO_CLK_SRC 157
+
+/* CAM_CC power domains */
+#define CAM_CC_TITAN_TOP_GDSC 0
+#define CAM_CC_BPS_GDSC 1
+#define CAM_CC_IFE_0_GDSC 2
+#define CAM_CC_IFE_1_GDSC 3
+#define CAM_CC_IFE_2_GDSC 4
+#define CAM_CC_IPE_0_GDSC 5
+#define CAM_CC_SBI_GDSC 6
+#define CAM_CC_SFE_0_GDSC 7
+#define CAM_CC_SFE_1_GDSC 8
+#define CAM_CC_SFE_2_GDSC 9
+
+/* CAM_CC resets */
+#define CAM_CC_BPS_BCR 0
+#define CAM_CC_DRV_BCR 1
+#define CAM_CC_ICP_BCR 2
+#define CAM_CC_IFE_0_BCR 3
+#define CAM_CC_IFE_1_BCR 4
+#define CAM_CC_IFE_2_BCR 5
+#define CAM_CC_IPE_0_BCR 6
+#define CAM_CC_QDSS_DEBUG_BCR 7
+#define CAM_CC_SBI_BCR 8
+#define CAM_CC_SFE_0_BCR 9
+#define CAM_CC_SFE_1_BCR 10
+#define CAM_CC_SFE_2_BCR 11
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,sm8650-videocc.h b/include/dt-bindings/clock/qcom,sm8650-videocc.h
new file mode 100644
index 000000000000..4e3c2d87280f
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,sm8650-videocc.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM8650_H
+#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM8650_H
+
+#include "qcom,sm8450-videocc.h"
+
+/* SM8650 introduces below new clocks and resets compared to SM8450 */
+
+/* VIDEO_CC clocks */
+#define VIDEO_CC_MVS0_SHIFT_CLK 12
+#define VIDEO_CC_MVS0C_SHIFT_CLK 13
+#define VIDEO_CC_MVS1_SHIFT_CLK 14
+#define VIDEO_CC_MVS1C_SHIFT_CLK 15
+#define VIDEO_CC_XO_CLK_SRC 16
+
+/* VIDEO_CC resets */
+#define VIDEO_CC_XO_CLK_ARES 7
+
+#endif
diff --git a/include/dt-bindings/clock/rk3128-cru.h b/include/dt-bindings/clock/rk3128-cru.h
index 6a47825dac5d..1be455ba4985 100644
--- a/include/dt-bindings/clock/rk3128-cru.h
+++ b/include/dt-bindings/clock/rk3128-cru.h
@@ -116,6 +116,7 @@
#define PCLK_GMAC 367
#define PCLK_PMU_PRE 368
#define PCLK_SIM_CARD 369
+#define PCLK_MIPIPHY 370
/* hclk gates */
#define HCLK_SPDIF 440
diff --git a/include/dt-bindings/clock/sun50i-h616-ccu.h b/include/dt-bindings/clock/sun50i-h616-ccu.h
index 6f8f01e67628..ebb146ab7f8c 100644
--- a/include/dt-bindings/clock/sun50i-h616-ccu.h
+++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
@@ -112,5 +112,6 @@
#define CLK_HDCP 126
#define CLK_BUS_HDCP 127
#define CLK_PLL_SYSTEM_32K 128
+#define CLK_BUS_GPADC 129
#endif /* _DT_BINDINGS_CLK_SUN50I_H616_H_ */
diff --git a/include/dt-bindings/input/cros-ec-keyboard.h b/include/dt-bindings/input/cros-ec-keyboard.h
index f0ae03634a96..afc12f6aa642 100644
--- a/include/dt-bindings/input/cros-ec-keyboard.h
+++ b/include/dt-bindings/input/cros-ec-keyboard.h
@@ -100,4 +100,108 @@
MATRIX_KEY(0x07, 0x0b, KEY_UP) \
MATRIX_KEY(0x07, 0x0c, KEY_LEFT)
+/* No numpad */
+#define CROS_TOP_ROW_KEYMAP_V30 \
+ MATRIX_KEY(0x00, 0x01, KEY_F11) /* T11 */ \
+ MATRIX_KEY(0x00, 0x02, KEY_F1) /* T1 */ \
+ MATRIX_KEY(0x00, 0x04, KEY_F10) /* T10 */ \
+ MATRIX_KEY(0x00, 0x0b, KEY_F14) /* T14 */ \
+ MATRIX_KEY(0x00, 0x0c, KEY_F15) /* T15 */ \
+ MATRIX_KEY(0x01, 0x02, KEY_F4) /* T4 */ \
+ MATRIX_KEY(0x01, 0x04, KEY_F7) /* T7 */ \
+ MATRIX_KEY(0x01, 0x05, KEY_F12) /* T12 */ \
+ MATRIX_KEY(0x01, 0x09, KEY_F9) /* T9 */ \
+ MATRIX_KEY(0x02, 0x02, KEY_F3) /* T3 */ \
+ MATRIX_KEY(0x02, 0x04, KEY_F6) /* T6 */ \
+ MATRIX_KEY(0x02, 0x0b, KEY_F8) /* T8 */ \
+ MATRIX_KEY(0x03, 0x02, KEY_F2) /* T2 */ \
+ MATRIX_KEY(0x03, 0x05, KEY_F13) /* T13 */ \
+ MATRIX_KEY(0x04, 0x04, KEY_F5) /* T5 */
+
+#define CROS_MAIN_KEYMAP_V30 /* Keycode */ \
+ MATRIX_KEY(0x00, 0x03, KEY_B) /* 50 */ \
+ MATRIX_KEY(0x00, 0x05, KEY_N) /* 51 */ \
+ MATRIX_KEY(0x00, 0x06, KEY_RO) /* 56 (JIS) */ \
+ MATRIX_KEY(0x00, 0x08, KEY_EQUAL) /* 13 */ \
+ MATRIX_KEY(0x00, 0x09, KEY_HOME) /* 80 (Numpad) */ \
+ MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT) /* 62 */ \
+ MATRIX_KEY(0x00, 0x10, KEY_FN) /* 127 */ \
+ \
+ MATRIX_KEY(0x01, 0x01, KEY_ESC) /* 110 */ \
+ MATRIX_KEY(0x01, 0x03, KEY_G) /* 35 */ \
+ MATRIX_KEY(0x01, 0x06, KEY_H) /* 36 */ \
+ MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE) /* 41 */ \
+ MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE) /* 15 */ \
+ MATRIX_KEY(0x01, 0x0c, KEY_HENKAN) /* 65 (JIS) */ \
+ MATRIX_KEY(0x01, 0x0e, KEY_LEFTCTRL) /* 58 */ \
+ \
+ MATRIX_KEY(0x02, 0x01, KEY_TAB) /* 16 */ \
+ MATRIX_KEY(0x02, 0x03, KEY_T) /* 21 */ \
+ MATRIX_KEY(0x02, 0x05, KEY_RIGHTBRACE) /* 28 */ \
+ MATRIX_KEY(0x02, 0x06, KEY_Y) /* 22 */ \
+ MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE) /* 27 */ \
+ MATRIX_KEY(0x02, 0x09, KEY_DELETE) /* 76 (Numpad) */ \
+ MATRIX_KEY(0x02, 0x0c, KEY_PAGEUP) /* 85 (Numpad) */ \
+ MATRIX_KEY(0x02, 0x011, KEY_YEN) /* 14 (JIS) */ \
+ \
+ MATRIX_KEY(0x03, 0x00, KEY_LEFTMETA) /* Launcher */ \
+ MATRIX_KEY(0x03, 0x01, KEY_GRAVE) /* 1 */ \
+ MATRIX_KEY(0x03, 0x03, KEY_5) /* 6 */ \
+ MATRIX_KEY(0x03, 0x04, KEY_S) /* 32 */ \
+ MATRIX_KEY(0x03, 0x06, KEY_MINUS) /* 12 */ \
+ MATRIX_KEY(0x03, 0x08, KEY_6) /* 7 */ \
+ MATRIX_KEY(0x03, 0x09, KEY_SLEEP) /* Lock */ \
+ MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH) /* 29 */ \
+ MATRIX_KEY(0x03, 0x0c, KEY_MUHENKAN) /* 63 (JIS) */ \
+ MATRIX_KEY(0x03, 0x0e, KEY_RIGHTCTRL) /* 64 */ \
+ \
+ MATRIX_KEY(0x04, 0x01, KEY_A) /* 31 */ \
+ MATRIX_KEY(0x04, 0x02, KEY_D) /* 33 */ \
+ MATRIX_KEY(0x04, 0x03, KEY_F) /* 34 */ \
+ MATRIX_KEY(0x04, 0x05, KEY_K) /* 38 */ \
+ MATRIX_KEY(0x04, 0x06, KEY_J) /* 37 */ \
+ MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON) /* 40 */ \
+ MATRIX_KEY(0x04, 0x09, KEY_L) /* 39 */ \
+ MATRIX_KEY(0x04, 0x0b, KEY_ENTER) /* 43 */ \
+ MATRIX_KEY(0x04, 0x0c, KEY_END) /* 81 (Numpad) */ \
+ \
+ MATRIX_KEY(0x05, 0x01, KEY_1) /* 2 */ \
+ MATRIX_KEY(0x05, 0x02, KEY_COMMA) /* 53 */ \
+ MATRIX_KEY(0x05, 0x03, KEY_DOT) /* 54 */ \
+ MATRIX_KEY(0x05, 0x04, KEY_SLASH) /* 55 */ \
+ MATRIX_KEY(0x05, 0x05, KEY_C) /* 48 */ \
+ MATRIX_KEY(0x05, 0x06, KEY_SPACE) /* 61 */ \
+ MATRIX_KEY(0x05, 0x07, KEY_LEFTSHIFT) /* 44 */ \
+ MATRIX_KEY(0x05, 0x08, KEY_X) /* 47 */ \
+ MATRIX_KEY(0x05, 0x09, KEY_V) /* 49 */ \
+ MATRIX_KEY(0x05, 0x0b, KEY_M) /* 52 */ \
+ MATRIX_KEY(0x05, 0x0c, KEY_PAGEDOWN) /* 86 (Numpad) */ \
+ \
+ MATRIX_KEY(0x06, 0x01, KEY_Z) /* 46 */ \
+ MATRIX_KEY(0x06, 0x02, KEY_3) /* 4 */ \
+ MATRIX_KEY(0x06, 0x03, KEY_4) /* 5 */ \
+ MATRIX_KEY(0x06, 0x04, KEY_2) /* 3 */ \
+ MATRIX_KEY(0x06, 0x05, KEY_8) /* 9 */ \
+ MATRIX_KEY(0x06, 0x06, KEY_0) /* 11 */ \
+ MATRIX_KEY(0x06, 0x08, KEY_7) /* 8 */ \
+ MATRIX_KEY(0x06, 0x09, KEY_9) /* 10 */ \
+ MATRIX_KEY(0x06, 0x0b, KEY_DOWN) /* 84 */ \
+ MATRIX_KEY(0x06, 0x0c, KEY_RIGHT) /* 89 */ \
+ MATRIX_KEY(0x06, 0x0d, KEY_LEFTALT) /* 60 */ \
+ MATRIX_KEY(0x06, 0x0f, KEY_ASSISTANT) /* 128 */ \
+ MATRIX_KEY(0x06, 0x11, KEY_BACKSLASH) /* 42 (JIS, ISO) */ \
+ \
+ MATRIX_KEY(0x07, 0x01, KEY_U) /* 23 */ \
+ MATRIX_KEY(0x07, 0x02, KEY_I) /* 24 */ \
+ MATRIX_KEY(0x07, 0x03, KEY_O) /* 25 */ \
+ MATRIX_KEY(0x07, 0x04, KEY_P) /* 26 */ \
+ MATRIX_KEY(0x07, 0x05, KEY_Q) /* 17 */ \
+ MATRIX_KEY(0x07, 0x06, KEY_W) /* 18 */ \
+ MATRIX_KEY(0x07, 0x07, KEY_RIGHTSHIFT) /* 57 */ \
+ MATRIX_KEY(0x07, 0x08, KEY_E) /* 19 */ \
+ MATRIX_KEY(0x07, 0x09, KEY_R) /* 20 */ \
+ MATRIX_KEY(0x07, 0x0b, KEY_UP) /* 83 */ \
+ MATRIX_KEY(0x07, 0x0c, KEY_LEFT) /* 79 */ \
+ MATRIX_KEY(0x07, 0x11, KEY_102ND) /* 45 (ISO) */
+
#endif /* _CROS_EC_KEYBOARD_H */
diff --git a/include/dt-bindings/interconnect/qcom,ipq9574.h b/include/dt-bindings/interconnect/qcom,ipq9574.h
new file mode 100644
index 000000000000..42019335c7dd
--- /dev/null
+++ b/include/dt-bindings/interconnect/qcom,ipq9574.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+#ifndef INTERCONNECT_QCOM_IPQ9574_H
+#define INTERCONNECT_QCOM_IPQ9574_H
+
+#define MASTER_ANOC_PCIE0 0
+#define SLAVE_ANOC_PCIE0 1
+#define MASTER_SNOC_PCIE0 2
+#define SLAVE_SNOC_PCIE0 3
+#define MASTER_ANOC_PCIE1 4
+#define SLAVE_ANOC_PCIE1 5
+#define MASTER_SNOC_PCIE1 6
+#define SLAVE_SNOC_PCIE1 7
+#define MASTER_ANOC_PCIE2 8
+#define SLAVE_ANOC_PCIE2 9
+#define MASTER_SNOC_PCIE2 10
+#define SLAVE_SNOC_PCIE2 11
+#define MASTER_ANOC_PCIE3 12
+#define SLAVE_ANOC_PCIE3 13
+#define MASTER_SNOC_PCIE3 14
+#define SLAVE_SNOC_PCIE3 15
+#define MASTER_USB 16
+#define SLAVE_USB 17
+#define MASTER_USB_AXI 18
+#define SLAVE_USB_AXI 19
+#define MASTER_NSSNOC_NSSCC 20
+#define SLAVE_NSSNOC_NSSCC 21
+#define MASTER_NSSNOC_SNOC_0 22
+#define SLAVE_NSSNOC_SNOC_0 23
+#define MASTER_NSSNOC_SNOC_1 24
+#define SLAVE_NSSNOC_SNOC_1 25
+#define MASTER_NSSNOC_PCNOC_1 26
+#define SLAVE_NSSNOC_PCNOC_1 27
+#define MASTER_NSSNOC_QOSGEN_REF 28
+#define SLAVE_NSSNOC_QOSGEN_REF 29
+#define MASTER_NSSNOC_TIMEOUT_REF 30
+#define SLAVE_NSSNOC_TIMEOUT_REF 31
+#define MASTER_NSSNOC_XO_DCD 32
+#define SLAVE_NSSNOC_XO_DCD 33
+#define MASTER_NSSNOC_ATB 34
+#define SLAVE_NSSNOC_ATB 35
+#define MASTER_MEM_NOC_NSSNOC 36
+#define SLAVE_MEM_NOC_NSSNOC 37
+#define MASTER_NSSNOC_MEMNOC 38
+#define SLAVE_NSSNOC_MEMNOC 39
+#define MASTER_NSSNOC_MEM_NOC_1 40
+#define SLAVE_NSSNOC_MEM_NOC_1 41
+
+#define MASTER_NSSNOC_PPE 0
+#define SLAVE_NSSNOC_PPE 1
+#define MASTER_NSSNOC_PPE_CFG 2
+#define SLAVE_NSSNOC_PPE_CFG 3
+#define MASTER_NSSNOC_NSS_CSR 4
+#define SLAVE_NSSNOC_NSS_CSR 5
+#define MASTER_NSSNOC_IMEM_QSB 6
+#define SLAVE_NSSNOC_IMEM_QSB 7
+#define MASTER_NSSNOC_IMEM_AHB 8
+#define SLAVE_NSSNOC_IMEM_AHB 9
+
+#endif /* INTERCONNECT_QCOM_IPQ9574_H */
diff --git a/include/dt-bindings/power/amlogic,a4-pwrc.h b/include/dt-bindings/power/amlogic,a4-pwrc.h
new file mode 100644
index 000000000000..bd2f9c558d22
--- /dev/null
+++ b/include/dt-bindings/power/amlogic,a4-pwrc.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Amlogic, Inc. All rights reserved
+ */
+#ifndef _DT_BINDINGS_AMLOGIC_A4_POWER_H
+#define _DT_BINDINGS_AMLOGIC_A4_POWER_H
+
+#define PWRC_A4_AUDIO_ID 0
+#define PWRC_A4_SDIOA_ID 1
+#define PWRC_A4_EMMC_ID 2
+#define PWRC_A4_USB_COMB_ID 3
+#define PWRC_A4_ETH_ID 4
+#define PWRC_A4_VOUT_ID 5
+#define PWRC_A4_AUDIO_PDM_ID 6
+#define PWRC_A4_DMC_ID 7
+#define PWRC_A4_SYS_WRAP_ID 8
+#define PWRC_A4_AO_I2C_S_ID 9
+#define PWRC_A4_AO_UART_ID 10
+#define PWRC_A4_AO_IR_ID 11
+
+#endif
diff --git a/include/dt-bindings/power/amlogic,a5-pwrc.h b/include/dt-bindings/power/amlogic,a5-pwrc.h
new file mode 100644
index 000000000000..3a6f53eb959f
--- /dev/null
+++ b/include/dt-bindings/power/amlogic,a5-pwrc.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024 Amlogic, Inc. All rights reserved
+ */
+
+#ifndef _DT_BINDINGS_AMLOGIC_A5_POWER_H
+#define _DT_BINDINGS_AMLOGIC_A5_POWER_H
+
+#define PWRC_A5_NNA_ID 0
+#define PWRC_A5_AUDIO_ID 1
+#define PWRC_A5_SDIOA_ID 2
+#define PWRC_A5_EMMC_ID 3
+#define PWRC_A5_USB_COMB_ID 4
+#define PWRC_A5_ETH_ID 5
+#define PWRC_A5_RSA_ID 6
+#define PWRC_A5_AUDIO_PDM_ID 7
+#define PWRC_A5_DMC_ID 8
+#define PWRC_A5_SYS_WRAP_ID 9
+#define PWRC_A5_DSPA_ID 10
+
+#endif
diff --git a/include/dt-bindings/regulator/st,stm32mp25-regulator.h b/include/dt-bindings/regulator/st,stm32mp25-regulator.h
new file mode 100644
index 000000000000..3c3d30911dd0
--- /dev/null
+++ b/include/dt-bindings/regulator/st,stm32mp25-regulator.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef __DT_BINDINGS_REGULATOR_ST_STM32MP25_REGULATOR_H
+#define __DT_BINDINGS_REGULATOR_ST_STM32MP25_REGULATOR_H
+
+/* SCMI voltage domains identifiers */
+
+/* SOC Internal regulators */
+#define VOLTD_SCMI_VDDIO1 0
+#define VOLTD_SCMI_VDDIO2 1
+#define VOLTD_SCMI_VDDIO3 2
+#define VOLTD_SCMI_VDDIO4 3
+#define VOLTD_SCMI_VDDIO 4
+#define VOLTD_SCMI_UCPD 5
+#define VOLTD_SCMI_USB33 6
+#define VOLTD_SCMI_ADC 7
+#define VOLTD_SCMI_GPU 8
+#define VOLTD_SCMI_VREFBUF 9
+
+/* STPMIC2 regulators */
+#define VOLTD_SCMI_STPMIC2_BUCK1 10
+#define VOLTD_SCMI_STPMIC2_BUCK2 11
+#define VOLTD_SCMI_STPMIC2_BUCK3 12
+#define VOLTD_SCMI_STPMIC2_BUCK4 13
+#define VOLTD_SCMI_STPMIC2_BUCK5 14
+#define VOLTD_SCMI_STPMIC2_BUCK6 15
+#define VOLTD_SCMI_STPMIC2_BUCK7 16
+#define VOLTD_SCMI_STPMIC2_LDO1 17
+#define VOLTD_SCMI_STPMIC2_LDO2 18
+#define VOLTD_SCMI_STPMIC2_LDO3 19
+#define VOLTD_SCMI_STPMIC2_LDO4 20
+#define VOLTD_SCMI_STPMIC2_LDO5 21
+#define VOLTD_SCMI_STPMIC2_LDO6 22
+#define VOLTD_SCMI_STPMIC2_LDO7 23
+#define VOLTD_SCMI_STPMIC2_LDO8 24
+#define VOLTD_SCMI_STPMIC2_REFDDR 25
+
+/* External regulators */
+#define VOLTD_SCMI_REGU0 26
+#define VOLTD_SCMI_REGU1 27
+#define VOLTD_SCMI_REGU2 28
+#define VOLTD_SCMI_REGU3 29
+#define VOLTD_SCMI_REGU4 30
+
+#endif /*__DT_BINDINGS_REGULATOR_ST_STM32MP25_REGULATOR_H */
diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h
index 1bd8bb0a11be..ed177c04afdd 100644
--- a/include/dt-bindings/reset/sun50i-h616-ccu.h
+++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
@@ -66,5 +66,6 @@
#define RST_BUS_TVE0 57
#define RST_BUS_HDCP 58
#define RST_BUS_KEYADC 59
+#define RST_BUS_GPADC 60
#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 28c3fb2bef0d..9f8c9d29b035 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -237,11 +237,6 @@ acpi_table_parse_cedt(enum acpi_cedt_type id,
int acpi_parse_mcfg (struct acpi_table_header *header);
void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);
-static inline bool acpi_gicc_is_usable(struct acpi_madt_generic_interrupt *gicc)
-{
- return gicc->flags & ACPI_MADT_ENABLED;
-}
-
#if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa);
#else
@@ -304,6 +299,8 @@ int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 acpi_id,
int acpi_unmap_cpu(int cpu);
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+acpi_handle acpi_get_processor_handle(int cpu);
+
#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);
#endif
@@ -1076,6 +1073,11 @@ static inline bool acpi_sleep_state_supported(u8 sleep_state)
return false;
}
+static inline acpi_handle acpi_get_processor_handle(int cpu)
+{
+ return NULL;
+}
+
#endif /* !CONFIG_ACPI */
extern void arch_post_acpi_subsys_init(void);
diff --git a/include/linux/blk-integrity.h b/include/linux/blk-integrity.h
index 7428cb43952d..804f856ed3e5 100644
--- a/include/linux/blk-integrity.h
+++ b/include/linux/blk-integrity.h
@@ -7,51 +7,38 @@
struct request;
enum blk_integrity_flags {
- BLK_INTEGRITY_VERIFY = 1 << 0,
- BLK_INTEGRITY_GENERATE = 1 << 1,
+ BLK_INTEGRITY_NOVERIFY = 1 << 0,
+ BLK_INTEGRITY_NOGENERATE = 1 << 1,
BLK_INTEGRITY_DEVICE_CAPABLE = 1 << 2,
- BLK_INTEGRITY_IP_CHECKSUM = 1 << 3,
+ BLK_INTEGRITY_REF_TAG = 1 << 3,
+ BLK_INTEGRITY_STACKED = 1 << 4,
};
-struct blk_integrity_iter {
- void *prot_buf;
- void *data_buf;
- sector_t seed;
- unsigned int data_size;
- unsigned short interval;
- unsigned char tuple_size;
- unsigned char pi_offset;
- const char *disk_name;
-};
-
-typedef blk_status_t (integrity_processing_fn) (struct blk_integrity_iter *);
-typedef void (integrity_prepare_fn) (struct request *);
-typedef void (integrity_complete_fn) (struct request *, unsigned int);
-
-struct blk_integrity_profile {
- integrity_processing_fn *generate_fn;
- integrity_processing_fn *verify_fn;
- integrity_prepare_fn *prepare_fn;
- integrity_complete_fn *complete_fn;
- const char *name;
-};
+const char *blk_integrity_profile_name(struct blk_integrity *bi);
+bool queue_limits_stack_integrity(struct queue_limits *t,
+ struct queue_limits *b);
+static inline bool queue_limits_stack_integrity_bdev(struct queue_limits *t,
+ struct block_device *bdev)
+{
+ return queue_limits_stack_integrity(t, &bdev->bd_disk->queue->limits);
+}
#ifdef CONFIG_BLK_DEV_INTEGRITY
-void blk_integrity_register(struct gendisk *, struct blk_integrity *);
-void blk_integrity_unregister(struct gendisk *);
-int blk_integrity_compare(struct gendisk *, struct gendisk *);
int blk_rq_map_integrity_sg(struct request_queue *, struct bio *,
struct scatterlist *);
int blk_rq_count_integrity_sg(struct request_queue *, struct bio *);
-static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk)
+static inline bool
+blk_integrity_queue_supports_integrity(struct request_queue *q)
{
- struct blk_integrity *bi = &disk->queue->integrity;
+ return q->limits.integrity.tuple_size;
+}
- if (!bi->profile)
+static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk)
+{
+ if (!blk_integrity_queue_supports_integrity(disk->queue))
return NULL;
-
- return bi;
+ return &disk->queue->limits.integrity;
}
static inline struct blk_integrity *
@@ -60,12 +47,6 @@ bdev_get_integrity(struct block_device *bdev)
return blk_get_integrity(bdev->bd_disk);
}
-static inline bool
-blk_integrity_queue_supports_integrity(struct request_queue *q)
-{
- return q->integrity.profile;
-}
-
static inline unsigned short
queue_max_integrity_segments(const struct request_queue *q)
{
@@ -100,14 +81,13 @@ static inline bool blk_integrity_rq(struct request *rq)
}
/*
- * Return the first bvec that contains integrity data. Only drivers that are
- * limited to a single integrity segment should use this helper.
+ * Return the current bvec that contains the integrity data. bip_iter may be
+ * advanced to iterate over the integrity data.
*/
-static inline struct bio_vec *rq_integrity_vec(struct request *rq)
+static inline struct bio_vec rq_integrity_vec(struct request *rq)
{
- if (WARN_ON_ONCE(queue_max_integrity_segments(rq->q) > 1))
- return NULL;
- return rq->bio->bi_integrity->bip_vec;
+ return mp_bvec_iter_bvec(rq->bio->bi_integrity->bip_vec,
+ rq->bio->bi_integrity->bip_iter);
}
#else /* CONFIG_BLK_DEV_INTEGRITY */
static inline int blk_rq_count_integrity_sg(struct request_queue *q,
@@ -134,17 +114,6 @@ blk_integrity_queue_supports_integrity(struct request_queue *q)
{
return false;
}
-static inline int blk_integrity_compare(struct gendisk *a, struct gendisk *b)
-{
- return 0;
-}
-static inline void blk_integrity_register(struct gendisk *d,
- struct blk_integrity *b)
-{
-}
-static inline void blk_integrity_unregister(struct gendisk *d)
-{
-}
static inline unsigned short
queue_max_integrity_segments(const struct request_queue *q)
{
@@ -167,9 +136,11 @@ static inline int blk_integrity_rq(struct request *rq)
return 0;
}
-static inline struct bio_vec *rq_integrity_vec(struct request *rq)
+static inline struct bio_vec rq_integrity_vec(struct request *rq)
{
- return NULL;
+ /* the optimizer will remove all calls to this function */
+ return (struct bio_vec){ };
}
#endif /* CONFIG_BLK_DEV_INTEGRITY */
+
#endif /* _LINUX_BLK_INTEGRITY_H */
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 781c4500491b..632edd71f8c6 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -162,6 +162,11 @@ typedef u16 blk_short_t;
*/
#define BLK_STS_DURATION_LIMIT ((__force blk_status_t)17)
+/*
+ * Invalid size or alignment.
+ */
+#define BLK_STS_INVAL ((__force blk_status_t)19)
+
/**
* blk_path_error - returns true if error may be path related
* @error: status the request was completed with
@@ -370,7 +375,7 @@ enum req_flag_bits {
__REQ_SWAP, /* swap I/O */
__REQ_DRV, /* for driver use */
__REQ_FS_PRIVATE, /* for file system (submitter) use */
-
+ __REQ_ATOMIC, /* for atomic write operations */
/*
* Command specific flags, keep last:
*/
@@ -402,6 +407,7 @@ enum req_flag_bits {
#define REQ_SWAP (__force blk_opf_t)(1ULL << __REQ_SWAP)
#define REQ_DRV (__force blk_opf_t)(1ULL << __REQ_DRV)
#define REQ_FS_PRIVATE (__force blk_opf_t)(1ULL << __REQ_FS_PRIVATE)
+#define REQ_ATOMIC (__force blk_opf_t)(1ULL << __REQ_ATOMIC)
#define REQ_NOUNMAP (__force blk_opf_t)(1ULL << __REQ_NOUNMAP)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 24c36929920b..b8196e219ac2 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -105,9 +105,16 @@ enum {
struct disk_events;
struct badblocks;
+enum blk_integrity_checksum {
+ BLK_INTEGRITY_CSUM_NONE = 0,
+ BLK_INTEGRITY_CSUM_IP = 1,
+ BLK_INTEGRITY_CSUM_CRC = 2,
+ BLK_INTEGRITY_CSUM_CRC64 = 3,
+} __packed ;
+
struct blk_integrity {
- const struct blk_integrity_profile *profile;
unsigned char flags;
+ enum blk_integrity_checksum csum_type;
unsigned char tuple_size;
unsigned char pi_offset;
unsigned char interval_exp;
@@ -261,6 +268,7 @@ static inline dev_t disk_devt(struct gendisk *disk)
return MKDEV(disk->major, disk->first_minor);
}
+/* blk_validate_limits() validates bsize, so drivers don't usually need to */
static inline int blk_validate_block_size(unsigned long bsize)
{
if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize))
@@ -275,17 +283,75 @@ static inline bool blk_op_is_passthrough(blk_opf_t op)
return op == REQ_OP_DRV_IN || op == REQ_OP_DRV_OUT;
}
+/* flags set by the driver in queue_limits.features */
+typedef unsigned int __bitwise blk_features_t;
+
+/* supports a volatile write cache */
+#define BLK_FEAT_WRITE_CACHE ((__force blk_features_t)(1u << 0))
+
+/* supports passing on the FUA bit */
+#define BLK_FEAT_FUA ((__force blk_features_t)(1u << 1))
+
+/* rotational device (hard drive or floppy) */
+#define BLK_FEAT_ROTATIONAL ((__force blk_features_t)(1u << 2))
+
+/* contributes to the random number pool */
+#define BLK_FEAT_ADD_RANDOM ((__force blk_features_t)(1u << 3))
+
+/* do disk/partitions IO accounting */
+#define BLK_FEAT_IO_STAT ((__force blk_features_t)(1u << 4))
+
+/* don't modify data until writeback is done */
+#define BLK_FEAT_STABLE_WRITES ((__force blk_features_t)(1u << 5))
+
+/* always completes in submit context */
+#define BLK_FEAT_SYNCHRONOUS ((__force blk_features_t)(1u << 6))
+
+/* supports REQ_NOWAIT */
+#define BLK_FEAT_NOWAIT ((__force blk_features_t)(1u << 7))
+
+/* supports DAX */
+#define BLK_FEAT_DAX ((__force blk_features_t)(1u << 8))
+
+/* supports I/O polling */
+#define BLK_FEAT_POLL ((__force blk_features_t)(1u << 9))
+
+/* is a zoned device */
+#define BLK_FEAT_ZONED ((__force blk_features_t)(1u << 10))
+
+/* supports PCI(e) p2p requests */
+#define BLK_FEAT_PCI_P2PDMA ((__force blk_features_t)(1u << 12))
+
+/* skip this queue in blk_mq_(un)quiesce_tagset */
+#define BLK_FEAT_SKIP_TAGSET_QUIESCE ((__force blk_features_t)(1u << 13))
+
+/* bounce all highmem pages */
+#define BLK_FEAT_BOUNCE_HIGH ((__force blk_features_t)(1u << 14))
+
+/* undocumented magic for bcache */
+#define BLK_FEAT_RAID_PARTIAL_STRIPES_EXPENSIVE \
+ ((__force blk_features_t)(1u << 15))
+
/*
- * BLK_BOUNCE_NONE: never bounce (default)
- * BLK_BOUNCE_HIGH: bounce all highmem pages
+ * Flags automatically inherited when stacking limits.
*/
-enum blk_bounce {
- BLK_BOUNCE_NONE,
- BLK_BOUNCE_HIGH,
-};
+#define BLK_FEAT_INHERIT_MASK \
+ (BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA | BLK_FEAT_ROTATIONAL | \
+ BLK_FEAT_STABLE_WRITES | BLK_FEAT_ZONED | BLK_FEAT_BOUNCE_HIGH | \
+ BLK_FEAT_RAID_PARTIAL_STRIPES_EXPENSIVE)
+
+/* internal flags in queue_limits.flags */
+typedef unsigned int __bitwise blk_flags_t;
+
+/* do not send FLUSH/FUA commands despite advertising a write cache */
+#define BLK_FLAG_WRITE_CACHE_DISABLED ((__force blk_flags_t)(1u << 0))
+
+/* I/O topology is misaligned */
+#define BLK_FLAG_MISALIGNED ((__force blk_flags_t)(1u << 1))
struct queue_limits {
- enum blk_bounce bounce;
+ blk_features_t features;
+ blk_flags_t flags;
unsigned long seg_boundary_mask;
unsigned long virt_boundary_mask;
@@ -310,14 +376,20 @@ struct queue_limits {
unsigned int discard_alignment;
unsigned int zone_write_granularity;
+ /* atomic write limits */
+ unsigned int atomic_write_hw_max;
+ unsigned int atomic_write_max_sectors;
+ unsigned int atomic_write_hw_boundary;
+ unsigned int atomic_write_boundary_sectors;
+ unsigned int atomic_write_hw_unit_min;
+ unsigned int atomic_write_unit_min;
+ unsigned int atomic_write_hw_unit_max;
+ unsigned int atomic_write_unit_max;
+
unsigned short max_segments;
unsigned short max_integrity_segments;
unsigned short max_discard_segments;
- unsigned char misaligned;
- unsigned char discard_misaligned;
- unsigned char raid_partial_stripes_expensive;
- bool zoned;
unsigned int max_open_zones;
unsigned int max_active_zones;
@@ -327,13 +399,14 @@ struct queue_limits {
* due to possible offsets.
*/
unsigned int dma_alignment;
+ unsigned int dma_pad_mask;
+
+ struct blk_integrity integrity;
};
typedef int (*report_zones_cb)(struct blk_zone *zone, unsigned int idx,
void *data);
-void disk_set_zoned(struct gendisk *disk);
-
#define BLK_ALL_ZONES ((unsigned int)-1)
int blkdev_report_zones(struct block_device *bdev, sector_t sector,
unsigned int nr_zones, report_zones_cb cb, void *data);
@@ -414,10 +487,6 @@ struct request_queue {
struct queue_limits limits;
-#ifdef CONFIG_BLK_DEV_INTEGRITY
- struct blk_integrity integrity;
-#endif /* CONFIG_BLK_DEV_INTEGRITY */
-
#ifdef CONFIG_PM
struct device *dev;
enum rpm_status rpm_status;
@@ -439,8 +508,6 @@ struct request_queue {
*/
int id;
- unsigned int dma_pad_mask;
-
/*
* queue settings
*/
@@ -526,38 +593,20 @@ struct request_queue {
#define QUEUE_FLAG_NOMERGES 3 /* disable merge attempts */
#define QUEUE_FLAG_SAME_COMP 4 /* complete on same CPU-group */
#define QUEUE_FLAG_FAIL_IO 5 /* fake timeout */
-#define QUEUE_FLAG_NONROT 6 /* non-rotational device (SSD) */
-#define QUEUE_FLAG_VIRT QUEUE_FLAG_NONROT /* paravirt device */
-#define QUEUE_FLAG_IO_STAT 7 /* do disk/partitions IO accounting */
#define QUEUE_FLAG_NOXMERGES 9 /* No extended merges */
-#define QUEUE_FLAG_ADD_RANDOM 10 /* Contributes to random pool */
-#define QUEUE_FLAG_SYNCHRONOUS 11 /* always completes in submit context */
#define QUEUE_FLAG_SAME_FORCE 12 /* force complete on same CPU */
-#define QUEUE_FLAG_HW_WC 13 /* Write back caching supported */
#define QUEUE_FLAG_INIT_DONE 14 /* queue is initialized */
-#define QUEUE_FLAG_STABLE_WRITES 15 /* don't modify blks until WB is done */
-#define QUEUE_FLAG_POLL 16 /* IO polling enabled if set */
-#define QUEUE_FLAG_WC 17 /* Write back caching */
-#define QUEUE_FLAG_FUA 18 /* device supports FUA writes */
-#define QUEUE_FLAG_DAX 19 /* device supports DAX */
#define QUEUE_FLAG_STATS 20 /* track IO start and completion times */
#define QUEUE_FLAG_REGISTERED 22 /* queue has been registered to a disk */
#define QUEUE_FLAG_QUIESCED 24 /* queue has been quiesced */
-#define QUEUE_FLAG_PCI_P2PDMA 25 /* device supports PCI p2p requests */
-#define QUEUE_FLAG_ZONE_RESETALL 26 /* supports Zone Reset All */
#define QUEUE_FLAG_RQ_ALLOC_TIME 27 /* record rq->alloc_time_ns */
#define QUEUE_FLAG_HCTX_ACTIVE 28 /* at least one blk-mq hctx is active */
-#define QUEUE_FLAG_NOWAIT 29 /* device supports NOWAIT */
#define QUEUE_FLAG_SQ_SCHED 30 /* single queue style io dispatch */
-#define QUEUE_FLAG_SKIP_TAGSET_QUIESCE 31 /* quiesce_tagset skip the queue*/
-#define QUEUE_FLAG_MQ_DEFAULT ((1UL << QUEUE_FLAG_IO_STAT) | \
- (1UL << QUEUE_FLAG_SAME_COMP) | \
- (1UL << QUEUE_FLAG_NOWAIT))
+#define QUEUE_FLAG_MQ_DEFAULT (1UL << QUEUE_FLAG_SAME_COMP)
void blk_queue_flag_set(unsigned int flag, struct request_queue *q);
void blk_queue_flag_clear(unsigned int flag, struct request_queue *q);
-bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
#define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
#define blk_queue_dying(q) test_bit(QUEUE_FLAG_DYING, &(q)->queue_flags)
@@ -565,16 +614,10 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
#define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags)
#define blk_queue_noxmerges(q) \
test_bit(QUEUE_FLAG_NOXMERGES, &(q)->queue_flags)
-#define blk_queue_nonrot(q) test_bit(QUEUE_FLAG_NONROT, &(q)->queue_flags)
-#define blk_queue_stable_writes(q) \
- test_bit(QUEUE_FLAG_STABLE_WRITES, &(q)->queue_flags)
-#define blk_queue_io_stat(q) test_bit(QUEUE_FLAG_IO_STAT, &(q)->queue_flags)
-#define blk_queue_add_random(q) test_bit(QUEUE_FLAG_ADD_RANDOM, &(q)->queue_flags)
-#define blk_queue_zone_resetall(q) \
- test_bit(QUEUE_FLAG_ZONE_RESETALL, &(q)->queue_flags)
-#define blk_queue_dax(q) test_bit(QUEUE_FLAG_DAX, &(q)->queue_flags)
-#define blk_queue_pci_p2pdma(q) \
- test_bit(QUEUE_FLAG_PCI_P2PDMA, &(q)->queue_flags)
+#define blk_queue_nonrot(q) (!((q)->limits.features & BLK_FEAT_ROTATIONAL))
+#define blk_queue_io_stat(q) ((q)->limits.features & BLK_FEAT_IO_STAT)
+#define blk_queue_dax(q) ((q)->limits.features & BLK_FEAT_DAX)
+#define blk_queue_pci_p2pdma(q) ((q)->limits.features & BLK_FEAT_PCI_P2PDMA)
#ifdef CONFIG_BLK_RQ_ALLOC_TIME
#define blk_queue_rq_alloc_time(q) \
test_bit(QUEUE_FLAG_RQ_ALLOC_TIME, &(q)->queue_flags)
@@ -590,7 +633,7 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
#define blk_queue_registered(q) test_bit(QUEUE_FLAG_REGISTERED, &(q)->queue_flags)
#define blk_queue_sq_sched(q) test_bit(QUEUE_FLAG_SQ_SCHED, &(q)->queue_flags)
#define blk_queue_skip_tagset_quiesce(q) \
- test_bit(QUEUE_FLAG_SKIP_TAGSET_QUIESCE, &(q)->queue_flags)
+ ((q)->limits.features & BLK_FEAT_SKIP_TAGSET_QUIESCE)
extern void blk_set_pm_only(struct request_queue *q);
extern void blk_clear_pm_only(struct request_queue *q);
@@ -620,16 +663,26 @@ static inline enum rpm_status queue_rpm_status(struct request_queue *q)
static inline bool blk_queue_is_zoned(struct request_queue *q)
{
- return IS_ENABLED(CONFIG_BLK_DEV_ZONED) && q->limits.zoned;
+ return IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
+ (q->limits.features & BLK_FEAT_ZONED);
}
#ifdef CONFIG_BLK_DEV_ZONED
-unsigned int bdev_nr_zones(struct block_device *bdev);
-
static inline unsigned int disk_nr_zones(struct gendisk *disk)
{
- return blk_queue_is_zoned(disk->queue) ? disk->nr_zones : 0;
+ return disk->nr_zones;
+}
+bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs);
+#else /* CONFIG_BLK_DEV_ZONED */
+static inline unsigned int disk_nr_zones(struct gendisk *disk)
+{
+ return 0;
}
+static inline bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs)
+{
+ return false;
+}
+#endif /* CONFIG_BLK_DEV_ZONED */
static inline unsigned int disk_zone_no(struct gendisk *disk, sector_t sector)
{
@@ -638,16 +691,9 @@ static inline unsigned int disk_zone_no(struct gendisk *disk, sector_t sector)
return sector >> ilog2(disk->queue->limits.chunk_sectors);
}
-static inline void disk_set_max_open_zones(struct gendisk *disk,
- unsigned int max_open_zones)
-{
- disk->queue->limits.max_open_zones = max_open_zones;
-}
-
-static inline void disk_set_max_active_zones(struct gendisk *disk,
- unsigned int max_active_zones)
+static inline unsigned int bdev_nr_zones(struct block_device *bdev)
{
- disk->queue->limits.max_active_zones = max_active_zones;
+ return disk_nr_zones(bdev->bd_disk);
}
static inline unsigned int bdev_max_open_zones(struct block_device *bdev)
@@ -660,36 +706,6 @@ static inline unsigned int bdev_max_active_zones(struct block_device *bdev)
return bdev->bd_disk->queue->limits.max_active_zones;
}
-bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs);
-#else /* CONFIG_BLK_DEV_ZONED */
-static inline unsigned int bdev_nr_zones(struct block_device *bdev)
-{
- return 0;
-}
-
-static inline unsigned int disk_nr_zones(struct gendisk *disk)
-{
- return 0;
-}
-static inline unsigned int disk_zone_no(struct gendisk *disk, sector_t sector)
-{
- return 0;
-}
-static inline unsigned int bdev_max_open_zones(struct block_device *bdev)
-{
- return 0;
-}
-
-static inline unsigned int bdev_max_active_zones(struct block_device *bdev)
-{
- return 0;
-}
-static inline bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs)
-{
- return false;
-}
-#endif /* CONFIG_BLK_DEV_ZONED */
-
static inline unsigned int blk_queue_depth(struct request_queue *q)
{
if (q->queue_depth)
@@ -880,14 +896,15 @@ static inline bool bio_straddles_zones(struct bio *bio)
}
/*
- * Return how much of the chunk is left to be used for I/O at a given offset.
+ * Return how much within the boundary is left to be used for I/O at a given
+ * offset.
*/
-static inline unsigned int blk_chunk_sectors_left(sector_t offset,
- unsigned int chunk_sectors)
+static inline unsigned int blk_boundary_sectors_left(sector_t offset,
+ unsigned int boundary_sectors)
{
- if (unlikely(!is_power_of_2(chunk_sectors)))
- return chunk_sectors - sector_div(offset, chunk_sectors);
- return chunk_sectors - (offset & (chunk_sectors - 1));
+ if (unlikely(!is_power_of_2(boundary_sectors)))
+ return boundary_sectors - sector_div(offset, boundary_sectors);
+ return boundary_sectors - (offset & (boundary_sectors - 1));
}
/**
@@ -904,7 +921,6 @@ static inline unsigned int blk_chunk_sectors_left(sector_t offset,
*/
static inline struct queue_limits
queue_limits_start_update(struct request_queue *q)
- __acquires(q->limits_lock)
{
mutex_lock(&q->limits_lock);
return q->limits;
@@ -927,26 +943,31 @@ static inline void queue_limits_cancel_update(struct request_queue *q)
}
/*
+ * These helpers are for drivers that have sloppy feature negotiation and might
+ * have to disable DISCARD, WRITE_ZEROES or SECURE_DISCARD from the I/O
+ * completion handler when the device returned an indicator that the respective
+ * feature is not actually supported. They are racy and the driver needs to
+ * cope with that. Try to avoid this scheme if you can.
+ */
+static inline void blk_queue_disable_discard(struct request_queue *q)
+{
+ q->limits.max_discard_sectors = 0;
+}
+
+static inline void blk_queue_disable_secure_erase(struct request_queue *q)
+{
+ q->limits.max_secure_erase_sectors = 0;
+}
+
+static inline void blk_queue_disable_write_zeroes(struct request_queue *q)
+{
+ q->limits.max_write_zeroes_sectors = 0;
+}
+
+/*
* Access functions for manipulating queue properties
*/
-extern void blk_queue_chunk_sectors(struct request_queue *, unsigned int);
-void blk_queue_max_secure_erase_sectors(struct request_queue *q,
- unsigned int max_sectors);
-extern void blk_queue_max_discard_sectors(struct request_queue *q,
- unsigned int max_discard_sectors);
-extern void blk_queue_max_write_zeroes_sectors(struct request_queue *q,
- unsigned int max_write_same_sectors);
-extern void blk_queue_logical_block_size(struct request_queue *, unsigned int);
-extern void blk_queue_max_zone_append_sectors(struct request_queue *q,
- unsigned int max_zone_append_sectors);
-extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
-void blk_queue_zone_write_granularity(struct request_queue *q,
- unsigned int size);
-extern void blk_queue_alignment_offset(struct request_queue *q,
- unsigned int alignment);
-void disk_update_readahead(struct gendisk *disk);
extern void blk_limits_io_min(struct queue_limits *limits, unsigned int min);
-extern void blk_queue_io_min(struct request_queue *q, unsigned int min);
extern void blk_limits_io_opt(struct queue_limits *limits, unsigned int opt);
extern void blk_set_queue_depth(struct request_queue *q, unsigned int depth);
extern void blk_set_stacking_limits(struct queue_limits *lim);
@@ -954,9 +975,7 @@ extern int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
sector_t offset);
void queue_limits_stack_bdev(struct queue_limits *t, struct block_device *bdev,
sector_t offset, const char *pfx);
-extern void blk_queue_update_dma_pad(struct request_queue *, unsigned int);
extern void blk_queue_rq_timeout(struct request_queue *, unsigned int);
-extern void blk_queue_write_cache(struct request_queue *q, bool enabled, bool fua);
struct blk_independent_access_ranges *
disk_alloc_independent_access_ranges(struct gendisk *disk, int nr_ia_ranges);
@@ -1077,6 +1096,7 @@ int blkdev_issue_secure_erase(struct block_device *bdev, sector_t sector,
#define BLKDEV_ZERO_NOUNMAP (1 << 0) /* do not free blocks */
#define BLKDEV_ZERO_NOFALLBACK (1 << 1) /* don't write explicit zeroes */
+#define BLKDEV_ZERO_KILLABLE (1 << 2) /* interruptible by fatal signals */
extern int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp_mask, struct bio **biop,
@@ -1204,12 +1224,7 @@ static inline unsigned int bdev_max_segments(struct block_device *bdev)
static inline unsigned queue_logical_block_size(const struct request_queue *q)
{
- int retval = 512;
-
- if (q && q->limits.logical_block_size)
- retval = q->limits.logical_block_size;
-
- return retval;
+ return q->limits.logical_block_size;
}
static inline unsigned int bdev_logical_block_size(struct block_device *bdev)
@@ -1295,29 +1310,38 @@ static inline bool bdev_nonrot(struct block_device *bdev)
static inline bool bdev_synchronous(struct block_device *bdev)
{
- return test_bit(QUEUE_FLAG_SYNCHRONOUS,
- &bdev_get_queue(bdev)->queue_flags);
+ return bdev->bd_disk->queue->limits.features & BLK_FEAT_SYNCHRONOUS;
}
static inline bool bdev_stable_writes(struct block_device *bdev)
{
- return test_bit(QUEUE_FLAG_STABLE_WRITES,
- &bdev_get_queue(bdev)->queue_flags);
+ struct request_queue *q = bdev_get_queue(bdev);
+
+ if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) &&
+ q->limits.integrity.csum_type != BLK_INTEGRITY_CSUM_NONE)
+ return true;
+ return q->limits.features & BLK_FEAT_STABLE_WRITES;
+}
+
+static inline bool blk_queue_write_cache(struct request_queue *q)
+{
+ return (q->limits.features & BLK_FEAT_WRITE_CACHE) &&
+ !(q->limits.flags & BLK_FLAG_WRITE_CACHE_DISABLED);
}
static inline bool bdev_write_cache(struct block_device *bdev)
{
- return test_bit(QUEUE_FLAG_WC, &bdev_get_queue(bdev)->queue_flags);
+ return blk_queue_write_cache(bdev_get_queue(bdev));
}
static inline bool bdev_fua(struct block_device *bdev)
{
- return test_bit(QUEUE_FLAG_FUA, &bdev_get_queue(bdev)->queue_flags);
+ return bdev_get_queue(bdev)->limits.features & BLK_FEAT_FUA;
}
static inline bool bdev_nowait(struct block_device *bdev)
{
- return test_bit(QUEUE_FLAG_NOWAIT, &bdev_get_queue(bdev)->queue_flags);
+ return bdev->bd_disk->queue->limits.features & BLK_FEAT_NOWAIT;
}
static inline bool bdev_is_zoned(struct block_device *bdev)
@@ -1359,7 +1383,31 @@ static inline bool bdev_is_zone_start(struct block_device *bdev,
static inline int queue_dma_alignment(const struct request_queue *q)
{
- return q ? q->limits.dma_alignment : 511;
+ return q->limits.dma_alignment;
+}
+
+static inline unsigned int
+queue_atomic_write_unit_max_bytes(const struct request_queue *q)
+{
+ return q->limits.atomic_write_unit_max;
+}
+
+static inline unsigned int
+queue_atomic_write_unit_min_bytes(const struct request_queue *q)
+{
+ return q->limits.atomic_write_unit_min;
+}
+
+static inline unsigned int
+queue_atomic_write_boundary_bytes(const struct request_queue *q)
+{
+ return q->limits.atomic_write_boundary_sectors << SECTOR_SHIFT;
+}
+
+static inline unsigned int
+queue_atomic_write_max_bytes(const struct request_queue *q)
+{
+ return q->limits.atomic_write_max_sectors << SECTOR_SHIFT;
}
static inline unsigned int bdev_dma_alignment(struct block_device *bdev)
@@ -1374,10 +1422,16 @@ static inline bool bdev_iter_is_aligned(struct block_device *bdev,
bdev_logical_block_size(bdev) - 1);
}
+static inline int blk_lim_dma_alignment_and_pad(struct queue_limits *lim)
+{
+ return lim->dma_alignment | lim->dma_pad_mask;
+}
+
static inline int blk_rq_aligned(struct request_queue *q, unsigned long addr,
unsigned int len)
{
- unsigned int alignment = queue_dma_alignment(q) | q->dma_pad_mask;
+ unsigned int alignment = blk_lim_dma_alignment_and_pad(&q->limits);
+
return !(addr & alignment) && !(len & alignment);
}
@@ -1563,7 +1617,7 @@ int sync_blockdev(struct block_device *bdev);
int sync_blockdev_range(struct block_device *bdev, loff_t lstart, loff_t lend);
int sync_blockdev_nowait(struct block_device *bdev);
void sync_bdevs(bool wait);
-void bdev_statx_dioalign(struct inode *inode, struct kstat *stat);
+void bdev_statx(struct path *, struct kstat *, u32);
void printk_all_partitions(void);
int __init early_lookup_bdev(const char *pathname, dev_t *dev);
#else
@@ -1581,7 +1635,8 @@ static inline int sync_blockdev_nowait(struct block_device *bdev)
static inline void sync_bdevs(bool wait)
{
}
-static inline void bdev_statx_dioalign(struct inode *inode, struct kstat *stat)
+static inline void bdev_statx(struct path *path, struct kstat *stat,
+ u32 request_mask)
{
}
static inline void printk_all_partitions(void)
@@ -1603,6 +1658,27 @@ struct io_comp_batch {
void (*complete)(struct io_comp_batch *);
};
+static inline bool bdev_can_atomic_write(struct block_device *bdev)
+{
+ struct request_queue *bd_queue = bdev->bd_queue;
+ struct queue_limits *limits = &bd_queue->limits;
+
+ if (!limits->atomic_write_unit_min)
+ return false;
+
+ if (bdev_is_partition(bdev)) {
+ sector_t bd_start_sect = bdev->bd_start_sect;
+ unsigned int alignment =
+ max(limits->atomic_write_unit_min,
+ limits->atomic_write_hw_boundary);
+
+ if (!IS_ALIGNED(bd_start_sect, alignment >> SECTOR_SHIFT))
+ return false;
+ }
+
+ return true;
+}
+
#define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { }
#endif /* _LINUX_BLKDEV_H */
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index bd1e361b351c..f41c7f0ef91e 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -280,4 +280,18 @@ static inline void *bvec_virt(struct bio_vec *bvec)
return page_address(bvec->bv_page) + bvec->bv_offset;
}
+/**
+ * bvec_phys - return the physical address for a bvec
+ * @bvec: bvec to return the physical address for
+ */
+static inline phys_addr_t bvec_phys(const struct bio_vec *bvec)
+{
+ /*
+ * Note this open codes page_to_phys because page_to_phys is defined in
+ * <asm/io.h>, which we don't want to pull in here. If it ever moves to
+ * a sensible place we should start using it.
+ */
+ return PFN_PHYS(page_to_pfn(bvec->bv_page)) + bvec->bv_offset;
+}
+
#endif /* __LINUX_BVEC_H */
diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h
index 2cb15fe4fe12..3dde175f4108 100644
--- a/include/linux/cacheinfo.h
+++ b/include/linux/cacheinfo.h
@@ -3,6 +3,7 @@
#define _LINUX_CACHEINFO_H
#include <linux/bitops.h>
+#include <linux/cpuhplock.h>
#include <linux/cpumask.h>
#include <linux/smp.h>
@@ -113,23 +114,37 @@ int acpi_get_cache_info(unsigned int cpu,
const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf);
/*
- * Get the id of the cache associated with @cpu at level @level.
+ * Get the cacheinfo structure for the cache associated with @cpu at
+ * level @level.
* cpuhp lock must be held.
*/
-static inline int get_cpu_cacheinfo_id(int cpu, int level)
+static inline struct cacheinfo *get_cpu_cacheinfo_level(int cpu, int level)
{
struct cpu_cacheinfo *ci = get_cpu_cacheinfo(cpu);
int i;
+ lockdep_assert_cpus_held();
+
for (i = 0; i < ci->num_leaves; i++) {
if (ci->info_list[i].level == level) {
if (ci->info_list[i].attributes & CACHE_ID)
- return ci->info_list[i].id;
- return -1;
+ return &ci->info_list[i];
+ return NULL;
}
}
- return -1;
+ return NULL;
+}
+
+/*
+ * Get the id of the cache associated with @cpu at level @level.
+ * cpuhp lock must be held.
+ */
+static inline int get_cpu_cacheinfo_id(int cpu, int level)
+{
+ struct cacheinfo *ci = get_cpu_cacheinfo_level(cpu, level);
+
+ return ci ? ci->id : -1;
}
#ifdef CONFIG_ARM64
diff --git a/include/linux/cc_platform.h b/include/linux/cc_platform.h
index 60693a145894..caa4b4430634 100644
--- a/include/linux/cc_platform.h
+++ b/include/linux/cc_platform.h
@@ -82,16 +82,6 @@ enum cc_attr {
CC_ATTR_GUEST_SEV_SNP,
/**
- * @CC_ATTR_HOTPLUG_DISABLED: Hotplug is not supported or disabled.
- *
- * The platform/OS is running as a guest/virtual machine does not
- * support CPU hotplug feature.
- *
- * Examples include TDX Guest.
- */
- CC_ATTR_HOTPLUG_DISABLED,
-
- /**
* @CC_ATTR_HOST_SEV_SNP: AMD SNP enabled on the host.
*
* The host kernel is running with the necessary features
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index ea48c861cd36..b36690ca0d3f 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -119,7 +119,12 @@ enum {
/*
* Enable hugetlb accounting for the memory controller.
*/
- CGRP_ROOT_MEMORY_HUGETLB_ACCOUNTING = (1 << 19),
+ CGRP_ROOT_MEMORY_HUGETLB_ACCOUNTING = (1 << 19),
+
+ /*
+ * Enable legacy local pids.events.
+ */
+ CGRP_ROOT_PIDS_LOCAL_EVENTS = (1 << 20),
};
/* cftype->flags */
diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h
index c2d09bc4f976..80c4181e194a 100644
--- a/include/linux/cleanup.h
+++ b/include/linux/cleanup.h
@@ -63,17 +63,20 @@
#define __free(_name) __cleanup(__free_##_name)
-#define __get_and_null_ptr(p) \
- ({ __auto_type __ptr = &(p); \
- __auto_type __val = *__ptr; \
- *__ptr = NULL; __val; })
+#define __get_and_null(p, nullvalue) \
+ ({ \
+ __auto_type __ptr = &(p); \
+ __auto_type __val = *__ptr; \
+ *__ptr = nullvalue; \
+ __val; \
+ })
static inline __must_check
const volatile void * __must_check_fn(const volatile void *val)
{ return val; }
#define no_free_ptr(p) \
- ((typeof(p)) __must_check_fn(__get_and_null_ptr(p)))
+ ((typeof(p)) __must_check_fn(__get_and_null(p, NULL)))
#define return_ptr(p) return no_free_ptr(p)
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 0ad8b550bb4b..d35b677b08fe 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -21,6 +21,7 @@
#include <asm/div64.h>
#include <asm/io.h>
+struct clocksource_base;
struct clocksource;
struct module;
@@ -50,6 +51,7 @@ struct module;
* multiplication
* @name: Pointer to clocksource name
* @list: List head for registration (internal)
+ * @freq_khz: Clocksource frequency in khz.
* @rating: Rating value for selection (higher is better)
* To avoid rating inflation the following
* list should give you a guide as to how
@@ -70,6 +72,8 @@ struct module;
* validate the clocksource from which the snapshot was
* taken.
* @flags: Flags describing special properties
+ * @base: Hardware abstraction for clock on which a clocksource
+ * is based
* @enable: Optional function to enable the clocksource
* @disable: Optional function to disable the clocksource
* @suspend: Optional suspend function for the clocksource
@@ -107,10 +111,12 @@ struct clocksource {
u64 max_cycles;
const char *name;
struct list_head list;
+ u32 freq_khz;
int rating;
enum clocksource_ids id;
enum vdso_clock_mode vdso_clock_mode;
unsigned long flags;
+ struct clocksource_base *base;
int (*enable)(struct clocksource *cs);
void (*disable)(struct clocksource *cs);
@@ -306,4 +312,25 @@ static inline unsigned int clocksource_get_max_watchdog_retry(void)
void clocksource_verify_percpu(struct clocksource *cs);
+/**
+ * struct clocksource_base - hardware abstraction for clock on which a clocksource
+ * is based
+ * @id: Defaults to CSID_GENERIC. The id value is used for conversion
+ * functions which require that the current clocksource is based
+ * on a clocksource_base with a particular ID in certain snapshot
+ * functions to allow callers to validate the clocksource from
+ * which the snapshot was taken.
+ * @freq_khz: Nominal frequency of the base clock in kHz
+ * @offset: Offset between the base clock and the clocksource
+ * @numerator: Numerator of the clock ratio between base clock and the clocksource
+ * @denominator: Denominator of the clock ratio between base clock and the clocksource
+ */
+struct clocksource_base {
+ enum clocksource_ids id;
+ u32 freq_khz;
+ u64 offset;
+ u32 numerator;
+ u32 denominator;
+};
+
#endif /* _LINUX_CLOCKSOURCE_H */
diff --git a/include/linux/clocksource_ids.h b/include/linux/clocksource_ids.h
index a4fa3436940c..2bb4d8c2f1b0 100644
--- a/include/linux/clocksource_ids.h
+++ b/include/linux/clocksource_ids.h
@@ -9,6 +9,7 @@ enum clocksource_ids {
CSID_X86_TSC_EARLY,
CSID_X86_TSC,
CSID_X86_KVM_CLK,
+ CSID_X86_ART,
CSID_MAX,
};
diff --git a/include/linux/closure.h b/include/linux/closure.h
index 59b8c06b11ff..2af44427107d 100644
--- a/include/linux/closure.h
+++ b/include/linux/closure.h
@@ -159,6 +159,7 @@ struct closure {
#ifdef CONFIG_DEBUG_CLOSURES
#define CLOSURE_MAGIC_DEAD 0xc054dead
#define CLOSURE_MAGIC_ALIVE 0xc054a11e
+#define CLOSURE_MAGIC_STACK 0xc05451cc
unsigned int magic;
struct list_head all;
@@ -323,12 +324,18 @@ static inline void closure_init_stack(struct closure *cl)
{
memset(cl, 0, sizeof(struct closure));
atomic_set(&cl->remaining, CLOSURE_REMAINING_INITIALIZER);
+#ifdef CONFIG_DEBUG_CLOSURES
+ cl->magic = CLOSURE_MAGIC_STACK;
+#endif
}
static inline void closure_init_stack_release(struct closure *cl)
{
memset(cl, 0, sizeof(struct closure));
atomic_set_release(&cl->remaining, CLOSURE_REMAINING_INITIALIZER);
+#ifdef CONFIG_DEBUG_CLOSURES
+ cl->magic = CLOSURE_MAGIC_STACK;
+#endif
}
/**
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 8c252e073bd8..68a24a3a6979 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -194,9 +194,17 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
* This data_race() macro is useful for situations in which data races
* should be forgiven. One example is diagnostic code that accesses
* shared variables but is not a part of the core synchronization design.
+ * For example, if accesses to a given variable are protected by a lock,
+ * except for diagnostic code, then the accesses under the lock should
+ * be plain C-language accesses and those in the diagnostic code should
+ * use data_race(). This way, KCSAN will complain if buggy lockless
+ * accesses to that variable are introduced, even if the buggy accesses
+ * are protected by READ_ONCE() or WRITE_ONCE().
*
* This macro *does not* affect normal code generation, but is a hint
- * to tooling that data races here are to be ignored.
+ * to tooling that data races here are to be ignored. If the access must
+ * be atomic *and* KCSAN should ignore the access, use both data_race()
+ * and READ_ONCE(), for example, data_race(READ_ONCE(x)).
*/
#define data_race(expr) \
({ \
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index 2606711adb18..c771e9d0d0b9 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -216,6 +216,9 @@ struct configfs_group_operations {
struct config_group *(*make_group)(struct config_group *group, const char *name);
void (*disconnect_notify)(struct config_group *group, struct config_item *item);
void (*drop_item)(struct config_group *group, struct config_item *item);
+ bool (*is_visible)(struct config_item *item, struct configfs_attribute *attr, int n);
+ bool (*is_bin_visible)(struct config_item *item, struct configfs_bin_attribute *attr,
+ int n);
};
struct configfs_subsystem {
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 861c3bfc5f17..a8926d0a28cd 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -18,6 +18,7 @@
#include <linux/compiler.h>
#include <linux/cpumask.h>
#include <linux/cpuhotplug.h>
+#include <linux/cpuhplock.h>
#include <linux/cpu_smt.h>
struct device;
@@ -132,38 +133,6 @@ static inline int add_cpu(unsigned int cpu) { return 0;}
#endif /* CONFIG_SMP */
extern const struct bus_type cpu_subsys;
-extern int lockdep_is_cpus_held(void);
-
-#ifdef CONFIG_HOTPLUG_CPU
-extern void cpus_write_lock(void);
-extern void cpus_write_unlock(void);
-extern void cpus_read_lock(void);
-extern void cpus_read_unlock(void);
-extern int cpus_read_trylock(void);
-extern void lockdep_assert_cpus_held(void);
-extern void cpu_hotplug_disable(void);
-extern void cpu_hotplug_enable(void);
-void clear_tasks_mm_cpumask(int cpu);
-int remove_cpu(unsigned int cpu);
-int cpu_device_down(struct device *dev);
-extern void smp_shutdown_nonboot_cpus(unsigned int primary_cpu);
-
-#else /* CONFIG_HOTPLUG_CPU */
-
-static inline void cpus_write_lock(void) { }
-static inline void cpus_write_unlock(void) { }
-static inline void cpus_read_lock(void) { }
-static inline void cpus_read_unlock(void) { }
-static inline int cpus_read_trylock(void) { return true; }
-static inline void lockdep_assert_cpus_held(void) { }
-static inline void cpu_hotplug_disable(void) { }
-static inline void cpu_hotplug_enable(void) { }
-static inline int remove_cpu(unsigned int cpu) { return -EPERM; }
-static inline void smp_shutdown_nonboot_cpus(unsigned int primary_cpu) { }
-#endif /* !CONFIG_HOTPLUG_CPU */
-
-DEFINE_LOCK_GUARD_0(cpus_read_lock, cpus_read_lock(), cpus_read_unlock())
-
#ifdef CONFIG_PM_SLEEP_SMP
extern int freeze_secondary_cpus(int primary);
extern void thaw_secondary_cpus(void);
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 7a5785f405b6..89f5c34ce4df 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -27,7 +27,7 @@
* startup callbacks sequentially from CPUHP_OFFLINE + 1 to CPUHP_ONLINE
* during a CPU online operation. During a CPU offline operation the
* installed teardown callbacks are invoked in the reverse order from
- * CPU_ONLINE - 1 down to CPUHP_OFFLINE.
+ * CPUHP_ONLINE - 1 down to CPUHP_OFFLINE.
*
* The state space has three sections: PREPARE, STARTING and ONLINE.
*
@@ -171,6 +171,7 @@ enum cpuhp_state {
CPUHP_AP_ARMADA_TIMER_STARTING,
CPUHP_AP_MIPS_GIC_TIMER_STARTING,
CPUHP_AP_ARC_TIMER_STARTING,
+ CPUHP_AP_REALTEK_TIMER_STARTING,
CPUHP_AP_RISCV_TIMER_STARTING,
CPUHP_AP_CLINT_TIMER_STARTING,
CPUHP_AP_CSKY_TIMER_STARTING,
diff --git a/include/linux/cpuhplock.h b/include/linux/cpuhplock.h
new file mode 100644
index 000000000000..f7aa20f62b87
--- /dev/null
+++ b/include/linux/cpuhplock.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * include/linux/cpuhplock.h - CPU hotplug locking
+ *
+ * Locking functions for CPU hotplug.
+ */
+#ifndef _LINUX_CPUHPLOCK_H_
+#define _LINUX_CPUHPLOCK_H_
+
+#include <linux/cleanup.h>
+#include <linux/errno.h>
+
+struct device;
+
+extern int lockdep_is_cpus_held(void);
+
+#ifdef CONFIG_HOTPLUG_CPU
+void cpus_write_lock(void);
+void cpus_write_unlock(void);
+void cpus_read_lock(void);
+void cpus_read_unlock(void);
+int cpus_read_trylock(void);
+void lockdep_assert_cpus_held(void);
+void cpu_hotplug_disable_offlining(void);
+void cpu_hotplug_disable(void);
+void cpu_hotplug_enable(void);
+void clear_tasks_mm_cpumask(int cpu);
+int remove_cpu(unsigned int cpu);
+int cpu_device_down(struct device *dev);
+void smp_shutdown_nonboot_cpus(unsigned int primary_cpu);
+
+#else /* CONFIG_HOTPLUG_CPU */
+
+static inline void cpus_write_lock(void) { }
+static inline void cpus_write_unlock(void) { }
+static inline void cpus_read_lock(void) { }
+static inline void cpus_read_unlock(void) { }
+static inline int cpus_read_trylock(void) { return true; }
+static inline void lockdep_assert_cpus_held(void) { }
+static inline void cpu_hotplug_disable_offlining(void) { }
+static inline void cpu_hotplug_disable(void) { }
+static inline void cpu_hotplug_enable(void) { }
+static inline int remove_cpu(unsigned int cpu) { return -EPERM; }
+static inline void smp_shutdown_nonboot_cpus(unsigned int primary_cpu) { }
+#endif /* !CONFIG_HOTPLUG_CPU */
+
+DEFINE_LOCK_GUARD_0(cpus_read_lock, cpus_read_lock(), cpus_read_unlock())
+
+#endif /* _LINUX_CPUHPLOCK_H_ */
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 23686bed441d..954d4adc8f81 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -93,6 +93,7 @@ static inline void set_nr_cpu_ids(unsigned int nr)
*
* cpu_possible_mask- has bit 'cpu' set iff cpu is populatable
* cpu_present_mask - has bit 'cpu' set iff cpu is populated
+ * cpu_enabled_mask - has bit 'cpu' set iff cpu can be brought online
* cpu_online_mask - has bit 'cpu' set iff cpu available to scheduler
* cpu_active_mask - has bit 'cpu' set iff cpu available to migration
*
@@ -125,11 +126,13 @@ static inline void set_nr_cpu_ids(unsigned int nr)
extern struct cpumask __cpu_possible_mask;
extern struct cpumask __cpu_online_mask;
+extern struct cpumask __cpu_enabled_mask;
extern struct cpumask __cpu_present_mask;
extern struct cpumask __cpu_active_mask;
extern struct cpumask __cpu_dying_mask;
#define cpu_possible_mask ((const struct cpumask *)&__cpu_possible_mask)
#define cpu_online_mask ((const struct cpumask *)&__cpu_online_mask)
+#define cpu_enabled_mask ((const struct cpumask *)&__cpu_enabled_mask)
#define cpu_present_mask ((const struct cpumask *)&__cpu_present_mask)
#define cpu_active_mask ((const struct cpumask *)&__cpu_active_mask)
#define cpu_dying_mask ((const struct cpumask *)&__cpu_dying_mask)
@@ -1075,6 +1078,7 @@ extern const DECLARE_BITMAP(cpu_all_bits, NR_CPUS);
#else
#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)
#define for_each_online_cpu(cpu) for_each_cpu((cpu), cpu_online_mask)
+#define for_each_enabled_cpu(cpu) for_each_cpu((cpu), cpu_enabled_mask)
#define for_each_present_cpu(cpu) for_each_cpu((cpu), cpu_present_mask)
#endif
@@ -1093,6 +1097,15 @@ set_cpu_possible(unsigned int cpu, bool possible)
}
static inline void
+set_cpu_enabled(unsigned int cpu, bool can_be_onlined)
+{
+ if (can_be_onlined)
+ cpumask_set_cpu(cpu, &__cpu_enabled_mask);
+ else
+ cpumask_clear_cpu(cpu, &__cpu_enabled_mask);
+}
+
+static inline void
set_cpu_present(unsigned int cpu, bool present)
{
if (present)
@@ -1173,6 +1186,7 @@ static __always_inline unsigned int num_online_cpus(void)
return raw_atomic_read(&__num_online_cpus);
}
#define num_possible_cpus() cpumask_weight(cpu_possible_mask)
+#define num_enabled_cpus() cpumask_weight(cpu_enabled_mask)
#define num_present_cpus() cpumask_weight(cpu_present_mask)
#define num_active_cpus() cpumask_weight(cpu_active_mask)
@@ -1181,6 +1195,11 @@ static inline bool cpu_online(unsigned int cpu)
return cpumask_test_cpu(cpu, cpu_online_mask);
}
+static inline bool cpu_enabled(unsigned int cpu)
+{
+ return cpumask_test_cpu(cpu, cpu_enabled_mask);
+}
+
static inline bool cpu_possible(unsigned int cpu)
{
return cpumask_test_cpu(cpu, cpu_possible_mask);
@@ -1205,6 +1224,7 @@ static inline bool cpu_dying(unsigned int cpu)
#define num_online_cpus() 1U
#define num_possible_cpus() 1U
+#define num_enabled_cpus() 1U
#define num_present_cpus() 1U
#define num_active_cpus() 1U
@@ -1218,6 +1238,11 @@ static inline bool cpu_possible(unsigned int cpu)
return cpu == 0;
}
+static inline bool cpu_enabled(unsigned int cpu)
+{
+ return cpu == 0;
+}
+
static inline bool cpu_present(unsigned int cpu)
{
return cpu == 0;
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index bf53e3894aae..bff956f7b2b9 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -71,7 +71,7 @@ extern const struct qstr dotdot_name;
# define DNAME_INLINE_LEN 40 /* 192 bytes */
#else
# ifdef CONFIG_SMP
-# define DNAME_INLINE_LEN 40 /* 128 bytes */
+# define DNAME_INLINE_LEN 36 /* 128 bytes */
# else
# define DNAME_INLINE_LEN 44 /* 128 bytes */
# endif
@@ -89,13 +89,18 @@ struct dentry {
struct inode *d_inode; /* Where the name belongs to - NULL is
* negative */
unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
+ /* --- cacheline 1 boundary (64 bytes) was 32 bytes ago --- */
/* Ref lookup also touches following */
- struct lockref d_lockref; /* per-dentry lock and refcount */
const struct dentry_operations *d_op;
struct super_block *d_sb; /* The root of the dentry tree */
unsigned long d_time; /* used by d_revalidate */
void *d_fsdata; /* fs-specific data */
+ /* --- cacheline 2 boundary (128 bytes) --- */
+ struct lockref d_lockref; /* per-dentry lock and refcount
+ * keep separate from RCU lookup area if
+ * possible!
+ */
union {
struct list_head d_lru; /* LRU list */
@@ -278,6 +283,8 @@ static inline unsigned d_count(const struct dentry *dentry)
return dentry->d_lockref.count;
}
+ino_t d_parent_ino(struct dentry *dentry);
+
/*
* helper function for dentry_operations.d_dname() members
*/
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 82b2195efaca..15d28164bbbd 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -358,6 +358,13 @@ struct dm_target {
bool discards_supported:1;
/*
+ * Automatically set by dm-core if this target supports
+ * REQ_OP_ZONE_RESET_ALL. Otherwise, this operation will be emulated
+ * using REQ_OP_ZONE_RESET. Target drivers must not set this manually.
+ */
+ bool zone_reset_all_supported:1;
+
+ /*
* Set if this target requires that discards be split on
* 'max_discard_sectors' boundaries.
*/
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 418e555459da..6bf3c4fe8511 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -74,10 +74,10 @@ typedef void *efi_handle_t;
*/
typedef guid_t efi_guid_t __aligned(__alignof__(u32));
-#define EFI_GUID(a, b, c, d...) (efi_guid_t){ { \
+#define EFI_GUID(a, b, c, d...) ((efi_guid_t){ { \
(a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
(b) & 0xff, ((b) >> 8) & 0xff, \
- (c) & 0xff, ((c) >> 8) & 0xff, d } }
+ (c) & 0xff, ((c) >> 8) & 0xff, d } })
/*
* Generic EFI table header
@@ -385,6 +385,7 @@ void efi_native_runtime_setup(void);
#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20)
#define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
#define APPLE_PROPERTIES_PROTOCOL_GUID EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb, 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0)
+#define APPLE_SET_OS_PROTOCOL_GUID EFI_GUID(0xc5c5da95, 0x7d5c, 0x45e6, 0xb2, 0xf1, 0x3f, 0xd5, 0x2b, 0xb1, 0x00, 0x77)
#define EFI_TCG2_PROTOCOL_GUID EFI_GUID(0x607f766c, 0x7455, 0x42be, 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
#define EFI_TCG2_FINAL_EVENTS_TABLE_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
#define EFI_LOAD_FILE_PROTOCOL_GUID EFI_GUID(0x56ec3091, 0x954c, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
@@ -607,7 +608,11 @@ typedef struct {
u32 num_entries;
u32 desc_size;
u32 flags;
- efi_memory_desc_t entry[0];
+ /*
+ * There are @num_entries following, each of size @desc_size bytes,
+ * including an efi_memory_desc_t header. See efi_memdesc_ptr().
+ */
+ efi_memory_desc_t entry[];
} efi_memory_attributes_table_t;
typedef struct {
@@ -783,7 +788,7 @@ extern int efi_memattr_apply_permissions(struct mm_struct *mm,
efi_memattr_perm_setter fn);
/*
- * efi_early_memdesc_ptr - get the n-th EFI memmap descriptor
+ * efi_memdesc_ptr - get the n-th EFI memmap descriptor
* @map: the start of efi memmap
* @desc_size: the size of space for each EFI memmap descriptor
* @n: the index of efi memmap descriptor
@@ -801,7 +806,7 @@ extern int efi_memattr_apply_permissions(struct mm_struct *mm,
* during bootup since for_each_efi_memory_desc_xxx() is available after the
* kernel initializes the EFI subsystem to set up struct efi_memory_map.
*/
-#define efi_early_memdesc_ptr(map, desc_size, n) \
+#define efi_memdesc_ptr(map, desc_size, n) \
(efi_memory_desc_t *)((void *)(map) + ((n) * (desc_size)))
/* Iterate through an efi_memory_map */
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index bb37ad5cc954..893a1d21dc1c 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -158,6 +158,7 @@ struct fid {
#define EXPORT_FH_CONNECTABLE 0x1 /* Encode file handle with parent */
#define EXPORT_FH_FID 0x2 /* File handle may be non-decodeable */
+#define EXPORT_FH_DIR_ONLY 0x4 /* Only decode file handle for a directory */
/**
* struct export_operations - for nfsd to communicate with file systems
@@ -305,6 +306,7 @@ static inline int exportfs_encode_fid(struct inode *inode, struct fid *fid,
extern struct dentry *exportfs_decode_fh_raw(struct vfsmount *mnt,
struct fid *fid, int fh_len,
int fileid_type,
+ unsigned int flags,
int (*acceptable)(void *, struct dentry *),
void *context);
extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
diff --git a/include/linux/file.h b/include/linux/file.h
index 45d0f4800abd..237931f20739 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -97,6 +97,26 @@ extern void put_unused_fd(unsigned int fd);
DEFINE_CLASS(get_unused_fd, int, if (_T >= 0) put_unused_fd(_T),
get_unused_fd_flags(flags), unsigned flags)
+/*
+ * take_fd() will take care to set @fd to -EBADF ensuring that
+ * CLASS(get_unused_fd) won't call put_unused_fd(). This makes it
+ * easier to rely on CLASS(get_unused_fd):
+ *
+ * struct file *f;
+ *
+ * CLASS(get_unused_fd, fd)(O_CLOEXEC);
+ * if (fd < 0)
+ * return fd;
+ *
+ * f = dentry_open(&path, O_RDONLY, current_cred());
+ * if (IS_ERR(f))
+ * return PTR_ERR(fd);
+ *
+ * fd_install(fd, f);
+ * return take_fd(fd);
+ */
+#define take_fd(fd) __get_and_null(fd, -EBADF)
+
extern void fd_install(unsigned int fd, struct file *file);
int receive_fd(struct file *file, int __user *ufd, unsigned int o_flags);
diff --git a/include/linux/firmware/qcom/qcom_qseecom.h b/include/linux/firmware/qcom/qcom_qseecom.h
index 366243ee9609..1dc5b3b50aa9 100644
--- a/include/linux/firmware/qcom/qcom_qseecom.h
+++ b/include/linux/firmware/qcom/qcom_qseecom.h
@@ -73,9 +73,9 @@ static inline void qseecom_dma_free(struct qseecom_client *client, size_t size,
/**
* qcom_qseecom_app_send() - Send to and receive data from a given QSEE app.
* @client: The QSEECOM client associated with the target app.
- * @req: DMA address of the request buffer sent to the app.
+ * @req: Request buffer sent to the app (must be TZ memory).
* @req_size: Size of the request buffer.
- * @rsp: DMA address of the response buffer, written to by the app.
+ * @rsp: Response buffer, written to by the app (must be TZ memory).
* @rsp_size: Size of the response buffer.
*
* Sends a request to the QSEE app associated with the given client and read
@@ -90,8 +90,8 @@ static inline void qseecom_dma_free(struct qseecom_client *client, size_t size,
* Return: Zero on success, nonzero on failure.
*/
static inline int qcom_qseecom_app_send(struct qseecom_client *client,
- dma_addr_t req, size_t req_size,
- dma_addr_t rsp, size_t rsp_size)
+ void *req, size_t req_size,
+ void *rsp, size_t rsp_size)
{
return qcom_scm_qseecom_app_send(client->app_id, req, req_size, rsp, rsp_size);
}
diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h
index aaa19f93ac43..9f14976399ab 100644
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -115,11 +115,40 @@ int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val,
int qcom_scm_lmh_profile_change(u32 profile_id);
bool qcom_scm_lmh_dcvsh_available(void);
+/*
+ * Request TZ to program set of access controlled registers necessary
+ * irrespective of any features
+ */
+#define QCOM_SCM_GPU_ALWAYS_EN_REQ BIT(0)
+/*
+ * Request TZ to program BCL id to access controlled register when BCL is
+ * enabled
+ */
+#define QCOM_SCM_GPU_BCL_EN_REQ BIT(1)
+/*
+ * Request TZ to program set of access controlled register for CLX feature
+ * when enabled
+ */
+#define QCOM_SCM_GPU_CLX_EN_REQ BIT(2)
+/*
+ * Request TZ to program tsense ids to access controlled registers for reading
+ * gpu temperature sensors
+ */
+#define QCOM_SCM_GPU_TSENSE_EN_REQ BIT(3)
+
+int qcom_scm_gpu_init_regs(u32 gpu_req);
+
+int qcom_scm_shm_bridge_enable(void);
+int qcom_scm_shm_bridge_create(struct device *dev, u64 pfn_and_ns_perm_flags,
+ u64 ipfn_and_s_perm_flags, u64 size_and_flags,
+ u64 ns_vmids, u64 *handle);
+int qcom_scm_shm_bridge_delete(struct device *dev, u64 handle);
+
#ifdef CONFIG_QCOM_QSEECOM
int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id);
-int qcom_scm_qseecom_app_send(u32 app_id, dma_addr_t req, size_t req_size,
- dma_addr_t rsp, size_t rsp_size);
+int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size,
+ void *rsp, size_t rsp_size);
#else /* CONFIG_QCOM_QSEECOM */
@@ -129,8 +158,8 @@ static inline int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id)
}
static inline int qcom_scm_qseecom_app_send(u32 app_id,
- dma_addr_t req, size_t req_size,
- dma_addr_t rsp, size_t rsp_size)
+ void *req, size_t req_size,
+ void *rsp, size_t rsp_size)
{
return -EINVAL;
}
diff --git a/include/linux/firmware/qcom/qcom_tzmem.h b/include/linux/firmware/qcom/qcom_tzmem.h
new file mode 100644
index 000000000000..b83b63a0c049
--- /dev/null
+++ b/include/linux/firmware/qcom/qcom_tzmem.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023-2024 Linaro Ltd.
+ */
+
+#ifndef __QCOM_TZMEM_H
+#define __QCOM_TZMEM_H
+
+#include <linux/cleanup.h>
+#include <linux/gfp.h>
+#include <linux/types.h>
+
+struct device;
+struct qcom_tzmem_pool;
+
+/**
+ * enum qcom_tzmem_policy - Policy for pool growth.
+ */
+enum qcom_tzmem_policy {
+ /**< Static pool, never grow above initial size. */
+ QCOM_TZMEM_POLICY_STATIC = 1,
+ /**< When out of memory, add increment * current size of memory. */
+ QCOM_TZMEM_POLICY_MULTIPLIER,
+ /**< When out of memory add as much as is needed until max_size. */
+ QCOM_TZMEM_POLICY_ON_DEMAND,
+};
+
+/**
+ * struct qcom_tzmem_pool_config - TZ memory pool configuration.
+ * @initial_size: Number of bytes to allocate for the pool during its creation.
+ * @policy: Pool size growth policy.
+ * @increment: Used with policies that allow pool growth.
+ * @max_size: Size above which the pool will never grow.
+ */
+struct qcom_tzmem_pool_config {
+ size_t initial_size;
+ enum qcom_tzmem_policy policy;
+ size_t increment;
+ size_t max_size;
+};
+
+struct qcom_tzmem_pool *
+qcom_tzmem_pool_new(const struct qcom_tzmem_pool_config *config);
+void qcom_tzmem_pool_free(struct qcom_tzmem_pool *pool);
+struct qcom_tzmem_pool *
+devm_qcom_tzmem_pool_new(struct device *dev,
+ const struct qcom_tzmem_pool_config *config);
+
+void *qcom_tzmem_alloc(struct qcom_tzmem_pool *pool, size_t size, gfp_t gfp);
+void qcom_tzmem_free(void *ptr);
+
+DEFINE_FREE(qcom_tzmem, void *, if (_T) qcom_tzmem_free(_T))
+
+phys_addr_t qcom_tzmem_to_phys(void *ptr);
+
+#endif /* __QCOM_TZMEM */
diff --git a/include/linux/firmware/xlnx-event-manager.h b/include/linux/firmware/xlnx-event-manager.h
index 82e8254b0f80..645dd34155e6 100644
--- a/include/linux/firmware/xlnx-event-manager.h
+++ b/include/linux/firmware/xlnx-event-manager.h
@@ -1,4 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Xilinx Event Management Driver
+ *
+ * Copyright (C) 2024, Advanced Micro Devices, Inc.
+ */
#ifndef _FIRMWARE_XLNX_EVENT_MANAGER_H_
#define _FIRMWARE_XLNX_EVENT_MANAGER_H_
@@ -7,6 +12,11 @@
#define CB_MAX_PAYLOAD_SIZE (4U) /*In payload maximum 32bytes */
+#define EVENT_SUBSYSTEM_RESTART (4U)
+
+#define PM_DEV_ACPU_0_0 (0x1810c0afU)
+#define PM_DEV_ACPU_0 (0x1810c003U)
+
/************************** Exported Function *****************************/
typedef void (*event_cb_func_t)(const u32 *payload, void *data);
diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h
index 1a069a56c961..d7d07afc0532 100644
--- a/include/linux/firmware/xlnx-zynqmp.h
+++ b/include/linux/firmware/xlnx-zynqmp.h
@@ -52,6 +52,9 @@
#define API_ID_MASK GENMASK(7, 0)
#define MODULE_ID_MASK GENMASK(11, 8)
+/* Firmware feature check version mask */
+#define FIRMWARE_VERSION_MASK 0xFFFFU
+
/* ATF only commands */
#define TF_A_PM_REGISTER_SGI 0xa04
#define PM_GET_TRUSTZONE_VERSION 0xa03
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0283cf366c2a..fd34b5755c0b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -125,8 +125,10 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define FMODE_EXEC ((__force fmode_t)(1 << 5))
/* File writes are restricted (block device specific) */
#define FMODE_WRITE_RESTRICTED ((__force fmode_t)(1 << 6))
+/* File supports atomic writes */
+#define FMODE_CAN_ATOMIC_WRITE ((__force fmode_t)(1 << 7))
-/* FMODE_* bits 7 to 8 */
+/* FMODE_* bit 8 */
/* 32bit hashes as llseek() offset (for directories) */
#define FMODE_32BITHASH ((__force fmode_t)(1 << 9))
@@ -317,6 +319,7 @@ struct readahead_control;
#define IOCB_SYNC (__force int) RWF_SYNC
#define IOCB_NOWAIT (__force int) RWF_NOWAIT
#define IOCB_APPEND (__force int) RWF_APPEND
+#define IOCB_ATOMIC (__force int) RWF_ATOMIC
/* non-RWF related bits - start at 16 */
#define IOCB_EVENTFD (1 << 16)
@@ -351,6 +354,7 @@ struct readahead_control;
{ IOCB_SYNC, "SYNC" }, \
{ IOCB_NOWAIT, "NOWAIT" }, \
{ IOCB_APPEND, "APPEND" }, \
+ { IOCB_ATOMIC, "ATOMIC"}, \
{ IOCB_EVENTFD, "EVENTFD"}, \
{ IOCB_DIRECT, "DIRECT" }, \
{ IOCB_WRITE, "WRITE" }, \
@@ -660,9 +664,13 @@ struct inode {
};
dev_t i_rdev;
loff_t i_size;
- struct timespec64 __i_atime;
- struct timespec64 __i_mtime;
- struct timespec64 __i_ctime; /* use inode_*_ctime accessors! */
+ time64_t i_atime_sec;
+ time64_t i_mtime_sec;
+ time64_t i_ctime_sec;
+ u32 i_atime_nsec;
+ u32 i_mtime_nsec;
+ u32 i_ctime_nsec;
+ u32 i_generation;
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
unsigned short i_bytes;
u8 i_blkbits;
@@ -719,10 +727,10 @@ struct inode {
unsigned i_dir_seq;
};
- __u32 i_generation;
#ifdef CONFIG_FSNOTIFY
__u32 i_fsnotify_mask; /* all events this inode cares about */
+ /* 32-bit hole reserved for expanding i_fsnotify_mask */
struct fsnotify_mark_connector __rcu *i_fsnotify_marks;
#endif
@@ -1538,23 +1546,27 @@ struct timespec64 inode_set_ctime_current(struct inode *inode);
static inline time64_t inode_get_atime_sec(const struct inode *inode)
{
- return inode->__i_atime.tv_sec;
+ return inode->i_atime_sec;
}
static inline long inode_get_atime_nsec(const struct inode *inode)
{
- return inode->__i_atime.tv_nsec;
+ return inode->i_atime_nsec;
}
static inline struct timespec64 inode_get_atime(const struct inode *inode)
{
- return inode->__i_atime;
+ struct timespec64 ts = { .tv_sec = inode_get_atime_sec(inode),
+ .tv_nsec = inode_get_atime_nsec(inode) };
+
+ return ts;
}
static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode,
struct timespec64 ts)
{
- inode->__i_atime = ts;
+ inode->i_atime_sec = ts.tv_sec;
+ inode->i_atime_nsec = ts.tv_nsec;
return ts;
}
@@ -1563,28 +1575,32 @@ static inline struct timespec64 inode_set_atime(struct inode *inode,
{
struct timespec64 ts = { .tv_sec = sec,
.tv_nsec = nsec };
+
return inode_set_atime_to_ts(inode, ts);
}
static inline time64_t inode_get_mtime_sec(const struct inode *inode)
{
- return inode->__i_mtime.tv_sec;
+ return inode->i_mtime_sec;
}
static inline long inode_get_mtime_nsec(const struct inode *inode)
{
- return inode->__i_mtime.tv_nsec;
+ return inode->i_mtime_nsec;
}
static inline struct timespec64 inode_get_mtime(const struct inode *inode)
{
- return inode->__i_mtime;
+ struct timespec64 ts = { .tv_sec = inode_get_mtime_sec(inode),
+ .tv_nsec = inode_get_mtime_nsec(inode) };
+ return ts;
}
static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode,
struct timespec64 ts)
{
- inode->__i_mtime = ts;
+ inode->i_mtime_sec = ts.tv_sec;
+ inode->i_mtime_nsec = ts.tv_nsec;
return ts;
}
@@ -1598,23 +1614,27 @@ static inline struct timespec64 inode_set_mtime(struct inode *inode,
static inline time64_t inode_get_ctime_sec(const struct inode *inode)
{
- return inode->__i_ctime.tv_sec;
+ return inode->i_ctime_sec;
}
static inline long inode_get_ctime_nsec(const struct inode *inode)
{
- return inode->__i_ctime.tv_nsec;
+ return inode->i_ctime_nsec;
}
static inline struct timespec64 inode_get_ctime(const struct inode *inode)
{
- return inode->__i_ctime;
+ struct timespec64 ts = { .tv_sec = inode_get_ctime_sec(inode),
+ .tv_nsec = inode_get_ctime_nsec(inode) };
+
+ return ts;
}
static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode,
struct timespec64 ts)
{
- inode->__i_ctime = ts;
+ inode->i_ctime_sec = ts.tv_sec;
+ inode->i_ctime_nsec = ts.tv_nsec;
return ts;
}
@@ -1926,6 +1946,8 @@ void inode_init_owner(struct mnt_idmap *idmap, struct inode *inode,
extern bool may_open_dev(const struct path *path);
umode_t mode_strip_sgid(struct mnt_idmap *idmap,
const struct inode *dir, umode_t mode);
+bool in_group_or_capable(struct mnt_idmap *idmap,
+ const struct inode *inode, vfsgid_t vfsgid);
/*
* This is the "filldir" function type, used by readdir() to let
@@ -2685,7 +2707,7 @@ static inline struct file *file_clone_open(struct file *file)
}
extern int filp_close(struct file *, fl_owner_t id);
-extern struct filename *getname_flags(const char __user *, int, int *);
+extern struct filename *getname_flags(const char __user *, int);
extern struct filename *getname_uflags(const char __user *, int);
extern struct filename *getname(const char __user *);
extern struct filename *getname_kernel(const char *);
@@ -3029,7 +3051,12 @@ extern struct inode *inode_insert5(struct inode *inode, unsigned long hashval,
int (*test)(struct inode *, void *),
int (*set)(struct inode *, void *),
void *data);
-extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
+struct inode *iget5_locked(struct super_block *, unsigned long,
+ int (*test)(struct inode *, void *),
+ int (*set)(struct inode *, void *), void *);
+struct inode *iget5_locked_rcu(struct super_block *, unsigned long,
+ int (*test)(struct inode *, void *),
+ int (*set)(struct inode *, void *), void *);
extern struct inode * iget_locked(struct super_block *, unsigned long);
extern struct inode *find_inode_nowait(struct super_block *,
unsigned long,
@@ -3231,6 +3258,9 @@ extern const struct inode_operations page_symlink_inode_operations;
extern void kfree_link(void *);
void generic_fillattr(struct mnt_idmap *, u32, struct inode *, struct kstat *);
void generic_fill_statx_attr(struct inode *inode, struct kstat *stat);
+void generic_fill_statx_atomic_writes(struct kstat *stat,
+ unsigned int unit_min,
+ unsigned int unit_max);
extern int vfs_getattr_nosec(const struct path *, struct kstat *, u32, unsigned int);
extern int vfs_getattr(const struct path *, struct kstat *, u32, unsigned int);
void __inode_add_bytes(struct inode *inode, loff_t bytes);
@@ -3351,6 +3381,10 @@ extern int generic_file_fsync(struct file *, loff_t, loff_t, int);
extern int generic_check_addressable(unsigned, u64);
extern void generic_set_sb_d_ops(struct super_block *sb);
+extern int generic_ci_match(const struct inode *parent,
+ const struct qstr *name,
+ const struct qstr *folded_name,
+ const u8 *de_name, u32 de_name_len);
static inline bool sb_has_encoding(const struct super_block *sb)
{
@@ -3403,7 +3437,8 @@ static inline int iocb_flags(struct file *file)
return res;
}
-static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags)
+static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags,
+ int rw_type)
{
int kiocb_flags = 0;
@@ -3422,6 +3457,12 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags)
return -EOPNOTSUPP;
kiocb_flags |= IOCB_NOIO;
}
+ if (flags & RWF_ATOMIC) {
+ if (rw_type != WRITE)
+ return -EOPNOTSUPP;
+ if (!(ki->ki_filp->f_mode & FMODE_CAN_ATOMIC_WRITE))
+ return -EOPNOTSUPP;
+ }
kiocb_flags |= (__force int) (flags & RWF_SUPPORTED);
if (flags & RWF_SYNC)
kiocb_flags |= IOCB_DSYNC;
@@ -3436,20 +3477,6 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags)
return 0;
}
-static inline ino_t parent_ino(struct dentry *dentry)
-{
- ino_t res;
-
- /*
- * Don't strictly need d_lock here? If the parent ino could change
- * then surely we'd have a deeper race in the caller?
- */
- spin_lock(&dentry->d_lock);
- res = dentry->d_parent->d_inode->i_ino;
- spin_unlock(&dentry->d_lock);
- return res;
-}
-
/* Transaction based IO helpers */
/*
@@ -3574,7 +3601,7 @@ static inline bool dir_emit_dot(struct file *file, struct dir_context *ctx)
static inline bool dir_emit_dotdot(struct file *file, struct dir_context *ctx)
{
return ctx->actor(ctx, "..", 2, ctx->pos,
- parent_ino(file->f_path.dentry), DT_DIR);
+ d_parent_ino(file->f_path.dentry), DT_DIR);
}
static inline bool dir_emit_dots(struct file *file, struct dir_context *ctx)
{
@@ -3613,4 +3640,23 @@ extern int vfs_fadvise(struct file *file, loff_t offset, loff_t len,
extern int generic_fadvise(struct file *file, loff_t offset, loff_t len,
int advice);
+static inline bool vfs_empty_path(int dfd, const char __user *path)
+{
+ char c;
+
+ if (dfd < 0)
+ return false;
+
+ /* We now allow NULL to be used for empty path. */
+ if (!path)
+ return true;
+
+ if (unlikely(get_user(c, path)))
+ return false;
+
+ return !c;
+}
+
+bool generic_atomic_write_valid(struct iov_iter *iter, loff_t pos);
+
#endif /* _LINUX_FS_H */
diff --git a/include/linux/fs_parser.h b/include/linux/fs_parser.h
index d3350979115f..6cf713a7e6c6 100644
--- a/include/linux/fs_parser.h
+++ b/include/linux/fs_parser.h
@@ -28,7 +28,7 @@ typedef int fs_param_type(struct p_log *,
*/
fs_param_type fs_param_is_bool, fs_param_is_u32, fs_param_is_s32, fs_param_is_u64,
fs_param_is_enum, fs_param_is_string, fs_param_is_blob, fs_param_is_blockdev,
- fs_param_is_path, fs_param_is_fd;
+ fs_param_is_path, fs_param_is_fd, fs_param_is_uid, fs_param_is_gid;
/*
* Specification of the type of value a parameter wants.
@@ -57,6 +57,8 @@ struct fs_parse_result {
int int_32; /* For spec_s32/spec_enum */
unsigned int uint_32; /* For spec_u32{,_octal,_hex}/spec_enum */
u64 uint_64; /* For spec_u64 */
+ kuid_t uid;
+ kgid_t gid;
};
};
@@ -131,6 +133,8 @@ static inline bool fs_validate_description(const char *name,
#define fsparam_bdev(NAME, OPT) __fsparam(fs_param_is_blockdev, NAME, OPT, 0, NULL)
#define fsparam_path(NAME, OPT) __fsparam(fs_param_is_path, NAME, OPT, 0, NULL)
#define fsparam_fd(NAME, OPT) __fsparam(fs_param_is_fd, NAME, OPT, 0, NULL)
+#define fsparam_uid(NAME, OPT) __fsparam(fs_param_is_uid, NAME, OPT, 0, NULL)
+#define fsparam_gid(NAME, OPT) __fsparam(fs_param_is_gid, NAME, OPT, 0, NULL)
/* String parameter that allows empty argument */
#define fsparam_string_empty(NAME, OPT) \
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index bdf7f3eddf0a..4c91a019972b 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -19,6 +19,7 @@
enum fscache_cache_trace;
enum fscache_cookie_trace;
enum fscache_access_trace;
+enum fscache_volume_trace;
enum fscache_cache_state {
FSCACHE_CACHE_IS_NOT_PRESENT, /* No cache is present for this name */
@@ -97,6 +98,11 @@ extern void fscache_withdraw_cookie(struct fscache_cookie *cookie);
extern void fscache_io_error(struct fscache_cache *cache);
+extern struct fscache_volume *
+fscache_try_get_volume(struct fscache_volume *volume,
+ enum fscache_volume_trace where);
+extern void fscache_put_volume(struct fscache_volume *volume,
+ enum fscache_volume_trace where);
extern void fscache_end_volume_access(struct fscache_volume *volume,
struct fscache_cookie *cookie,
enum fscache_access_trace why);
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 4da80e92f804..278620e063ab 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -112,7 +112,13 @@ static inline int fsnotify_file(struct file *file, __u32 mask)
{
const struct path *path;
- if (file->f_mode & FMODE_NONOTIFY)
+ /*
+ * FMODE_NONOTIFY are fds generated by fanotify itself which should not
+ * generate new events. We also don't want to generate events for
+ * FMODE_PATH fds (involves open & close events) as they are just
+ * handle creation / destruction events and not "real" file events.
+ */
+ if (file->f_mode & (FMODE_NONOTIFY | FMODE_PATH))
return 0;
path = &file->f_path;
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 56ac7e7a2889..063f71b18a7c 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * <linux/gpio.h>
+ * NOTE: This header *must not* be included.
*
* This is the LEGACY GPIO bulk include file, including legacy APIs. It is
* used for GPIO drivers still referencing the global GPIO numberspace,
@@ -16,8 +16,6 @@
struct device;
-/* see Documentation/driver-api/gpio/legacy.rst */
-
/* make these flag values available regardless of GPIO kconfig options */
#define GPIOF_DIR_OUT (0 << 0)
#define GPIOF_DIR_IN (1 << 0)
@@ -121,8 +119,6 @@ static inline int gpio_to_irq(unsigned gpio)
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
-/* CONFIG_GPIOLIB: bindings for managed devices that want to request gpios */
-
int devm_gpio_request(struct device *dev, unsigned gpio, const char *label);
int devm_gpio_request_one(struct device *dev, unsigned gpio,
unsigned long flags, const char *label);
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 0032bb6e7d8f..2dd7cb9cc270 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -632,10 +632,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
devm_gpiochip_add_data_with_key(dev, gc, data, NULL, NULL)
#endif /* CONFIG_LOCKDEP */
-static inline int gpiochip_add(struct gpio_chip *gc)
-{
- return gpiochip_add_data(gc, NULL);
-}
void gpiochip_remove(struct gpio_chip *gc);
int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc,
void *data, struct lock_class_key *lock_key,
@@ -791,7 +787,6 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,
enum gpiod_flags dflags);
void gpiochip_free_own_desc(struct gpio_desc *desc);
-struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum);
struct gpio_desc *
gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum);
diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
index edf96f249eb5..e94314760aab 100644
--- a/include/linux/hwmon.h
+++ b/include/linux/hwmon.h
@@ -45,6 +45,7 @@ enum hwmon_chip_attributes {
hwmon_chip_power_samples,
hwmon_chip_temp_samples,
hwmon_chip_beep_enable,
+ hwmon_chip_pec,
};
#define HWMON_C_TEMP_RESET_HISTORY BIT(hwmon_chip_temp_reset_history)
@@ -60,6 +61,7 @@ enum hwmon_chip_attributes {
#define HWMON_C_POWER_SAMPLES BIT(hwmon_chip_power_samples)
#define HWMON_C_TEMP_SAMPLES BIT(hwmon_chip_temp_samples)
#define HWMON_C_BEEP_ENABLE BIT(hwmon_chip_beep_enable)
+#define HWMON_C_PEC BIT(hwmon_chip_pec)
enum hwmon_temp_attributes {
hwmon_temp_enable,
diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h
index 7abdc0927124..3bb6198d1523 100644
--- a/include/linux/io_uring_types.h
+++ b/include/linux/io_uring_types.h
@@ -50,7 +50,7 @@ struct io_wq_work_list {
struct io_wq_work {
struct io_wq_work_node list;
- unsigned flags;
+ atomic_t flags;
/* place it here instead of io_kiocb as it fills padding and saves 4B */
int cancel_seq;
};
@@ -210,14 +210,6 @@ struct io_submit_state {
struct blk_plug plug;
};
-struct io_ev_fd {
- struct eventfd_ctx *cq_ev_fd;
- unsigned int eventfd_async: 1;
- struct rcu_head rcu;
- atomic_t refs;
- atomic_t ops;
-};
-
struct io_alloc_cache {
void **entries;
unsigned int nr_cached;
@@ -372,7 +364,6 @@ struct io_ring_ctx {
struct io_restriction restrictions;
/* slow path rsrc auxilary data, used by update/register */
- struct io_mapped_ubuf *dummy_ubuf;
struct io_rsrc_data *file_data;
struct io_rsrc_data *buf_data;
@@ -405,6 +396,9 @@ struct io_ring_ctx {
struct callback_head poll_wq_task_work;
struct list_head defer_list;
+ struct io_alloc_cache msg_cache;
+ spinlock_t msg_lock;
+
#ifdef CONFIG_NET_RX_BUSY_POLL
struct list_head napi_list; /* track busy poll napi_id */
spinlock_t napi_lock; /* napi_list lock */
diff --git a/include/linux/irq_sim.h b/include/linux/irq_sim.h
index ab831e5ae748..89b4d8ff274b 100644
--- a/include/linux/irq_sim.h
+++ b/include/linux/irq_sim.h
@@ -16,11 +16,28 @@
* requested like normal irqs and enqueued from process context.
*/
+struct irq_sim_ops {
+ int (*irq_sim_irq_requested)(struct irq_domain *domain,
+ irq_hw_number_t hwirq, void *data);
+ void (*irq_sim_irq_released)(struct irq_domain *domain,
+ irq_hw_number_t hwirq, void *data);
+};
+
struct irq_domain *irq_domain_create_sim(struct fwnode_handle *fwnode,
unsigned int num_irqs);
struct irq_domain *devm_irq_domain_create_sim(struct device *dev,
struct fwnode_handle *fwnode,
unsigned int num_irqs);
+struct irq_domain *irq_domain_create_sim_full(struct fwnode_handle *fwnode,
+ unsigned int num_irqs,
+ const struct irq_sim_ops *ops,
+ void *data);
+struct irq_domain *
+devm_irq_domain_create_sim_full(struct device *dev,
+ struct fwnode_handle *fwnode,
+ unsigned int num_irqs,
+ const struct irq_sim_ops *ops,
+ void *data);
void irq_domain_remove_sim(struct irq_domain *domain);
#endif /* _LINUX_IRQ_SIM_H */
diff --git a/include/linux/irqchip/arm-gic-common.h b/include/linux/irqchip/arm-gic-common.h
index 1177f3a1aed5..fc0246cc05ac 100644
--- a/include/linux/irqchip/arm-gic-common.h
+++ b/include/linux/irqchip/arm-gic-common.h
@@ -10,10 +10,6 @@
#include <linux/irqchip/arm-vgic-info.h>
#define GICD_INT_DEF_PRI 0xa0
-#define GICD_INT_DEF_PRI_X4 ((GICD_INT_DEF_PRI << 24) |\
- (GICD_INT_DEF_PRI << 16) |\
- (GICD_INT_DEF_PRI << 8) |\
- GICD_INT_DEF_PRI)
struct irq_domain;
struct fwnode_handle;
diff --git a/include/linux/irqchip/arm-gic-v3-prio.h b/include/linux/irqchip/arm-gic-v3-prio.h
new file mode 100644
index 000000000000..44157c9abb78
--- /dev/null
+++ b/include/linux/irqchip/arm-gic-v3-prio.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __LINUX_IRQCHIP_ARM_GIC_V3_PRIO_H
+#define __LINUX_IRQCHIP_ARM_GIC_V3_PRIO_H
+
+/*
+ * GIC priorities from the view of the PMR/RPR.
+ *
+ * These values are chosen to be valid in either the absolute priority space or
+ * the NS view of the priority space. The value programmed into the distributor
+ * and ITS will be chosen at boot time such that these values appear in the
+ * PMR/RPR.
+ *
+ * GICV3_PRIO_UNMASKED is the PMR view of the priority to use to permit both
+ * IRQs and pseudo-NMIs.
+ *
+ * GICV3_PRIO_IRQ is the PMR view of the priority of regular interrupts. This
+ * can be written to the PMR to mask regular IRQs.
+ *
+ * GICV3_PRIO_NMI is the PMR view of the priority of pseudo-NMIs. This can be
+ * written to the PMR to mask pseudo-NMIs.
+ *
+ * On arm64 some code sections either automatically switch back to PSR.I or
+ * explicitly require to not use priority masking. If bit GICV3_PRIO_PSR_I_SET
+ * is included in the priority mask, it indicates that PSR.I should be set and
+ * interrupt disabling temporarily does not rely on IRQ priorities.
+ */
+#define GICV3_PRIO_UNMASKED 0xe0
+#define GICV3_PRIO_IRQ 0xc0
+#define GICV3_PRIO_NMI 0x80
+
+#define GICV3_PRIO_PSR_I_SET (1 << 4)
+
+#ifndef __ASSEMBLER__
+
+#define __gicv3_prio_to_ns(p) (0xff & ((p) << 1))
+#define __gicv3_ns_to_prio(ns) (0x80 | ((ns) >> 1))
+
+#define __gicv3_prio_valid_ns(p) \
+ (__gicv3_ns_to_prio(__gicv3_prio_to_ns(p)) == (p))
+
+static_assert(__gicv3_prio_valid_ns(GICV3_PRIO_NMI));
+static_assert(__gicv3_prio_valid_ns(GICV3_PRIO_IRQ));
+
+static_assert(GICV3_PRIO_NMI < GICV3_PRIO_IRQ);
+static_assert(GICV3_PRIO_IRQ < GICV3_PRIO_UNMASKED);
+
+static_assert(GICV3_PRIO_IRQ < (GICV3_PRIO_IRQ | GICV3_PRIO_PSR_I_SET));
+
+#endif /* __ASSEMBLER */
+
+#endif /* __LINUX_IRQCHIP_ARM_GIC_V3_PRIO_H */
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 728691365464..70c0948f978e 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -638,7 +638,7 @@ struct fwnode_handle;
int __init its_lpi_memreserve_init(void);
int its_cpu_init(void);
int its_init(struct fwnode_handle *handle, struct rdists *rdists,
- struct irq_domain *domain);
+ struct irq_domain *domain, u8 irq_prio);
int mbi_init(struct fwnode_handle *fwnode, struct irq_domain *parent);
static inline bool gic_enable_sre(void)
diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h
index 9eb17481b07f..f09ba598c97a 100644
--- a/include/linux/mfd/stm32-timers.h
+++ b/include/linux/mfd/stm32-timers.h
@@ -12,97 +12,106 @@
#include <linux/dma-mapping.h>
#include <linux/regmap.h>
-#define TIM_CR1 0x00 /* Control Register 1 */
-#define TIM_CR2 0x04 /* Control Register 2 */
-#define TIM_SMCR 0x08 /* Slave mode control reg */
-#define TIM_DIER 0x0C /* DMA/interrupt register */
-#define TIM_SR 0x10 /* Status register */
-#define TIM_EGR 0x14 /* Event Generation Reg */
-#define TIM_CCMR1 0x18 /* Capt/Comp 1 Mode Reg */
-#define TIM_CCMR2 0x1C /* Capt/Comp 2 Mode Reg */
-#define TIM_CCER 0x20 /* Capt/Comp Enable Reg */
-#define TIM_CNT 0x24 /* Counter */
-#define TIM_PSC 0x28 /* Prescaler */
-#define TIM_ARR 0x2c /* Auto-Reload Register */
-#define TIM_CCR1 0x34 /* Capt/Comp Register 1 */
-#define TIM_CCR2 0x38 /* Capt/Comp Register 2 */
-#define TIM_CCR3 0x3C /* Capt/Comp Register 3 */
-#define TIM_CCR4 0x40 /* Capt/Comp Register 4 */
-#define TIM_BDTR 0x44 /* Break and Dead-Time Reg */
-#define TIM_DCR 0x48 /* DMA control register */
-#define TIM_DMAR 0x4C /* DMA register for transfer */
-#define TIM_TISEL 0x68 /* Input Selection */
+#define TIM_CR1 0x00 /* Control Register 1 */
+#define TIM_CR2 0x04 /* Control Register 2 */
+#define TIM_SMCR 0x08 /* Slave mode control reg */
+#define TIM_DIER 0x0C /* DMA/interrupt register */
+#define TIM_SR 0x10 /* Status register */
+#define TIM_EGR 0x14 /* Event Generation Reg */
+#define TIM_CCMR1 0x18 /* Capt/Comp 1 Mode Reg */
+#define TIM_CCMR2 0x1C /* Capt/Comp 2 Mode Reg */
+#define TIM_CCER 0x20 /* Capt/Comp Enable Reg */
+#define TIM_CNT 0x24 /* Counter */
+#define TIM_PSC 0x28 /* Prescaler */
+#define TIM_ARR 0x2c /* Auto-Reload Register */
+#define TIM_CCRx(x) (0x34 + 4 * ((x) - 1)) /* Capt/Comp Register x (x ∈ {1, .. 4}) */
+#define TIM_CCR1 TIM_CCRx(1) /* Capt/Comp Register 1 */
+#define TIM_CCR2 TIM_CCRx(2) /* Capt/Comp Register 2 */
+#define TIM_CCR3 TIM_CCRx(3) /* Capt/Comp Register 3 */
+#define TIM_CCR4 TIM_CCRx(4) /* Capt/Comp Register 4 */
+#define TIM_BDTR 0x44 /* Break and Dead-Time Reg */
+#define TIM_DCR 0x48 /* DMA control register */
+#define TIM_DMAR 0x4C /* DMA register for transfer */
+#define TIM_TISEL 0x68 /* Input Selection */
-#define TIM_CR1_CEN BIT(0) /* Counter Enable */
-#define TIM_CR1_DIR BIT(4) /* Counter Direction */
-#define TIM_CR1_ARPE BIT(7) /* Auto-reload Preload Ena */
-#define TIM_CR2_MMS (BIT(4) | BIT(5) | BIT(6)) /* Master mode selection */
-#define TIM_CR2_MMS2 GENMASK(23, 20) /* Master mode selection 2 */
-#define TIM_SMCR_SMS (BIT(0) | BIT(1) | BIT(2)) /* Slave mode selection */
-#define TIM_SMCR_TS (BIT(4) | BIT(5) | BIT(6)) /* Trigger selection */
-#define TIM_DIER_UIE BIT(0) /* Update interrupt */
-#define TIM_DIER_CC1IE BIT(1) /* CC1 Interrupt Enable */
-#define TIM_DIER_CC2IE BIT(2) /* CC2 Interrupt Enable */
-#define TIM_DIER_CC3IE BIT(3) /* CC3 Interrupt Enable */
-#define TIM_DIER_CC4IE BIT(4) /* CC4 Interrupt Enable */
-#define TIM_DIER_CC_IE(x) BIT((x) + 1) /* CC1, CC2, CC3, CC4 interrupt enable */
-#define TIM_DIER_UDE BIT(8) /* Update DMA request Enable */
-#define TIM_DIER_CC1DE BIT(9) /* CC1 DMA request Enable */
-#define TIM_DIER_CC2DE BIT(10) /* CC2 DMA request Enable */
-#define TIM_DIER_CC3DE BIT(11) /* CC3 DMA request Enable */
-#define TIM_DIER_CC4DE BIT(12) /* CC4 DMA request Enable */
-#define TIM_DIER_COMDE BIT(13) /* COM DMA request Enable */
-#define TIM_DIER_TDE BIT(14) /* Trigger DMA request Enable */
-#define TIM_SR_UIF BIT(0) /* Update interrupt flag */
-#define TIM_SR_CC_IF(x) BIT((x) + 1) /* CC1, CC2, CC3, CC4 interrupt flag */
-#define TIM_EGR_UG BIT(0) /* Update Generation */
-#define TIM_CCMR_PE BIT(3) /* Channel Preload Enable */
-#define TIM_CCMR_M1 (BIT(6) | BIT(5)) /* Channel PWM Mode 1 */
-#define TIM_CCMR_CC1S (BIT(0) | BIT(1)) /* Capture/compare 1 sel */
-#define TIM_CCMR_IC1PSC GENMASK(3, 2) /* Input capture 1 prescaler */
-#define TIM_CCMR_CC2S (BIT(8) | BIT(9)) /* Capture/compare 2 sel */
-#define TIM_CCMR_IC2PSC GENMASK(11, 10) /* Input capture 2 prescaler */
-#define TIM_CCMR_CC1S_TI1 BIT(0) /* IC1/IC3 selects TI1/TI3 */
-#define TIM_CCMR_CC1S_TI2 BIT(1) /* IC1/IC3 selects TI2/TI4 */
-#define TIM_CCMR_CC2S_TI2 BIT(8) /* IC2/IC4 selects TI2/TI4 */
-#define TIM_CCMR_CC2S_TI1 BIT(9) /* IC2/IC4 selects TI1/TI3 */
-#define TIM_CCMR_CC3S (BIT(0) | BIT(1)) /* Capture/compare 3 sel */
-#define TIM_CCMR_CC4S (BIT(8) | BIT(9)) /* Capture/compare 4 sel */
-#define TIM_CCMR_CC3S_TI3 BIT(0) /* IC3 selects TI3 */
-#define TIM_CCMR_CC4S_TI4 BIT(8) /* IC4 selects TI4 */
-#define TIM_CCER_CC1E BIT(0) /* Capt/Comp 1 out Ena */
-#define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */
-#define TIM_CCER_CC1NE BIT(2) /* Capt/Comp 1N out Ena */
-#define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */
-#define TIM_CCER_CC2E BIT(4) /* Capt/Comp 2 out Ena */
-#define TIM_CCER_CC2P BIT(5) /* Capt/Comp 2 Polarity */
-#define TIM_CCER_CC2NP BIT(7) /* Capt/Comp 2N Polarity */
-#define TIM_CCER_CC3E BIT(8) /* Capt/Comp 3 out Ena */
-#define TIM_CCER_CC3P BIT(9) /* Capt/Comp 3 Polarity */
-#define TIM_CCER_CC3NP BIT(11) /* Capt/Comp 3N Polarity */
-#define TIM_CCER_CC4E BIT(12) /* Capt/Comp 4 out Ena */
-#define TIM_CCER_CC4P BIT(13) /* Capt/Comp 4 Polarity */
-#define TIM_CCER_CC4NP BIT(15) /* Capt/Comp 4N Polarity */
-#define TIM_CCER_CCXE (BIT(0) | BIT(4) | BIT(8) | BIT(12))
-#define TIM_BDTR_BKE(x) BIT(12 + (x) * 12) /* Break input enable */
-#define TIM_BDTR_BKP(x) BIT(13 + (x) * 12) /* Break input polarity */
-#define TIM_BDTR_AOE BIT(14) /* Automatic Output Enable */
-#define TIM_BDTR_MOE BIT(15) /* Main Output Enable */
-#define TIM_BDTR_BKF(x) (0xf << (16 + (x) * 4))
-#define TIM_DCR_DBA GENMASK(4, 0) /* DMA base addr */
-#define TIM_DCR_DBL GENMASK(12, 8) /* DMA burst len */
+#define TIM_CR1_CEN BIT(0) /* Counter Enable */
+#define TIM_CR1_DIR BIT(4) /* Counter Direction */
+#define TIM_CR1_ARPE BIT(7) /* Auto-reload Preload Ena */
+#define TIM_CR2_MMS (BIT(4) | BIT(5) | BIT(6)) /* Master mode selection */
+#define TIM_CR2_MMS2 GENMASK(23, 20) /* Master mode selection 2 */
+#define TIM_SMCR_SMS (BIT(0) | BIT(1) | BIT(2)) /* Slave mode selection */
+#define TIM_SMCR_TS (BIT(4) | BIT(5) | BIT(6)) /* Trigger selection */
+#define TIM_DIER_UIE BIT(0) /* Update interrupt */
+#define TIM_DIER_CCxIE(x) BIT(1 + ((x) - 1)) /* CCx Interrupt Enable (x ∈ {1, .. 4}) */
+#define TIM_DIER_CC1IE TIM_DIER_CCxIE(1) /* CC1 Interrupt Enable */
+#define TIM_DIER_CC2IE TIM_DIER_CCxIE(2) /* CC2 Interrupt Enable */
+#define TIM_DIER_CC3IE TIM_DIER_CCxIE(3) /* CC3 Interrupt Enable */
+#define TIM_DIER_CC4IE TIM_DIER_CCxIE(4) /* CC4 Interrupt Enable */
+#define TIM_DIER_UDE BIT(8) /* Update DMA request Enable */
+#define TIM_DIER_CCxDE(x) BIT(9 + ((x) - 1)) /* CCx DMA request Enable (x ∈ {1, .. 4}) */
+#define TIM_DIER_CC1DE TIM_DIER_CCxDE(1) /* CC1 DMA request Enable */
+#define TIM_DIER_CC2DE TIM_DIER_CCxDE(2) /* CC2 DMA request Enable */
+#define TIM_DIER_CC3DE TIM_DIER_CCxDE(3) /* CC3 DMA request Enable */
+#define TIM_DIER_CC4DE TIM_DIER_CCxDE(4) /* CC4 DMA request Enable */
+#define TIM_DIER_COMDE BIT(13) /* COM DMA request Enable */
+#define TIM_DIER_TDE BIT(14) /* Trigger DMA request Enable */
+#define TIM_SR_UIF BIT(0) /* Update interrupt flag */
+#define TIM_SR_CC_IF(x) BIT((x) + 1) /* CC1, CC2, CC3, CC4 interrupt flag */
+#define TIM_EGR_UG BIT(0) /* Update Generation */
+#define TIM_CCMR_PE BIT(3) /* Channel Preload Enable */
+#define TIM_CCMR_M1 (BIT(6) | BIT(5)) /* Channel PWM Mode 1 */
+#define TIM_CCMR_CC1S (BIT(0) | BIT(1)) /* Capture/compare 1 sel */
+#define TIM_CCMR_IC1PSC GENMASK(3, 2) /* Input capture 1 prescaler */
+#define TIM_CCMR_CC2S (BIT(8) | BIT(9)) /* Capture/compare 2 sel */
+#define TIM_CCMR_IC2PSC GENMASK(11, 10) /* Input capture 2 prescaler */
+#define TIM_CCMR_CC1S_TI1 BIT(0) /* IC1/IC3 selects TI1/TI3 */
+#define TIM_CCMR_CC1S_TI2 BIT(1) /* IC1/IC3 selects TI2/TI4 */
+#define TIM_CCMR_CC2S_TI2 BIT(8) /* IC2/IC4 selects TI2/TI4 */
+#define TIM_CCMR_CC2S_TI1 BIT(9) /* IC2/IC4 selects TI1/TI3 */
+#define TIM_CCMR_CC3S (BIT(0) | BIT(1)) /* Capture/compare 3 sel */
+#define TIM_CCMR_CC4S (BIT(8) | BIT(9)) /* Capture/compare 4 sel */
+#define TIM_CCMR_CC3S_TI3 BIT(0) /* IC3 selects TI3 */
+#define TIM_CCMR_CC4S_TI4 BIT(8) /* IC4 selects TI4 */
+#define TIM_CCER_CCxE(x) BIT(0 + 4 * ((x) - 1)) /* Capt/Comp x out Ena (x ∈ {1, .. 4}) */
+#define TIM_CCER_CCxP(x) BIT(1 + 4 * ((x) - 1)) /* Capt/Comp x Polarity (x ∈ {1, .. 4}) */
+#define TIM_CCER_CCxNE(x) BIT(2 + 4 * ((x) - 1)) /* Capt/Comp xN out Ena (x ∈ {1, .. 4}) */
+#define TIM_CCER_CCxNP(x) BIT(3 + 4 * ((x) - 1)) /* Capt/Comp xN Polarity (x ∈ {1, .. 4}) */
+#define TIM_CCER_CC1E TIM_CCER_CCxE(1) /* Capt/Comp 1 out Ena */
+#define TIM_CCER_CC1P TIM_CCER_CCxP(1) /* Capt/Comp 1 Polarity */
+#define TIM_CCER_CC1NE TIM_CCER_CCxNE(1) /* Capt/Comp 1N out Ena */
+#define TIM_CCER_CC1NP TIM_CCER_CCxNP(1) /* Capt/Comp 1N Polarity */
+#define TIM_CCER_CC2E TIM_CCER_CCxE(2) /* Capt/Comp 2 out Ena */
+#define TIM_CCER_CC2P TIM_CCER_CCxP(2) /* Capt/Comp 2 Polarity */
+#define TIM_CCER_CC2NE TIM_CCER_CCxNE(2) /* Capt/Comp 2N out Ena */
+#define TIM_CCER_CC2NP TIM_CCER_CCxNP(2) /* Capt/Comp 2N Polarity */
+#define TIM_CCER_CC3E TIM_CCER_CCxE(3) /* Capt/Comp 3 out Ena */
+#define TIM_CCER_CC3P TIM_CCER_CCxP(3) /* Capt/Comp 3 Polarity */
+#define TIM_CCER_CC3NE TIM_CCER_CCxNE(3) /* Capt/Comp 3N out Ena */
+#define TIM_CCER_CC3NP TIM_CCER_CCxNP(3) /* Capt/Comp 3N Polarity */
+#define TIM_CCER_CC4E TIM_CCER_CCxE(4) /* Capt/Comp 4 out Ena */
+#define TIM_CCER_CC4P TIM_CCER_CCxP(4) /* Capt/Comp 4 Polarity */
+#define TIM_CCER_CC4NE TIM_CCER_CCxNE(4) /* Capt/Comp 4N out Ena */
+#define TIM_CCER_CC4NP TIM_CCER_CCxNP(4) /* Capt/Comp 4N Polarity */
+#define TIM_CCER_CCXE (BIT(0) | BIT(4) | BIT(8) | BIT(12))
+#define TIM_BDTR_BKE(x) BIT(12 + (x) * 12) /* Break input enable */
+#define TIM_BDTR_BKP(x) BIT(13 + (x) * 12) /* Break input polarity */
+#define TIM_BDTR_AOE BIT(14) /* Automatic Output Enable */
+#define TIM_BDTR_MOE BIT(15) /* Main Output Enable */
+#define TIM_BDTR_BKF(x) (0xf << (16 + (x) * 4))
+#define TIM_DCR_DBA GENMASK(4, 0) /* DMA base addr */
+#define TIM_DCR_DBL GENMASK(12, 8) /* DMA burst len */
-#define MAX_TIM_PSC 0xFFFF
-#define MAX_TIM_ICPSC 0x3
-#define TIM_CR2_MMS_SHIFT 4
-#define TIM_CR2_MMS2_SHIFT 20
+#define MAX_TIM_PSC 0xFFFF
+#define MAX_TIM_ICPSC 0x3
+#define TIM_CR2_MMS_SHIFT 4
+#define TIM_CR2_MMS2_SHIFT 20
#define TIM_SMCR_SMS_SLAVE_MODE_DISABLED 0 /* counts on internal clock when CEN=1 */
#define TIM_SMCR_SMS_ENCODER_MODE_1 1 /* counts TI1FP1 edges, depending on TI2FP2 level */
#define TIM_SMCR_SMS_ENCODER_MODE_2 2 /* counts TI2FP2 edges, depending on TI1FP1 level */
#define TIM_SMCR_SMS_ENCODER_MODE_3 3 /* counts on both TI1FP1 and TI2FP2 edges */
-#define TIM_SMCR_TS_SHIFT 4
-#define TIM_BDTR_BKF_MASK 0xF
-#define TIM_BDTR_BKF_SHIFT(x) (16 + (x) * 4)
+#define TIM_SMCR_TS_SHIFT 4
+#define TIM_BDTR_BKF_MASK 0xF
+#define TIM_BDTR_BKF_SHIFT(x) (16 + (x) * 4)
enum stm32_timers_dmas {
STM32_TIMERS_DMA_CH1,
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index eace8ea6cda0..8c09d14a3a28 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -100,8 +100,6 @@ struct tmio_mmc_data {
dma_addr_t dma_rx_offset;
unsigned int max_blk_count;
unsigned short max_segs;
- void (*set_pwr)(struct platform_device *host, int state);
- void (*set_clk_div)(struct platform_device *host, int state);
};
/*
diff --git a/include/linux/misc_cgroup.h b/include/linux/misc_cgroup.h
index e799b1f8d05b..49eef10c8e59 100644
--- a/include/linux/misc_cgroup.h
+++ b/include/linux/misc_cgroup.h
@@ -9,15 +9,16 @@
#define _MISC_CGROUP_H_
/**
- * Types of misc cgroup entries supported by the host.
+ * enum misc_res_type - Types of misc cgroup entries supported by the host.
*/
enum misc_res_type {
#ifdef CONFIG_KVM_AMD_SEV
- /* AMD SEV ASIDs resource */
+ /** @MISC_CG_RES_SEV: AMD SEV ASIDs resource */
MISC_CG_RES_SEV,
- /* AMD SEV-ES ASIDs resource */
+ /** @MISC_CG_RES_SEV_ES: AMD SEV-ES ASIDs resource */
MISC_CG_RES_SEV_ES,
#endif
+ /** @MISC_CG_RES_TYPES: count of enum misc_res_type constants */
MISC_CG_RES_TYPES
};
@@ -30,13 +31,16 @@ struct misc_cg;
/**
* struct misc_res: Per cgroup per misc type resource
* @max: Maximum limit on the resource.
+ * @watermark: Historical maximum usage of the resource.
* @usage: Current usage of the resource.
* @events: Number of times, the resource limit exceeded.
*/
struct misc_res {
u64 max;
+ atomic64_t watermark;
atomic64_t usage;
atomic64_t events;
+ atomic64_t events_local;
};
/**
@@ -50,6 +54,8 @@ struct misc_cg {
/* misc.events */
struct cgroup_file events_file;
+ /* misc.events.local */
+ struct cgroup_file events_local_file;
struct misc_res res[MISC_CG_RES_TYPES];
};
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 5df52e15f7d6..d45bfb7cf81d 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -2029,7 +2029,11 @@ struct mlx5_ifc_cmd_hca_cap_2_bits {
u8 pcc_ifa2[0x1];
u8 reserved_at_3f1[0xf];
- u8 reserved_at_400[0x400];
+ u8 reserved_at_400[0x40];
+
+ u8 reserved_at_440[0x8];
+ u8 max_num_eqs_24b[0x18];
+ u8 reserved_at_460[0x3a0];
};
enum mlx5_ifc_flow_destination_type {
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 586a8f0104d7..1dc6248feb83 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -1979,8 +1979,9 @@ static inline int subsection_map_index(unsigned long pfn)
static inline int pfn_section_valid(struct mem_section *ms, unsigned long pfn)
{
int idx = subsection_map_index(pfn);
+ struct mem_section_usage *usage = READ_ONCE(ms->usage);
- return test_bit(idx, READ_ONCE(ms->usage)->subsection_map);
+ return usage ? test_bit(idx, usage->subsection_map) : 0;
}
#else
static inline int pfn_section_valid(struct mem_section *ms, unsigned long pfn)
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 967aa9ea9f96..8ec8fed3bce8 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -50,13 +50,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT};
extern int path_pts(struct path *path);
-extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);
-
-static inline int user_path_at(int dfd, const char __user *name, unsigned flags,
- struct path *path)
-{
- return user_path_at_empty(dfd, name, flags, path, NULL);
-}
+extern int user_path_at(int, const char __user *, unsigned, struct path *);
struct dentry *lookup_one_qstr_excl(const struct qstr *name,
struct dentry *base,
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 5601d14e2886..dab6a1734a22 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -42,6 +42,17 @@ struct nsproxy {
};
extern struct nsproxy init_nsproxy;
+#define to_ns_common(__ns) \
+ _Generic((__ns), \
+ struct cgroup_namespace *: &(__ns->ns), \
+ struct ipc_namespace *: &(__ns->ns), \
+ struct net *: &(__ns->ns), \
+ struct pid_namespace *: &(__ns->ns), \
+ struct mnt_namespace *: &(__ns->ns), \
+ struct time_namespace *: &(__ns->ns), \
+ struct user_namespace *: &(__ns->ns), \
+ struct uts_namespace *: &(__ns->ns))
+
/*
* A structure to encompass all bits needed to install
* a partial or complete new set of namespaces.
@@ -112,4 +123,6 @@ static inline void get_nsproxy(struct nsproxy *ns)
refcount_inc(&ns->count);
}
+DEFINE_FREE(put_nsproxy, struct nsproxy *, if (_T) put_nsproxy(_T))
+
#endif
diff --git a/include/linux/nvme-fc-driver.h b/include/linux/nvme-fc-driver.h
index 4109f1bd6128..89ea1ebd975a 100644
--- a/include/linux/nvme-fc-driver.h
+++ b/include/linux/nvme-fc-driver.h
@@ -920,6 +920,9 @@ struct nvmet_fc_target_port {
* further references to hosthandle.
* Entrypoint is Mandatory if the lldd calls nvmet_fc_invalidate_host().
*
+ * @host_traddr: called by the transport to retrieve the node name and
+ * port name of the host port address.
+ *
* @max_hw_queues: indicates the maximum number of hw queues the LLDD
* supports for cpu affinitization.
* Value is Mandatory. Must be at least 1.
@@ -975,6 +978,7 @@ struct nvmet_fc_target_template {
void (*ls_abort)(struct nvmet_fc_target_port *targetport,
void *hosthandle, struct nvmefc_ls_req *lsreq);
void (*host_release)(void *hosthandle);
+ int (*host_traddr)(void *hosthandle, u64 *wwnn, u64 *wwpn);
u32 max_hw_queues;
u16 max_sgl_segments;
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index c693ac344ec0..c12a329dd463 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -25,6 +25,9 @@
#define NVME_NSID_ALL 0xffffffff
+/* Special NSSR value, 'NVMe' */
+#define NVME_SUBSYS_RESET 0x4E564D65
+
enum nvme_subsys_type {
/* Referral to another discovery type target subsystem */
NVME_NQN_DISC = 1,
@@ -1848,6 +1851,7 @@ enum {
/*
* Generic Command Status:
*/
+ NVME_SCT_GENERIC = 0x0,
NVME_SC_SUCCESS = 0x0,
NVME_SC_INVALID_OPCODE = 0x1,
NVME_SC_INVALID_FIELD = 0x2,
@@ -1895,6 +1899,7 @@ enum {
/*
* Command Specific Status:
*/
+ NVME_SCT_COMMAND_SPECIFIC = 0x100,
NVME_SC_CQ_INVALID = 0x100,
NVME_SC_QID_INVALID = 0x101,
NVME_SC_QUEUE_SIZE = 0x102,
@@ -1968,6 +1973,7 @@ enum {
/*
* Media and Data Integrity Errors:
*/
+ NVME_SCT_MEDIA_ERROR = 0x200,
NVME_SC_WRITE_FAULT = 0x280,
NVME_SC_READ_ERROR = 0x281,
NVME_SC_GUARD_CHECK = 0x282,
@@ -1980,6 +1986,7 @@ enum {
/*
* Path-related Errors:
*/
+ NVME_SCT_PATH = 0x300,
NVME_SC_INTERNAL_PATH_ERROR = 0x300,
NVME_SC_ANA_PERSISTENT_LOSS = 0x301,
NVME_SC_ANA_INACCESSIBLE = 0x302,
@@ -1988,11 +1995,17 @@ enum {
NVME_SC_HOST_PATH_ERROR = 0x370,
NVME_SC_HOST_ABORTED_CMD = 0x371,
- NVME_SC_CRD = 0x1800,
- NVME_SC_MORE = 0x2000,
- NVME_SC_DNR = 0x4000,
+ NVME_SC_MASK = 0x00ff, /* Status Code */
+ NVME_SCT_MASK = 0x0700, /* Status Code Type */
+ NVME_SCT_SC_MASK = NVME_SCT_MASK | NVME_SC_MASK,
+
+ NVME_STATUS_CRD = 0x1800, /* Command Retry Delayed */
+ NVME_STATUS_MORE = 0x2000,
+ NVME_STATUS_DNR = 0x4000, /* Do Not Retry */
};
+#define NVME_SCT(status) ((status) >> 8 & 7)
+
struct nvme_completion {
/*
* Used by Admin and Fabrics commands to return data:
diff --git a/include/linux/page_ref.h b/include/linux/page_ref.h
index 1acf5bac7f50..8c236c651d1d 100644
--- a/include/linux/page_ref.h
+++ b/include/linux/page_ref.h
@@ -230,7 +230,13 @@ static inline int folio_ref_dec_return(struct folio *folio)
static inline bool page_ref_add_unless(struct page *page, int nr, int u)
{
- bool ret = atomic_add_unless(&page->_refcount, nr, u);
+ bool ret = false;
+
+ rcu_read_lock();
+ /* avoid writing to the vmemmap area being remapped */
+ if (!page_is_fake_head(page) && page_ref_count(page) != u)
+ ret = atomic_add_unless(&page->_refcount, nr, u);
+ rcu_read_unlock();
if (page_ref_tracepoint_active(page_ref_mod_unless))
__page_ref_mod_unless(page, nr, ret);
@@ -258,54 +264,9 @@ static inline bool folio_try_get(struct folio *folio)
return folio_ref_add_unless(folio, 1, 0);
}
-static inline bool folio_ref_try_add_rcu(struct folio *folio, int count)
-{
-#ifdef CONFIG_TINY_RCU
- /*
- * The caller guarantees the folio will not be freed from interrupt
- * context, so (on !SMP) we only need preemption to be disabled
- * and TINY_RCU does that for us.
- */
-# ifdef CONFIG_PREEMPT_COUNT
- VM_BUG_ON(!in_atomic() && !irqs_disabled());
-# endif
- VM_BUG_ON_FOLIO(folio_ref_count(folio) == 0, folio);
- folio_ref_add(folio, count);
-#else
- if (unlikely(!folio_ref_add_unless(folio, count, 0))) {
- /* Either the folio has been freed, or will be freed. */
- return false;
- }
-#endif
- return true;
-}
-
-/**
- * folio_try_get_rcu - Attempt to increase the refcount on a folio.
- * @folio: The folio.
- *
- * This is a version of folio_try_get() optimised for non-SMP kernels.
- * If you are still holding the rcu_read_lock() after looking up the
- * page and know that the page cannot have its refcount decreased to
- * zero in interrupt context, you can use this instead of folio_try_get().
- *
- * Example users include get_user_pages_fast() (as pages are not unmapped
- * from interrupt context) and the page cache lookups (as pages are not
- * truncated from interrupt context). We also know that pages are not
- * frozen in interrupt context for the purposes of splitting or migration.
- *
- * You can also use this function if you're holding a lock that prevents
- * pages being frozen & removed; eg the i_pages lock for the page cache
- * or the mmap_lock or page table lock for page tables. In this case,
- * it will always succeed, and you could have used a plain folio_get(),
- * but it's sometimes more convenient to have a common function called
- * from both locked and RCU-protected contexts.
- *
- * Return: True if the reference count was successfully incremented.
- */
-static inline bool folio_try_get_rcu(struct folio *folio)
+static inline bool folio_ref_try_add(struct folio *folio, int count)
{
- return folio_ref_try_add_rcu(folio, 1);
+ return folio_ref_add_unless(folio, count, 0);
}
static inline int page_ref_freeze(struct page *page, int count)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 59f1df0cde5a..a0a026d2d244 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -354,11 +354,18 @@ static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask)
* a good order (that's 1MB if you're using 4kB pages)
*/
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define MAX_PAGECACHE_ORDER HPAGE_PMD_ORDER
+#define PREFERRED_MAX_PAGECACHE_ORDER HPAGE_PMD_ORDER
#else
-#define MAX_PAGECACHE_ORDER 8
+#define PREFERRED_MAX_PAGECACHE_ORDER 8
#endif
+/*
+ * xas_split_alloc() does not support arbitrary orders. This implies no
+ * 512MB THP on ARM64 with 64KB base page size.
+ */
+#define MAX_XAS_ORDER (XA_CHUNK_SHIFT * 2 - 1)
+#define MAX_PAGECACHE_ORDER min(MAX_XAS_ORDER, PREFERRED_MAX_PAGECACHE_ORDER)
+
/**
* mapping_set_large_folios() - Indicate the file supports large folios.
* @mapping: The file.
diff --git a/include/linux/path.h b/include/linux/path.h
index 475225a03d0d..ca073e70decd 100644
--- a/include/linux/path.h
+++ b/include/linux/path.h
@@ -24,4 +24,13 @@ static inline void path_put_init(struct path *path)
*path = (struct path) { };
}
+/*
+ * Cleanup macro for use with __free(path_put). Avoids dereference and
+ * copying @path unlike DEFINE_FREE(). path_put() will handle the empty
+ * path correctly just ensure @path is initialized:
+ *
+ * struct path path __free(path_put) = {};
+ */
+#define __free_path_put path_put
+
#endif /* _LINUX_PATH_H */
diff --git a/include/linux/pci-pwrctl.h b/include/linux/pci-pwrctl.h
new file mode 100644
index 000000000000..45e9cfe740e4
--- /dev/null
+++ b/include/linux/pci-pwrctl.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#ifndef __PCI_PWRCTL_H__
+#define __PCI_PWRCTL_H__
+
+#include <linux/notifier.h>
+
+struct device;
+struct device_link;
+
+/*
+ * This is a simple framework for solving the issue of PCI devices that require
+ * certain resources (regulators, GPIOs, clocks) to be enabled before the
+ * device can actually be detected on the PCI bus.
+ *
+ * The idea is to reuse the platform bus to populate OF nodes describing the
+ * PCI device and its resources, let these platform devices probe and enable
+ * relevant resources and then trigger a rescan of the PCI bus allowing for the
+ * same device (with a second associated struct device) to be registered with
+ * the PCI subsystem.
+ *
+ * To preserve a correct hierarchy for PCI power management and device reset,
+ * we create a device link between the power control platform device (parent)
+ * and the supplied PCI device (child).
+ */
+
+/**
+ * struct pci_pwrctl - PCI device power control context.
+ * @dev: Address of the power controlling device.
+ *
+ * An object of this type must be allocated by the PCI power control device and
+ * passed to the pwrctl subsystem to trigger a bus rescan and setup a device
+ * link with the device once it's up.
+ */
+struct pci_pwrctl {
+ struct device *dev;
+
+ /* Private: don't use. */
+ struct notifier_block nb;
+ struct device_link *link;
+};
+
+int pci_pwrctl_device_set_ready(struct pci_pwrctl *pwrctl);
+void pci_pwrctl_device_unset_ready(struct pci_pwrctl *pwrctl);
+int devm_pci_pwrctl_device_set_ready(struct device *dev,
+ struct pci_pwrctl *pwrctl);
+
+#endif /* __PCI_PWRCTL_H__ */
diff --git a/include/linux/perf/arm_pmuv3.h b/include/linux/perf/arm_pmuv3.h
index 46377e134d67..7867db04ec98 100644
--- a/include/linux/perf/arm_pmuv3.h
+++ b/include/linux/perf/arm_pmuv3.h
@@ -309,4 +309,6 @@
} \
} while (0)
+#include <asm/arm_pmuv3.h>
+
#endif
diff --git a/include/linux/phy.h b/include/linux/phy.h
index e6e83304558e..3be430cf3132 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1122,7 +1122,7 @@ struct phy_driver {
u8 index, enum led_brightness value);
/**
- * @led_blink_set: Set a PHY LED brightness. Index indicates
+ * @led_blink_set: Set a PHY LED blinking. Index indicates
* which of the PHYs led should be configured to blink. Delays
* are in milliseconds and if both are zero then a sensible
* default should be chosen. The call should adjust the
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index ecc47d5fe239..e574b790be6f 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -3463,6 +3463,34 @@ union __ec_align_offset1 ec_response_get_next_data_v1 {
};
BUILD_ASSERT(sizeof(union ec_response_get_next_data_v1) == 16);
+union __ec_align_offset1 ec_response_get_next_data_v3 {
+ uint8_t key_matrix[18];
+
+ /* Unaligned */
+ uint32_t host_event;
+ uint64_t host_event64;
+
+ struct __ec_todo_unpacked {
+ /* For aligning the fifo_info */
+ uint8_t reserved[3];
+ struct ec_response_motion_sense_fifo_info info;
+ } sensor_fifo;
+
+ uint32_t buttons;
+
+ uint32_t switches;
+
+ uint32_t fp_events;
+
+ uint32_t sysrq;
+
+ /* CEC events from enum mkbp_cec_event */
+ uint32_t cec_events;
+
+ uint8_t cec_message[16];
+};
+BUILD_ASSERT(sizeof(union ec_response_get_next_data_v3) == 18);
+
struct ec_response_get_next_event {
uint8_t event_type;
/* Followed by event data if any */
@@ -3475,6 +3503,12 @@ struct ec_response_get_next_event_v1 {
union ec_response_get_next_data_v1 data;
} __ec_align1;
+struct ec_response_get_next_event_v3 {
+ uint8_t event_type;
+ /* Followed by event data if any */
+ union ec_response_get_next_data_v3 data;
+} __ec_align1;
+
/* Bit indices for buttons and switches.*/
/* Buttons */
#define EC_MKBP_POWER_BUTTON 0
@@ -3809,16 +3843,61 @@ struct ec_params_i2c_write {
* discharge the battery.
*/
#define EC_CMD_CHARGE_CONTROL 0x0096
-#define EC_VER_CHARGE_CONTROL 1
+#define EC_VER_CHARGE_CONTROL 3
enum ec_charge_control_mode {
CHARGE_CONTROL_NORMAL = 0,
CHARGE_CONTROL_IDLE,
CHARGE_CONTROL_DISCHARGE,
+ /* Add no more entry below. */
+ CHARGE_CONTROL_COUNT,
+};
+
+#define EC_CHARGE_MODE_TEXT \
+ { \
+ [CHARGE_CONTROL_NORMAL] = "NORMAL", \
+ [CHARGE_CONTROL_IDLE] = "IDLE", \
+ [CHARGE_CONTROL_DISCHARGE] = "DISCHARGE", \
+ }
+
+enum ec_charge_control_cmd {
+ EC_CHARGE_CONTROL_CMD_SET = 0,
+ EC_CHARGE_CONTROL_CMD_GET,
+};
+
+enum ec_charge_control_flag {
+ EC_CHARGE_CONTROL_FLAG_NO_IDLE = BIT(0),
};
struct ec_params_charge_control {
- uint32_t mode; /* enum charge_control_mode */
+ uint32_t mode; /* enum charge_control_mode */
+
+ /* Below are the fields added in V2. */
+ uint8_t cmd; /* enum ec_charge_control_cmd. */
+ uint8_t flags; /* enum ec_charge_control_flag (v3+) */
+ /*
+ * Lower and upper thresholds for battery sustainer. This struct isn't
+ * named to avoid tainting foreign projects' name spaces.
+ *
+ * If charge mode is explicitly set (e.g. DISCHARGE), battery sustainer
+ * will be disabled. To disable battery sustainer, set mode=NORMAL,
+ * lower=-1, upper=-1.
+ */
+ struct {
+ int8_t lower; /* Display SoC in percentage. */
+ int8_t upper; /* Display SoC in percentage. */
+ } sustain_soc;
+} __ec_align4;
+
+/* Added in v2 */
+struct ec_response_charge_control {
+ uint32_t mode; /* enum charge_control_mode */
+ struct { /* Battery sustainer thresholds */
+ int8_t lower;
+ int8_t upper;
+ } sustain_soc;
+ uint8_t flags; /* enum ec_charge_control_flag (v3+) */
+ uint8_t reserved;
} __ec_align4;
/*****************************************************************************/
diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h
index 8865e350c12a..b34ed0cc1f8d 100644
--- a/include/linux/platform_data/cros_ec_proto.h
+++ b/include/linux/platform_data/cros_ec_proto.h
@@ -185,7 +185,7 @@ struct cros_ec_device {
bool host_sleep_v1;
struct blocking_notifier_head event_notifier;
- struct ec_response_get_next_event_v1 event_data;
+ struct ec_response_get_next_event_v3 event_data;
int event_size;
u32 host_event_wake_mask;
u32 last_resume_result;
@@ -261,6 +261,10 @@ int cros_ec_get_sensor_count(struct cros_ec_dev *ec);
int cros_ec_cmd(struct cros_ec_device *ec_dev, unsigned int version, int command, const void *outdata,
size_t outsize, void *indata, size_t insize);
+int cros_ec_cmd_readmem(struct cros_ec_device *ec_dev, u8 offset, u8 size, void *dest);
+
+int cros_ec_get_cmd_versions(struct cros_ec_device *ec_dev, u16 cmd);
+
/**
* cros_ec_get_time_ns() - Return time in ns.
*
diff --git a/include/linux/platform_data/mmc-pxamci.h b/include/linux/platform_data/mmc-pxamci.h
index 7e44e84e7150..652f323b5ecc 100644
--- a/include/linux/platform_data/mmc-pxamci.h
+++ b/include/linux/platform_data/mmc-pxamci.h
@@ -7,6 +7,7 @@
struct device;
struct mmc_host;
+struct property_entry;
struct pxamci_platform_data {
unsigned int ocr_mask; /* available voltages */
@@ -18,7 +19,8 @@ struct pxamci_platform_data {
bool gpio_card_ro_invert; /* gpio ro is inverted */
};
-extern void pxa_set_mci_info(struct pxamci_platform_data *info);
+extern void pxa_set_mci_info(const struct pxamci_platform_data *info,
+ const struct property_entry *props);
extern void pxa3xx_set_mci2_info(struct pxamci_platform_data *info);
extern void pxa3xx_set_mci3_info(struct pxamci_platform_data *info);
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index f24546a3d3db..015751b64746 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -175,6 +175,10 @@ struct generic_pm_domain {
int (*set_performance_state)(struct generic_pm_domain *genpd,
unsigned int state);
struct gpd_dev_ops dev_ops;
+ int (*set_hwmode_dev)(struct generic_pm_domain *domain,
+ struct device *dev, bool enable);
+ bool (*get_hwmode_dev)(struct generic_pm_domain *domain,
+ struct device *dev);
int (*attach_dev)(struct generic_pm_domain *domain,
struct device *dev);
void (*detach_dev)(struct generic_pm_domain *domain,
@@ -237,6 +241,7 @@ struct generic_pm_domain_data {
unsigned int performance_state;
unsigned int default_pstate;
unsigned int rpm_pstate;
+ bool hw_mode;
void *data;
};
@@ -267,6 +272,8 @@ int dev_pm_genpd_remove_notifier(struct device *dev);
void dev_pm_genpd_set_next_wakeup(struct device *dev, ktime_t next);
ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev);
void dev_pm_genpd_synced_poweroff(struct device *dev);
+int dev_pm_genpd_set_hwmode(struct device *dev, bool enable);
+bool dev_pm_genpd_get_hwmode(struct device *dev);
extern struct dev_power_governor simple_qos_governor;
extern struct dev_power_governor pm_domain_always_on_gov;
@@ -340,6 +347,16 @@ static inline ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev)
static inline void dev_pm_genpd_synced_poweroff(struct device *dev)
{ }
+static inline int dev_pm_genpd_set_hwmode(struct device *dev, bool enable)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline bool dev_pm_genpd_get_hwmode(struct device *dev)
+{
+ return false;
+}
+
#define simple_qos_governor (*(struct dev_power_governor *)(NULL))
#define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL))
#endif
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 60b92c2c75ef..f8c2dc12dbd3 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -4,9 +4,12 @@
#include <linux/device.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
+MODULE_IMPORT_NS(PWM);
+
struct pwm_chip;
/**
@@ -249,9 +252,7 @@ struct pwm_capture {
* @free: optional hook for freeing a PWM
* @capture: capture and report PWM signal
* @apply: atomically apply a new PWM config
- * @get_state: get the current PWM state. This function is only
- * called once per PWM device when the PWM chip is
- * registered.
+ * @get_state: get the current PWM state.
*/
struct pwm_ops {
int (*request)(struct pwm_chip *chip, struct pwm_device *pwm);
@@ -407,10 +408,6 @@ void pwmchip_remove(struct pwm_chip *chip);
int __devm_pwmchip_add(struct device *dev, struct pwm_chip *chip, struct module *owner);
#define devm_pwmchip_add(dev, chip) __devm_pwmchip_add(dev, chip, THIS_MODULE)
-struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
- unsigned int index,
- const char *label);
-
struct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *chip,
const struct of_phandle_args *args);
struct pwm_device *of_pwm_single_xlate(struct pwm_chip *chip,
@@ -505,14 +502,6 @@ static inline int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip)
return -EINVAL;
}
-static inline struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
- unsigned int index,
- const char *label)
-{
- might_sleep();
- return ERR_PTR(-ENODEV);
-}
-
static inline struct pwm_device *pwm_get(struct device *dev,
const char *consumer)
{
@@ -574,13 +563,6 @@ static inline void pwm_apply_args(struct pwm_device *pwm)
pwm_apply_might_sleep(pwm, &state);
}
-/* only for backwards-compatibility, new code should not use this */
-static inline int pwm_apply_state(struct pwm_device *pwm,
- const struct pwm_state *state)
-{
- return pwm_apply_might_sleep(pwm, state);
-}
-
struct pwm_lookup {
struct list_head list;
const char *provider;
diff --git a/include/linux/pwrseq/consumer.h b/include/linux/pwrseq/consumer.h
new file mode 100644
index 000000000000..7d583b4f266e
--- /dev/null
+++ b/include/linux/pwrseq/consumer.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#ifndef __POWER_SEQUENCING_CONSUMER_H__
+#define __POWER_SEQUENCING_CONSUMER_H__
+
+#include <linux/err.h>
+
+struct device;
+struct pwrseq_desc;
+
+#if IS_ENABLED(CONFIG_POWER_SEQUENCING)
+
+struct pwrseq_desc * __must_check
+pwrseq_get(struct device *dev, const char *target);
+void pwrseq_put(struct pwrseq_desc *desc);
+
+struct pwrseq_desc * __must_check
+devm_pwrseq_get(struct device *dev, const char *target);
+
+int pwrseq_power_on(struct pwrseq_desc *desc);
+int pwrseq_power_off(struct pwrseq_desc *desc);
+
+#else /* CONFIG_POWER_SEQUENCING */
+
+static inline struct pwrseq_desc * __must_check
+pwrseq_get(struct device *dev, const char *target)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void pwrseq_put(struct pwrseq_desc *desc)
+{
+}
+
+static inline struct pwrseq_desc * __must_check
+devm_pwrseq_get(struct device *dev, const char *target)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline int pwrseq_power_on(struct pwrseq_desc *desc)
+{
+ return -ENOSYS;
+}
+
+static inline int pwrseq_power_off(struct pwrseq_desc *desc)
+{
+ return -ENOSYS;
+}
+
+#endif /* CONFIG_POWER_SEQUENCING */
+
+#endif /* __POWER_SEQUENCING_CONSUMER_H__ */
diff --git a/include/linux/pwrseq/provider.h b/include/linux/pwrseq/provider.h
new file mode 100644
index 000000000000..cbc3607cbfcf
--- /dev/null
+++ b/include/linux/pwrseq/provider.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#ifndef __POWER_SEQUENCING_PROVIDER_H__
+#define __POWER_SEQUENCING_PROVIDER_H__
+
+struct device;
+struct module;
+struct pwrseq_device;
+
+typedef int (*pwrseq_power_state_func)(struct pwrseq_device *);
+typedef int (*pwrseq_match_func)(struct pwrseq_device *, struct device *);
+
+/**
+ * struct pwrseq_unit_data - Configuration of a single power sequencing
+ * unit.
+ * @name: Name of the unit.
+ * @deps: Units that must be enabled before this one and disabled after it
+ * in the order they come in this array. Must be NULL-terminated.
+ * @enable: Callback running the part of the power-on sequence provided by
+ * this unit.
+ * @disable: Callback running the part of the power-off sequence provided
+ * by this unit.
+ */
+struct pwrseq_unit_data {
+ const char *name;
+ const struct pwrseq_unit_data **deps;
+ pwrseq_power_state_func enable;
+ pwrseq_power_state_func disable;
+};
+
+/**
+ * struct pwrseq_target_data - Configuration of a power sequencing target.
+ * @name: Name of the target.
+ * @unit: Final unit that this target must reach in order to be considered
+ * enabled.
+ * @post_enable: Callback run after the target unit has been enabled, *after*
+ * the state lock has been released. It's useful for implementing
+ * boot-up delays without blocking other users from powering up
+ * using the same power sequencer.
+ */
+struct pwrseq_target_data {
+ const char *name;
+ const struct pwrseq_unit_data *unit;
+ pwrseq_power_state_func post_enable;
+};
+
+/**
+ * struct pwrseq_config - Configuration used for registering a new provider.
+ * @parent: Parent device for the sequencer. Must be set.
+ * @owner: Module providing this device.
+ * @drvdata: Private driver data.
+ * @match: Provider callback used to match the consumer device to the sequencer.
+ * @targets: Array of targets for this power sequencer. Must be NULL-terminated.
+ */
+struct pwrseq_config {
+ struct device *parent;
+ struct module *owner;
+ void *drvdata;
+ pwrseq_match_func match;
+ const struct pwrseq_target_data **targets;
+};
+
+struct pwrseq_device *
+pwrseq_device_register(const struct pwrseq_config *config);
+void pwrseq_device_unregister(struct pwrseq_device *pwrseq);
+struct pwrseq_device *
+devm_pwrseq_device_register(struct device *dev,
+ const struct pwrseq_config *config);
+
+void *pwrseq_device_get_drvdata(struct pwrseq_device *pwrseq);
+
+#endif /* __POWER_SEQUENCING_PROVIDER_H__ */
diff --git a/include/linux/rcu_segcblist.h b/include/linux/rcu_segcblist.h
index 659d13a7ddaa..ba95c06675e1 100644
--- a/include/linux/rcu_segcblist.h
+++ b/include/linux/rcu_segcblist.h
@@ -80,36 +80,35 @@ struct rcu_cblist {
* | SEGCBLIST_RCU_CORE | SEGCBLIST_LOCKING | SEGCBLIST_OFFLOADED |
* | |
* | Callbacks processed by rcu_core() from softirqs or local |
- * | rcuc kthread, while holding nocb_lock. Waking up CB and GP kthreads, |
- * | allowing nocb_timer to be armed. |
+ * | rcuc kthread, while holding nocb_lock. Waking up CB and GP kthreads. |
* ----------------------------------------------------------------------------
* |
* v
- * -----------------------------------
- * | |
- * v v
- * --------------------------------------- ----------------------------------|
- * | SEGCBLIST_RCU_CORE | | | SEGCBLIST_RCU_CORE | |
- * | SEGCBLIST_LOCKING | | | SEGCBLIST_LOCKING | |
- * | SEGCBLIST_OFFLOADED | | | SEGCBLIST_OFFLOADED | |
- * | SEGCBLIST_KTHREAD_CB | | SEGCBLIST_KTHREAD_GP |
- * | | | |
- * | | | |
- * | CB kthread woke up and | | GP kthread woke up and |
- * | acknowledged SEGCBLIST_OFFLOADED. | | acknowledged SEGCBLIST_OFFLOADED|
- * | Processes callbacks concurrently | | |
- * | with rcu_core(), holding | | |
- * | nocb_lock. | | |
- * --------------------------------------- -----------------------------------
- * | |
- * -----------------------------------
+ * ----------------------------------------------------------------------------
+ * | SEGCBLIST_RCU_CORE | SEGCBLIST_LOCKING | SEGCBLIST_OFFLOADED |
+ * | + unparked CB kthread |
+ * | |
+ * | CB kthread got unparked and processes callbacks concurrently with |
+ * | rcu_core(), holding nocb_lock. |
+ * ---------------------------------------------------------------------------
+ * |
+ * v
+ * ---------------------------------------------------------------------------|
+ * | SEGCBLIST_RCU_CORE | |
+ * | SEGCBLIST_LOCKING | |
+ * | SEGCBLIST_OFFLOADED | |
+ * | SEGCBLIST_KTHREAD_GP |
+ * | + unparked CB kthread |
+ * | |
+ * | GP kthread woke up and acknowledged nocb_lock. |
+ * ---------------------------------------- -----------------------------------
* |
* v
* |--------------------------------------------------------------------------|
- * | SEGCBLIST_LOCKING | |
- * | SEGCBLIST_OFFLOADED | |
+ * | SEGCBLIST_LOCKING | |
+ * | SEGCBLIST_OFFLOADED | |
* | SEGCBLIST_KTHREAD_GP | |
- * | SEGCBLIST_KTHREAD_CB |
+ * | + unparked CB kthread |
* | |
* | Kthreads handle callbacks holding nocb_lock, local rcu_core() stops |
* | handling callbacks. Enable bypass queueing. |
@@ -125,8 +124,8 @@ struct rcu_cblist {
* |--------------------------------------------------------------------------|
* | SEGCBLIST_LOCKING | |
* | SEGCBLIST_OFFLOADED | |
- * | SEGCBLIST_KTHREAD_CB | |
* | SEGCBLIST_KTHREAD_GP |
+ * | + unparked CB kthread |
* | |
* | CB/GP kthreads handle callbacks holding nocb_lock, local rcu_core() |
* | ignores callbacks. Bypass enqueue is enabled. |
@@ -137,11 +136,11 @@ struct rcu_cblist {
* | SEGCBLIST_RCU_CORE | |
* | SEGCBLIST_LOCKING | |
* | SEGCBLIST_OFFLOADED | |
- * | SEGCBLIST_KTHREAD_CB | |
* | SEGCBLIST_KTHREAD_GP |
+ * | + unparked CB kthread |
* | |
* | CB/GP kthreads handle callbacks holding nocb_lock, local rcu_core() |
- * | handles callbacks concurrently. Bypass enqueue is enabled. |
+ * | handles callbacks concurrently. Bypass enqueue is disabled. |
* | Invoke RCU core so we make sure not to preempt it in the middle with |
* | leaving some urgent work unattended within a jiffy. |
* ----------------------------------------------------------------------------
@@ -150,42 +149,31 @@ struct rcu_cblist {
* |--------------------------------------------------------------------------|
* | SEGCBLIST_RCU_CORE | |
* | SEGCBLIST_LOCKING | |
- * | SEGCBLIST_KTHREAD_CB | |
* | SEGCBLIST_KTHREAD_GP |
+ * | + unparked CB kthread |
* | |
* | CB/GP kthreads and local rcu_core() handle callbacks concurrently |
- * | holding nocb_lock. Wake up CB and GP kthreads if necessary. Disable |
- * | bypass enqueue. |
+ * | holding nocb_lock. Wake up GP kthread if necessary. |
* ----------------------------------------------------------------------------
* |
* v
- * -----------------------------------
- * | |
- * v v
- * ---------------------------------------------------------------------------|
- * | | |
- * | SEGCBLIST_RCU_CORE | | SEGCBLIST_RCU_CORE | |
- * | SEGCBLIST_LOCKING | | SEGCBLIST_LOCKING | |
- * | SEGCBLIST_KTHREAD_CB | SEGCBLIST_KTHREAD_GP |
- * | | |
- * | GP kthread woke up and | CB kthread woke up and |
- * | acknowledged the fact that | acknowledged the fact that |
- * | SEGCBLIST_OFFLOADED got cleared. | SEGCBLIST_OFFLOADED got cleared. |
- * | | The CB kthread goes to sleep |
- * | The callbacks from the target CPU | until it ever gets re-offloaded. |
- * | will be ignored from the GP kthread | |
- * | loop. | |
+ * |--------------------------------------------------------------------------|
+ * | SEGCBLIST_RCU_CORE | |
+ * | SEGCBLIST_LOCKING | |
+ * | + unparked CB kthread |
+ * | |
+ * | GP kthread woke up and acknowledged the fact that SEGCBLIST_OFFLOADED |
+ * | got cleared. The callbacks from the target CPU will be ignored from the|
+ * | GP kthread loop. |
* ----------------------------------------------------------------------------
- * | |
- * -----------------------------------
* |
* v
* ----------------------------------------------------------------------------
* | SEGCBLIST_RCU_CORE | SEGCBLIST_LOCKING |
+ * | + parked CB kthread |
* | |
- * | Callbacks processed by rcu_core() from softirqs or local |
- * | rcuc kthread, while holding nocb_lock. Forbid nocb_timer to be armed. |
- * | Flush pending nocb_timer. Flush nocb bypass callbacks. |
+ * | CB kthread is parked. Callbacks processed by rcu_core() from softirqs or |
+ * | local rcuc kthread, while holding nocb_lock. |
* ----------------------------------------------------------------------------
* |
* v
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index dfd2399f2cde..be450a3477be 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -209,7 +209,6 @@ void synchronize_rcu_tasks_rude(void);
#define rcu_note_voluntary_context_switch(t) rcu_tasks_qs(t, false)
void exit_tasks_rcu_start(void);
-void exit_tasks_rcu_stop(void);
void exit_tasks_rcu_finish(void);
#else /* #ifdef CONFIG_TASKS_RCU_GENERIC */
#define rcu_tasks_classic_qs(t, preempt) do { } while (0)
@@ -218,7 +217,6 @@ void exit_tasks_rcu_finish(void);
#define call_rcu_tasks call_rcu
#define synchronize_rcu_tasks synchronize_rcu
static inline void exit_tasks_rcu_start(void) { }
-static inline void exit_tasks_rcu_stop(void) { }
static inline void exit_tasks_rcu_finish(void) { }
#endif /* #else #ifdef CONFIG_TASKS_RCU_GENERIC */
@@ -421,11 +419,71 @@ static inline void rcu_preempt_sleep_check(void) { }
"Illegal context switch in RCU-sched read-side critical section"); \
} while (0)
+// See RCU_LOCKDEP_WARN() for an explanation of the double call to
+// debug_lockdep_rcu_enabled().
+static inline bool lockdep_assert_rcu_helper(bool c)
+{
+ return debug_lockdep_rcu_enabled() &&
+ (c || !rcu_is_watching() || !rcu_lockdep_current_cpu_online()) &&
+ debug_lockdep_rcu_enabled();
+}
+
+/**
+ * lockdep_assert_in_rcu_read_lock - WARN if not protected by rcu_read_lock()
+ *
+ * Splats if lockdep is enabled and there is no rcu_read_lock() in effect.
+ */
+#define lockdep_assert_in_rcu_read_lock() \
+ WARN_ON_ONCE(lockdep_assert_rcu_helper(!lock_is_held(&rcu_lock_map)))
+
+/**
+ * lockdep_assert_in_rcu_read_lock_bh - WARN if not protected by rcu_read_lock_bh()
+ *
+ * Splats if lockdep is enabled and there is no rcu_read_lock_bh() in effect.
+ * Note that local_bh_disable() and friends do not suffice here, instead an
+ * actual rcu_read_lock_bh() is required.
+ */
+#define lockdep_assert_in_rcu_read_lock_bh() \
+ WARN_ON_ONCE(lockdep_assert_rcu_helper(!lock_is_held(&rcu_bh_lock_map)))
+
+/**
+ * lockdep_assert_in_rcu_read_lock_sched - WARN if not protected by rcu_read_lock_sched()
+ *
+ * Splats if lockdep is enabled and there is no rcu_read_lock_sched()
+ * in effect. Note that preempt_disable() and friends do not suffice here,
+ * instead an actual rcu_read_lock_sched() is required.
+ */
+#define lockdep_assert_in_rcu_read_lock_sched() \
+ WARN_ON_ONCE(lockdep_assert_rcu_helper(!lock_is_held(&rcu_sched_lock_map)))
+
+/**
+ * lockdep_assert_in_rcu_reader - WARN if not within some type of RCU reader
+ *
+ * Splats if lockdep is enabled and there is no RCU reader of any
+ * type in effect. Note that regions of code protected by things like
+ * preempt_disable, local_bh_disable(), and local_irq_disable() all qualify
+ * as RCU readers.
+ *
+ * Note that this will never trigger in PREEMPT_NONE or PREEMPT_VOLUNTARY
+ * kernels that are not also built with PREEMPT_COUNT. But if you have
+ * lockdep enabled, you might as well also enable PREEMPT_COUNT.
+ */
+#define lockdep_assert_in_rcu_reader() \
+ WARN_ON_ONCE(lockdep_assert_rcu_helper(!lock_is_held(&rcu_lock_map) && \
+ !lock_is_held(&rcu_bh_lock_map) && \
+ !lock_is_held(&rcu_sched_lock_map) && \
+ preemptible()))
+
#else /* #ifdef CONFIG_PROVE_RCU */
#define RCU_LOCKDEP_WARN(c, s) do { } while (0 && (c))
#define rcu_sleep_check() do { } while (0)
+#define lockdep_assert_in_rcu_read_lock() do { } while (0)
+#define lockdep_assert_in_rcu_read_lock_bh() do { } while (0)
+#define lockdep_assert_in_rcu_read_lock_sched() do { } while (0)
+#define lockdep_assert_in_rcu_reader() do { } while (0)
+
#endif /* #else #ifdef CONFIG_PROVE_RCU */
/*
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index a6bc2980a98b..122e38161acb 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -1237,6 +1237,8 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
void *val, size_t val_len);
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
size_t val_count);
+int regmap_multi_reg_read(struct regmap *map, unsigned int *reg, void *val,
+ size_t val_count);
int regmap_update_bits_base(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val,
bool *change, bool async, bool force);
@@ -1607,7 +1609,7 @@ struct regmap_irq_chip {
unsigned int main_status;
unsigned int num_main_status_bits;
- struct regmap_irq_sub_irq_map *sub_reg_offsets;
+ const struct regmap_irq_sub_irq_map *sub_reg_offsets;
int num_main_regs;
unsigned int status_base;
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 59d0b9a79e6e..d986ec13092e 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -128,11 +128,11 @@ struct regulator;
*
* @supply: The name of the supply. Initialised by the user before
* using the bulk regulator APIs.
+ * @consumer: The regulator consumer for the supply. This will be managed
+ * by the bulk API.
* @init_load_uA: After getting the regulator, regulator_set_load() will be
* called with this load. Initialised by the user before
* using the bulk regulator APIs.
- * @consumer: The regulator consumer for the supply. This will be managed
- * by the bulk API.
*
* The regulator APIs provide a series of regulator_bulk_() API calls as
* a convenience to consumers which require multiple supplies. This
@@ -140,8 +140,8 @@ struct regulator;
*/
struct regulator_bulk_data {
const char *supply;
- int init_load_uA;
struct regulator *consumer;
+ int init_load_uA;
/* private: Internal use */
int ret;
@@ -250,6 +250,7 @@ int regulator_get_hardware_vsel_register(struct regulator *regulator,
unsigned *vsel_mask);
int regulator_list_hardware_vsel(struct regulator *regulator,
unsigned selector);
+int regulator_hardware_enable(struct regulator *regulator, bool enable);
/* regulator notifier block */
int regulator_register_notifier(struct regulator *regulator,
@@ -571,6 +572,12 @@ static inline int regulator_list_hardware_vsel(struct regulator *regulator,
return -EOPNOTSUPP;
}
+static inline int regulator_hardware_enable(struct regulator *regulator,
+ bool enable)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int regulator_register_notifier(struct regulator *regulator,
struct notifier_block *nb)
{
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index a365f67131ec..b0875b99e811 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -2,6 +2,7 @@
#ifndef _RESCTRL_H
#define _RESCTRL_H
+#include <linux/cacheinfo.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/pid.h>
@@ -58,11 +59,45 @@ struct resctrl_staged_config {
bool have_new_ctrl;
};
+enum resctrl_domain_type {
+ RESCTRL_CTRL_DOMAIN,
+ RESCTRL_MON_DOMAIN,
+};
+
/**
- * struct rdt_domain - group of CPUs sharing a resctrl resource
+ * struct rdt_domain_hdr - common header for different domain types
* @list: all instances of this resource
* @id: unique id for this instance
+ * @type: type of this instance
* @cpu_mask: which CPUs share this resource
+ */
+struct rdt_domain_hdr {
+ struct list_head list;
+ int id;
+ enum resctrl_domain_type type;
+ struct cpumask cpu_mask;
+};
+
+/**
+ * struct rdt_ctrl_domain - group of CPUs sharing a resctrl control resource
+ * @hdr: common header for different domain types
+ * @plr: pseudo-locked region (if any) associated with domain
+ * @staged_config: parsed configuration to be applied
+ * @mbps_val: When mba_sc is enabled, this holds the array of user
+ * specified control values for mba_sc in MBps, indexed
+ * by closid
+ */
+struct rdt_ctrl_domain {
+ struct rdt_domain_hdr hdr;
+ struct pseudo_lock_region *plr;
+ struct resctrl_staged_config staged_config[CDP_NUM_TYPES];
+ u32 *mbps_val;
+};
+
+/**
+ * struct rdt_mon_domain - group of CPUs sharing a resctrl monitor resource
+ * @hdr: common header for different domain types
+ * @ci: cache info for this domain
* @rmid_busy_llc: bitmap of which limbo RMIDs are above threshold
* @mbm_total: saved state for MBM total bandwidth
* @mbm_local: saved state for MBM local bandwidth
@@ -70,16 +105,10 @@ struct resctrl_staged_config {
* @cqm_limbo: worker to periodically read CQM h/w counters
* @mbm_work_cpu: worker CPU for MBM h/w counters
* @cqm_work_cpu: worker CPU for CQM h/w counters
- * @plr: pseudo-locked region (if any) associated with domain
- * @staged_config: parsed configuration to be applied
- * @mbps_val: When mba_sc is enabled, this holds the array of user
- * specified control values for mba_sc in MBps, indexed
- * by closid
*/
-struct rdt_domain {
- struct list_head list;
- int id;
- struct cpumask cpu_mask;
+struct rdt_mon_domain {
+ struct rdt_domain_hdr hdr;
+ struct cacheinfo *ci;
unsigned long *rmid_busy_llc;
struct mbm_state *mbm_total;
struct mbm_state *mbm_local;
@@ -87,9 +116,6 @@ struct rdt_domain {
struct delayed_work cqm_limbo;
int mbm_work_cpu;
int cqm_work_cpu;
- struct pseudo_lock_region *plr;
- struct resctrl_staged_config staged_config[CDP_NUM_TYPES];
- u32 *mbps_val;
};
/**
@@ -150,16 +176,24 @@ struct resctrl_membw {
struct rdt_parse_data;
struct resctrl_schema;
+enum resctrl_scope {
+ RESCTRL_L2_CACHE = 2,
+ RESCTRL_L3_CACHE = 3,
+ RESCTRL_L3_NODE,
+};
+
/**
* struct rdt_resource - attributes of a resctrl resource
* @rid: The index of the resource
* @alloc_capable: Is allocation available on this machine
* @mon_capable: Is monitor feature available on this machine
* @num_rmid: Number of RMIDs available
- * @cache_level: Which cache level defines scope of this resource
+ * @ctrl_scope: Scope of this resource for control functions
+ * @mon_scope: Scope of this resource for monitor functions
* @cache: Cache allocation related data
* @membw: If the component has bandwidth controls, their properties.
- * @domains: RCU list of all domains for this resource
+ * @ctrl_domains: RCU list of all control domains for this resource
+ * @mon_domains: RCU list of all monitor domains for this resource
* @name: Name to use in "schemata" file.
* @data_width: Character width of data when displaying
* @default_ctrl: Specifies default cache cbm or memory B/W percent.
@@ -174,17 +208,19 @@ struct rdt_resource {
bool alloc_capable;
bool mon_capable;
int num_rmid;
- int cache_level;
+ enum resctrl_scope ctrl_scope;
+ enum resctrl_scope mon_scope;
struct resctrl_cache cache;
struct resctrl_membw membw;
- struct list_head domains;
+ struct list_head ctrl_domains;
+ struct list_head mon_domains;
char *name;
int data_width;
u32 default_ctrl;
const char *format_str;
int (*parse_ctrlval)(struct rdt_parse_data *data,
struct resctrl_schema *s,
- struct rdt_domain *d);
+ struct rdt_ctrl_domain *d);
struct list_head evt_list;
unsigned long fflags;
bool cdp_capable;
@@ -218,13 +254,15 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid);
* Update the ctrl_val and apply this config right now.
* Must be called on one of the domain's CPUs.
*/
-int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d,
+int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
u32 closid, enum resctrl_conf_type t, u32 cfg_val);
-u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d,
+u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
u32 closid, enum resctrl_conf_type type);
-int resctrl_online_domain(struct rdt_resource *r, struct rdt_domain *d);
-void resctrl_offline_domain(struct rdt_resource *r, struct rdt_domain *d);
+int resctrl_online_ctrl_domain(struct rdt_resource *r, struct rdt_ctrl_domain *d);
+int resctrl_online_mon_domain(struct rdt_resource *r, struct rdt_mon_domain *d);
+void resctrl_offline_ctrl_domain(struct rdt_resource *r, struct rdt_ctrl_domain *d);
+void resctrl_offline_mon_domain(struct rdt_resource *r, struct rdt_mon_domain *d);
void resctrl_online_cpu(unsigned int cpu);
void resctrl_offline_cpu(unsigned int cpu);
@@ -253,7 +291,7 @@ void resctrl_offline_cpu(unsigned int cpu);
* Return:
* 0 on success, or -EIO, -EINVAL etc on error.
*/
-int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain *d,
+int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_mon_domain *d,
u32 closid, u32 rmid, enum resctrl_event_id eventid,
u64 *val, void *arch_mon_ctx);
@@ -286,7 +324,7 @@ static inline void resctrl_arch_rmid_read_context_check(void)
*
* This can be called from any CPU.
*/
-void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_domain *d,
+void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_mon_domain *d,
u32 closid, u32 rmid,
enum resctrl_event_id eventid);
@@ -299,7 +337,7 @@ void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_domain *d,
*
* This can be called from any CPU.
*/
-void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_domain *d);
+void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain *d);
extern unsigned int resctrl_rmid_realloc_threshold;
extern unsigned int resctrl_rmid_realloc_limit;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 61591ac6eab6..a5f4b48fca18 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2192,13 +2192,13 @@ static inline int sched_core_idle_cpu(int cpu) { return idle_cpu(cpu); }
extern void sched_set_stop_task(int cpu, struct task_struct *stop);
#ifdef CONFIG_MEM_ALLOC_PROFILING
-static inline struct alloc_tag *alloc_tag_save(struct alloc_tag *tag)
+static __always_inline struct alloc_tag *alloc_tag_save(struct alloc_tag *tag)
{
swap(current->alloc_tag, tag);
return tag;
}
-static inline void alloc_tag_restore(struct alloc_tag *tag, struct alloc_tag *old)
+static __always_inline void alloc_tag_restore(struct alloc_tag *tag, struct alloc_tag *old)
{
#ifdef CONFIG_MEM_ALLOC_PROFILING_DEBUG
WARN(current->alloc_tag != tag, "current->alloc_tag was changed:\n");
diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h
index d4a8e34505e6..5bee6f7fc400 100644
--- a/include/linux/soc/mediatek/mtk-cmdq.h
+++ b/include/linux/soc/mediatek/mtk-cmdq.h
@@ -25,6 +25,31 @@
struct cmdq_pkt;
+enum cmdq_logic_op {
+ CMDQ_LOGIC_ASSIGN = 0,
+ CMDQ_LOGIC_ADD = 1,
+ CMDQ_LOGIC_SUBTRACT = 2,
+ CMDQ_LOGIC_MULTIPLY = 3,
+ CMDQ_LOGIC_XOR = 8,
+ CMDQ_LOGIC_NOT = 9,
+ CMDQ_LOGIC_OR = 10,
+ CMDQ_LOGIC_AND = 11,
+ CMDQ_LOGIC_LEFT_SHIFT = 12,
+ CMDQ_LOGIC_RIGHT_SHIFT = 13,
+ CMDQ_LOGIC_MAX,
+};
+
+struct cmdq_operand {
+ /* register type */
+ bool reg;
+ union {
+ /* index */
+ u16 idx;
+ /* value */
+ u16 value;
+ };
+};
+
struct cmdq_client_reg {
u8 subsys;
u16 offset;
@@ -273,6 +298,23 @@ int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys,
u16 offset, u32 value, u32 mask);
/**
+ * cmdq_pkt_logic_command() - Append logic command to the CMDQ packet, ask GCE to
+ * execute an instruction that store the result of logic operation
+ * with left and right operand into result_reg_idx.
+ * @pkt: the CMDQ packet
+ * @result_reg_idx: SPR index that store operation result of left_operand and right_operand
+ * @left_operand: left operand
+ * @s_op: the logic operator enum
+ * @right_operand: right operand
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx,
+ struct cmdq_operand *left_operand,
+ enum cmdq_logic_op s_op,
+ struct cmdq_operand *right_operand);
+
+/**
* cmdq_pkt_assign() - Append logic assign command to the CMDQ packet, ask GCE
* to execute an instruction that set a constant value into
* internal register and use as value, mask or address in
diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
index 1a886666bbb6..9e9f528b1370 100644
--- a/include/linux/soc/qcom/llcc-qcom.h
+++ b/include/linux/soc/qcom/llcc-qcom.h
@@ -115,7 +115,8 @@ struct llcc_edac_reg_offset {
/**
* struct llcc_drv_data - Data associated with the llcc driver
* @regmaps: regmaps associated with the llcc device
- * @bcast_regmap: regmap associated with llcc broadcast offset
+ * @bcast_regmap: regmap associated with llcc broadcast OR offset
+ * @bcast_and_regmap: regmap associated with llcc broadcast AND offset
* @cfg: pointer to the data structure for slice configuration
* @edac_reg_offset: Offset of the LLCC EDAC registers
* @lock: mutex associated with each slice
@@ -129,6 +130,7 @@ struct llcc_edac_reg_offset {
struct llcc_drv_data {
struct regmap **regmaps;
struct regmap *bcast_regmap;
+ struct regmap *bcast_and_regmap;
const struct llcc_slice_config *cfg;
const struct llcc_edac_reg_offset *edac_reg_offset;
struct mutex lock;
diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h
index a36a3b9d4929..0943bf419e11 100644
--- a/include/linux/soc/qcom/smem.h
+++ b/include/linux/soc/qcom/smem.h
@@ -13,5 +13,6 @@ int qcom_smem_get_free_space(unsigned host);
phys_addr_t qcom_smem_virt_to_phys(void *p);
int qcom_smem_get_soc_id(u32 *id);
+int qcom_smem_get_feature_code(u32 *code);
#endif
diff --git a/include/linux/soc/qcom/socinfo.h b/include/linux/soc/qcom/socinfo.h
index e78777bb0f4a..608950443eee 100644
--- a/include/linux/soc/qcom/socinfo.h
+++ b/include/linux/soc/qcom/socinfo.h
@@ -3,6 +3,8 @@
#ifndef __QCOM_SOCINFO_H__
#define __QCOM_SOCINFO_H__
+#include <linux/types.h>
+
/*
* SMEM item id, used to acquire handles to respective
* SMEM region.
@@ -12,6 +14,14 @@
#define SMEM_SOCINFO_BUILD_ID_LENGTH 32
#define SMEM_SOCINFO_CHIP_ID_LENGTH 32
+/*
+ * SoC version type with major number in the upper 16 bits and minor
+ * number in the lower 16 bits.
+ */
+#define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff)
+#define SOCINFO_MINOR(ver) ((ver) & 0xffff)
+#define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff))
+
/* Socinfo SMEM item structure */
struct socinfo {
__le32 fmt;
@@ -74,4 +84,28 @@ struct socinfo {
__le32 boot_core;
};
+/* Internal feature codes */
+enum qcom_socinfo_feature_code {
+ /* External feature codes */
+ SOCINFO_FC_UNKNOWN = 0x0,
+ SOCINFO_FC_AA,
+ SOCINFO_FC_AB,
+ SOCINFO_FC_AC,
+ SOCINFO_FC_AD,
+ SOCINFO_FC_AE,
+ SOCINFO_FC_AF,
+ SOCINFO_FC_AG,
+ SOCINFO_FC_AH,
+};
+
+/* Internal feature codes */
+/* Valid values: 0 <= n <= 0xf */
+#define SOCINFO_FC_Yn(n) (0xf1 + (n))
+#define SOCINFO_FC_INT_MAX SOCINFO_FC_Yn(0xf)
+
+/* Product codes */
+#define SOCINFO_PC_UNKNOWN 0
+#define SOCINFO_PCn(n) ((n) + 1)
+#define SOCINFO_PC_RESERVE (BIT(31) - 1)
+
#endif
diff --git a/include/linux/soc/samsung/exynos-regs-pmu.h b/include/linux/soc/samsung/exynos-regs-pmu.h
index aa840ed043e1..f411c176536d 100644
--- a/include/linux/soc/samsung/exynos-regs-pmu.h
+++ b/include/linux/soc/samsung/exynos-regs-pmu.h
@@ -657,4 +657,8 @@
#define EXYNOS5433_PAD_RETENTION_UFS_OPTION (0x3268)
#define EXYNOS5433_PAD_RETENTION_FSYSGENIO_OPTION (0x32A8)
+/* For Tensor GS101 */
+#define GS101_SYSIP_DAT0 (0x810)
+#define GS101_SYSTEM_CONFIGURATION (0x3A00)
+
#endif /* __LINUX_SOC_EXYNOS_REGS_PMU_H */
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 89d16b90370b..c1f16cdab677 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -442,11 +442,14 @@ extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
extern int __sys_socket(int family, int type, int protocol);
extern struct file *__sys_socket_file(int family, int type, int protocol);
extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
+extern int __sys_bind_socket(struct socket *sock, struct sockaddr_storage *address,
+ int addrlen);
extern int __sys_connect_file(struct file *file, struct sockaddr_storage *addr,
int addrlen, int file_flags);
extern int __sys_connect(int fd, struct sockaddr __user *uservaddr,
int addrlen);
extern int __sys_listen(int fd, int backlog);
+extern int __sys_listen_socket(struct socket *sock, int backlog);
extern int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
int __user *usockaddr_len);
extern int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 98fdef6e28f2..d7a16e0adf44 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -447,7 +447,6 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
* @cur_msg_need_completion: Flag used internally to opportunistically skip
* the @cur_msg_completion. This flag is used to signal the context that
* is running spi_finalize_current_message() that it needs to complete()
- * @cur_msg_mapped: message has been mapped for DMA
* @fallback: fallback to PIO if DMA transfer return failure with
* SPI_TRANS_FAIL_NO_START.
* @last_cs_mode_high: was (mode & SPI_CS_HIGH) true on the last call to set_cs.
@@ -533,6 +532,9 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
* @queue_empty: signal green light for opportunistically skipping the queue
* for spi_sync transfers.
* @must_async: disable all fast paths in the core
+ * @defer_optimize_message: set to true if controller cannot pre-optimize messages
+ * and needs to defer the optimization step until the message is actually
+ * being transferred
*
* Each SPI controller can communicate with one or more @spi_device
* children. These make a small bus, sharing MOSI, MISO and SCK signals
@@ -708,7 +710,6 @@ struct spi_controller {
bool running;
bool rt;
bool auto_runtime_pm;
- bool cur_msg_mapped;
bool fallback;
bool last_cs_mode_high;
s8 last_cs[SPI_CS_CNT_MAX];
@@ -776,6 +777,7 @@ struct spi_controller {
/* Flag for enabling opportunistic skipping of the queue in spi_sync */
bool queue_empty;
bool must_async;
+ bool defer_optimize_message;
};
static inline void *spi_controller_get_devdata(struct spi_controller *ctlr)
@@ -981,6 +983,8 @@ struct spi_res {
* transfer this transfer. Set to 0 if the SPI bus driver does
* not support it.
* @transfer_list: transfers are sequenced through @spi_message.transfers
+ * @tx_sg_mapped: If true, the @tx_sg is mapped for DMA
+ * @rx_sg_mapped: If true, the @rx_sg is mapped for DMA
* @tx_sg: Scatterlist for transmit, currently not for client use
* @rx_sg: Scatterlist for receive, currently not for client use
* @ptp_sts_word_pre: The word (subject to bits_per_word semantics) offset
@@ -1077,10 +1081,13 @@ struct spi_transfer {
#define SPI_TRANS_FAIL_IO BIT(1)
u16 error;
- dma_addr_t tx_dma;
- dma_addr_t rx_dma;
+ bool tx_sg_mapped;
+ bool rx_sg_mapped;
+
struct sg_table tx_sg;
struct sg_table rx_sg;
+ dma_addr_t tx_dma;
+ dma_addr_t rx_dma;
unsigned dummy_data:1;
unsigned cs_off:1;
@@ -1269,6 +1276,8 @@ static inline void spi_message_free(struct spi_message *m)
extern int spi_optimize_message(struct spi_device *spi, struct spi_message *msg);
extern void spi_unoptimize_message(struct spi_message *msg);
+extern int devm_spi_optimize_message(struct device *dev, struct spi_device *spi,
+ struct spi_message *msg);
extern int spi_setup(struct spi_device *spi);
extern int spi_async(struct spi_device *spi, struct spi_message *message);
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index b930eca2ef7b..d4cb83195f7a 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -4,6 +4,8 @@
#include <linux/workqueue.h>
+typedef u32 (*spi_bb_txrx_word_fn)(struct spi_device *, unsigned int, u32, u8, unsigned int);
+
struct spi_bitbang {
struct mutex lock;
u8 busy;
@@ -28,9 +30,8 @@ struct spi_bitbang {
int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);
/* txrx_word[SPI_MODE_*]() just looks like a shift register */
- u32 (*txrx_word[4])(struct spi_device *spi,
- unsigned nsecs,
- u32 word, u8 bits, unsigned flags);
+ spi_bb_txrx_word_fn txrx_word[SPI_MODE_X_MASK + 1];
+
int (*set_line_direction)(struct spi_device *spi, bool output);
};
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 236610e4a8fa..6f6cb5fc1242 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -57,10 +57,45 @@ void cleanup_srcu_struct(struct srcu_struct *ssp);
int __srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp);
void __srcu_read_unlock(struct srcu_struct *ssp, int idx) __releases(ssp);
void synchronize_srcu(struct srcu_struct *ssp);
+
+#define SRCU_GET_STATE_COMPLETED 0x1
+
+/**
+ * get_completed_synchronize_srcu - Return a pre-completed polled state cookie
+ *
+ * Returns a value that poll_state_synchronize_srcu() will always treat
+ * as a cookie whose grace period has already completed.
+ */
+static inline unsigned long get_completed_synchronize_srcu(void)
+{
+ return SRCU_GET_STATE_COMPLETED;
+}
+
unsigned long get_state_synchronize_srcu(struct srcu_struct *ssp);
unsigned long start_poll_synchronize_srcu(struct srcu_struct *ssp);
bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie);
+// Maximum number of unsigned long values corresponding to
+// not-yet-completed SRCU grace periods.
+#define NUM_ACTIVE_SRCU_POLL_OLDSTATE 2
+
+/**
+ * same_state_synchronize_srcu - Are two old-state values identical?
+ * @oldstate1: First old-state value.
+ * @oldstate2: Second old-state value.
+ *
+ * The two old-state values must have been obtained from either
+ * get_state_synchronize_srcu(), start_poll_synchronize_srcu(), or
+ * get_completed_synchronize_srcu(). Returns @true if the two values are
+ * identical and @false otherwise. This allows structures whose lifetimes
+ * are tracked by old-state values to push these values to a list header,
+ * allowing those structures to be slightly smaller.
+ */
+static inline bool same_state_synchronize_srcu(unsigned long oldstate1, unsigned long oldstate2)
+{
+ return oldstate1 == oldstate2;
+}
+
#ifdef CONFIG_NEED_SRCU_NMI_SAFE
int __srcu_read_lock_nmisafe(struct srcu_struct *ssp) __acquires(ssp);
void __srcu_read_unlock_nmisafe(struct srcu_struct *ssp, int idx) __releases(ssp);
diff --git a/include/linux/stat.h b/include/linux/stat.h
index bf92441dbad2..3d900c86981c 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -54,6 +54,9 @@ struct kstat {
u32 dio_offset_align;
u64 change_cookie;
u64 subvol;
+ u32 atomic_write_unit_min;
+ u32 atomic_write_unit_max;
+ u32 atomic_write_segments_max;
};
/* These definitions are internal to the kernel for now. Mainly used by nfsd. */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index bd450023b9a4..e685e93ba354 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -354,7 +354,8 @@ static inline swp_entry_t page_swap_entry(struct page *page)
}
/* linux/mm/workingset.c */
-bool workingset_test_recent(void *shadow, bool file, bool *workingset);
+bool workingset_test_recent(void *shadow, bool file, bool *workingset,
+ bool flush);
void workingset_age_nonresident(struct lruvec *lruvec, unsigned long nr_pages);
void *workingset_eviction(struct folio *folio, struct mem_cgroup *target_memcg);
void workingset_refault(struct folio *folio, void *shadow);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 63424af87bba..fff820c3e93e 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -859,9 +859,15 @@ asmlinkage long sys_prlimit64(pid_t pid, unsigned int resource,
const struct rlimit64 __user *new_rlim,
struct rlimit64 __user *old_rlim);
asmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags);
+#if defined(CONFIG_ARCH_SPLIT_ARG64)
+asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags,
+ unsigned int mask_1, unsigned int mask_2,
+ int dfd, const char __user * pathname);
+#else
asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags,
u64 mask, int fd,
const char __user *pathname);
+#endif
asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name,
struct file_handle __user *handle,
int __user *mnt_id, int flag);
diff --git a/include/linux/t10-pi.h b/include/linux/t10-pi.h
index 248f4ac95642..2c59fe3efcd4 100644
--- a/include/linux/t10-pi.h
+++ b/include/linux/t10-pi.h
@@ -41,18 +41,12 @@ static inline u32 t10_pi_ref_tag(struct request *rq)
{
unsigned int shift = ilog2(queue_logical_block_size(rq->q));
-#ifdef CONFIG_BLK_DEV_INTEGRITY
- if (rq->q->integrity.interval_exp)
- shift = rq->q->integrity.interval_exp;
-#endif
+ if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) &&
+ rq->q->limits.integrity.interval_exp)
+ shift = rq->q->limits.integrity.interval_exp;
return blk_rq_pos(rq) >> (shift - SECTOR_SHIFT) & 0xffffffff;
}
-extern const struct blk_integrity_profile t10_pi_type1_crc;
-extern const struct blk_integrity_profile t10_pi_type1_ip;
-extern const struct blk_integrity_profile t10_pi_type3_crc;
-extern const struct blk_integrity_profile t10_pi_type3_ip;
-
struct crc64_pi_tuple {
__be64 guard_tag;
__be16 app_tag;
@@ -72,14 +66,10 @@ static inline u64 ext_pi_ref_tag(struct request *rq)
{
unsigned int shift = ilog2(queue_logical_block_size(rq->q));
-#ifdef CONFIG_BLK_DEV_INTEGRITY
- if (rq->q->integrity.interval_exp)
- shift = rq->q->integrity.interval_exp;
-#endif
+ if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) &&
+ rq->q->limits.integrity.interval_exp)
+ shift = rq->q->limits.integrity.interval_exp;
return lower_48_bits(blk_rq_pos(rq) >> (shift - SECTOR_SHIFT));
}
-extern const struct blk_integrity_profile ext_pi_type1_crc64;
-extern const struct blk_integrity_profile ext_pi_type3_crc64;
-
#endif
diff --git a/include/linux/tick.h b/include/linux/tick.h
index 4924a33700b7..72744638c5b0 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -139,7 +139,6 @@ extern void tick_nohz_irq_exit(void);
extern bool tick_nohz_idle_got_tick(void);
extern ktime_t tick_nohz_get_next_hrtimer(void);
extern ktime_t tick_nohz_get_sleep_length(ktime_t *delta_next);
-extern unsigned long tick_nohz_get_idle_calls(void);
extern unsigned long tick_nohz_get_idle_calls_cpu(int cpu);
extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time);
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
index 0ea7823b7f31..fc12a9ba2c88 100644
--- a/include/linux/timekeeping.h
+++ b/include/linux/timekeeping.h
@@ -310,12 +310,18 @@ struct system_device_crosststamp {
* timekeeping code to verify comparability of two cycle values.
* The default ID, CSID_GENERIC, does not identify a specific
* clocksource.
+ * @use_nsecs: @cycles is in nanoseconds.
*/
struct system_counterval_t {
u64 cycles;
enum clocksource_ids cs_id;
+ bool use_nsecs;
};
+extern bool ktime_real_to_base_clock(ktime_t treal,
+ enum clocksource_ids base_id, u64 *cycles);
+extern bool timekeeping_clocksource_has_base(enum clocksource_ids id);
+
/*
* Get cross timestamp between system clock and device clock
*/
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 21a67dc9efe8..e93ee8d936a9 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -490,9 +490,16 @@ static inline void tpm_buf_append_empty_auth(struct tpm_buf *buf, u32 handle)
{
}
#endif
+
+static inline struct tpm2_auth *tpm2_chip_auth(struct tpm_chip *chip)
+{
#ifdef CONFIG_TCG_TPM2_HMAC
+ return chip->auth;
+#else
+ return NULL;
+#endif
+}
-int tpm2_start_auth_session(struct tpm_chip *chip);
void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
u32 handle, u8 *name);
void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
@@ -504,9 +511,27 @@ static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip,
u8 *passphrase,
int passphraselen)
{
- tpm_buf_append_hmac_session(chip, buf, attributes, passphrase,
- passphraselen);
+ struct tpm_header *head;
+ int offset;
+
+ if (tpm2_chip_auth(chip)) {
+ tpm_buf_append_hmac_session(chip, buf, attributes, passphrase, passphraselen);
+ } else {
+ offset = buf->handles * 4 + TPM_HEADER_SIZE;
+ head = (struct tpm_header *)buf->data;
+
+ /*
+ * If the only sessions are optional, the command tag must change to
+ * TPM2_ST_NO_SESSIONS.
+ */
+ if (tpm_buf_length(buf) == offset)
+ head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
+ }
}
+
+#ifdef CONFIG_TCG_TPM2_HMAC
+
+int tpm2_start_auth_session(struct tpm_chip *chip);
void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf);
int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
int rc);
@@ -521,56 +546,6 @@ static inline int tpm2_start_auth_session(struct tpm_chip *chip)
static inline void tpm2_end_auth_session(struct tpm_chip *chip)
{
}
-static inline void tpm_buf_append_name(struct tpm_chip *chip,
- struct tpm_buf *buf,
- u32 handle, u8 *name)
-{
- tpm_buf_append_u32(buf, handle);
- /* count the number of handles in the upper bits of flags */
- buf->handles++;
-}
-static inline void tpm_buf_append_hmac_session(struct tpm_chip *chip,
- struct tpm_buf *buf,
- u8 attributes, u8 *passphrase,
- int passphraselen)
-{
- /* offset tells us where the sessions area begins */
- int offset = buf->handles * 4 + TPM_HEADER_SIZE;
- u32 len = 9 + passphraselen;
-
- 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, passphraselen);
- tpm_buf_append(buf, passphrase, passphraselen);
-}
-static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip,
- struct tpm_buf *buf,
- u8 attributes,
- u8 *passphrase,
- int passphraselen)
-{
- int offset = buf->handles * 4 + TPM_HEADER_SIZE;
- struct tpm_header *head = (struct tpm_header *) buf->data;
-
- /*
- * if the only sessions are optional, the command tag
- * must change to TPM2_ST_NO_SESSIONS
- */
- if (tpm_buf_length(buf) == offset)
- head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
-}
static inline void tpm_buf_fill_hmac_session(struct tpm_chip *chip,
struct tpm_buf *buf)
{
diff --git a/include/linux/tsm.h b/include/linux/tsm.h
index de8324a2223c..11b0c525be30 100644
--- a/include/linux/tsm.h
+++ b/include/linux/tsm.h
@@ -4,6 +4,7 @@
#include <linux/sizes.h>
#include <linux/types.h>
+#include <linux/uuid.h>
#define TSM_INBLOB_MAX 64
#define TSM_OUTBLOB_MAX SZ_32K
@@ -19,11 +20,17 @@
* @privlevel: optional privilege level to associate with @outblob
* @inblob_len: sizeof @inblob
* @inblob: arbitrary input data
+ * @service_provider: optional name of where to obtain the tsm report blob
+ * @service_guid: optional service-provider service guid to attest
+ * @service_manifest_version: optional service-provider service manifest version requested
*/
struct tsm_desc {
unsigned int privlevel;
size_t inblob_len;
u8 inblob[TSM_INBLOB_MAX];
+ char *service_provider;
+ guid_t service_guid;
+ unsigned int service_manifest_version;
};
/**
@@ -33,6 +40,8 @@ struct tsm_desc {
* @outblob: generated evidence to provider to the attestation agent
* @auxblob_len: sizeof(@auxblob)
* @auxblob: (optional) auxiliary data to the report (e.g. certificate data)
+ * @manifestblob_len: sizeof(@manifestblob)
+ * @manifestblob: (optional) manifest data associated with the report
*/
struct tsm_report {
struct tsm_desc desc;
@@ -40,6 +49,42 @@ struct tsm_report {
u8 *outblob;
size_t auxblob_len;
u8 *auxblob;
+ size_t manifestblob_len;
+ u8 *manifestblob;
+};
+
+/**
+ * enum tsm_attr_index - index used to reference report attributes
+ * @TSM_REPORT_GENERATION: index of the report generation number attribute
+ * @TSM_REPORT_PROVIDER: index of the provider name attribute
+ * @TSM_REPORT_PRIVLEVEL: index of the desired privilege level attribute
+ * @TSM_REPORT_PRIVLEVEL_FLOOR: index of the minimum allowed privileg level attribute
+ * @TSM_REPORT_SERVICE_PROVIDER: index of the service provider identifier attribute
+ * @TSM_REPORT_SERVICE_GUID: index of the service GUID attribute
+ * @TSM_REPORT_SERVICE_MANIFEST_VER: index of the service manifest version attribute
+ */
+enum tsm_attr_index {
+ TSM_REPORT_GENERATION,
+ TSM_REPORT_PROVIDER,
+ TSM_REPORT_PRIVLEVEL,
+ TSM_REPORT_PRIVLEVEL_FLOOR,
+ TSM_REPORT_SERVICE_PROVIDER,
+ TSM_REPORT_SERVICE_GUID,
+ TSM_REPORT_SERVICE_MANIFEST_VER,
+};
+
+/**
+ * enum tsm_bin_attr_index - index used to reference binary report attributes
+ * @TSM_REPORT_INBLOB: index of the binary report input attribute
+ * @TSM_REPORT_OUTBLOB: index of the binary report output attribute
+ * @TSM_REPORT_AUXBLOB: index of the binary auxiliary data attribute
+ * @TSM_REPORT_MANIFESTBLOB: index of the binary manifest data attribute
+ */
+enum tsm_bin_attr_index {
+ TSM_REPORT_INBLOB,
+ TSM_REPORT_OUTBLOB,
+ TSM_REPORT_AUXBLOB,
+ TSM_REPORT_MANIFESTBLOB,
};
/**
@@ -48,22 +93,20 @@ struct tsm_report {
* @privlevel_floor: convey base privlevel for nested scenarios
* @report_new: Populate @report with the report blob and auxblob
* (optional), return 0 on successful population, or -errno otherwise
+ * @report_attr_visible: show or hide a report attribute entry
+ * @report_bin_attr_visible: show or hide a report binary attribute entry
*
* Implementation specific ops, only one is expected to be registered at
* a time i.e. only one of "sev-guest", "tdx-guest", etc.
*/
struct tsm_ops {
const char *name;
- const unsigned int privlevel_floor;
+ unsigned int privlevel_floor;
int (*report_new)(struct tsm_report *report, void *data);
+ bool (*report_attr_visible)(int n);
+ bool (*report_bin_attr_visible)(int n);
};
-extern const struct config_item_type tsm_report_default_type;
-
-/* publish @privlevel, @privlevel_floor, and @auxblob attributes */
-extern const struct config_item_type tsm_report_extra_type;
-
-int tsm_register(const struct tsm_ops *ops, void *priv,
- const struct config_item_type *type);
+int tsm_register(const struct tsm_ops *ops, void *priv);
int tsm_unregister(const struct tsm_ops *ops);
#endif /* __TSM_H */
diff --git a/include/linux/turris-omnia-mcu-interface.h b/include/linux/turris-omnia-mcu-interface.h
new file mode 100644
index 000000000000..2da8cbeb158a
--- /dev/null
+++ b/include/linux/turris-omnia-mcu-interface.h
@@ -0,0 +1,249 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * CZ.NIC's Turris Omnia MCU I2C interface commands definitions
+ *
+ * 2024 by Marek Behún <[email protected]>
+ */
+
+#ifndef __TURRIS_OMNIA_MCU_INTERFACE_H
+#define __TURRIS_OMNIA_MCU_INTERFACE_H
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+
+enum omnia_commands_e {
+ OMNIA_CMD_GET_STATUS_WORD = 0x01, /* slave sends status word back */
+ OMNIA_CMD_GENERAL_CONTROL = 0x02,
+ OMNIA_CMD_LED_MODE = 0x03, /* default/user */
+ OMNIA_CMD_LED_STATE = 0x04, /* LED on/off */
+ OMNIA_CMD_LED_COLOR = 0x05, /* LED number + RED + GREEN + BLUE */
+ OMNIA_CMD_USER_VOLTAGE = 0x06,
+ OMNIA_CMD_SET_BRIGHTNESS = 0x07,
+ OMNIA_CMD_GET_BRIGHTNESS = 0x08,
+ OMNIA_CMD_GET_RESET = 0x09,
+ OMNIA_CMD_GET_FW_VERSION_APP = 0x0A, /* 20B git hash number */
+ OMNIA_CMD_SET_WATCHDOG_STATE = 0x0B, /* 0 - disable
+ * 1 - enable / ping
+ * after boot watchdog is started
+ * with 2 minutes timeout
+ */
+
+ /* OMNIA_CMD_WATCHDOG_STATUS = 0x0C, not implemented anymore */
+
+ OMNIA_CMD_GET_WATCHDOG_STATE = 0x0D,
+ OMNIA_CMD_GET_FW_VERSION_BOOT = 0x0E, /* 20B Git hash number */
+ OMNIA_CMD_GET_FW_CHECKSUM = 0x0F, /* 4B length, 4B checksum */
+
+ /* available if FEATURES_SUPPORTED bit set in status word */
+ OMNIA_CMD_GET_FEATURES = 0x10,
+
+ /* available if EXT_CMD bit set in features */
+ OMNIA_CMD_GET_EXT_STATUS_DWORD = 0x11,
+ OMNIA_CMD_EXT_CONTROL = 0x12,
+ OMNIA_CMD_GET_EXT_CONTROL_STATUS = 0x13,
+
+ /* available if NEW_INT_API bit set in features */
+ OMNIA_CMD_GET_INT_AND_CLEAR = 0x14,
+ OMNIA_CMD_GET_INT_MASK = 0x15,
+ OMNIA_CMD_SET_INT_MASK = 0x16,
+
+ /* available if FLASHING bit set in features */
+ OMNIA_CMD_FLASH = 0x19,
+
+ /* available if WDT_PING bit set in features */
+ OMNIA_CMD_SET_WDT_TIMEOUT = 0x20,
+ OMNIA_CMD_GET_WDT_TIMELEFT = 0x21,
+
+ /* available if POWEROFF_WAKEUP bit set in features */
+ OMNIA_CMD_SET_WAKEUP = 0x22,
+ OMNIA_CMD_GET_UPTIME_AND_WAKEUP = 0x23,
+ OMNIA_CMD_POWER_OFF = 0x24,
+
+ /* available if USB_OVC_PROT_SETTING bit set in features */
+ OMNIA_CMD_SET_USB_OVC_PROT = 0x25,
+ OMNIA_CMD_GET_USB_OVC_PROT = 0x26,
+
+ /* available if TRNG bit set in features */
+ OMNIA_CMD_TRNG_COLLECT_ENTROPY = 0x28,
+
+ /* available if CRYPTO bit set in features */
+ OMNIA_CMD_CRYPTO_GET_PUBLIC_KEY = 0x29,
+ OMNIA_CMD_CRYPTO_SIGN_MESSAGE = 0x2A,
+ OMNIA_CMD_CRYPTO_COLLECT_SIGNATURE = 0x2B,
+
+ /* available if BOARD_INFO it set in features */
+ OMNIA_CMD_BOARD_INFO_GET = 0x2C,
+ OMNIA_CMD_BOARD_INFO_BURN = 0x2D,
+
+ /* available only at address 0x2b (LED-controller) */
+ /* available only if LED_GAMMA_CORRECTION bit set in features */
+ OMNIA_CMD_SET_GAMMA_CORRECTION = 0x30,
+ OMNIA_CMD_GET_GAMMA_CORRECTION = 0x31,
+
+ /* available only at address 0x2b (LED-controller) */
+ /* available only if PER_LED_CORRECTION bit set in features */
+ /* available only if FROM_BIT_16_INVALID bit NOT set in features */
+ OMNIA_CMD_SET_LED_CORRECTIONS = 0x32,
+ OMNIA_CMD_GET_LED_CORRECTIONS = 0x33,
+};
+
+enum omnia_flashing_commands_e {
+ OMNIA_FLASH_CMD_UNLOCK = 0x01,
+ OMNIA_FLASH_CMD_SIZE_AND_CSUM = 0x02,
+ OMNIA_FLASH_CMD_PROGRAM = 0x03,
+ OMNIA_FLASH_CMD_RESET = 0x04,
+};
+
+enum omnia_sts_word_e {
+ OMNIA_STS_MCU_TYPE_MASK = GENMASK(1, 0),
+ OMNIA_STS_MCU_TYPE_STM32 = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 0),
+ OMNIA_STS_MCU_TYPE_GD32 = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 1),
+ OMNIA_STS_MCU_TYPE_MKL = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 2),
+ OMNIA_STS_FEATURES_SUPPORTED = BIT(2),
+ OMNIA_STS_USER_REGULATOR_NOT_SUPPORTED = BIT(3),
+ OMNIA_STS_CARD_DET = BIT(4),
+ OMNIA_STS_MSATA_IND = BIT(5),
+ OMNIA_STS_USB30_OVC = BIT(6),
+ OMNIA_STS_USB31_OVC = BIT(7),
+ OMNIA_STS_USB30_PWRON = BIT(8),
+ OMNIA_STS_USB31_PWRON = BIT(9),
+ OMNIA_STS_ENABLE_4V5 = BIT(10),
+ OMNIA_STS_BUTTON_MODE = BIT(11),
+ OMNIA_STS_BUTTON_PRESSED = BIT(12),
+ OMNIA_STS_BUTTON_COUNTER_MASK = GENMASK(15, 13),
+};
+
+enum omnia_ctl_byte_e {
+ OMNIA_CTL_LIGHT_RST = BIT(0),
+ OMNIA_CTL_HARD_RST = BIT(1),
+ /* BIT(2) is currently reserved */
+ OMNIA_CTL_USB30_PWRON = BIT(3),
+ OMNIA_CTL_USB31_PWRON = BIT(4),
+ OMNIA_CTL_ENABLE_4V5 = BIT(5),
+ OMNIA_CTL_BUTTON_MODE = BIT(6),
+ OMNIA_CTL_BOOTLOADER = BIT(7),
+};
+
+enum omnia_features_e {
+ OMNIA_FEAT_PERIPH_MCU = BIT(0),
+ OMNIA_FEAT_EXT_CMDS = BIT(1),
+ OMNIA_FEAT_WDT_PING = BIT(2),
+ OMNIA_FEAT_LED_STATE_EXT_MASK = GENMASK(4, 3),
+ OMNIA_FEAT_LED_STATE_EXT = FIELD_PREP_CONST(OMNIA_FEAT_LED_STATE_EXT_MASK, 1),
+ OMNIA_FEAT_LED_STATE_EXT_V32 = FIELD_PREP_CONST(OMNIA_FEAT_LED_STATE_EXT_MASK, 2),
+ OMNIA_FEAT_LED_GAMMA_CORRECTION = BIT(5),
+ OMNIA_FEAT_NEW_INT_API = BIT(6),
+ OMNIA_FEAT_BOOTLOADER = BIT(7),
+ OMNIA_FEAT_FLASHING = BIT(8),
+ OMNIA_FEAT_NEW_MESSAGE_API = BIT(9),
+ OMNIA_FEAT_BRIGHTNESS_INT = BIT(10),
+ OMNIA_FEAT_POWEROFF_WAKEUP = BIT(11),
+ OMNIA_FEAT_CAN_OLD_MESSAGE_API = BIT(12),
+ OMNIA_FEAT_TRNG = BIT(13),
+ OMNIA_FEAT_CRYPTO = BIT(14),
+ OMNIA_FEAT_BOARD_INFO = BIT(15),
+
+ /*
+ * Orginally the features command replied only 16 bits. If more were
+ * read, either the I2C transaction failed or 0xff bytes were sent.
+ * Therefore to consider bits 16 - 31 valid, one bit (20) was reserved
+ * to be zero.
+ */
+
+ /* Bits 16 - 19 correspond to bits 0 - 3 of status word */
+ OMNIA_FEAT_MCU_TYPE_MASK = GENMASK(17, 16),
+ OMNIA_FEAT_MCU_TYPE_STM32 = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 0),
+ OMNIA_FEAT_MCU_TYPE_GD32 = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 1),
+ OMNIA_FEAT_MCU_TYPE_MKL = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 2),
+ OMNIA_FEAT_FEATURES_SUPPORTED = BIT(18),
+ OMNIA_FEAT_USER_REGULATOR_NOT_SUPPORTED = BIT(19),
+
+ /* must not be set */
+ OMNIA_FEAT_FROM_BIT_16_INVALID = BIT(20),
+
+ OMNIA_FEAT_PER_LED_CORRECTION = BIT(21),
+ OMNIA_FEAT_USB_OVC_PROT_SETTING = BIT(22),
+};
+
+enum omnia_ext_sts_dword_e {
+ OMNIA_EXT_STS_SFP_nDET = BIT(0),
+ OMNIA_EXT_STS_LED_STATES_MASK = GENMASK(31, 12),
+ OMNIA_EXT_STS_WLAN0_MSATA_LED = BIT(12),
+ OMNIA_EXT_STS_WLAN1_LED = BIT(13),
+ OMNIA_EXT_STS_WLAN2_LED = BIT(14),
+ OMNIA_EXT_STS_WPAN0_LED = BIT(15),
+ OMNIA_EXT_STS_WPAN1_LED = BIT(16),
+ OMNIA_EXT_STS_WPAN2_LED = BIT(17),
+ OMNIA_EXT_STS_WAN_LED0 = BIT(18),
+ OMNIA_EXT_STS_WAN_LED1 = BIT(19),
+ OMNIA_EXT_STS_LAN0_LED0 = BIT(20),
+ OMNIA_EXT_STS_LAN0_LED1 = BIT(21),
+ OMNIA_EXT_STS_LAN1_LED0 = BIT(22),
+ OMNIA_EXT_STS_LAN1_LED1 = BIT(23),
+ OMNIA_EXT_STS_LAN2_LED0 = BIT(24),
+ OMNIA_EXT_STS_LAN2_LED1 = BIT(25),
+ OMNIA_EXT_STS_LAN3_LED0 = BIT(26),
+ OMNIA_EXT_STS_LAN3_LED1 = BIT(27),
+ OMNIA_EXT_STS_LAN4_LED0 = BIT(28),
+ OMNIA_EXT_STS_LAN4_LED1 = BIT(29),
+ OMNIA_EXT_STS_LAN5_LED0 = BIT(30),
+ OMNIA_EXT_STS_LAN5_LED1 = BIT(31),
+};
+
+enum omnia_ext_ctl_e {
+ OMNIA_EXT_CTL_nRES_MMC = BIT(0),
+ OMNIA_EXT_CTL_nRES_LAN = BIT(1),
+ OMNIA_EXT_CTL_nRES_PHY = BIT(2),
+ OMNIA_EXT_CTL_nPERST0 = BIT(3),
+ OMNIA_EXT_CTL_nPERST1 = BIT(4),
+ OMNIA_EXT_CTL_nPERST2 = BIT(5),
+ OMNIA_EXT_CTL_PHY_SFP = BIT(6),
+ OMNIA_EXT_CTL_PHY_SFP_AUTO = BIT(7),
+ OMNIA_EXT_CTL_nVHV_CTRL = BIT(8),
+};
+
+enum omnia_int_e {
+ OMNIA_INT_CARD_DET = BIT(0),
+ OMNIA_INT_MSATA_IND = BIT(1),
+ OMNIA_INT_USB30_OVC = BIT(2),
+ OMNIA_INT_USB31_OVC = BIT(3),
+ OMNIA_INT_BUTTON_PRESSED = BIT(4),
+ OMNIA_INT_SFP_nDET = BIT(5),
+ OMNIA_INT_BRIGHTNESS_CHANGED = BIT(6),
+ OMNIA_INT_TRNG = BIT(7),
+ OMNIA_INT_MESSAGE_SIGNED = BIT(8),
+
+ OMNIA_INT_LED_STATES_MASK = GENMASK(31, 12),
+ OMNIA_INT_WLAN0_MSATA_LED = BIT(12),
+ OMNIA_INT_WLAN1_LED = BIT(13),
+ OMNIA_INT_WLAN2_LED = BIT(14),
+ OMNIA_INT_WPAN0_LED = BIT(15),
+ OMNIA_INT_WPAN1_LED = BIT(16),
+ OMNIA_INT_WPAN2_LED = BIT(17),
+ OMNIA_INT_WAN_LED0 = BIT(18),
+ OMNIA_INT_WAN_LED1 = BIT(19),
+ OMNIA_INT_LAN0_LED0 = BIT(20),
+ OMNIA_INT_LAN0_LED1 = BIT(21),
+ OMNIA_INT_LAN1_LED0 = BIT(22),
+ OMNIA_INT_LAN1_LED1 = BIT(23),
+ OMNIA_INT_LAN2_LED0 = BIT(24),
+ OMNIA_INT_LAN2_LED1 = BIT(25),
+ OMNIA_INT_LAN3_LED0 = BIT(26),
+ OMNIA_INT_LAN3_LED1 = BIT(27),
+ OMNIA_INT_LAN4_LED0 = BIT(28),
+ OMNIA_INT_LAN4_LED1 = BIT(29),
+ OMNIA_INT_LAN5_LED0 = BIT(30),
+ OMNIA_INT_LAN5_LED1 = BIT(31),
+};
+
+enum omnia_cmd_poweroff_e {
+ OMNIA_CMD_POWER_OFF_POWERON_BUTTON = BIT(0),
+ OMNIA_CMD_POWER_OFF_MAGIC = 0xdead,
+};
+
+enum omnia_cmd_usb_ovc_prot_e {
+ OMNIA_CMD_xET_USB_OVC_PROT_PORT_MASK = GENMASK(3, 0),
+ OMNIA_CMD_xET_USB_OVC_PROT_ENABLE = BIT(4),
+};
+
+#endif /* __TURRIS_OMNIA_MCU_INTERFACE_H */
diff --git a/include/linux/wordpart.h b/include/linux/wordpart.h
index 4ca1ba66d2f0..5a7b97bb7c95 100644
--- a/include/linux/wordpart.h
+++ b/include/linux/wordpart.h
@@ -39,6 +39,14 @@
*/
#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
+/**
+ * REPEAT_BYTE_U32 - repeat the value @x multiple times as a u32 value
+ * @x: value to repeat
+ *
+ * NOTE: @x is not checked for > 0xff; larger values produce odd results.
+ */
+#define REPEAT_BYTE_U32(x) lower_32_bits(REPEAT_BYTE(x))
+
/* Set bits in the first 'n' bytes when loaded from memory */
#ifdef __LITTLE_ENDIAN
# define aligned_byte_mask(n) ((1UL << 8*(n))-1)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index fe932ca3bc8c..e372a88e8c3f 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -324,6 +324,17 @@ enum {
* claim to support it.
*/
HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE,
+
+ /*
+ * When this quirk is set, the reserved bits of Primary/Secondary_PHY
+ * inside the LE Extended Advertising Report events are discarded.
+ * This is required for some Apple/Broadcom controllers which
+ * abuse these reserved bits for unrelated flags.
+ *
+ * This quirk can be set before hci_register_dev is called or
+ * during the hdev->setup vendor callback.
+ */
+ HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY,
};
/* HCI device flags */
diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h
index 6a9d063e9f47..534c3386e714 100644
--- a/include/net/bluetooth/hci_sync.h
+++ b/include/net/bluetooth/hci_sync.h
@@ -38,6 +38,8 @@ int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen,
int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
const void *param, u8 event, u32 timeout,
struct sock *sk);
+int hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen,
+ const void *param, u32 timeout);
void hci_cmd_sync_init(struct hci_dev *hdev);
void hci_cmd_sync_clear(struct hci_dev *hdev);
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index cafc664ee531..45ad37adbe32 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -395,7 +395,7 @@ enum ieee80211_bss_change {
BSS_CHANGED_HE_OBSS_PD = 1<<28,
BSS_CHANGED_HE_BSS_COLOR = 1<<29,
BSS_CHANGED_FILS_DISCOVERY = 1<<30,
- BSS_CHANGED_UNSOL_BCAST_PROBE_RESP = 1<<31,
+ BSS_CHANGED_UNSOL_BCAST_PROBE_RESP = BIT_ULL(31),
BSS_CHANGED_MLD_VALID_LINKS = BIT_ULL(33),
BSS_CHANGED_MLD_TTLM = BIT_ULL(34),
diff --git a/include/net/tcx.h b/include/net/tcx.h
index 72a3e75e539f..5ce0ce9e0c02 100644
--- a/include/net/tcx.h
+++ b/include/net/tcx.h
@@ -13,7 +13,7 @@ struct mini_Qdisc;
struct tcx_entry {
struct mini_Qdisc __rcu *miniq;
struct bpf_mprog_bundle bundle;
- bool miniq_active;
+ u32 miniq_active;
struct rcu_head rcu;
};
@@ -125,11 +125,16 @@ static inline void tcx_skeys_dec(bool ingress)
tcx_dec();
}
-static inline void tcx_miniq_set_active(struct bpf_mprog_entry *entry,
- const bool active)
+static inline void tcx_miniq_inc(struct bpf_mprog_entry *entry)
{
ASSERT_RTNL();
- tcx_entry(entry)->miniq_active = active;
+ tcx_entry(entry)->miniq_active++;
+}
+
+static inline void tcx_miniq_dec(struct bpf_mprog_entry *entry)
+{
+ ASSERT_RTNL();
+ tcx_entry(entry)->miniq_active--;
}
static inline bool tcx_entry_is_active(struct bpf_mprog_entry *entry)
diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
index 843106e1109f..70e1262b2e20 100644
--- a/include/scsi/scsi_proto.h
+++ b/include/scsi/scsi_proto.h
@@ -120,6 +120,7 @@
#define WRITE_SAME_16 0x93
#define ZBC_OUT 0x94
#define ZBC_IN 0x95
+#define WRITE_ATOMIC_16 0x9c
#define SERVICE_ACTION_BIDIRECTIONAL 0x9d
#define SERVICE_ACTION_IN_16 0x9e
#define SERVICE_ACTION_OUT_16 0x9f
diff --git a/include/trace/events/block.h b/include/trace/events/block.h
index 0e128ad51460..1527d5d45e01 100644
--- a/include/trace/events/block.h
+++ b/include/trace/events/block.h
@@ -9,9 +9,17 @@
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include <linux/tracepoint.h>
+#include <uapi/linux/ioprio.h>
#define RWBS_LEN 8
+#define IOPRIO_CLASS_STRINGS \
+ { IOPRIO_CLASS_NONE, "none" }, \
+ { IOPRIO_CLASS_RT, "rt" }, \
+ { IOPRIO_CLASS_BE, "be" }, \
+ { IOPRIO_CLASS_IDLE, "idle" }, \
+ { IOPRIO_CLASS_INVALID, "invalid"}
+
#ifdef CONFIG_BUFFER_HEAD
DECLARE_EVENT_CLASS(block_buffer,
@@ -82,6 +90,7 @@ TRACE_EVENT(block_rq_requeue,
__field( dev_t, dev )
__field( sector_t, sector )
__field( unsigned int, nr_sector )
+ __field( unsigned short, ioprio )
__array( char, rwbs, RWBS_LEN )
__dynamic_array( char, cmd, 1 )
),
@@ -90,16 +99,20 @@ TRACE_EVENT(block_rq_requeue,
__entry->dev = rq->q->disk ? disk_devt(rq->q->disk) : 0;
__entry->sector = blk_rq_trace_sector(rq);
__entry->nr_sector = blk_rq_trace_nr_sectors(rq);
+ __entry->ioprio = rq->ioprio;
blk_fill_rwbs(__entry->rwbs, rq->cmd_flags);
__get_str(cmd)[0] = '\0';
),
- TP_printk("%d,%d %s (%s) %llu + %u [%d]",
+ TP_printk("%d,%d %s (%s) %llu + %u %s,%u,%u [%d]",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->rwbs, __get_str(cmd),
- (unsigned long long)__entry->sector,
- __entry->nr_sector, 0)
+ (unsigned long long)__entry->sector, __entry->nr_sector,
+ __print_symbolic(IOPRIO_PRIO_CLASS(__entry->ioprio),
+ IOPRIO_CLASS_STRINGS),
+ IOPRIO_PRIO_HINT(__entry->ioprio),
+ IOPRIO_PRIO_LEVEL(__entry->ioprio), 0)
);
DECLARE_EVENT_CLASS(block_rq_completion,
@@ -113,6 +126,7 @@ DECLARE_EVENT_CLASS(block_rq_completion,
__field( sector_t, sector )
__field( unsigned int, nr_sector )
__field( int , error )
+ __field( unsigned short, ioprio )
__array( char, rwbs, RWBS_LEN )
__dynamic_array( char, cmd, 1 )
),
@@ -122,16 +136,20 @@ DECLARE_EVENT_CLASS(block_rq_completion,
__entry->sector = blk_rq_pos(rq);
__entry->nr_sector = nr_bytes >> 9;
__entry->error = blk_status_to_errno(error);
+ __entry->ioprio = rq->ioprio;
blk_fill_rwbs(__entry->rwbs, rq->cmd_flags);
__get_str(cmd)[0] = '\0';
),
- TP_printk("%d,%d %s (%s) %llu + %u [%d]",
+ TP_printk("%d,%d %s (%s) %llu + %u %s,%u,%u [%d]",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->rwbs, __get_str(cmd),
- (unsigned long long)__entry->sector,
- __entry->nr_sector, __entry->error)
+ (unsigned long long)__entry->sector, __entry->nr_sector,
+ __print_symbolic(IOPRIO_PRIO_CLASS(__entry->ioprio),
+ IOPRIO_CLASS_STRINGS),
+ IOPRIO_PRIO_HINT(__entry->ioprio),
+ IOPRIO_PRIO_LEVEL(__entry->ioprio), __entry->error)
);
/**
@@ -180,6 +198,7 @@ DECLARE_EVENT_CLASS(block_rq,
__field( sector_t, sector )
__field( unsigned int, nr_sector )
__field( unsigned int, bytes )
+ __field( unsigned short, ioprio )
__array( char, rwbs, RWBS_LEN )
__array( char, comm, TASK_COMM_LEN )
__dynamic_array( char, cmd, 1 )
@@ -190,17 +209,21 @@ DECLARE_EVENT_CLASS(block_rq,
__entry->sector = blk_rq_trace_sector(rq);
__entry->nr_sector = blk_rq_trace_nr_sectors(rq);
__entry->bytes = blk_rq_bytes(rq);
+ __entry->ioprio = rq->ioprio;
blk_fill_rwbs(__entry->rwbs, rq->cmd_flags);
__get_str(cmd)[0] = '\0';
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
- TP_printk("%d,%d %s %u (%s) %llu + %u [%s]",
+ TP_printk("%d,%d %s %u (%s) %llu + %u %s,%u,%u [%s]",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->rwbs, __entry->bytes, __get_str(cmd),
- (unsigned long long)__entry->sector,
- __entry->nr_sector, __entry->comm)
+ (unsigned long long)__entry->sector, __entry->nr_sector,
+ __print_symbolic(IOPRIO_PRIO_CLASS(__entry->ioprio),
+ IOPRIO_CLASS_STRINGS),
+ IOPRIO_PRIO_HINT(__entry->ioprio),
+ IOPRIO_PRIO_LEVEL(__entry->ioprio), __entry->comm)
);
/**
diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
index fadf406b5260..c978fa2893a5 100644
--- a/include/trace/events/btrfs.h
+++ b/include/trace/events/btrfs.h
@@ -2556,9 +2556,10 @@ TRACE_EVENT(btrfs_extent_map_shrinker_count,
TRACE_EVENT(btrfs_extent_map_shrinker_scan_enter,
- TP_PROTO(const struct btrfs_fs_info *fs_info, long nr_to_scan, long nr),
+ TP_PROTO(const struct btrfs_fs_info *fs_info, long nr_to_scan, long nr,
+ u64 last_root_id, u64 last_ino),
- TP_ARGS(fs_info, nr_to_scan, nr),
+ TP_ARGS(fs_info, nr_to_scan, nr, last_root_id, last_ino),
TP_STRUCT__entry_btrfs(
__field( long, nr_to_scan )
@@ -2570,8 +2571,8 @@ TRACE_EVENT(btrfs_extent_map_shrinker_scan_enter,
TP_fast_assign_btrfs(fs_info,
__entry->nr_to_scan = nr_to_scan;
__entry->nr = nr;
- __entry->last_root_id = fs_info->extent_map_shrinker_last_root;
- __entry->last_ino = fs_info->extent_map_shrinker_last_ino;
+ __entry->last_root_id = last_root_id;
+ __entry->last_ino = last_ino;
),
TP_printk_btrfs("nr_to_scan=%ld nr=%ld last_root=%llu(%s) last_ino=%llu",
@@ -2581,9 +2582,10 @@ TRACE_EVENT(btrfs_extent_map_shrinker_scan_enter,
TRACE_EVENT(btrfs_extent_map_shrinker_scan_exit,
- TP_PROTO(const struct btrfs_fs_info *fs_info, long nr_dropped, long nr),
+ TP_PROTO(const struct btrfs_fs_info *fs_info, long nr_dropped, long nr,
+ u64 last_root_id, u64 last_ino),
- TP_ARGS(fs_info, nr_dropped, nr),
+ TP_ARGS(fs_info, nr_dropped, nr, last_root_id, last_ino),
TP_STRUCT__entry_btrfs(
__field( long, nr_dropped )
@@ -2595,8 +2597,8 @@ TRACE_EVENT(btrfs_extent_map_shrinker_scan_exit,
TP_fast_assign_btrfs(fs_info,
__entry->nr_dropped = nr_dropped;
__entry->nr = nr;
- __entry->last_root_id = fs_info->extent_map_shrinker_last_root;
- __entry->last_ino = fs_info->extent_map_shrinker_last_ino;
+ __entry->last_root_id = last_root_id;
+ __entry->last_ino = last_ino;
),
TP_printk_btrfs("nr_dropped=%ld nr=%ld last_root=%llu(%s) last_ino=%llu",
diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h
index a6190aa1b406..f1a73aa83fbb 100644
--- a/include/trace/events/fscache.h
+++ b/include/trace/events/fscache.h
@@ -35,12 +35,14 @@ enum fscache_volume_trace {
fscache_volume_get_cookie,
fscache_volume_get_create_work,
fscache_volume_get_hash_collision,
+ fscache_volume_get_withdraw,
fscache_volume_free,
fscache_volume_new_acquire,
fscache_volume_put_cookie,
fscache_volume_put_create_work,
fscache_volume_put_hash_collision,
fscache_volume_put_relinquish,
+ fscache_volume_put_withdraw,
fscache_volume_see_create_work,
fscache_volume_see_hash_wake,
fscache_volume_wait_create_work,
@@ -120,12 +122,14 @@ enum fscache_access_trace {
EM(fscache_volume_get_cookie, "GET cook ") \
EM(fscache_volume_get_create_work, "GET creat") \
EM(fscache_volume_get_hash_collision, "GET hcoll") \
+ EM(fscache_volume_get_withdraw, "GET withd") \
EM(fscache_volume_free, "FREE ") \
EM(fscache_volume_new_acquire, "NEW acq ") \
EM(fscache_volume_put_cookie, "PUT cook ") \
EM(fscache_volume_put_create_work, "PUT creat") \
EM(fscache_volume_put_hash_collision, "PUT hcoll") \
EM(fscache_volume_put_relinquish, "PUT relnq") \
+ EM(fscache_volume_put_withdraw, "PUT withd") \
EM(fscache_volume_see_create_work, "SEE creat") \
EM(fscache_volume_see_hash_wake, "SEE hwake") \
E_(fscache_volume_wait_create_work, "WAIT crea")
diff --git a/include/trace/events/scsi.h b/include/trace/events/scsi.h
index 8e2d9b1b0e77..05f1945ed204 100644
--- a/include/trace/events/scsi.h
+++ b/include/trace/events/scsi.h
@@ -102,6 +102,7 @@
scsi_opcode_name(WRITE_32), \
scsi_opcode_name(WRITE_SAME_32), \
scsi_opcode_name(ATA_16), \
+ scsi_opcode_name(WRITE_ATOMIC_16), \
scsi_opcode_name(ATA_12))
#define scsi_hostbyte_name(result) { result, #result }
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index d4cc26932ff4..5bf6148cac2b 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -776,12 +776,8 @@ __SYSCALL(__NR_fsmount, sys_fsmount)
__SYSCALL(__NR_fspick, sys_fspick)
#define __NR_pidfd_open 434
__SYSCALL(__NR_pidfd_open, sys_pidfd_open)
-
-#ifdef __ARCH_WANT_SYS_CLONE3
#define __NR_clone3 435
__SYSCALL(__NR_clone3, sys_clone3)
-#endif
-
#define __NR_close_range 436
__SYSCALL(__NR_close_range, sys_close_range)
#define __NR_openat2 437
diff --git a/include/uapi/drm/panthor_drm.h b/include/uapi/drm/panthor_drm.h
index aaed8e12ad0b..926b1deb1116 100644
--- a/include/uapi/drm/panthor_drm.h
+++ b/include/uapi/drm/panthor_drm.h
@@ -802,6 +802,9 @@ struct drm_panthor_queue_submit {
* Must be 64-bit/8-byte aligned (the size of a CS instruction)
*
* Can be zero if stream_addr is zero too.
+ *
+ * When the stream size is zero, the queue submit serves as a
+ * synchronization point.
*/
__u32 stream_size;
@@ -822,6 +825,8 @@ struct drm_panthor_queue_submit {
* ensure the GPU doesn't get garbage when reading the indirect command
* stream buffers. If you want the cache flush to happen
* unconditionally, pass a zero here.
+ *
+ * Ignored when stream_size is zero.
*/
__u32 latest_flush;
diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index 1446c3bae515..d425b83181df 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -776,7 +776,13 @@ struct drm_xe_gem_create {
#define DRM_XE_GEM_CPU_CACHING_WC 2
/**
* @cpu_caching: The CPU caching mode to select for this object. If
- * mmaping the object the mode selected here will also be used.
+ * mmaping the object the mode selected here will also be used. The
+ * exception is when mapping system memory (including data evicted
+ * to system) on discrete GPUs. The caching mode selected will
+ * then be overridden to DRM_XE_GEM_CPU_CACHING_WB, and coherency
+ * between GPU- and CPU is guaranteed. The caching mode of
+ * existing CPU-mappings will be updated transparently to
+ * user-space clients.
*/
__u16 cpu_caching;
/** @pad: MBZ */
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 45e4e64fd664..191a7e88a8ab 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -329,9 +329,12 @@ typedef int __bitwise __kernel_rwf_t;
/* per-IO negation of O_APPEND */
#define RWF_NOAPPEND ((__force __kernel_rwf_t)0x00000020)
+/* Atomic Write */
+#define RWF_ATOMIC ((__force __kernel_rwf_t)0x00000040)
+
/* mask of flags supported by the kernel */
#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT |\
- RWF_APPEND | RWF_NOAPPEND)
+ RWF_APPEND | RWF_NOAPPEND | RWF_ATOMIC)
/* Pagemap ioctl */
#define PAGEMAP_SCAN _IOWR('f', 16, struct pm_scan_arg)
diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 994bf7af0efe..2aaf7ee256ac 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -257,6 +257,8 @@ enum io_uring_op {
IORING_OP_FUTEX_WAITV,
IORING_OP_FIXED_FD_INSTALL,
IORING_OP_FTRUNCATE,
+ IORING_OP_BIND,
+ IORING_OP_LISTEN,
/* this goes last, obviously */
IORING_OP_LAST,
diff --git a/include/uapi/linux/mount.h b/include/uapi/linux/mount.h
index ad5478dbad00..225bc366ffcb 100644
--- a/include/uapi/linux/mount.h
+++ b/include/uapi/linux/mount.h
@@ -154,7 +154,7 @@ struct mount_attr {
*/
struct statmount {
__u32 size; /* Total size, including strings */
- __u32 __spare1;
+ __u32 mnt_opts; /* [str] Mount options of the mount */
__u64 mask; /* What results were written */
__u32 sb_dev_major; /* Device ID */
__u32 sb_dev_minor;
@@ -172,7 +172,8 @@ struct statmount {
__u64 propagate_from; /* Propagation from in current namespace */
__u32 mnt_root; /* [str] Root of mount relative to root of fs */
__u32 mnt_point; /* [str] Mountpoint relative to current root */
- __u64 __spare2[50];
+ __u64 mnt_ns_id; /* ID of the mount namespace */
+ __u64 __spare2[49];
char str[]; /* Variable size part containing strings */
};
@@ -188,10 +189,12 @@ struct mnt_id_req {
__u32 spare;
__u64 mnt_id;
__u64 param;
+ __u64 mnt_ns_id;
};
/* List of all mnt_id_req versions. */
#define MNT_ID_REQ_SIZE_VER0 24 /* sizeof first published struct */
+#define MNT_ID_REQ_SIZE_VER1 32 /* sizeof second published struct */
/*
* @mask bits for statmount(2)
@@ -202,10 +205,13 @@ struct mnt_id_req {
#define STATMOUNT_MNT_ROOT 0x00000008U /* Want/got mnt_root */
#define STATMOUNT_MNT_POINT 0x00000010U /* Want/got mnt_point */
#define STATMOUNT_FS_TYPE 0x00000020U /* Want/got fs_type */
+#define STATMOUNT_MNT_NS_ID 0x00000040U /* Want/got mnt_ns_id */
+#define STATMOUNT_MNT_OPTS 0x00000080U /* Want/got mnt_opts */
/*
* Special @mnt_id values that can be passed to listmount
*/
#define LSMT_ROOT 0xffffffffffffffff /* root mount */
+#define LISTMOUNT_REVERSE (1 << 0) /* List later mounts first */
#endif /* _UAPI_LINUX_MOUNT_H */
diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h
index a0c8552b64ee..b133211331f6 100644
--- a/include/uapi/linux/nsfs.h
+++ b/include/uapi/linux/nsfs.h
@@ -15,5 +15,15 @@
#define NS_GET_NSTYPE _IO(NSIO, 0x3)
/* Get owner UID (in the caller's user namespace) for a user namespace */
#define NS_GET_OWNER_UID _IO(NSIO, 0x4)
+/* Get the id for a mount namespace */
+#define NS_GET_MNTNS_ID _IO(NSIO, 0x5)
+/* Translate pid from target pid namespace into the caller's pid namespace. */
+#define NS_GET_PID_FROM_PIDNS _IOR(NSIO, 0x6, int)
+/* Return thread-group leader id of pid in the callers pid namespace. */
+#define NS_GET_TGID_FROM_PIDNS _IOR(NSIO, 0x7, int)
+/* Translate pid from caller's pid namespace into a target pid namespace. */
+#define NS_GET_PID_IN_PIDNS _IOR(NSIO, 0x8, int)
+/* Return thread-group leader id of pid in the target pid namespace. */
+#define NS_GET_TGID_IN_PIDNS _IOR(NSIO, 0x9, int)
#endif /* __LINUX_NSFS_H */
diff --git a/include/uapi/linux/pidfd.h b/include/uapi/linux/pidfd.h
index 72ec000a97cd..565fc0629fff 100644
--- a/include/uapi/linux/pidfd.h
+++ b/include/uapi/linux/pidfd.h
@@ -5,6 +5,7 @@
#include <linux/types.h>
#include <linux/fcntl.h>
+#include <linux/ioctl.h>
/* Flags for pidfd_open(). */
#define PIDFD_NONBLOCK O_NONBLOCK
@@ -15,4 +16,17 @@
#define PIDFD_SIGNAL_THREAD_GROUP (1UL << 1)
#define PIDFD_SIGNAL_PROCESS_GROUP (1UL << 2)
+#define PIDFS_IOCTL_MAGIC 0xFF
+
+#define PIDFD_GET_CGROUP_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 1)
+#define PIDFD_GET_IPC_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 2)
+#define PIDFD_GET_MNT_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 3)
+#define PIDFD_GET_NET_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 4)
+#define PIDFD_GET_PID_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 5)
+#define PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 6)
+#define PIDFD_GET_TIME_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 7)
+#define PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 8)
+#define PIDFD_GET_USER_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 9)
+#define PIDFD_GET_UTS_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 10)
+
#endif /* _UAPI_LINUX_PIDFD_H */
diff --git a/include/uapi/linux/stat.h b/include/uapi/linux/stat.h
index 95770941ee2c..887a25286441 100644
--- a/include/uapi/linux/stat.h
+++ b/include/uapi/linux/stat.h
@@ -128,7 +128,13 @@ struct statx {
__u32 stx_dio_offset_align; /* File offset alignment for direct I/O */
/* 0xa0 */
__u64 stx_subvol; /* Subvolume identifier */
- __u64 __spare3[11]; /* Spare space for future expansion */
+ __u32 stx_atomic_write_unit_min; /* Min atomic write unit in bytes */
+ __u32 stx_atomic_write_unit_max; /* Max atomic write unit in bytes */
+ /* 0xb0 */
+ __u32 stx_atomic_write_segments_max; /* Max atomic write segment count */
+ __u32 __spare1[1];
+ /* 0xb8 */
+ __u64 __spare3[9]; /* Spare space for future expansion */
/* 0x100 */
};
@@ -157,6 +163,7 @@ struct statx {
#define STATX_DIOALIGN 0x00002000U /* Want/got direct I/O alignment info */
#define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id */
#define STATX_SUBVOL 0x00008000U /* Want/got stx_subvol */
+#define STATX_WRITE_ATOMIC 0x00010000U /* Want/got atomic_write_* fields */
#define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */
@@ -192,6 +199,7 @@ struct statx {
#define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */
#define STATX_ATTR_VERITY 0x00100000 /* [I] Verity protected file */
#define STATX_ATTR_DAX 0x00200000 /* File is currently in DAX state */
+#define STATX_ATTR_WRITE_ATOMIC 0x00400000 /* File supports atomic write operations */
#endif /* _UAPI_LINUX_STAT_H */
diff --git a/include/uapi/linux/trace_mmap.h b/include/uapi/linux/trace_mmap.h
index bd1066754220..c102ef35d11e 100644
--- a/include/uapi/linux/trace_mmap.h
+++ b/include/uapi/linux/trace_mmap.h
@@ -43,6 +43,6 @@ struct trace_buffer_meta {
__u64 Reserved2;
};
-#define TRACE_MMAP_IOCTL_GET_READER _IO('T', 0x1)
+#define TRACE_MMAP_IOCTL_GET_READER _IO('R', 0x20)
#endif /* _TRACE_MMAP_H_ */
diff --git a/include/uapi/linux/zorro_ids.h b/include/uapi/linux/zorro_ids.h
index 6e574d7b7d79..393f2ee9c042 100644
--- a/include/uapi/linux/zorro_ids.h
+++ b/include/uapi/linux/zorro_ids.h
@@ -449,6 +449,9 @@
#define ZORRO_PROD_VMC_ISDN_BLASTER_Z2 ZORRO_ID(VMC, 0x01, 0)
#define ZORRO_PROD_VMC_HYPERCOM_4 ZORRO_ID(VMC, 0x02, 0)
+#define ZORRO_MANUF_CSLAB 0x1400
+#define ZORRO_PROD_CSLAB_WARP_1260 ZORRO_ID(CSLAB, 0x65, 0)
+
#define ZORRO_MANUF_INFORMATION 0x157C
#define ZORRO_PROD_INFORMATION_ISDN_ENGINE_I ZORRO_ID(INFORMATION, 0x64, 0)
diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h
index f33d914d8f46..91583690bddc 100644
--- a/include/uapi/misc/fastrpc.h
+++ b/include/uapi/misc/fastrpc.h
@@ -8,11 +8,14 @@
#define FASTRPC_IOCTL_ALLOC_DMA_BUFF _IOWR('R', 1, struct fastrpc_alloc_dma_buf)
#define FASTRPC_IOCTL_FREE_DMA_BUFF _IOWR('R', 2, __u32)
#define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke)
+/* This ioctl is only supported with secure device nodes */
#define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4)
#define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create)
#define FASTRPC_IOCTL_MMAP _IOWR('R', 6, struct fastrpc_req_mmap)
#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 7, struct fastrpc_req_munmap)
+/* This ioctl is only supported with secure device nodes */
#define FASTRPC_IOCTL_INIT_ATTACH_SNS _IO('R', 8)
+/* This ioctl is only supported with secure device nodes */
#define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_init_create_static)
#define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map)
#define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap)
diff --git a/include/vdso/datapage.h b/include/vdso/datapage.h
index d04d394db064..7647e0946f50 100644
--- a/include/vdso/datapage.h
+++ b/include/vdso/datapage.h
@@ -77,6 +77,10 @@ struct vdso_timestamp {
* vdso_data will be accessed by 64 bit and compat code at the same time
* so we should be careful before modifying this structure.
*
+ * The ordering of the struct members is optimized to have fast access to the
+ * often required struct members which are related to CLOCK_REALTIME and
+ * CLOCK_MONOTONIC. This information is stored in the first cache lines.
+ *
* @basetime is used to store the base time for the system wide time getter
* VVAR page.
*
diff --git a/io_uring/Makefile b/io_uring/Makefile
index fc1b23c524e8..61923e11c767 100644
--- a/io_uring/Makefile
+++ b/io_uring/Makefile
@@ -4,9 +4,9 @@
obj-$(CONFIG_IO_URING) += io_uring.o opdef.o kbuf.o rsrc.o notif.o \
tctx.o filetable.o rw.o net.o poll.o \
- uring_cmd.o openclose.o sqpoll.o \
- xattr.o nop.o fs.o splice.o sync.o \
- msg_ring.o advise.o openclose.o \
+ eventfd.o uring_cmd.o openclose.o \
+ sqpoll.o xattr.o nop.o fs.o splice.o \
+ sync.o msg_ring.o advise.o openclose.o \
epoll.o statx.o timeout.o fdinfo.o \
cancel.o waitid.o register.o \
truncate.o memmap.o
diff --git a/io_uring/advise.c b/io_uring/advise.c
index 7085804c513c..cb7b881665e5 100644
--- a/io_uring/advise.c
+++ b/io_uring/advise.c
@@ -17,14 +17,14 @@
struct io_fadvise {
struct file *file;
u64 offset;
- u32 len;
+ u64 len;
u32 advice;
};
struct io_madvise {
struct file *file;
u64 addr;
- u32 len;
+ u64 len;
u32 advice;
};
@@ -33,11 +33,13 @@ int io_madvise_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
#if defined(CONFIG_ADVISE_SYSCALLS) && defined(CONFIG_MMU)
struct io_madvise *ma = io_kiocb_to_cmd(req, struct io_madvise);
- if (sqe->buf_index || sqe->off || sqe->splice_fd_in)
+ if (sqe->buf_index || sqe->splice_fd_in)
return -EINVAL;
ma->addr = READ_ONCE(sqe->addr);
- ma->len = READ_ONCE(sqe->len);
+ ma->len = READ_ONCE(sqe->off);
+ if (!ma->len)
+ ma->len = READ_ONCE(sqe->len);
ma->advice = READ_ONCE(sqe->fadvise_advice);
req->flags |= REQ_F_FORCE_ASYNC;
return 0;
@@ -78,11 +80,13 @@ int io_fadvise_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
{
struct io_fadvise *fa = io_kiocb_to_cmd(req, struct io_fadvise);
- if (sqe->buf_index || sqe->addr || sqe->splice_fd_in)
+ if (sqe->buf_index || sqe->splice_fd_in)
return -EINVAL;
fa->offset = READ_ONCE(sqe->off);
- fa->len = READ_ONCE(sqe->len);
+ fa->len = READ_ONCE(sqe->addr);
+ if (!fa->len)
+ fa->len = READ_ONCE(sqe->len);
fa->advice = READ_ONCE(sqe->fadvise_advice);
if (io_fadvise_force_async(fa))
req->flags |= REQ_F_FORCE_ASYNC;
diff --git a/io_uring/eventfd.c b/io_uring/eventfd.c
new file mode 100644
index 000000000000..b9384503a2b7
--- /dev/null
+++ b/io_uring/eventfd.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/eventfd.h>
+#include <linux/eventpoll.h>
+#include <linux/io_uring.h>
+#include <linux/io_uring_types.h>
+
+#include "io-wq.h"
+#include "eventfd.h"
+
+struct io_ev_fd {
+ struct eventfd_ctx *cq_ev_fd;
+ unsigned int eventfd_async: 1;
+ struct rcu_head rcu;
+ atomic_t refs;
+ atomic_t ops;
+};
+
+enum {
+ IO_EVENTFD_OP_SIGNAL_BIT,
+};
+
+static void io_eventfd_free(struct rcu_head *rcu)
+{
+ struct io_ev_fd *ev_fd = container_of(rcu, struct io_ev_fd, rcu);
+
+ eventfd_ctx_put(ev_fd->cq_ev_fd);
+ kfree(ev_fd);
+}
+
+static void io_eventfd_do_signal(struct rcu_head *rcu)
+{
+ struct io_ev_fd *ev_fd = container_of(rcu, struct io_ev_fd, rcu);
+
+ eventfd_signal_mask(ev_fd->cq_ev_fd, EPOLL_URING_WAKE);
+
+ if (atomic_dec_and_test(&ev_fd->refs))
+ io_eventfd_free(rcu);
+}
+
+void io_eventfd_signal(struct io_ring_ctx *ctx)
+{
+ struct io_ev_fd *ev_fd = NULL;
+
+ if (READ_ONCE(ctx->rings->cq_flags) & IORING_CQ_EVENTFD_DISABLED)
+ return;
+
+ guard(rcu)();
+
+ /*
+ * rcu_dereference ctx->io_ev_fd once and use it for both for checking
+ * and eventfd_signal
+ */
+ ev_fd = rcu_dereference(ctx->io_ev_fd);
+
+ /*
+ * Check again if ev_fd exists incase an io_eventfd_unregister call
+ * completed between the NULL check of ctx->io_ev_fd at the start of
+ * the function and rcu_read_lock.
+ */
+ if (unlikely(!ev_fd))
+ return;
+ if (!atomic_inc_not_zero(&ev_fd->refs))
+ return;
+ if (ev_fd->eventfd_async && !io_wq_current_is_worker())
+ goto out;
+
+ if (likely(eventfd_signal_allowed())) {
+ eventfd_signal_mask(ev_fd->cq_ev_fd, EPOLL_URING_WAKE);
+ } else {
+ if (!atomic_fetch_or(BIT(IO_EVENTFD_OP_SIGNAL_BIT), &ev_fd->ops)) {
+ call_rcu_hurry(&ev_fd->rcu, io_eventfd_do_signal);
+ return;
+ }
+ }
+out:
+ if (atomic_dec_and_test(&ev_fd->refs))
+ call_rcu(&ev_fd->rcu, io_eventfd_free);
+}
+
+void io_eventfd_flush_signal(struct io_ring_ctx *ctx)
+{
+ bool skip;
+
+ spin_lock(&ctx->completion_lock);
+
+ /*
+ * Eventfd should only get triggered when at least one event has been
+ * posted. Some applications rely on the eventfd notification count
+ * only changing IFF a new CQE has been added to the CQ ring. There's
+ * no depedency on 1:1 relationship between how many times this
+ * function is called (and hence the eventfd count) and number of CQEs
+ * posted to the CQ ring.
+ */
+ skip = ctx->cached_cq_tail == ctx->evfd_last_cq_tail;
+ ctx->evfd_last_cq_tail = ctx->cached_cq_tail;
+ spin_unlock(&ctx->completion_lock);
+ if (skip)
+ return;
+
+ io_eventfd_signal(ctx);
+}
+
+int io_eventfd_register(struct io_ring_ctx *ctx, void __user *arg,
+ unsigned int eventfd_async)
+{
+ struct io_ev_fd *ev_fd;
+ __s32 __user *fds = arg;
+ int fd;
+
+ ev_fd = rcu_dereference_protected(ctx->io_ev_fd,
+ lockdep_is_held(&ctx->uring_lock));
+ if (ev_fd)
+ return -EBUSY;
+
+ if (copy_from_user(&fd, fds, sizeof(*fds)))
+ return -EFAULT;
+
+ ev_fd = kmalloc(sizeof(*ev_fd), GFP_KERNEL);
+ if (!ev_fd)
+ return -ENOMEM;
+
+ ev_fd->cq_ev_fd = eventfd_ctx_fdget(fd);
+ if (IS_ERR(ev_fd->cq_ev_fd)) {
+ int ret = PTR_ERR(ev_fd->cq_ev_fd);
+ kfree(ev_fd);
+ return ret;
+ }
+
+ spin_lock(&ctx->completion_lock);
+ ctx->evfd_last_cq_tail = ctx->cached_cq_tail;
+ spin_unlock(&ctx->completion_lock);
+
+ ev_fd->eventfd_async = eventfd_async;
+ ctx->has_evfd = true;
+ atomic_set(&ev_fd->refs, 1);
+ atomic_set(&ev_fd->ops, 0);
+ rcu_assign_pointer(ctx->io_ev_fd, ev_fd);
+ return 0;
+}
+
+int io_eventfd_unregister(struct io_ring_ctx *ctx)
+{
+ struct io_ev_fd *ev_fd;
+
+ ev_fd = rcu_dereference_protected(ctx->io_ev_fd,
+ lockdep_is_held(&ctx->uring_lock));
+ if (ev_fd) {
+ ctx->has_evfd = false;
+ rcu_assign_pointer(ctx->io_ev_fd, NULL);
+ if (atomic_dec_and_test(&ev_fd->refs))
+ call_rcu(&ev_fd->rcu, io_eventfd_free);
+ return 0;
+ }
+
+ return -ENXIO;
+}
diff --git a/io_uring/eventfd.h b/io_uring/eventfd.h
new file mode 100644
index 000000000000..d394f49c6321
--- /dev/null
+++ b/io_uring/eventfd.h
@@ -0,0 +1,8 @@
+
+struct io_ring_ctx;
+int io_eventfd_register(struct io_ring_ctx *ctx, void __user *arg,
+ unsigned int eventfd_async);
+int io_eventfd_unregister(struct io_ring_ctx *ctx);
+
+void io_eventfd_flush_signal(struct io_ring_ctx *ctx);
+void io_eventfd_signal(struct io_ring_ctx *ctx);
diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c
index 7d3316fe9bfc..f1e7c670add8 100644
--- a/io_uring/io-wq.c
+++ b/io_uring/io-wq.c
@@ -23,6 +23,7 @@
#include "io_uring.h"
#define WORKER_IDLE_TIMEOUT (5 * HZ)
+#define WORKER_INIT_LIMIT 3
enum {
IO_WORKER_F_UP = 0, /* up and active */
@@ -58,6 +59,7 @@ struct io_worker {
unsigned long create_state;
struct callback_head create_work;
+ int init_retries;
union {
struct rcu_head rcu;
@@ -159,7 +161,7 @@ static inline struct io_wq_acct *io_get_acct(struct io_wq *wq, bool bound)
static inline struct io_wq_acct *io_work_get_acct(struct io_wq *wq,
struct io_wq_work *work)
{
- return io_get_acct(wq, !(work->flags & IO_WQ_WORK_UNBOUND));
+ return io_get_acct(wq, !(atomic_read(&work->flags) & IO_WQ_WORK_UNBOUND));
}
static inline struct io_wq_acct *io_wq_get_acct(struct io_worker *worker)
@@ -451,7 +453,7 @@ static void __io_worker_idle(struct io_wq *wq, struct io_worker *worker)
static inline unsigned int io_get_work_hash(struct io_wq_work *work)
{
- return work->flags >> IO_WQ_HASH_SHIFT;
+ return atomic_read(&work->flags) >> IO_WQ_HASH_SHIFT;
}
static bool io_wait_on_hash(struct io_wq *wq, unsigned int hash)
@@ -592,8 +594,9 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
next_hashed = wq_next_work(work);
- if (unlikely(do_kill) && (work->flags & IO_WQ_WORK_UNBOUND))
- work->flags |= IO_WQ_WORK_CANCEL;
+ if (do_kill &&
+ (atomic_read(&work->flags) & IO_WQ_WORK_UNBOUND))
+ atomic_or(IO_WQ_WORK_CANCEL, &work->flags);
wq->do_work(work);
io_assign_current_work(worker, NULL);
@@ -744,7 +747,7 @@ static bool io_wq_work_match_all(struct io_wq_work *work, void *data)
return true;
}
-static inline bool io_should_retry_thread(long err)
+static inline bool io_should_retry_thread(struct io_worker *worker, long err)
{
/*
* Prevent perpetual task_work retry, if the task (or its group) is
@@ -752,6 +755,8 @@ static inline bool io_should_retry_thread(long err)
*/
if (fatal_signal_pending(current))
return false;
+ if (worker->init_retries++ >= WORKER_INIT_LIMIT)
+ return false;
switch (err) {
case -EAGAIN:
@@ -778,7 +783,7 @@ static void create_worker_cont(struct callback_head *cb)
io_init_new_worker(wq, worker, tsk);
io_worker_release(worker);
return;
- } else if (!io_should_retry_thread(PTR_ERR(tsk))) {
+ } else if (!io_should_retry_thread(worker, PTR_ERR(tsk))) {
struct io_wq_acct *acct = io_wq_get_acct(worker);
atomic_dec(&acct->nr_running);
@@ -845,7 +850,7 @@ fail:
tsk = create_io_thread(io_wq_worker, worker, NUMA_NO_NODE);
if (!IS_ERR(tsk)) {
io_init_new_worker(wq, worker, tsk);
- } else if (!io_should_retry_thread(PTR_ERR(tsk))) {
+ } else if (!io_should_retry_thread(worker, PTR_ERR(tsk))) {
kfree(worker);
goto fail;
} else {
@@ -891,7 +896,7 @@ static bool io_wq_worker_wake(struct io_worker *worker, void *data)
static void io_run_cancel(struct io_wq_work *work, struct io_wq *wq)
{
do {
- work->flags |= IO_WQ_WORK_CANCEL;
+ atomic_or(IO_WQ_WORK_CANCEL, &work->flags);
wq->do_work(work);
work = wq->free_work(work);
} while (work);
@@ -926,7 +931,7 @@ static bool io_wq_work_match_item(struct io_wq_work *work, void *data)
void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work)
{
struct io_wq_acct *acct = io_work_get_acct(wq, work);
- unsigned long work_flags = work->flags;
+ unsigned int work_flags = atomic_read(&work->flags);
struct io_cb_cancel_data match = {
.fn = io_wq_work_match_item,
.data = work,
@@ -939,7 +944,7 @@ void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work)
* been marked as one that should not get executed, cancel it here.
*/
if (test_bit(IO_WQ_BIT_EXIT, &wq->state) ||
- (work->flags & IO_WQ_WORK_CANCEL)) {
+ (work_flags & IO_WQ_WORK_CANCEL)) {
io_run_cancel(work, wq);
return;
}
@@ -982,7 +987,7 @@ void io_wq_hash_work(struct io_wq_work *work, void *val)
unsigned int bit;
bit = hash_ptr(val, IO_WQ_HASH_ORDER);
- work->flags |= (IO_WQ_WORK_HASHED | (bit << IO_WQ_HASH_SHIFT));
+ atomic_or(IO_WQ_WORK_HASHED | (bit << IO_WQ_HASH_SHIFT), &work->flags);
}
static bool __io_wq_worker_cancel(struct io_worker *worker,
@@ -990,7 +995,7 @@ static bool __io_wq_worker_cancel(struct io_worker *worker,
struct io_wq_work *work)
{
if (work && match->fn(work, match->data)) {
- work->flags |= IO_WQ_WORK_CANCEL;
+ atomic_or(IO_WQ_WORK_CANCEL, &work->flags);
__set_notify_signal(worker->task);
return true;
}
diff --git a/io_uring/io-wq.h b/io_uring/io-wq.h
index 2b2a6406dd8e..b3b004a7b625 100644
--- a/io_uring/io-wq.h
+++ b/io_uring/io-wq.h
@@ -56,7 +56,7 @@ bool io_wq_worker_stopped(void);
static inline bool io_wq_is_hashed(struct io_wq_work *work)
{
- return work->flags & IO_WQ_WORK_HASHED;
+ return atomic_read(&work->flags) & IO_WQ_WORK_HASHED;
}
typedef bool (work_cancel_fn)(struct io_wq_work *, void *);
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index c326e2127dd4..8e6faa942a6f 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -95,12 +95,14 @@
#include "futex.h"
#include "napi.h"
#include "uring_cmd.h"
+#include "msg_ring.h"
#include "memmap.h"
#include "timeout.h"
#include "poll.h"
#include "rw.h"
#include "alloc_cache.h"
+#include "eventfd.h"
#define IORING_MAX_ENTRIES 32768
#define IORING_MAX_CQ_ENTRIES (2 * IORING_MAX_ENTRIES)
@@ -314,6 +316,9 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
sizeof(struct io_async_rw));
ret |= io_alloc_cache_init(&ctx->uring_cache, IO_ALLOC_CACHE_MAX,
sizeof(struct uring_cache));
+ spin_lock_init(&ctx->msg_lock);
+ ret |= io_alloc_cache_init(&ctx->msg_cache, IO_ALLOC_CACHE_MAX,
+ sizeof(struct io_kiocb));
ret |= io_futex_cache_init(ctx);
if (ret)
goto err;
@@ -350,6 +355,7 @@ err:
io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
io_alloc_cache_free(&ctx->rw_cache, io_rw_cache_free);
io_alloc_cache_free(&ctx->uring_cache, kfree);
+ io_alloc_cache_free(&ctx->msg_cache, io_msg_cache_free);
io_futex_cache_free(ctx);
kfree(ctx->cancel_table.hbs);
kfree(ctx->cancel_table_locked.hbs);
@@ -461,9 +467,9 @@ static void io_prep_async_work(struct io_kiocb *req)
}
req->work.list.next = NULL;
- req->work.flags = 0;
+ atomic_set(&req->work.flags, 0);
if (req->flags & REQ_F_FORCE_ASYNC)
- req->work.flags |= IO_WQ_WORK_CONCURRENT;
+ atomic_or(IO_WQ_WORK_CONCURRENT, &req->work.flags);
if (req->file && !(req->flags & REQ_F_FIXED_FILE))
req->flags |= io_file_get_flags(req->file);
@@ -479,7 +485,7 @@ static void io_prep_async_work(struct io_kiocb *req)
io_wq_hash_work(&req->work, file_inode(req->file));
} else if (!req->file || !S_ISBLK(file_inode(req->file)->i_mode)) {
if (def->unbound_nonreg_file)
- req->work.flags |= IO_WQ_WORK_UNBOUND;
+ atomic_or(IO_WQ_WORK_UNBOUND, &req->work.flags);
}
}
@@ -519,7 +525,7 @@ static void io_queue_iowq(struct io_kiocb *req)
* worker for it).
*/
if (WARN_ON_ONCE(!same_thread_group(req->task, current)))
- req->work.flags |= IO_WQ_WORK_CANCEL;
+ atomic_or(IO_WQ_WORK_CANCEL, &req->work.flags);
trace_io_uring_queue_async_work(req, io_wq_is_hashed(&req->work));
io_wq_enqueue(tctx->io_wq, &req->work);
@@ -541,84 +547,6 @@ static __cold void io_queue_deferred(struct io_ring_ctx *ctx)
}
}
-void io_eventfd_ops(struct rcu_head *rcu)
-{
- struct io_ev_fd *ev_fd = container_of(rcu, struct io_ev_fd, rcu);
- int ops = atomic_xchg(&ev_fd->ops, 0);
-
- if (ops & BIT(IO_EVENTFD_OP_SIGNAL_BIT))
- eventfd_signal_mask(ev_fd->cq_ev_fd, EPOLL_URING_WAKE);
-
- /* IO_EVENTFD_OP_FREE_BIT may not be set here depending on callback
- * ordering in a race but if references are 0 we know we have to free
- * it regardless.
- */
- if (atomic_dec_and_test(&ev_fd->refs)) {
- eventfd_ctx_put(ev_fd->cq_ev_fd);
- kfree(ev_fd);
- }
-}
-
-static void io_eventfd_signal(struct io_ring_ctx *ctx)
-{
- struct io_ev_fd *ev_fd = NULL;
-
- rcu_read_lock();
- /*
- * rcu_dereference ctx->io_ev_fd once and use it for both for checking
- * and eventfd_signal
- */
- ev_fd = rcu_dereference(ctx->io_ev_fd);
-
- /*
- * Check again if ev_fd exists incase an io_eventfd_unregister call
- * completed between the NULL check of ctx->io_ev_fd at the start of
- * the function and rcu_read_lock.
- */
- if (unlikely(!ev_fd))
- goto out;
- if (READ_ONCE(ctx->rings->cq_flags) & IORING_CQ_EVENTFD_DISABLED)
- goto out;
- if (ev_fd->eventfd_async && !io_wq_current_is_worker())
- goto out;
-
- if (likely(eventfd_signal_allowed())) {
- eventfd_signal_mask(ev_fd->cq_ev_fd, EPOLL_URING_WAKE);
- } else {
- atomic_inc(&ev_fd->refs);
- if (!atomic_fetch_or(BIT(IO_EVENTFD_OP_SIGNAL_BIT), &ev_fd->ops))
- call_rcu_hurry(&ev_fd->rcu, io_eventfd_ops);
- else
- atomic_dec(&ev_fd->refs);
- }
-
-out:
- rcu_read_unlock();
-}
-
-static void io_eventfd_flush_signal(struct io_ring_ctx *ctx)
-{
- bool skip;
-
- spin_lock(&ctx->completion_lock);
-
- /*
- * Eventfd should only get triggered when at least one event has been
- * posted. Some applications rely on the eventfd notification count
- * only changing IFF a new CQE has been added to the CQ ring. There's
- * no depedency on 1:1 relationship between how many times this
- * function is called (and hence the eventfd count) and number of CQEs
- * posted to the CQ ring.
- */
- skip = ctx->cached_cq_tail == ctx->evfd_last_cq_tail;
- ctx->evfd_last_cq_tail = ctx->cached_cq_tail;
- spin_unlock(&ctx->completion_lock);
- if (skip)
- return;
-
- io_eventfd_signal(ctx);
-}
-
void __io_commit_cqring_flush(struct io_ring_ctx *ctx)
{
if (ctx->poll_activated)
@@ -878,20 +806,43 @@ static bool io_fill_cqe_aux(struct io_ring_ctx *ctx, u64 user_data, s32 res,
return false;
}
-bool io_post_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags)
+static bool __io_post_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res,
+ u32 cflags)
{
bool filled;
- io_cq_lock(ctx);
filled = io_fill_cqe_aux(ctx, user_data, res, cflags);
if (!filled)
filled = io_cqring_event_overflow(ctx, user_data, res, cflags, 0, 0);
+ return filled;
+}
+
+bool io_post_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags)
+{
+ bool filled;
+
+ io_cq_lock(ctx);
+ filled = __io_post_aux_cqe(ctx, user_data, res, cflags);
io_cq_unlock_post(ctx);
return filled;
}
/*
+ * Must be called from inline task_work so we now a flush will happen later,
+ * and obviously with ctx->uring_lock held (tw always has that).
+ */
+void io_add_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags)
+{
+ if (!io_fill_cqe_aux(ctx, user_data, res, cflags)) {
+ spin_lock(&ctx->completion_lock);
+ io_cqring_event_overflow(ctx, user_data, res, cflags, 0, 0);
+ spin_unlock(&ctx->completion_lock);
+ }
+ ctx->submit_state.cq_flush = true;
+}
+
+/*
* A helper for multishot requests posting additional CQEs.
* Should only be used from a task_work including IO_URING_F_MULTISHOT.
*/
@@ -1175,9 +1126,10 @@ void tctx_task_work(struct callback_head *cb)
WARN_ON_ONCE(ret);
}
-static inline void io_req_local_work_add(struct io_kiocb *req, unsigned flags)
+static inline void io_req_local_work_add(struct io_kiocb *req,
+ struct io_ring_ctx *ctx,
+ unsigned flags)
{
- struct io_ring_ctx *ctx = req->ctx;
unsigned nr_wait, nr_tw, nr_tw_prev;
struct llist_node *head;
@@ -1191,6 +1143,8 @@ static inline void io_req_local_work_add(struct io_kiocb *req, unsigned flags)
if (req->flags & (REQ_F_LINK | REQ_F_HARDLINK))
flags &= ~IOU_F_TWQ_LAZY_WAKE;
+ guard(rcu)();
+
head = READ_ONCE(ctx->work_llist.first);
do {
nr_tw_prev = 0;
@@ -1272,13 +1226,18 @@ static void io_req_normal_work_add(struct io_kiocb *req)
void __io_req_task_work_add(struct io_kiocb *req, unsigned flags)
{
- if (req->ctx->flags & IORING_SETUP_DEFER_TASKRUN) {
- rcu_read_lock();
- io_req_local_work_add(req, flags);
- rcu_read_unlock();
- } else {
+ if (req->ctx->flags & IORING_SETUP_DEFER_TASKRUN)
+ io_req_local_work_add(req, req->ctx, flags);
+ else
io_req_normal_work_add(req);
- }
+}
+
+void io_req_task_work_add_remote(struct io_kiocb *req, struct io_ring_ctx *ctx,
+ unsigned flags)
+{
+ if (WARN_ON_ONCE(!(ctx->flags & IORING_SETUP_DEFER_TASKRUN)))
+ return;
+ io_req_local_work_add(req, ctx, flags);
}
static void __cold io_move_task_work_from_local(struct io_ring_ctx *ctx)
@@ -1467,7 +1426,7 @@ void __io_submit_flush_completions(struct io_ring_ctx *ctx)
}
__io_cq_unlock_post(ctx);
- if (!wq_list_empty(&ctx->submit_state.compl_reqs)) {
+ if (!wq_list_empty(&state->compl_reqs)) {
io_free_batch_list(ctx, state->compl_reqs.first);
INIT_WQ_LIST(&state->compl_reqs);
}
@@ -1813,14 +1772,14 @@ void io_wq_submit_work(struct io_wq_work *work)
io_arm_ltimeout(req);
/* either cancelled or io-wq is dying, so don't touch tctx->iowq */
- if (work->flags & IO_WQ_WORK_CANCEL) {
+ if (atomic_read(&work->flags) & IO_WQ_WORK_CANCEL) {
fail:
io_req_task_queue_fail(req, err);
return;
}
if (!io_assign_file(req, def, issue_flags)) {
err = -EBADF;
- work->flags |= IO_WQ_WORK_CANCEL;
+ atomic_or(IO_WQ_WORK_CANCEL, &work->flags);
goto fail;
}
@@ -2649,6 +2608,7 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
io_alloc_cache_free(&ctx->rw_cache, io_rw_cache_free);
io_alloc_cache_free(&ctx->uring_cache, kfree);
+ io_alloc_cache_free(&ctx->msg_cache, io_msg_cache_free);
io_futex_cache_free(ctx);
io_destroy_buffers(ctx);
mutex_unlock(&ctx->uring_lock);
diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h
index 726e6367af4d..e1ce908f0679 100644
--- a/io_uring/io_uring.h
+++ b/io_uring/io_uring.h
@@ -65,6 +65,7 @@ bool io_cqe_cache_refill(struct io_ring_ctx *ctx, bool overflow);
int io_run_task_work_sig(struct io_ring_ctx *ctx);
void io_req_defer_failed(struct io_kiocb *req, s32 res);
bool io_post_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags);
+void io_add_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags);
bool io_req_post_cqe(struct io_kiocb *req, s32 res, u32 cflags);
void __io_commit_cqring_flush(struct io_ring_ctx *ctx);
@@ -73,6 +74,8 @@ struct file *io_file_get_fixed(struct io_kiocb *req, int fd,
unsigned issue_flags);
void __io_req_task_work_add(struct io_kiocb *req, unsigned flags);
+void io_req_task_work_add_remote(struct io_kiocb *req, struct io_ring_ctx *ctx,
+ unsigned flags);
bool io_alloc_async_data(struct io_kiocb *req);
void io_req_task_queue(struct io_kiocb *req);
void io_req_task_complete(struct io_kiocb *req, struct io_tw_state *ts);
@@ -104,12 +107,6 @@ bool __io_alloc_req_refill(struct io_ring_ctx *ctx);
bool io_match_task_safe(struct io_kiocb *head, struct task_struct *task,
bool cancel_all);
-enum {
- IO_EVENTFD_OP_SIGNAL_BIT,
- IO_EVENTFD_OP_FREE_BIT,
-};
-
-void io_eventfd_ops(struct rcu_head *rcu);
void io_activate_pollwq(struct io_ring_ctx *ctx);
static inline void io_lockdep_assert_cq_locked(struct io_ring_ctx *ctx)
diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c
index 81c4a9d43729..29fa9285a33d 100644
--- a/io_uring/msg_ring.c
+++ b/io_uring/msg_ring.c
@@ -11,9 +11,9 @@
#include "io_uring.h"
#include "rsrc.h"
#include "filetable.h"
+#include "alloc_cache.h"
#include "msg_ring.h"
-
/* All valid masks for MSG_RING */
#define IORING_MSG_RING_MASK (IORING_MSG_RING_CQE_SKIP | \
IORING_MSG_RING_FLAGS_PASS)
@@ -68,59 +68,70 @@ void io_msg_ring_cleanup(struct io_kiocb *req)
static inline bool io_msg_need_remote(struct io_ring_ctx *target_ctx)
{
- if (!target_ctx->task_complete)
- return false;
- return current != target_ctx->submitter_task;
+ return target_ctx->task_complete;
}
-static int io_msg_exec_remote(struct io_kiocb *req, task_work_func_t func)
+static void io_msg_tw_complete(struct io_kiocb *req, struct io_tw_state *ts)
{
- struct io_ring_ctx *ctx = req->file->private_data;
- struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
- struct task_struct *task = READ_ONCE(ctx->submitter_task);
+ struct io_ring_ctx *ctx = req->ctx;
- if (unlikely(!task))
- return -EOWNERDEAD;
+ io_add_aux_cqe(ctx, req->cqe.user_data, req->cqe.res, req->cqe.flags);
+ if (spin_trylock(&ctx->msg_lock)) {
+ if (io_alloc_cache_put(&ctx->msg_cache, req))
+ req = NULL;
+ spin_unlock(&ctx->msg_lock);
+ }
+ if (req)
+ kmem_cache_free(req_cachep, req);
+ percpu_ref_put(&ctx->refs);
+}
- init_task_work(&msg->tw, func);
- if (task_work_add(task, &msg->tw, TWA_SIGNAL))
+static int io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req,
+ int res, u32 cflags, u64 user_data)
+{
+ req->task = READ_ONCE(ctx->submitter_task);
+ if (!req->task) {
+ kmem_cache_free(req_cachep, req);
return -EOWNERDEAD;
+ }
+ req->cqe.user_data = user_data;
+ io_req_set_res(req, res, cflags);
+ percpu_ref_get(&ctx->refs);
+ req->ctx = ctx;
+ req->io_task_work.func = io_msg_tw_complete;
+ io_req_task_work_add_remote(req, ctx, IOU_F_TWQ_LAZY_WAKE);
+ return 0;
+}
- return IOU_ISSUE_SKIP_COMPLETE;
+static struct io_kiocb *io_msg_get_kiocb(struct io_ring_ctx *ctx)
+{
+ struct io_kiocb *req = NULL;
+
+ if (spin_trylock(&ctx->msg_lock)) {
+ req = io_alloc_cache_get(&ctx->msg_cache);
+ spin_unlock(&ctx->msg_lock);
+ }
+ if (req)
+ return req;
+ return kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN);
}
-static void io_msg_tw_complete(struct callback_head *head)
+static int io_msg_data_remote(struct io_kiocb *req)
{
- struct io_msg *msg = container_of(head, struct io_msg, tw);
- struct io_kiocb *req = cmd_to_io_kiocb(msg);
struct io_ring_ctx *target_ctx = req->file->private_data;
- int ret = 0;
-
- if (current->flags & PF_EXITING) {
- ret = -EOWNERDEAD;
- } else {
- u32 flags = 0;
-
- if (msg->flags & IORING_MSG_RING_FLAGS_PASS)
- flags = msg->cqe_flags;
-
- /*
- * If the target ring is using IOPOLL mode, then we need to be
- * holding the uring_lock for posting completions. Other ring
- * types rely on the regular completion locking, which is
- * handled while posting.
- */
- if (target_ctx->flags & IORING_SETUP_IOPOLL)
- mutex_lock(&target_ctx->uring_lock);
- if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, flags))
- ret = -EOVERFLOW;
- if (target_ctx->flags & IORING_SETUP_IOPOLL)
- mutex_unlock(&target_ctx->uring_lock);
- }
+ struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
+ struct io_kiocb *target;
+ u32 flags = 0;
- if (ret < 0)
- req_set_fail(req);
- io_req_queue_tw_complete(req, ret);
+ target = io_msg_get_kiocb(req->ctx);
+ if (unlikely(!target))
+ return -ENOMEM;
+
+ if (msg->flags & IORING_MSG_RING_FLAGS_PASS)
+ flags = msg->cqe_flags;
+
+ return io_msg_remote_post(target_ctx, target, msg->len, flags,
+ msg->user_data);
}
static int io_msg_ring_data(struct io_kiocb *req, unsigned int issue_flags)
@@ -138,7 +149,7 @@ static int io_msg_ring_data(struct io_kiocb *req, unsigned int issue_flags)
return -EBADFD;
if (io_msg_need_remote(target_ctx))
- return io_msg_exec_remote(req, io_msg_tw_complete);
+ return io_msg_data_remote(req);
if (msg->flags & IORING_MSG_RING_FLAGS_PASS)
flags = msg->cqe_flags;
@@ -218,6 +229,22 @@ static void io_msg_tw_fd_complete(struct callback_head *head)
io_req_queue_tw_complete(req, ret);
}
+static int io_msg_fd_remote(struct io_kiocb *req)
+{
+ struct io_ring_ctx *ctx = req->file->private_data;
+ struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
+ struct task_struct *task = READ_ONCE(ctx->submitter_task);
+
+ if (unlikely(!task))
+ return -EOWNERDEAD;
+
+ init_task_work(&msg->tw, io_msg_tw_fd_complete);
+ if (task_work_add(task, &msg->tw, TWA_SIGNAL))
+ return -EOWNERDEAD;
+
+ return IOU_ISSUE_SKIP_COMPLETE;
+}
+
static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags)
{
struct io_ring_ctx *target_ctx = req->file->private_data;
@@ -240,7 +267,7 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags)
}
if (io_msg_need_remote(target_ctx))
- return io_msg_exec_remote(req, io_msg_tw_fd_complete);
+ return io_msg_fd_remote(req);
return io_msg_install_complete(req, issue_flags);
}
@@ -294,3 +321,10 @@ done:
io_req_set_res(req, ret, 0);
return IOU_OK;
}
+
+void io_msg_cache_free(const void *entry)
+{
+ struct io_kiocb *req = (struct io_kiocb *) entry;
+
+ kmem_cache_free(req_cachep, req);
+}
diff --git a/io_uring/msg_ring.h b/io_uring/msg_ring.h
index 3987ee6c0e5f..3030f3942f0f 100644
--- a/io_uring/msg_ring.h
+++ b/io_uring/msg_ring.h
@@ -3,3 +3,4 @@
int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags);
void io_msg_ring_cleanup(struct io_kiocb *req);
+void io_msg_cache_free(const void *entry);
diff --git a/io_uring/napi.c b/io_uring/napi.c
index 8c18ede595c4..762254a7ff3f 100644
--- a/io_uring/napi.c
+++ b/io_uring/napi.c
@@ -283,7 +283,7 @@ void __io_napi_adjust_timeout(struct io_ring_ctx *ctx, struct io_wait_queue *iow
s64 poll_to_ns = timespec64_to_ns(ts);
if (poll_to_ns > 0) {
u64 val = poll_to_ns + 999;
- do_div(val, (s64) 1000);
+ do_div(val, 1000);
poll_to = val;
}
}
diff --git a/io_uring/net.c b/io_uring/net.c
index 7c98c4d50946..7b75da2e7826 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -51,6 +51,16 @@ struct io_connect {
bool seen_econnaborted;
};
+struct io_bind {
+ struct file *file;
+ int addr_len;
+};
+
+struct io_listen {
+ struct file *file;
+ int backlog;
+};
+
struct io_sr_msg {
struct file *file;
union {
@@ -817,20 +827,20 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
bool mshot_finished, unsigned issue_flags)
{
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
- unsigned int cflags;
-
- if (sr->flags & IORING_RECVSEND_BUNDLE)
- cflags = io_put_kbufs(req, io_bundle_nbufs(kmsg, *ret),
- issue_flags);
- else
- cflags = io_put_kbuf(req, issue_flags);
+ unsigned int cflags = 0;
if (kmsg->msg.msg_inq > 0)
cflags |= IORING_CQE_F_SOCK_NONEMPTY;
- /* bundle with no more immediate buffers, we're done */
- if (sr->flags & IORING_RECVSEND_BUNDLE && req->flags & REQ_F_BL_EMPTY)
- goto finish;
+ if (sr->flags & IORING_RECVSEND_BUNDLE) {
+ cflags |= io_put_kbufs(req, io_bundle_nbufs(kmsg, *ret),
+ issue_flags);
+ /* bundle with no more immediate buffers, we're done */
+ if (req->flags & REQ_F_BL_EMPTY)
+ goto finish;
+ } else {
+ cflags |= io_put_kbuf(req, issue_flags);
+ }
/*
* Fill CQE for this receive and see if we should keep trying to
@@ -1127,16 +1137,18 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
flags |= MSG_DONTWAIT;
retry_multishot:
- kmsg->msg.msg_inq = -1;
- kmsg->msg.msg_flags = 0;
-
if (io_do_buffer_select(req)) {
ret = io_recv_buf_select(req, kmsg, &len, issue_flags);
- if (unlikely(ret))
+ if (unlikely(ret)) {
+ kmsg->msg.msg_inq = -1;
goto out_free;
+ }
sr->buf = NULL;
}
+ kmsg->msg.msg_flags = 0;
+ kmsg->msg.msg_inq = -1;
+
if (flags & MSG_WAITALL)
min_ret = iov_iter_count(&kmsg->msg.msg_iter);
@@ -1715,6 +1727,70 @@ out:
return IOU_OK;
}
+int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+ struct io_bind *bind = io_kiocb_to_cmd(req, struct io_bind);
+ struct sockaddr __user *uaddr;
+ struct io_async_msghdr *io;
+
+ if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in)
+ return -EINVAL;
+
+ uaddr = u64_to_user_ptr(READ_ONCE(sqe->addr));
+ bind->addr_len = READ_ONCE(sqe->addr2);
+
+ io = io_msg_alloc_async(req);
+ if (unlikely(!io))
+ return -ENOMEM;
+ return move_addr_to_kernel(uaddr, bind->addr_len, &io->addr);
+}
+
+int io_bind(struct io_kiocb *req, unsigned int issue_flags)
+{
+ struct io_bind *bind = io_kiocb_to_cmd(req, struct io_bind);
+ struct io_async_msghdr *io = req->async_data;
+ struct socket *sock;
+ int ret;
+
+ sock = sock_from_file(req->file);
+ if (unlikely(!sock))
+ return -ENOTSOCK;
+
+ ret = __sys_bind_socket(sock, &io->addr, bind->addr_len);
+ if (ret < 0)
+ req_set_fail(req);
+ io_req_set_res(req, ret, 0);
+ return 0;
+}
+
+int io_listen_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+ struct io_listen *listen = io_kiocb_to_cmd(req, struct io_listen);
+
+ if (sqe->addr || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in || sqe->addr2)
+ return -EINVAL;
+
+ listen->backlog = READ_ONCE(sqe->len);
+ return 0;
+}
+
+int io_listen(struct io_kiocb *req, unsigned int issue_flags)
+{
+ struct io_listen *listen = io_kiocb_to_cmd(req, struct io_listen);
+ struct socket *sock;
+ int ret;
+
+ sock = sock_from_file(req->file);
+ if (unlikely(!sock))
+ return -ENOTSOCK;
+
+ ret = __sys_listen_socket(sock, listen->backlog);
+ if (ret < 0)
+ req_set_fail(req);
+ io_req_set_res(req, ret, 0);
+ return 0;
+}
+
void io_netmsg_cache_free(const void *entry)
{
struct io_async_msghdr *kmsg = (struct io_async_msghdr *) entry;
diff --git a/io_uring/net.h b/io_uring/net.h
index 0eb1c1920fc9..52bfee05f06a 100644
--- a/io_uring/net.h
+++ b/io_uring/net.h
@@ -49,6 +49,12 @@ int io_sendmsg_zc(struct io_kiocb *req, unsigned int issue_flags);
int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
void io_send_zc_cleanup(struct io_kiocb *req);
+int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_bind(struct io_kiocb *req, unsigned int issue_flags);
+
+int io_listen_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_listen(struct io_kiocb *req, unsigned int issue_flags);
+
void io_netmsg_cache_free(const void *entry);
#else
static inline void io_netmsg_cache_free(const void *entry)
diff --git a/io_uring/opdef.c b/io_uring/opdef.c
index 2e3b7b16effb..a2be3bbca5ff 100644
--- a/io_uring/opdef.c
+++ b/io_uring/opdef.c
@@ -495,6 +495,26 @@ const struct io_issue_def io_issue_defs[] = {
.prep = io_ftruncate_prep,
.issue = io_ftruncate,
},
+ [IORING_OP_BIND] = {
+#if defined(CONFIG_NET)
+ .needs_file = 1,
+ .prep = io_bind_prep,
+ .issue = io_bind,
+ .async_size = sizeof(struct io_async_msghdr),
+#else
+ .prep = io_eopnotsupp_prep,
+#endif
+ },
+ [IORING_OP_LISTEN] = {
+#if defined(CONFIG_NET)
+ .needs_file = 1,
+ .prep = io_listen_prep,
+ .issue = io_listen,
+ .async_size = sizeof(struct io_async_msghdr),
+#else
+ .prep = io_eopnotsupp_prep,
+#endif
+ },
};
const struct io_cold_def io_cold_defs[] = {
@@ -716,6 +736,12 @@ const struct io_cold_def io_cold_defs[] = {
[IORING_OP_FTRUNCATE] = {
.name = "FTRUNCATE",
},
+ [IORING_OP_BIND] = {
+ .name = "BIND",
+ },
+ [IORING_OP_LISTEN] = {
+ .name = "LISTEN",
+ },
};
const char *io_uring_get_opcode(u8 opcode)
@@ -725,6 +751,14 @@ const char *io_uring_get_opcode(u8 opcode)
return "INVALID";
}
+bool io_uring_op_supported(u8 opcode)
+{
+ if (opcode < IORING_OP_LAST &&
+ io_issue_defs[opcode].prep != io_eopnotsupp_prep)
+ return true;
+ return false;
+}
+
void __init io_uring_optable_init(void)
{
int i;
diff --git a/io_uring/opdef.h b/io_uring/opdef.h
index 7ee6f5aa90aa..14456436ff74 100644
--- a/io_uring/opdef.h
+++ b/io_uring/opdef.h
@@ -17,8 +17,6 @@ struct io_issue_def {
unsigned poll_exclusive : 1;
/* op supports buffer selection */
unsigned buffer_select : 1;
- /* opcode is not supported by this kernel */
- unsigned not_supported : 1;
/* skip auditing */
unsigned audit_skip : 1;
/* supports ioprio */
@@ -47,5 +45,7 @@ struct io_cold_def {
extern const struct io_issue_def io_issue_defs[];
extern const struct io_cold_def io_cold_defs[];
+bool io_uring_op_supported(u8 opcode);
+
void io_uring_optable_init(void);
#endif
diff --git a/io_uring/register.c b/io_uring/register.c
index c0010a66a6f2..e3c20be5a198 100644
--- a/io_uring/register.c
+++ b/io_uring/register.c
@@ -27,65 +27,11 @@
#include "cancel.h"
#include "kbuf.h"
#include "napi.h"
+#include "eventfd.h"
#define IORING_MAX_RESTRICTIONS (IORING_RESTRICTION_LAST + \
IORING_REGISTER_LAST + IORING_OP_LAST)
-static int io_eventfd_register(struct io_ring_ctx *ctx, void __user *arg,
- unsigned int eventfd_async)
-{
- struct io_ev_fd *ev_fd;
- __s32 __user *fds = arg;
- int fd;
-
- ev_fd = rcu_dereference_protected(ctx->io_ev_fd,
- lockdep_is_held(&ctx->uring_lock));
- if (ev_fd)
- return -EBUSY;
-
- if (copy_from_user(&fd, fds, sizeof(*fds)))
- return -EFAULT;
-
- ev_fd = kmalloc(sizeof(*ev_fd), GFP_KERNEL);
- if (!ev_fd)
- return -ENOMEM;
-
- ev_fd->cq_ev_fd = eventfd_ctx_fdget(fd);
- if (IS_ERR(ev_fd->cq_ev_fd)) {
- int ret = PTR_ERR(ev_fd->cq_ev_fd);
- kfree(ev_fd);
- return ret;
- }
-
- spin_lock(&ctx->completion_lock);
- ctx->evfd_last_cq_tail = ctx->cached_cq_tail;
- spin_unlock(&ctx->completion_lock);
-
- ev_fd->eventfd_async = eventfd_async;
- ctx->has_evfd = true;
- rcu_assign_pointer(ctx->io_ev_fd, ev_fd);
- atomic_set(&ev_fd->refs, 1);
- atomic_set(&ev_fd->ops, 0);
- return 0;
-}
-
-int io_eventfd_unregister(struct io_ring_ctx *ctx)
-{
- struct io_ev_fd *ev_fd;
-
- ev_fd = rcu_dereference_protected(ctx->io_ev_fd,
- lockdep_is_held(&ctx->uring_lock));
- if (ev_fd) {
- ctx->has_evfd = false;
- rcu_assign_pointer(ctx->io_ev_fd, NULL);
- if (!atomic_fetch_or(BIT(IO_EVENTFD_OP_FREE_BIT), &ev_fd->ops))
- call_rcu(&ev_fd->rcu, io_eventfd_ops);
- return 0;
- }
-
- return -ENXIO;
-}
-
static __cold int io_probe(struct io_ring_ctx *ctx, void __user *arg,
unsigned nr_args)
{
@@ -93,9 +39,10 @@ static __cold int io_probe(struct io_ring_ctx *ctx, void __user *arg,
size_t size;
int i, ret;
+ if (nr_args > IORING_OP_LAST)
+ nr_args = IORING_OP_LAST;
+
size = struct_size(p, ops, nr_args);
- if (size == SIZE_MAX)
- return -EOVERFLOW;
p = kzalloc(size, GFP_KERNEL);
if (!p)
return -ENOMEM;
@@ -108,12 +55,10 @@ static __cold int io_probe(struct io_ring_ctx *ctx, void __user *arg,
goto out;
p->last_op = IORING_OP_LAST - 1;
- if (nr_args > IORING_OP_LAST)
- nr_args = IORING_OP_LAST;
for (i = 0; i < nr_args; i++) {
p->ops[i].op = i;
- if (!io_issue_defs[i].not_supported)
+ if (io_uring_op_supported(i))
p->ops[i].flags = IO_URING_OP_SUPPORTED;
}
p->ops_len = i;
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 570bfa6a31aa..a860516bf448 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -85,31 +85,6 @@ static int io_account_mem(struct io_ring_ctx *ctx, unsigned long nr_pages)
return 0;
}
-static int io_copy_iov(struct io_ring_ctx *ctx, struct iovec *dst,
- void __user *arg, unsigned index)
-{
- struct iovec __user *src;
-
-#ifdef CONFIG_COMPAT
- if (ctx->compat) {
- struct compat_iovec __user *ciovs;
- struct compat_iovec ciov;
-
- ciovs = (struct compat_iovec __user *) arg;
- if (copy_from_user(&ciov, &ciovs[index], sizeof(ciov)))
- return -EFAULT;
-
- dst->iov_base = u64_to_user_ptr((u64)ciov.iov_base);
- dst->iov_len = ciov.iov_len;
- return 0;
- }
-#endif
- src = (struct iovec __user *) arg;
- if (copy_from_user(dst, &src[index], sizeof(*dst)))
- return -EFAULT;
- return 0;
-}
-
static int io_buffer_validate(struct iovec *iov)
{
unsigned long tmp, acct_len = iov->iov_len + (PAGE_SIZE - 1);
@@ -249,7 +224,7 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
ret = io_run_task_work_sig(ctx);
if (ret < 0) {
- __set_current_state(TASK_RUNNING);
+ finish_wait(&ctx->rsrc_quiesce_wq, &we);
mutex_lock(&ctx->uring_lock);
if (list_empty(&ctx->rsrc_ref_list))
ret = 0;
@@ -257,7 +232,6 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
}
schedule();
- __set_current_state(TASK_RUNNING);
mutex_lock(&ctx->uring_lock);
ret = 0;
} while (!list_empty(&ctx->rsrc_ref_list));
@@ -420,8 +394,9 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
struct io_uring_rsrc_update2 *up,
unsigned int nr_args)
{
+ struct iovec __user *uvec = u64_to_user_ptr(up->data);
u64 __user *tags = u64_to_user_ptr(up->tags);
- struct iovec iov, __user *iovs = u64_to_user_ptr(up->data);
+ struct iovec fast_iov, *iov;
struct page *last_hpage = NULL;
__u32 done;
int i, err;
@@ -435,21 +410,23 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
struct io_mapped_ubuf *imu;
u64 tag = 0;
- err = io_copy_iov(ctx, &iov, iovs, done);
- if (err)
+ iov = iovec_from_user(&uvec[done], 1, 1, &fast_iov, ctx->compat);
+ if (IS_ERR(iov)) {
+ err = PTR_ERR(iov);
break;
+ }
if (tags && copy_from_user(&tag, &tags[done], sizeof(tag))) {
err = -EFAULT;
break;
}
- err = io_buffer_validate(&iov);
+ err = io_buffer_validate(iov);
if (err)
break;
- if (!iov.iov_base && tag) {
+ if (!iov->iov_base && tag) {
err = -EINVAL;
break;
}
- err = io_sqe_buffer_register(ctx, &iov, &imu, &last_hpage);
+ err = io_sqe_buffer_register(ctx, iov, &imu, &last_hpage);
if (err)
break;
@@ -971,8 +948,9 @@ int io_sqe_buffers_register(struct io_ring_ctx *ctx, void __user *arg,
{
struct page *last_hpage = NULL;
struct io_rsrc_data *data;
+ struct iovec fast_iov, *iov = &fast_iov;
+ const struct iovec __user *uvec = (struct iovec * __user) arg;
int i, ret;
- struct iovec iov;
BUILD_BUG_ON(IORING_MAX_REG_BUFFERS >= (1u << 16));
@@ -989,24 +967,27 @@ int io_sqe_buffers_register(struct io_ring_ctx *ctx, void __user *arg,
return ret;
}
+ if (!arg)
+ memset(iov, 0, sizeof(*iov));
+
for (i = 0; i < nr_args; i++, ctx->nr_user_bufs++) {
if (arg) {
- ret = io_copy_iov(ctx, &iov, arg, i);
- if (ret)
+ iov = iovec_from_user(&uvec[i], 1, 1, &fast_iov, ctx->compat);
+ if (IS_ERR(iov)) {
+ ret = PTR_ERR(iov);
break;
- ret = io_buffer_validate(&iov);
+ }
+ ret = io_buffer_validate(iov);
if (ret)
break;
- } else {
- memset(&iov, 0, sizeof(iov));
}
- if (!iov.iov_base && *io_get_tag_slot(data, i)) {
+ if (!iov->iov_base && *io_get_tag_slot(data, i)) {
ret = -EINVAL;
break;
}
- ret = io_sqe_buffer_register(ctx, &iov, &ctx->user_bufs[i],
+ ret = io_sqe_buffer_register(ctx, iov, &ctx->user_bufs[i],
&last_hpage);
if (ret)
break;
diff --git a/io_uring/rw.c b/io_uring/rw.c
index 1a2128459cb4..c004d21e2f12 100644
--- a/io_uring/rw.c
+++ b/io_uring/rw.c
@@ -772,7 +772,7 @@ static bool need_complete_io(struct io_kiocb *req)
S_ISBLK(file_inode(req->file)->i_mode);
}
-static int io_rw_init_file(struct io_kiocb *req, fmode_t mode)
+static int io_rw_init_file(struct io_kiocb *req, fmode_t mode, int rw_type)
{
struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
struct kiocb *kiocb = &rw->kiocb;
@@ -787,7 +787,7 @@ static int io_rw_init_file(struct io_kiocb *req, fmode_t mode)
req->flags |= io_file_get_flags(file);
kiocb->ki_flags = file->f_iocb_flags;
- ret = kiocb_set_rw_flags(kiocb, rw->flags);
+ ret = kiocb_set_rw_flags(kiocb, rw->flags, rw_type);
if (unlikely(ret))
return ret;
kiocb->ki_flags |= IOCB_ALLOC_CACHE;
@@ -832,8 +832,7 @@ static int __io_read(struct io_kiocb *req, unsigned int issue_flags)
if (unlikely(ret < 0))
return ret;
}
-
- ret = io_rw_init_file(req, FMODE_READ);
+ ret = io_rw_init_file(req, FMODE_READ, READ);
if (unlikely(ret))
return ret;
req->cqe.res = iov_iter_count(&io->iter);
@@ -1013,7 +1012,7 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags)
ssize_t ret, ret2;
loff_t *ppos;
- ret = io_rw_init_file(req, FMODE_WRITE);
+ ret = io_rw_init_file(req, FMODE_WRITE, WRITE);
if (unlikely(ret))
return ret;
req->cqe.res = iov_iter_count(&io->iter);
diff --git a/io_uring/statx.c b/io_uring/statx.c
index abb874209caa..f7f9b202eec0 100644
--- a/io_uring/statx.c
+++ b/io_uring/statx.c
@@ -37,8 +37,7 @@ int io_statx_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
sx->flags = READ_ONCE(sqe->statx_flags);
sx->filename = getname_flags(path,
- getname_statx_lookup_flags(sx->flags),
- NULL);
+ getname_statx_lookup_flags(sx->flags));
if (IS_ERR(sx->filename)) {
int ret = PTR_ERR(sx->filename);
diff --git a/io_uring/xattr.c b/io_uring/xattr.c
index 44905b82eea8..6cf41c3bc369 100644
--- a/io_uring/xattr.c
+++ b/io_uring/xattr.c
@@ -96,7 +96,7 @@ int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
- ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
+ ix->filename = getname_flags(path, LOOKUP_FOLLOW);
if (IS_ERR(ix->filename)) {
ret = PTR_ERR(ix->filename);
ix->filename = NULL;
@@ -189,7 +189,7 @@ int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
- ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
+ ix->filename = getname_flags(path, LOOKUP_FOLLOW);
if (IS_ERR(ix->filename)) {
ret = PTR_ERR(ix->filename);
ix->filename = NULL;
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 5eea4dc0509e..a7cbd69efbef 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -903,7 +903,8 @@ static int do_mq_open(const char __user *u_name, int oflag, umode_t mode,
audit_mq_open(oflag, mode, attr);
- if (IS_ERR(name = getname(u_name)))
+ name = getname(u_name);
+ if (IS_ERR(name))
return PTR_ERR(name);
fd = get_unused_fd_flags(O_CLOEXEC);
diff --git a/kernel/bpf/bpf_local_storage.c b/kernel/bpf/bpf_local_storage.c
index 976cb258a0ed..c938dea5ddbf 100644
--- a/kernel/bpf/bpf_local_storage.c
+++ b/kernel/bpf/bpf_local_storage.c
@@ -782,8 +782,8 @@ bpf_local_storage_map_alloc(union bpf_attr *attr,
nbuckets = max_t(u32, 2, nbuckets);
smap->bucket_log = ilog2(nbuckets);
- smap->buckets = bpf_map_kvcalloc(&smap->map, sizeof(*smap->buckets),
- nbuckets, GFP_USER | __GFP_NOWARN);
+ smap->buckets = bpf_map_kvcalloc(&smap->map, nbuckets,
+ sizeof(*smap->buckets), GFP_USER | __GFP_NOWARN);
if (!smap->buckets) {
err = -ENOMEM;
goto free_smap;
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 2a69a9a36c0f..3243c83ef3e3 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -1084,7 +1084,10 @@ struct bpf_async_cb {
struct bpf_prog *prog;
void __rcu *callback_fn;
void *value;
- struct rcu_head rcu;
+ union {
+ struct rcu_head rcu;
+ struct work_struct delete_work;
+ };
u64 flags;
};
@@ -1107,6 +1110,7 @@ struct bpf_async_cb {
struct bpf_hrtimer {
struct bpf_async_cb cb;
struct hrtimer timer;
+ atomic_t cancelling;
};
struct bpf_work {
@@ -1219,6 +1223,21 @@ static void bpf_wq_delete_work(struct work_struct *work)
kfree_rcu(w, cb.rcu);
}
+static void bpf_timer_delete_work(struct work_struct *work)
+{
+ struct bpf_hrtimer *t = container_of(work, struct bpf_hrtimer, cb.delete_work);
+
+ /* Cancel the timer and wait for callback to complete if it was running.
+ * If hrtimer_cancel() can be safely called it's safe to call
+ * kfree_rcu(t) right after for both preallocated and non-preallocated
+ * maps. The async->cb = NULL was already done and no code path can see
+ * address 't' anymore. Timer if armed for existing bpf_hrtimer before
+ * bpf_timer_cancel_and_free will have been cancelled.
+ */
+ hrtimer_cancel(&t->timer);
+ kfree_rcu(t, cb.rcu);
+}
+
static int __bpf_async_init(struct bpf_async_kern *async, struct bpf_map *map, u64 flags,
enum bpf_async_type type)
{
@@ -1262,6 +1281,8 @@ static int __bpf_async_init(struct bpf_async_kern *async, struct bpf_map *map, u
clockid = flags & (MAX_CLOCKS - 1);
t = (struct bpf_hrtimer *)cb;
+ atomic_set(&t->cancelling, 0);
+ INIT_WORK(&t->cb.delete_work, bpf_timer_delete_work);
hrtimer_init(&t->timer, clockid, HRTIMER_MODE_REL_SOFT);
t->timer.function = bpf_timer_cb;
cb->value = (void *)async - map->record->timer_off;
@@ -1440,7 +1461,8 @@ static void drop_prog_refcnt(struct bpf_async_cb *async)
BPF_CALL_1(bpf_timer_cancel, struct bpf_async_kern *, timer)
{
- struct bpf_hrtimer *t;
+ struct bpf_hrtimer *t, *cur_t;
+ bool inc = false;
int ret = 0;
if (in_nmi())
@@ -1452,14 +1474,41 @@ BPF_CALL_1(bpf_timer_cancel, struct bpf_async_kern *, timer)
ret = -EINVAL;
goto out;
}
- if (this_cpu_read(hrtimer_running) == t) {
+
+ cur_t = this_cpu_read(hrtimer_running);
+ if (cur_t == t) {
/* If bpf callback_fn is trying to bpf_timer_cancel()
* its own timer the hrtimer_cancel() will deadlock
- * since it waits for callback_fn to finish
+ * since it waits for callback_fn to finish.
*/
ret = -EDEADLK;
goto out;
}
+
+ /* Only account in-flight cancellations when invoked from a timer
+ * callback, since we want to avoid waiting only if other _callbacks_
+ * are waiting on us, to avoid introducing lockups. Non-callback paths
+ * are ok, since nobody would synchronously wait for their completion.
+ */
+ if (!cur_t)
+ goto drop;
+ atomic_inc(&t->cancelling);
+ /* Need full barrier after relaxed atomic_inc */
+ smp_mb__after_atomic();
+ inc = true;
+ if (atomic_read(&cur_t->cancelling)) {
+ /* We're cancelling timer t, while some other timer callback is
+ * attempting to cancel us. In such a case, it might be possible
+ * that timer t belongs to the other callback, or some other
+ * callback waiting upon it (creating transitive dependencies
+ * upon us), and we will enter a deadlock if we continue
+ * cancelling and waiting for it synchronously, since it might
+ * do the same. Bail!
+ */
+ ret = -EDEADLK;
+ goto out;
+ }
+drop:
drop_prog_refcnt(&t->cb);
out:
__bpf_spin_unlock_irqrestore(&timer->lock);
@@ -1467,6 +1516,8 @@ out:
* if it was running.
*/
ret = ret ?: hrtimer_cancel(&t->timer);
+ if (inc)
+ atomic_dec(&t->cancelling);
rcu_read_unlock();
return ret;
}
@@ -1512,25 +1563,39 @@ void bpf_timer_cancel_and_free(void *val)
if (!t)
return;
- /* Cancel the timer and wait for callback to complete if it was running.
- * If hrtimer_cancel() can be safely called it's safe to call kfree(t)
- * right after for both preallocated and non-preallocated maps.
- * The async->cb = NULL was already done and no code path can
- * see address 't' anymore.
- *
- * Check that bpf_map_delete/update_elem() wasn't called from timer
- * callback_fn. In such case don't call hrtimer_cancel() (since it will
- * deadlock) and don't call hrtimer_try_to_cancel() (since it will just
- * return -1). Though callback_fn is still running on this cpu it's
+ /* We check that bpf_map_delete/update_elem() was called from timer
+ * callback_fn. In such case we don't call hrtimer_cancel() (since it
+ * will deadlock) and don't call hrtimer_try_to_cancel() (since it will
+ * just return -1). Though callback_fn is still running on this cpu it's
* safe to do kfree(t) because bpf_timer_cb() read everything it needed
* from 't'. The bpf subprog callback_fn won't be able to access 't',
* since async->cb = NULL was already done. The timer will be
* effectively cancelled because bpf_timer_cb() will return
* HRTIMER_NORESTART.
+ *
+ * However, it is possible the timer callback_fn calling us armed the
+ * timer _before_ calling us, such that failing to cancel it here will
+ * cause it to possibly use struct hrtimer after freeing bpf_hrtimer.
+ * Therefore, we _need_ to cancel any outstanding timers before we do
+ * kfree_rcu, even though no more timers can be armed.
+ *
+ * Moreover, we need to schedule work even if timer does not belong to
+ * the calling callback_fn, as on two different CPUs, we can end up in a
+ * situation where both sides run in parallel, try to cancel one
+ * another, and we end up waiting on both sides in hrtimer_cancel
+ * without making forward progress, since timer1 depends on time2
+ * callback to finish, and vice versa.
+ *
+ * CPU 1 (timer1_cb) CPU 2 (timer2_cb)
+ * bpf_timer_cancel_and_free(timer2) bpf_timer_cancel_and_free(timer1)
+ *
+ * To avoid these issues, punt to workqueue context when we are in a
+ * timer callback.
*/
- if (this_cpu_read(hrtimer_running) != t)
- hrtimer_cancel(&t->timer);
- kfree_rcu(t, cb.rcu);
+ if (this_cpu_read(hrtimer_running))
+ queue_work(system_unbound_wq, &t->cb.delete_work);
+ else
+ bpf_timer_delete_work(&t->cb.delete_work);
}
/* This function is called by map_delete/update_elem for individual element and
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index e32b6972c478..c8e4b62b436a 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1744,8 +1744,11 @@ static int css_populate_dir(struct cgroup_subsys_state *css)
if (cgroup_psi_enabled()) {
ret = cgroup_addrm_files(css, cgrp,
cgroup_psi_files, true);
- if (ret < 0)
+ if (ret < 0) {
+ cgroup_addrm_files(css, cgrp,
+ cgroup_base_files, false);
return ret;
+ }
}
} else {
ret = cgroup_addrm_files(css, cgrp,
@@ -1839,9 +1842,9 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
RCU_INIT_POINTER(scgrp->subsys[ssid], NULL);
rcu_assign_pointer(dcgrp->subsys[ssid], css);
ss->root = dst_root;
- css->cgroup = dcgrp;
spin_lock_irq(&css_set_lock);
+ css->cgroup = dcgrp;
WARN_ON(!list_empty(&dcgrp->e_csets[ss->id]));
list_for_each_entry_safe(cset, cset_pos, &scgrp->e_csets[ss->id],
e_cset_node[ss->id]) {
@@ -1922,6 +1925,7 @@ enum cgroup2_param {
Opt_memory_localevents,
Opt_memory_recursiveprot,
Opt_memory_hugetlb_accounting,
+ Opt_pids_localevents,
nr__cgroup2_params
};
@@ -1931,6 +1935,7 @@ static const struct fs_parameter_spec cgroup2_fs_parameters[] = {
fsparam_flag("memory_localevents", Opt_memory_localevents),
fsparam_flag("memory_recursiveprot", Opt_memory_recursiveprot),
fsparam_flag("memory_hugetlb_accounting", Opt_memory_hugetlb_accounting),
+ fsparam_flag("pids_localevents", Opt_pids_localevents),
{}
};
@@ -1960,6 +1965,9 @@ static int cgroup2_parse_param(struct fs_context *fc, struct fs_parameter *param
case Opt_memory_hugetlb_accounting:
ctx->flags |= CGRP_ROOT_MEMORY_HUGETLB_ACCOUNTING;
return 0;
+ case Opt_pids_localevents:
+ ctx->flags |= CGRP_ROOT_PIDS_LOCAL_EVENTS;
+ return 0;
}
return -EINVAL;
}
@@ -1989,6 +1997,11 @@ static void apply_cgroup_root_flags(unsigned int root_flags)
cgrp_dfl_root.flags |= CGRP_ROOT_MEMORY_HUGETLB_ACCOUNTING;
else
cgrp_dfl_root.flags &= ~CGRP_ROOT_MEMORY_HUGETLB_ACCOUNTING;
+
+ if (root_flags & CGRP_ROOT_PIDS_LOCAL_EVENTS)
+ cgrp_dfl_root.flags |= CGRP_ROOT_PIDS_LOCAL_EVENTS;
+ else
+ cgrp_dfl_root.flags &= ~CGRP_ROOT_PIDS_LOCAL_EVENTS;
}
}
@@ -2004,6 +2017,8 @@ static int cgroup_show_options(struct seq_file *seq, struct kernfs_root *kf_root
seq_puts(seq, ",memory_recursiveprot");
if (cgrp_dfl_root.flags & CGRP_ROOT_MEMORY_HUGETLB_ACCOUNTING)
seq_puts(seq, ",memory_hugetlb_accounting");
+ if (cgrp_dfl_root.flags & CGRP_ROOT_PIDS_LOCAL_EVENTS)
+ seq_puts(seq, ",pids_localevents");
return 0;
}
@@ -6686,8 +6701,10 @@ void cgroup_exit(struct task_struct *tsk)
WARN_ON_ONCE(list_empty(&tsk->cg_list));
cset = task_css_set(tsk);
css_set_move_task(tsk, cset, NULL, false);
- list_add_tail(&tsk->cg_list, &cset->dying_tasks);
cset->nr_tasks--;
+ /* matches the signal->live check in css_task_iter_advance() */
+ if (thread_group_leader(tsk) && atomic_read(&tsk->signal->live))
+ list_add_tail(&tsk->cg_list, &cset->dying_tasks);
if (dl_task(tsk))
dec_dl_tasks_cs(tsk);
@@ -6714,10 +6731,12 @@ void cgroup_release(struct task_struct *task)
ss->release(task);
} while_each_subsys_mask();
- spin_lock_irq(&css_set_lock);
- css_set_skip_task_iters(task_css_set(task), task);
- list_del_init(&task->cg_list);
- spin_unlock_irq(&css_set_lock);
+ if (!list_empty(&task->cg_list)) {
+ spin_lock_irq(&css_set_lock);
+ css_set_skip_task_iters(task_css_set(task), task);
+ list_del_init(&task->cg_list);
+ spin_unlock_irq(&css_set_lock);
+ }
}
void cgroup_free(struct task_struct *task)
@@ -7062,7 +7081,8 @@ static ssize_t features_show(struct kobject *kobj, struct kobj_attribute *attr,
"favordynmods\n"
"memory_localevents\n"
"memory_recursiveprot\n"
- "memory_hugetlb_accounting\n");
+ "memory_hugetlb_accounting\n"
+ "pids_localevents\n");
}
static struct kobj_attribute cgroup_features_attr = __ATTR_RO(features);
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index c12b9fdb22a4..40ec4abaf440 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -21,6 +21,7 @@
* License. See the file COPYING in the main directory of the Linux
* distribution for more details.
*/
+#include "cgroup-internal.h"
#include <linux/cpu.h>
#include <linux/cpumask.h>
@@ -87,7 +88,7 @@ static const char * const perr_strings[] = {
[PERR_NOTEXCL] = "Cpu list in cpuset.cpus not exclusive",
[PERR_NOCPUS] = "Parent unable to distribute cpu downstream",
[PERR_HOTPLUG] = "No cpu available due to hotplug",
- [PERR_CPUSEMPTY] = "cpuset.cpus is empty",
+ [PERR_CPUSEMPTY] = "cpuset.cpus and cpuset.cpus.exclusive are empty",
[PERR_HKEEPING] = "partition config conflicts with housekeeping setup",
};
@@ -127,19 +128,28 @@ struct cpuset {
/*
* Exclusive CPUs dedicated to current cgroup (default hierarchy only)
*
- * This exclusive CPUs must be a subset of cpus_allowed. A parent
- * cgroup can only grant exclusive CPUs to one of its children.
+ * The effective_cpus of a valid partition root comes solely from its
+ * effective_xcpus and some of the effective_xcpus may be distributed
+ * to sub-partitions below & hence excluded from its effective_cpus.
+ * For a valid partition root, its effective_cpus have no relationship
+ * with cpus_allowed unless its exclusive_cpus isn't set.
*
- * When the cgroup becomes a valid partition root, effective_xcpus
- * defaults to cpus_allowed if not set. The effective_cpus of a valid
- * partition root comes solely from its effective_xcpus and some of the
- * effective_xcpus may be distributed to sub-partitions below & hence
- * excluded from its effective_cpus.
+ * This value will only be set if either exclusive_cpus is set or
+ * when this cpuset becomes a local partition root.
*/
cpumask_var_t effective_xcpus;
/*
* Exclusive CPUs as requested by the user (default hierarchy only)
+ *
+ * Its value is independent of cpus_allowed and designates the set of
+ * CPUs that can be granted to the current cpuset or its children when
+ * it becomes a valid partition root. The effective set of exclusive
+ * CPUs granted (effective_xcpus) depends on whether those exclusive
+ * CPUs are passed down by its ancestors and not yet taken up by
+ * another sibling partition root along the way.
+ *
+ * If its value isn't set, it defaults to cpus_allowed.
*/
cpumask_var_t exclusive_cpus;
@@ -169,7 +179,7 @@ struct cpuset {
/* for custom sched domain */
int relax_domain_level;
- /* number of valid sub-partitions */
+ /* number of valid local child partitions */
int nr_subparts;
/* partition root state */
@@ -230,6 +240,17 @@ static struct list_head remote_children;
* 2 - partition root without load balancing (isolated)
* -1 - invalid partition root
* -2 - invalid isolated partition root
+ *
+ * There are 2 types of partitions - local or remote. Local partitions are
+ * those whose parents are partition root themselves. Setting of
+ * cpuset.cpus.exclusive are optional in setting up local partitions.
+ * Remote partitions are those whose parents are not partition roots. Passing
+ * down exclusive CPUs by setting cpuset.cpus.exclusive along its ancestor
+ * nodes are mandatory in creating a remote partition.
+ *
+ * For simplicity, a local partition can be created under a local or remote
+ * partition but a remote partition cannot have any partition root in its
+ * ancestor chain except the cgroup root.
*/
#define PRS_MEMBER 0
#define PRS_ROOT 1
@@ -434,7 +455,7 @@ static struct cpuset top_cpuset = {
* by other task, we use alloc_lock in the task_struct fields to protect
* them.
*
- * The cpuset_common_file_read() handlers only hold callback_lock across
+ * The cpuset_common_seq_show() handlers only hold callback_lock across
* small pieces of code, such as when reading out possibly multi-word
* cpumasks and nodemasks.
*
@@ -709,6 +730,19 @@ static inline void free_cpuset(struct cpuset *cs)
kfree(cs);
}
+/* Return user specified exclusive CPUs */
+static inline struct cpumask *user_xcpus(struct cpuset *cs)
+{
+ return cpumask_empty(cs->exclusive_cpus) ? cs->cpus_allowed
+ : cs->exclusive_cpus;
+}
+
+static inline bool xcpus_empty(struct cpuset *cs)
+{
+ return cpumask_empty(cs->cpus_allowed) &&
+ cpumask_empty(cs->exclusive_cpus);
+}
+
static inline struct cpumask *fetch_xcpus(struct cpuset *cs)
{
return !cpumask_empty(cs->exclusive_cpus) ? cs->exclusive_cpus :
@@ -825,17 +859,41 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
/*
* If either I or some sibling (!= me) is exclusive, we can't
- * overlap
+ * overlap. exclusive_cpus cannot overlap with each other if set.
*/
ret = -EINVAL;
cpuset_for_each_child(c, css, par) {
- if ((is_cpu_exclusive(trial) || is_cpu_exclusive(c)) &&
- c != cur) {
+ bool txset, cxset; /* Are exclusive_cpus set? */
+
+ if (c == cur)
+ continue;
+
+ txset = !cpumask_empty(trial->exclusive_cpus);
+ cxset = !cpumask_empty(c->exclusive_cpus);
+ if (is_cpu_exclusive(trial) || is_cpu_exclusive(c) ||
+ (txset && cxset)) {
if (!cpusets_are_exclusive(trial, c))
goto out;
+ } else if (txset || cxset) {
+ struct cpumask *xcpus, *acpus;
+
+ /*
+ * When just one of the exclusive_cpus's is set,
+ * cpus_allowed of the other cpuset, if set, cannot be
+ * a subset of it or none of those CPUs will be
+ * available if these exclusive CPUs are activated.
+ */
+ if (txset) {
+ xcpus = trial->exclusive_cpus;
+ acpus = c->cpus_allowed;
+ } else {
+ xcpus = c->exclusive_cpus;
+ acpus = trial->cpus_allowed;
+ }
+ if (!cpumask_empty(acpus) && cpumask_subset(acpus, xcpus))
+ goto out;
}
if ((is_mem_exclusive(trial) || is_mem_exclusive(c)) &&
- c != cur &&
nodes_intersects(trial->mems_allowed, c->mems_allowed))
goto out;
}
@@ -957,13 +1015,15 @@ static int generate_sched_domains(cpumask_var_t **domains,
int nslot; /* next empty doms[] struct cpumask slot */
struct cgroup_subsys_state *pos_css;
bool root_load_balance = is_sched_load_balance(&top_cpuset);
+ bool cgrpv2 = cgroup_subsys_on_dfl(cpuset_cgrp_subsys);
doms = NULL;
dattr = NULL;
csa = NULL;
/* Special case for the 99% of systems with one, full, sched domain */
- if (root_load_balance && !top_cpuset.nr_subparts) {
+ if (root_load_balance && cpumask_empty(subpartitions_cpus)) {
+single_root_domain:
ndoms = 1;
doms = alloc_sched_domains(ndoms);
if (!doms)
@@ -991,16 +1051,18 @@ static int generate_sched_domains(cpumask_var_t **domains,
cpuset_for_each_descendant_pre(cp, pos_css, &top_cpuset) {
if (cp == &top_cpuset)
continue;
+
+ if (cgrpv2)
+ goto v2;
+
/*
+ * v1:
* Continue traversing beyond @cp iff @cp has some CPUs and
* isn't load balancing. The former is obvious. The
* latter: All child cpusets contain a subset of the
* parent's cpus, so just skip them, and then we call
* update_domain_attr_tree() to calc relax_domain_level of
* the corresponding sched domain.
- *
- * If root is load-balancing, we can skip @cp if it
- * is a subset of the root's effective_cpus.
*/
if (!cpumask_empty(cp->cpus_allowed) &&
!(is_sched_load_balance(cp) &&
@@ -1008,20 +1070,39 @@ static int generate_sched_domains(cpumask_var_t **domains,
housekeeping_cpumask(HK_TYPE_DOMAIN))))
continue;
- if (root_load_balance &&
- cpumask_subset(cp->cpus_allowed, top_cpuset.effective_cpus))
- continue;
-
if (is_sched_load_balance(cp) &&
!cpumask_empty(cp->effective_cpus))
csa[csn++] = cp;
- /* skip @cp's subtree if not a partition root */
- if (!is_partition_valid(cp))
+ /* skip @cp's subtree */
+ pos_css = css_rightmost_descendant(pos_css);
+ continue;
+
+v2:
+ /*
+ * Only valid partition roots that are not isolated and with
+ * non-empty effective_cpus will be saved into csn[].
+ */
+ if ((cp->partition_root_state == PRS_ROOT) &&
+ !cpumask_empty(cp->effective_cpus))
+ csa[csn++] = cp;
+
+ /*
+ * Skip @cp's subtree if not a partition root and has no
+ * exclusive CPUs to be granted to child cpusets.
+ */
+ if (!is_partition_valid(cp) && cpumask_empty(cp->exclusive_cpus))
pos_css = css_rightmost_descendant(pos_css);
}
rcu_read_unlock();
+ /*
+ * If there are only isolated partitions underneath the cgroup root,
+ * we can optimize out unneeded sched domains scanning.
+ */
+ if (root_load_balance && (csn == 1))
+ goto single_root_domain;
+
for (i = 0; i < csn; i++)
csa[i]->pn = i;
ndoms = csn;
@@ -1064,6 +1145,20 @@ restart:
dattr = kmalloc_array(ndoms, sizeof(struct sched_domain_attr),
GFP_KERNEL);
+ /*
+ * Cgroup v2 doesn't support domain attributes, just set all of them
+ * to SD_ATTR_INIT. Also non-isolating partition root CPUs are a
+ * subset of HK_TYPE_DOMAIN housekeeping CPUs.
+ */
+ if (cgrpv2) {
+ for (i = 0; i < ndoms; i++) {
+ cpumask_copy(doms[i], csa[i]->effective_cpus);
+ if (dattr)
+ dattr[i] = SD_ATTR_INIT;
+ }
+ goto done;
+ }
+
for (nslot = 0, i = 0; i < csn; i++) {
struct cpuset *a = csa[i];
struct cpumask *dp;
@@ -1223,7 +1318,7 @@ static void rebuild_sched_domains_locked(void)
* root should be only a subset of the active CPUs. Since a CPU in any
* partition root could be offlined, all must be checked.
*/
- if (top_cpuset.nr_subparts) {
+ if (!cpumask_empty(subpartitions_cpus)) {
rcu_read_lock();
cpuset_for_each_descendant_pre(cs, pos_css, &top_cpuset) {
if (!is_partition_valid(cs)) {
@@ -1338,7 +1433,7 @@ static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs,
*/
static int update_partition_exclusive(struct cpuset *cs, int new_prs)
{
- bool exclusive = (new_prs > 0);
+ bool exclusive = (new_prs > PRS_MEMBER);
if (exclusive && !is_cpu_exclusive(cs)) {
if (update_flag(CS_CPU_EXCLUSIVE, cs, 1))
@@ -1532,7 +1627,7 @@ EXPORT_SYMBOL_GPL(cpuset_cpu_is_isolated);
* Return: true if xcpus is not empty, false otherwise.
*
* Starting with exclusive_cpus (cpus_allowed if exclusive_cpus is not set),
- * it must be a subset of cpus_allowed and parent's effective_xcpus.
+ * it must be a subset of parent's effective_xcpus.
*/
static bool compute_effective_exclusive_cpumask(struct cpuset *cs,
struct cpumask *xcpus)
@@ -1542,12 +1637,7 @@ static bool compute_effective_exclusive_cpumask(struct cpuset *cs,
if (!xcpus)
xcpus = cs->effective_xcpus;
- if (!cpumask_empty(cs->exclusive_cpus))
- cpumask_and(xcpus, cs->exclusive_cpus, cs->cpus_allowed);
- else
- cpumask_copy(xcpus, cs->cpus_allowed);
-
- return cpumask_and(xcpus, xcpus, parent->effective_xcpus);
+ return cpumask_and(xcpus, user_xcpus(cs), parent->effective_xcpus);
}
static inline bool is_remote_partition(struct cpuset *cs)
@@ -1826,8 +1916,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
*/
adding = deleting = false;
old_prs = new_prs = cs->partition_root_state;
- xcpus = !cpumask_empty(cs->exclusive_cpus)
- ? cs->effective_xcpus : cs->cpus_allowed;
+ xcpus = user_xcpus(cs);
if (cmd == partcmd_invalidate) {
if (is_prs_invalid(old_prs))
@@ -1855,7 +1944,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
return is_partition_invalid(parent)
? PERR_INVPARENT : PERR_NOTPART;
}
- if (!newmask && cpumask_empty(cs->cpus_allowed))
+ if (!newmask && xcpus_empty(cs))
return PERR_CPUSEMPTY;
nocpu = tasks_nocpu_error(parent, cs, xcpus);
@@ -2583,8 +2672,6 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs,
retval = cpulist_parse(buf, trialcs->exclusive_cpus);
if (retval < 0)
return retval;
- if (!is_cpu_exclusive(cs))
- set_bit(CS_CPU_EXCLUSIVE, &trialcs->flags);
}
/* Nothing to do if the CPUs didn't change */
@@ -3071,9 +3158,9 @@ static int update_prstate(struct cpuset *cs, int new_prs)
? partcmd_enable : partcmd_enablei;
/*
- * cpus_allowed cannot be empty.
+ * cpus_allowed and exclusive_cpus cannot be both empty.
*/
- if (cpumask_empty(cs->cpus_allowed)) {
+ if (xcpus_empty(cs)) {
err = PERR_CPUSEMPTY;
goto out;
}
@@ -4009,8 +4096,6 @@ cpuset_css_alloc(struct cgroup_subsys_state *parent_css)
}
__set_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
- nodes_clear(cs->mems_allowed);
- nodes_clear(cs->effective_mems);
fmeter_init(&cs->fmeter);
cs->relax_domain_level = -1;
INIT_LIST_HEAD(&cs->remote_sibling);
@@ -4040,6 +4125,12 @@ static int cpuset_css_online(struct cgroup_subsys_state *css)
set_bit(CS_SPREAD_PAGE, &cs->flags);
if (is_spread_slab(parent))
set_bit(CS_SPREAD_SLAB, &cs->flags);
+ /*
+ * For v2, clear CS_SCHED_LOAD_BALANCE if parent is isolated
+ */
+ if (cgroup_subsys_on_dfl(cpuset_cgrp_subsys) &&
+ !is_sched_load_balance(parent))
+ clear_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
cpuset_inc();
@@ -4050,14 +4141,6 @@ static int cpuset_css_online(struct cgroup_subsys_state *css)
cs->use_parent_ecpus = true;
parent->child_ecpus_count++;
}
-
- /*
- * For v2, clear CS_SCHED_LOAD_BALANCE if parent is isolated
- */
- if (cgroup_subsys_on_dfl(cpuset_cgrp_subsys) &&
- !is_sched_load_balance(parent))
- clear_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
-
spin_unlock_irq(&callback_lock);
if (!test_bit(CGRP_CPUSET_CLONE_CHILDREN, &css->cgroup->flags))
@@ -4571,7 +4654,7 @@ static void cpuset_handle_hotplug(void)
* In the rare case that hotplug removes all the cpus in
* subpartitions_cpus, we assumed that cpus are updated.
*/
- if (!cpus_updated && top_cpuset.nr_subparts)
+ if (!cpus_updated && !cpumask_empty(subpartitions_cpus))
cpus_updated = true;
/* For v1, synchronize cpus_allowed to cpu_active_mask */
@@ -5051,10 +5134,14 @@ int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns,
if (!buf)
goto out;
- css = task_get_css(tsk, cpuset_cgrp_id);
- retval = cgroup_path_ns(css->cgroup, buf, PATH_MAX,
- current->nsproxy->cgroup_ns);
- css_put(css);
+ rcu_read_lock();
+ spin_lock_irq(&css_set_lock);
+ css = task_css(tsk, cpuset_cgrp_id);
+ retval = cgroup_path_ns_locked(css->cgroup, buf, PATH_MAX,
+ current->nsproxy->cgroup_ns);
+ spin_unlock_irq(&css_set_lock);
+ rcu_read_unlock();
+
if (retval == -E2BIG)
retval = -ENAMETOOLONG;
if (retval < 0)
diff --git a/kernel/cgroup/misc.c b/kernel/cgroup/misc.c
index 79a3717a5803..0e26068995a6 100644
--- a/kernel/cgroup/misc.c
+++ b/kernel/cgroup/misc.c
@@ -121,6 +121,30 @@ static void misc_cg_cancel_charge(enum misc_res_type type, struct misc_cg *cg,
misc_res_name[type]);
}
+static void misc_cg_update_watermark(struct misc_res *res, u64 new_usage)
+{
+ u64 old;
+
+ while (true) {
+ old = atomic64_read(&res->watermark);
+ if (new_usage <= old)
+ break;
+ if (atomic64_cmpxchg(&res->watermark, old, new_usage) == old)
+ break;
+ }
+}
+
+static void misc_cg_event(enum misc_res_type type, struct misc_cg *cg)
+{
+ atomic64_inc(&cg->res[type].events_local);
+ cgroup_file_notify(&cg->events_local_file);
+
+ for (; parent_misc(cg); cg = parent_misc(cg)) {
+ atomic64_inc(&cg->res[type].events);
+ cgroup_file_notify(&cg->events_file);
+ }
+}
+
/**
* misc_cg_try_charge() - Try charging the misc cgroup.
* @type: Misc res type to charge.
@@ -159,14 +183,12 @@ int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, u64 amount)
ret = -EBUSY;
goto err_charge;
}
+ misc_cg_update_watermark(res, new_usage);
}
return 0;
err_charge:
- for (j = i; j; j = parent_misc(j)) {
- atomic64_inc(&j->res[type].events);
- cgroup_file_notify(&j->events_file);
- }
+ misc_cg_event(type, i);
for (j = cg; j != i; j = parent_misc(j))
misc_cg_cancel_charge(type, j, amount);
@@ -308,6 +330,29 @@ static int misc_cg_current_show(struct seq_file *sf, void *v)
}
/**
+ * misc_cg_peak_show() - Show the peak usage of the misc cgroup.
+ * @sf: Interface file
+ * @v: Arguments passed
+ *
+ * Context: Any context.
+ * Return: 0 to denote successful print.
+ */
+static int misc_cg_peak_show(struct seq_file *sf, void *v)
+{
+ int i;
+ u64 watermark;
+ struct misc_cg *cg = css_misc(seq_css(sf));
+
+ for (i = 0; i < MISC_CG_RES_TYPES; i++) {
+ watermark = atomic64_read(&cg->res[i].watermark);
+ if (READ_ONCE(misc_res_capacity[i]) || watermark)
+ seq_printf(sf, "%s %llu\n", misc_res_name[i], watermark);
+ }
+
+ return 0;
+}
+
+/**
* misc_cg_capacity_show() - Show the total capacity of misc res on the host.
* @sf: Interface file
* @v: Arguments passed
@@ -331,20 +376,33 @@ static int misc_cg_capacity_show(struct seq_file *sf, void *v)
return 0;
}
-static int misc_events_show(struct seq_file *sf, void *v)
+static int __misc_events_show(struct seq_file *sf, bool local)
{
struct misc_cg *cg = css_misc(seq_css(sf));
u64 events;
int i;
for (i = 0; i < MISC_CG_RES_TYPES; i++) {
- events = atomic64_read(&cg->res[i].events);
+ if (local)
+ events = atomic64_read(&cg->res[i].events_local);
+ else
+ events = atomic64_read(&cg->res[i].events);
if (READ_ONCE(misc_res_capacity[i]) || events)
seq_printf(sf, "%s.max %llu\n", misc_res_name[i], events);
}
return 0;
}
+static int misc_events_show(struct seq_file *sf, void *v)
+{
+ return __misc_events_show(sf, false);
+}
+
+static int misc_events_local_show(struct seq_file *sf, void *v)
+{
+ return __misc_events_show(sf, true);
+}
+
/* Misc cgroup interface files */
static struct cftype misc_cg_files[] = {
{
@@ -358,6 +416,10 @@ static struct cftype misc_cg_files[] = {
.seq_show = misc_cg_current_show,
},
{
+ .name = "peak",
+ .seq_show = misc_cg_peak_show,
+ },
+ {
.name = "capacity",
.seq_show = misc_cg_capacity_show,
.flags = CFTYPE_ONLY_ON_ROOT,
@@ -368,6 +430,12 @@ static struct cftype misc_cg_files[] = {
.file_offset = offsetof(struct misc_cg, events_file),
.seq_show = misc_events_show,
},
+ {
+ .name = "events.local",
+ .flags = CFTYPE_NOT_ON_ROOT,
+ .file_offset = offsetof(struct misc_cg, events_local_file),
+ .seq_show = misc_events_local_show,
+ },
{}
};
diff --git a/kernel/cgroup/pids.c b/kernel/cgroup/pids.c
index 0e5ec7d59b4d..f5cb0ec45b9d 100644
--- a/kernel/cgroup/pids.c
+++ b/kernel/cgroup/pids.c
@@ -38,6 +38,14 @@
#define PIDS_MAX (PID_MAX_LIMIT + 1ULL)
#define PIDS_MAX_STR "max"
+enum pidcg_event {
+ /* Fork failed in subtree because this pids_cgroup limit was hit. */
+ PIDCG_MAX,
+ /* Fork failed in this pids_cgroup because ancestor limit was hit. */
+ PIDCG_FORKFAIL,
+ NR_PIDCG_EVENTS,
+};
+
struct pids_cgroup {
struct cgroup_subsys_state css;
@@ -49,11 +57,12 @@ struct pids_cgroup {
atomic64_t limit;
int64_t watermark;
- /* Handle for "pids.events" */
+ /* Handles for pids.events[.local] */
struct cgroup_file events_file;
+ struct cgroup_file events_local_file;
- /* Number of times fork failed because limit was hit. */
- atomic64_t events_limit;
+ atomic64_t events[NR_PIDCG_EVENTS];
+ atomic64_t events_local[NR_PIDCG_EVENTS];
};
static struct pids_cgroup *css_pids(struct cgroup_subsys_state *css)
@@ -148,12 +157,13 @@ static void pids_charge(struct pids_cgroup *pids, int num)
* pids_try_charge - hierarchically try to charge the pid count
* @pids: the pid cgroup state
* @num: the number of pids to charge
+ * @fail: storage of pid cgroup causing the fail
*
* This function follows the set limit. It will fail if the charge would cause
* the new value to exceed the hierarchical limit. Returns 0 if the charge
* succeeded, otherwise -EAGAIN.
*/
-static int pids_try_charge(struct pids_cgroup *pids, int num)
+static int pids_try_charge(struct pids_cgroup *pids, int num, struct pids_cgroup **fail)
{
struct pids_cgroup *p, *q;
@@ -166,9 +176,10 @@ static int pids_try_charge(struct pids_cgroup *pids, int num)
* p->limit is %PIDS_MAX then we know that this test will never
* fail.
*/
- if (new > limit)
+ if (new > limit) {
+ *fail = p;
goto revert;
-
+ }
/*
* Not technically accurate if we go over limit somewhere up
* the hierarchy, but that's tolerable for the watermark.
@@ -229,6 +240,36 @@ static void pids_cancel_attach(struct cgroup_taskset *tset)
}
}
+static void pids_event(struct pids_cgroup *pids_forking,
+ struct pids_cgroup *pids_over_limit)
+{
+ struct pids_cgroup *p = pids_forking;
+ bool limit = false;
+
+ /* Only log the first time limit is hit. */
+ if (atomic64_inc_return(&p->events_local[PIDCG_FORKFAIL]) == 1) {
+ pr_info("cgroup: fork rejected by pids controller in ");
+ pr_cont_cgroup_path(p->css.cgroup);
+ pr_cont("\n");
+ }
+ cgroup_file_notify(&p->events_local_file);
+ if (!cgroup_subsys_on_dfl(pids_cgrp_subsys) ||
+ cgrp_dfl_root.flags & CGRP_ROOT_PIDS_LOCAL_EVENTS)
+ return;
+
+ for (; parent_pids(p); p = parent_pids(p)) {
+ if (p == pids_over_limit) {
+ limit = true;
+ atomic64_inc(&p->events_local[PIDCG_MAX]);
+ cgroup_file_notify(&p->events_local_file);
+ }
+ if (limit)
+ atomic64_inc(&p->events[PIDCG_MAX]);
+
+ cgroup_file_notify(&p->events_file);
+ }
+}
+
/*
* task_css_check(true) in pids_can_fork() and pids_cancel_fork() relies
* on cgroup_threadgroup_change_begin() held by the copy_process().
@@ -236,7 +277,7 @@ static void pids_cancel_attach(struct cgroup_taskset *tset)
static int pids_can_fork(struct task_struct *task, struct css_set *cset)
{
struct cgroup_subsys_state *css;
- struct pids_cgroup *pids;
+ struct pids_cgroup *pids, *pids_over_limit;
int err;
if (cset)
@@ -244,16 +285,10 @@ static int pids_can_fork(struct task_struct *task, struct css_set *cset)
else
css = task_css_check(current, pids_cgrp_id, true);
pids = css_pids(css);
- err = pids_try_charge(pids, 1);
- if (err) {
- /* Only log the first time events_limit is incremented. */
- if (atomic64_inc_return(&pids->events_limit) == 1) {
- pr_info("cgroup: fork rejected by pids controller in ");
- pr_cont_cgroup_path(css->cgroup);
- pr_cont("\n");
- }
- cgroup_file_notify(&pids->events_file);
- }
+ err = pids_try_charge(pids, 1, &pids_over_limit);
+ if (err)
+ pids_event(pids, pids_over_limit);
+
return err;
}
@@ -337,11 +372,32 @@ static s64 pids_peak_read(struct cgroup_subsys_state *css,
return READ_ONCE(pids->watermark);
}
-static int pids_events_show(struct seq_file *sf, void *v)
+static int __pids_events_show(struct seq_file *sf, bool local)
{
struct pids_cgroup *pids = css_pids(seq_css(sf));
+ enum pidcg_event pe = PIDCG_MAX;
+ atomic64_t *events;
+
+ if (!cgroup_subsys_on_dfl(pids_cgrp_subsys) ||
+ cgrp_dfl_root.flags & CGRP_ROOT_PIDS_LOCAL_EVENTS) {
+ pe = PIDCG_FORKFAIL;
+ local = true;
+ }
+ events = local ? pids->events_local : pids->events;
+
+ seq_printf(sf, "max %lld\n", (s64)atomic64_read(&events[pe]));
+ return 0;
+}
- seq_printf(sf, "max %lld\n", (s64)atomic64_read(&pids->events_limit));
+static int pids_events_show(struct seq_file *sf, void *v)
+{
+ __pids_events_show(sf, false);
+ return 0;
+}
+
+static int pids_events_local_show(struct seq_file *sf, void *v)
+{
+ __pids_events_show(sf, true);
return 0;
}
@@ -368,9 +424,42 @@ static struct cftype pids_files[] = {
.file_offset = offsetof(struct pids_cgroup, events_file),
.flags = CFTYPE_NOT_ON_ROOT,
},
+ {
+ .name = "events.local",
+ .seq_show = pids_events_local_show,
+ .file_offset = offsetof(struct pids_cgroup, events_local_file),
+ .flags = CFTYPE_NOT_ON_ROOT,
+ },
+ { } /* terminate */
+};
+
+static struct cftype pids_files_legacy[] = {
+ {
+ .name = "max",
+ .write = pids_max_write,
+ .seq_show = pids_max_show,
+ .flags = CFTYPE_NOT_ON_ROOT,
+ },
+ {
+ .name = "current",
+ .read_s64 = pids_current_read,
+ .flags = CFTYPE_NOT_ON_ROOT,
+ },
+ {
+ .name = "peak",
+ .flags = CFTYPE_NOT_ON_ROOT,
+ .read_s64 = pids_peak_read,
+ },
+ {
+ .name = "events",
+ .seq_show = pids_events_show,
+ .file_offset = offsetof(struct pids_cgroup, events_file),
+ .flags = CFTYPE_NOT_ON_ROOT,
+ },
{ } /* terminate */
};
+
struct cgroup_subsys pids_cgrp_subsys = {
.css_alloc = pids_css_alloc,
.css_free = pids_css_free,
@@ -379,7 +468,7 @@ struct cgroup_subsys pids_cgrp_subsys = {
.can_fork = pids_can_fork,
.cancel_fork = pids_cancel_fork,
.release = pids_release,
- .legacy_cftypes = pids_files,
+ .legacy_cftypes = pids_files_legacy,
.dfl_cftypes = pids_files,
.threaded = true,
};
diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c
index fb8b49437573..a06b45272411 100644
--- a/kernel/cgroup/rstat.c
+++ b/kernel/cgroup/rstat.c
@@ -594,49 +594,46 @@ static void root_cgroup_cputime(struct cgroup_base_stat *bstat)
}
}
+
+static void cgroup_force_idle_show(struct seq_file *seq, struct cgroup_base_stat *bstat)
+{
+#ifdef CONFIG_SCHED_CORE
+ u64 forceidle_time = bstat->forceidle_sum;
+
+ do_div(forceidle_time, NSEC_PER_USEC);
+ seq_printf(seq, "core_sched.force_idle_usec %llu\n", forceidle_time);
+#endif
+}
+
void cgroup_base_stat_cputime_show(struct seq_file *seq)
{
struct cgroup *cgrp = seq_css(seq)->cgroup;
u64 usage, utime, stime;
- struct cgroup_base_stat bstat;
-#ifdef CONFIG_SCHED_CORE
- u64 forceidle_time;
-#endif
if (cgroup_parent(cgrp)) {
cgroup_rstat_flush_hold(cgrp);
usage = cgrp->bstat.cputime.sum_exec_runtime;
cputime_adjust(&cgrp->bstat.cputime, &cgrp->prev_cputime,
&utime, &stime);
-#ifdef CONFIG_SCHED_CORE
- forceidle_time = cgrp->bstat.forceidle_sum;
-#endif
cgroup_rstat_flush_release(cgrp);
} else {
- root_cgroup_cputime(&bstat);
- usage = bstat.cputime.sum_exec_runtime;
- utime = bstat.cputime.utime;
- stime = bstat.cputime.stime;
-#ifdef CONFIG_SCHED_CORE
- forceidle_time = bstat.forceidle_sum;
-#endif
+ /* cgrp->bstat of root is not actually used, reuse it */
+ root_cgroup_cputime(&cgrp->bstat);
+ usage = cgrp->bstat.cputime.sum_exec_runtime;
+ utime = cgrp->bstat.cputime.utime;
+ stime = cgrp->bstat.cputime.stime;
}
do_div(usage, NSEC_PER_USEC);
do_div(utime, NSEC_PER_USEC);
do_div(stime, NSEC_PER_USEC);
-#ifdef CONFIG_SCHED_CORE
- do_div(forceidle_time, NSEC_PER_USEC);
-#endif
seq_printf(seq, "usage_usec %llu\n"
"user_usec %llu\n"
"system_usec %llu\n",
usage, utime, stime);
-#ifdef CONFIG_SCHED_CORE
- seq_printf(seq, "core_sched.force_idle_usec %llu\n", forceidle_time);
-#endif
+ cgroup_force_idle_show(seq, &cgrp->bstat);
}
/* Add bpf kfuncs for cgroup_rstat_updated() and cgroup_rstat_flush() */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 3d2bf1d50a0c..1209ddaec026 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -483,6 +483,8 @@ static int cpu_hotplug_disabled;
DEFINE_STATIC_PERCPU_RWSEM(cpu_hotplug_lock);
+static bool cpu_hotplug_offline_disabled __ro_after_init;
+
void cpus_read_lock(void)
{
percpu_down_read(&cpu_hotplug_lock);
@@ -542,6 +544,14 @@ static void lockdep_release_cpus_lock(void)
rwsem_release(&cpu_hotplug_lock.dep_map, _THIS_IP_);
}
+/* Declare CPU offlining not supported */
+void cpu_hotplug_disable_offlining(void)
+{
+ cpu_maps_update_begin();
+ cpu_hotplug_offline_disabled = true;
+ cpu_maps_update_done();
+}
+
/*
* Wait for currently running CPU hotplug operations to complete (if any) and
* disable future CPU hotplug (from sysfs). The 'cpu_add_remove_lock' protects
@@ -1471,7 +1481,7 @@ static int cpu_down_maps_locked(unsigned int cpu, enum cpuhp_state target)
* If the platform does not support hotplug, report it explicitly to
* differentiate it from a transient offlining failure.
*/
- if (cc_platform_has(CC_ATTR_HOTPLUG_DISABLED))
+ if (cpu_hotplug_offline_disabled)
return -EOPNOTSUPP;
if (cpu_hotplug_disabled)
return -EBUSY;
@@ -1894,8 +1904,8 @@ int freeze_secondary_cpus(int primary)
cpumask_clear(frozen_cpus);
pr_info("Disabling non-boot CPUs ...\n");
- for_each_online_cpu(cpu) {
- if (cpu == primary)
+ for (cpu = nr_cpu_ids - 1; cpu >= 0; cpu--) {
+ if (!cpu_online(cpu) || cpu == primary)
continue;
if (pm_wakeup_pending()) {
@@ -3072,6 +3082,9 @@ EXPORT_SYMBOL(__cpu_possible_mask);
struct cpumask __cpu_online_mask __read_mostly;
EXPORT_SYMBOL(__cpu_online_mask);
+struct cpumask __cpu_enabled_mask __read_mostly;
+EXPORT_SYMBOL(__cpu_enabled_mask);
+
struct cpumask __cpu_present_mask __read_mostly;
EXPORT_SYMBOL(__cpu_present_mask);
diff --git a/kernel/exit.c b/kernel/exit.c
index f95a2c1338a8..81fcee45d630 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -484,6 +484,8 @@ retry:
* Search through everything else, we should not get here often.
*/
for_each_process(g) {
+ if (atomic_read(&mm->mm_users) <= 1)
+ break;
if (g->flags & PF_KTHREAD)
continue;
for_each_thread(g, c) {
diff --git a/kernel/fork.c b/kernel/fork.c
index 99076dbe27d8..63a76166497a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -616,12 +616,6 @@ static void dup_mm_exe_file(struct mm_struct *mm, struct mm_struct *oldmm)
exe_file = get_mm_exe_file(oldmm);
RCU_INIT_POINTER(mm->exe_file, exe_file);
- /*
- * We depend on the oldmm having properly denied write access to the
- * exe_file already.
- */
- if (exe_file && deny_write_access(exe_file))
- pr_warn_once("deny_write_access() failed in %s\n", __func__);
}
#ifdef CONFIG_MMU
@@ -1412,20 +1406,11 @@ int set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
*/
old_exe_file = rcu_dereference_raw(mm->exe_file);
- if (new_exe_file) {
- /*
- * We expect the caller (i.e., sys_execve) to already denied
- * write access, so this is unlikely to fail.
- */
- if (unlikely(deny_write_access(new_exe_file)))
- return -EACCES;
+ if (new_exe_file)
get_file(new_exe_file);
- }
rcu_assign_pointer(mm->exe_file, new_exe_file);
- if (old_exe_file) {
- allow_write_access(old_exe_file);
+ if (old_exe_file)
fput(old_exe_file);
- }
return 0;
}
@@ -1464,9 +1449,6 @@ int replace_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
return ret;
}
- ret = deny_write_access(new_exe_file);
- if (ret)
- return -EACCES;
get_file(new_exe_file);
/* set the new file */
@@ -1475,10 +1457,8 @@ int replace_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
rcu_assign_pointer(mm->exe_file, new_exe_file);
mmap_write_unlock(mm);
- if (old_exe_file) {
- allow_write_access(old_exe_file);
+ if (old_exe_file)
fput(old_exe_file);
- }
return 0;
}
@@ -2941,8 +2921,6 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
}
#endif
-#ifdef __ARCH_WANT_SYS_CLONE3
-
noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
struct clone_args __user *uargs,
size_t usize)
@@ -3086,6 +3064,11 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size)
struct kernel_clone_args kargs;
pid_t set_tid[MAX_PID_NS_LEVEL];
+#ifdef __ARCH_BROKEN_SYS_CLONE3
+#warning clone3() entry point is missing, please fix
+ return -ENOSYS;
+#endif
+
kargs.set_tid = set_tid;
err = copy_clone_args_from_user(&kargs, uargs, size);
@@ -3097,7 +3080,6 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size)
return kernel_clone(&kargs);
}
-#endif
void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data)
{
diff --git a/kernel/irq/irq_sim.c b/kernel/irq/irq_sim.c
index 38d6ae651ac7..3d4036db15ac 100644
--- a/kernel/irq/irq_sim.c
+++ b/kernel/irq/irq_sim.c
@@ -17,6 +17,8 @@ struct irq_sim_work_ctx {
unsigned int irq_count;
unsigned long *pending;
struct irq_domain *domain;
+ struct irq_sim_ops ops;
+ void *user_data;
};
struct irq_sim_irq_ctx {
@@ -88,6 +90,31 @@ static int irq_sim_set_irqchip_state(struct irq_data *data,
return 0;
}
+static int irq_sim_request_resources(struct irq_data *data)
+{
+ struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data);
+ struct irq_sim_work_ctx *work_ctx = irq_ctx->work_ctx;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+
+ if (work_ctx->ops.irq_sim_irq_requested)
+ return work_ctx->ops.irq_sim_irq_requested(work_ctx->domain,
+ hwirq,
+ work_ctx->user_data);
+
+ return 0;
+}
+
+static void irq_sim_release_resources(struct irq_data *data)
+{
+ struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data);
+ struct irq_sim_work_ctx *work_ctx = irq_ctx->work_ctx;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+
+ if (work_ctx->ops.irq_sim_irq_released)
+ work_ctx->ops.irq_sim_irq_released(work_ctx->domain, hwirq,
+ work_ctx->user_data);
+}
+
static struct irq_chip irq_sim_irqchip = {
.name = "irq_sim",
.irq_mask = irq_sim_irqmask,
@@ -95,6 +122,8 @@ static struct irq_chip irq_sim_irqchip = {
.irq_set_type = irq_sim_set_type,
.irq_get_irqchip_state = irq_sim_get_irqchip_state,
.irq_set_irqchip_state = irq_sim_set_irqchip_state,
+ .irq_request_resources = irq_sim_request_resources,
+ .irq_release_resources = irq_sim_release_resources,
};
static void irq_sim_handle_irq(struct irq_work *work)
@@ -164,6 +193,15 @@ static const struct irq_domain_ops irq_sim_domain_ops = {
struct irq_domain *irq_domain_create_sim(struct fwnode_handle *fwnode,
unsigned int num_irqs)
{
+ return irq_domain_create_sim_full(fwnode, num_irqs, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(irq_domain_create_sim);
+
+struct irq_domain *irq_domain_create_sim_full(struct fwnode_handle *fwnode,
+ unsigned int num_irqs,
+ const struct irq_sim_ops *ops,
+ void *data)
+{
struct irq_sim_work_ctx *work_ctx __free(kfree) =
kmalloc(sizeof(*work_ctx), GFP_KERNEL);
@@ -183,10 +221,14 @@ struct irq_domain *irq_domain_create_sim(struct fwnode_handle *fwnode,
work_ctx->irq_count = num_irqs;
work_ctx->work = IRQ_WORK_INIT_HARD(irq_sim_handle_irq);
work_ctx->pending = no_free_ptr(pending);
+ work_ctx->user_data = data;
+
+ if (ops)
+ memcpy(&work_ctx->ops, ops, sizeof(*ops));
return no_free_ptr(work_ctx)->domain;
}
-EXPORT_SYMBOL_GPL(irq_domain_create_sim);
+EXPORT_SYMBOL_GPL(irq_domain_create_sim_full);
/**
* irq_domain_remove_sim - Deinitialize the interrupt simulator domain: free
@@ -228,10 +270,22 @@ struct irq_domain *devm_irq_domain_create_sim(struct device *dev,
struct fwnode_handle *fwnode,
unsigned int num_irqs)
{
+ return devm_irq_domain_create_sim_full(dev, fwnode, num_irqs,
+ NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(devm_irq_domain_create_sim);
+
+struct irq_domain *
+devm_irq_domain_create_sim_full(struct device *dev,
+ struct fwnode_handle *fwnode,
+ unsigned int num_irqs,
+ const struct irq_sim_ops *ops,
+ void *data)
+{
struct irq_domain *domain;
int ret;
- domain = irq_domain_create_sim(fwnode, num_irqs);
+ domain = irq_domain_create_sim_full(fwnode, num_irqs, ops, data);
if (IS_ERR(domain))
return domain;
@@ -241,4 +295,4 @@ struct irq_domain *devm_irq_domain_create_sim(struct device *dev,
return domain;
}
-EXPORT_SYMBOL_GPL(devm_irq_domain_create_sim);
+EXPORT_SYMBOL_GPL(devm_irq_domain_create_sim_full);
diff --git a/kernel/kcsan/kcsan_test.c b/kernel/kcsan/kcsan_test.c
index 0c17b4c83e1c..117d9d4d3c3b 100644
--- a/kernel/kcsan/kcsan_test.c
+++ b/kernel/kcsan/kcsan_test.c
@@ -1620,5 +1620,6 @@ static struct kunit_suite kcsan_test_suite = {
kunit_test_suites(&kcsan_test_suite);
+MODULE_DESCRIPTION("KCSAN test suite");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Marco Elver <[email protected]>");
diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
index 415d81e6ce70..de95ec07e477 100644
--- a/kernel/locking/locktorture.c
+++ b/kernel/locking/locktorture.c
@@ -30,6 +30,7 @@
#include <linux/torture.h>
#include <linux/reboot.h>
+MODULE_DESCRIPTION("torture test facility for locking");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <[email protected]>");
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 25f3cf679b35..bdf0087d6442 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -249,24 +249,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
set_current_state(TASK_INTERRUPTIBLE);
if (pid_ns->pid_allocated == init_pids)
break;
- /*
- * Release tasks_rcu_exit_srcu to avoid following deadlock:
- *
- * 1) TASK A unshare(CLONE_NEWPID)
- * 2) TASK A fork() twice -> TASK B (child reaper for new ns)
- * and TASK C
- * 3) TASK B exits, kills TASK C, waits for TASK A to reap it
- * 4) TASK A calls synchronize_rcu_tasks()
- * -> synchronize_srcu(tasks_rcu_exit_srcu)
- * 5) *DEADLOCK*
- *
- * It is considered safe to release tasks_rcu_exit_srcu here
- * because we assume the current task can not be concurrently
- * reaped at this point.
- */
- exit_tasks_rcu_stop();
schedule();
- exit_tasks_rcu_start();
}
__set_current_state(TASK_RUNNING);
diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c
index 8db4fedaaa1e..b53a9e8f5904 100644
--- a/kernel/rcu/rcuscale.c
+++ b/kernel/rcu/rcuscale.c
@@ -42,6 +42,7 @@
#include "rcu.h"
+MODULE_DESCRIPTION("Read-Copy Update module-based scalability-test facility");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <[email protected]>");
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 807fbf6123a7..08bf7c669dd3 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -51,6 +51,7 @@
#include "rcu.h"
+MODULE_DESCRIPTION("Read-Copy Update module-based torture test facility");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <[email protected]> and Josh Triplett <[email protected]>");
@@ -390,6 +391,7 @@ struct rcu_torture_ops {
int extendables;
int slow_gps;
int no_pi_lock;
+ int debug_objects;
const char *name;
};
@@ -577,6 +579,7 @@ static struct rcu_torture_ops rcu_ops = {
.irq_capable = 1,
.can_boost = IS_ENABLED(CONFIG_RCU_BOOST),
.extendables = RCUTORTURE_MAX_EXTEND,
+ .debug_objects = 1,
.name = "rcu"
};
@@ -747,6 +750,7 @@ static struct rcu_torture_ops srcu_ops = {
.cbflood_max = 50000,
.irq_capable = 1,
.no_pi_lock = IS_ENABLED(CONFIG_TINY_SRCU),
+ .debug_objects = 1,
.name = "srcu"
};
@@ -786,6 +790,7 @@ static struct rcu_torture_ops srcud_ops = {
.cbflood_max = 50000,
.irq_capable = 1,
.no_pi_lock = IS_ENABLED(CONFIG_TINY_SRCU),
+ .debug_objects = 1,
.name = "srcud"
};
@@ -2626,7 +2631,7 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp)
spin_lock_irqsave(&rfp->rcu_fwd_lock, flags);
rfcpp = rfp->rcu_fwd_cb_tail;
rfp->rcu_fwd_cb_tail = &rfcp->rfc_next;
- WRITE_ONCE(*rfcpp, rfcp);
+ smp_store_release(rfcpp, rfcp);
WRITE_ONCE(rfp->n_launders_cb, rfp->n_launders_cb + 1);
i = ((jiffies - rfp->rcu_fwd_startat) / (HZ / FWD_CBS_HIST_DIV));
if (i >= ARRAY_SIZE(rfp->n_launders_hist))
@@ -3455,7 +3460,6 @@ rcu_torture_cleanup(void)
cur_ops->gp_slow_unregister(NULL);
}
-#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
static void rcu_torture_leak_cb(struct rcu_head *rhp)
{
}
@@ -3473,7 +3477,6 @@ static void rcu_torture_err_cb(struct rcu_head *rhp)
*/
pr_alert("%s: duplicated callback was invoked.\n", KBUILD_MODNAME);
}
-#endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
/*
* Verify that double-free causes debug-objects to complain, but only
@@ -3482,39 +3485,43 @@ static void rcu_torture_err_cb(struct rcu_head *rhp)
*/
static void rcu_test_debug_objects(void)
{
-#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
struct rcu_head rh1;
struct rcu_head rh2;
+ int idx;
+
+ if (!IS_ENABLED(CONFIG_DEBUG_OBJECTS_RCU_HEAD)) {
+ pr_alert("%s: !CONFIG_DEBUG_OBJECTS_RCU_HEAD, not testing duplicate call_%s()\n",
+ KBUILD_MODNAME, cur_ops->name);
+ return;
+ }
+
+ if (WARN_ON_ONCE(cur_ops->debug_objects &&
+ (!cur_ops->call || !cur_ops->cb_barrier)))
+ return;
+
struct rcu_head *rhp = kmalloc(sizeof(*rhp), GFP_KERNEL);
init_rcu_head_on_stack(&rh1);
init_rcu_head_on_stack(&rh2);
- pr_alert("%s: WARN: Duplicate call_rcu() test starting.\n", KBUILD_MODNAME);
+ pr_alert("%s: WARN: Duplicate call_%s() test starting.\n", KBUILD_MODNAME, cur_ops->name);
/* Try to queue the rh2 pair of callbacks for the same grace period. */
- preempt_disable(); /* Prevent preemption from interrupting test. */
- rcu_read_lock(); /* Make it impossible to finish a grace period. */
- call_rcu_hurry(&rh1, rcu_torture_leak_cb); /* Start grace period. */
- local_irq_disable(); /* Make it harder to start a new grace period. */
- call_rcu_hurry(&rh2, rcu_torture_leak_cb);
- call_rcu_hurry(&rh2, rcu_torture_err_cb); /* Duplicate callback. */
+ idx = cur_ops->readlock(); /* Make it impossible to finish a grace period. */
+ cur_ops->call(&rh1, rcu_torture_leak_cb); /* Start grace period. */
+ cur_ops->call(&rh2, rcu_torture_leak_cb);
+ cur_ops->call(&rh2, rcu_torture_err_cb); /* Duplicate callback. */
if (rhp) {
- call_rcu_hurry(rhp, rcu_torture_leak_cb);
- call_rcu_hurry(rhp, rcu_torture_err_cb); /* Another duplicate callback. */
+ cur_ops->call(rhp, rcu_torture_leak_cb);
+ cur_ops->call(rhp, rcu_torture_err_cb); /* Another duplicate callback. */
}
- local_irq_enable();
- rcu_read_unlock();
- preempt_enable();
+ cur_ops->readunlock(idx);
/* Wait for them all to get done so we can safely return. */
- rcu_barrier();
- pr_alert("%s: WARN: Duplicate call_rcu() test complete.\n", KBUILD_MODNAME);
+ cur_ops->cb_barrier();
+ pr_alert("%s: WARN: Duplicate call_%s() test complete.\n", KBUILD_MODNAME, cur_ops->name);
destroy_rcu_head_on_stack(&rh1);
destroy_rcu_head_on_stack(&rh2);
kfree(rhp);
-#else /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
- pr_alert("%s: !CONFIG_DEBUG_OBJECTS_RCU_HEAD, not testing duplicate call_rcu()\n", KBUILD_MODNAME);
-#endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
}
static void rcutorture_sync(void)
diff --git a/kernel/rcu/refscale.c b/kernel/rcu/refscale.c
index 2c2648a3ad30..f4ea5b1ec068 100644
--- a/kernel/rcu/refscale.c
+++ b/kernel/rcu/refscale.c
@@ -63,6 +63,7 @@ do { \
#define SCALEOUT_ERRSTRING(s, x...) pr_alert("%s" SCALE_FLAG "!!! " s "\n", scale_type, ## x)
+MODULE_DESCRIPTION("Scalability test for object reference mechanisms");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Joel Fernandes (Google) <[email protected]>");
diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c
index 5afd5cf494db..549c03336ee9 100644
--- a/kernel/rcu/srcutiny.c
+++ b/kernel/rcu/srcutiny.c
@@ -277,7 +277,8 @@ bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie)
unsigned long cur_s = READ_ONCE(ssp->srcu_idx);
barrier();
- return ULONG_CMP_GE(cur_s, cookie) || ULONG_CMP_LT(cur_s, cookie - 3);
+ return cookie == SRCU_GET_STATE_COMPLETED ||
+ ULONG_CMP_GE(cur_s, cookie) || ULONG_CMP_LT(cur_s, cookie - 3);
}
EXPORT_SYMBOL_GPL(poll_state_synchronize_srcu);
diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
index bc4b58b0204e..b24db425f16d 100644
--- a/kernel/rcu/srcutree.c
+++ b/kernel/rcu/srcutree.c
@@ -667,7 +667,10 @@ void cleanup_srcu_struct(struct srcu_struct *ssp)
pr_info("%s: Active srcu_struct %p read state: %d gp state: %lu/%lu\n",
__func__, ssp, rcu_seq_state(READ_ONCE(sup->srcu_gp_seq)),
rcu_seq_current(&sup->srcu_gp_seq), sup->srcu_gp_seq_needed);
- return; /* Caller forgot to stop doing call_srcu()? */
+ return; // Caller forgot to stop doing call_srcu()?
+ // Or caller invoked start_poll_synchronize_srcu()
+ // and then cleanup_srcu_struct() before that grace
+ // period ended?
}
kfree(sup->node);
sup->node = NULL;
@@ -845,7 +848,6 @@ static void srcu_gp_end(struct srcu_struct *ssp)
bool cbs;
bool last_lvl;
int cpu;
- unsigned long flags;
unsigned long gpseq;
int idx;
unsigned long mask;
@@ -907,12 +909,12 @@ static void srcu_gp_end(struct srcu_struct *ssp)
if (!(gpseq & counter_wrap_check))
for_each_possible_cpu(cpu) {
sdp = per_cpu_ptr(ssp->sda, cpu);
- spin_lock_irqsave_rcu_node(sdp, flags);
+ spin_lock_irq_rcu_node(sdp);
if (ULONG_CMP_GE(gpseq, sdp->srcu_gp_seq_needed + 100))
sdp->srcu_gp_seq_needed = gpseq;
if (ULONG_CMP_GE(gpseq, sdp->srcu_gp_seq_needed_exp + 100))
sdp->srcu_gp_seq_needed_exp = gpseq;
- spin_unlock_irqrestore_rcu_node(sdp, flags);
+ spin_unlock_irq_rcu_node(sdp);
}
/* Callback initiation done, allow grace periods after next. */
@@ -1540,7 +1542,8 @@ EXPORT_SYMBOL_GPL(start_poll_synchronize_srcu);
*/
bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie)
{
- if (!rcu_seq_done(&ssp->srcu_sup->srcu_gp_seq, cookie))
+ if (cookie != SRCU_GET_STATE_COMPLETED &&
+ !rcu_seq_done(&ssp->srcu_sup->srcu_gp_seq, cookie))
return false;
// Ensure that the end of the SRCU grace period happens before
// any subsequent code that the caller might execute.
diff --git a/kernel/rcu/sync.c b/kernel/rcu/sync.c
index 6c2bd9001adc..da60a9947c00 100644
--- a/kernel/rcu/sync.c
+++ b/kernel/rcu/sync.c
@@ -122,7 +122,7 @@ void rcu_sync_enter(struct rcu_sync *rsp)
* we are called at early boot time but this shouldn't happen.
*/
}
- WRITE_ONCE(rsp->gp_count, rsp->gp_count + 1);
+ rsp->gp_count++;
spin_unlock_irq(&rsp->rss_lock);
if (gp_state == GP_IDLE) {
@@ -151,15 +151,11 @@ void rcu_sync_enter(struct rcu_sync *rsp)
*/
void rcu_sync_exit(struct rcu_sync *rsp)
{
- int gpc;
-
WARN_ON_ONCE(READ_ONCE(rsp->gp_state) == GP_IDLE);
- WARN_ON_ONCE(READ_ONCE(rsp->gp_count) == 0);
spin_lock_irq(&rsp->rss_lock);
- gpc = rsp->gp_count - 1;
- WRITE_ONCE(rsp->gp_count, gpc);
- if (!gpc) {
+ WARN_ON_ONCE(rsp->gp_count == 0);
+ if (!--rsp->gp_count) {
if (rsp->gp_state == GP_PASSED) {
WRITE_ONCE(rsp->gp_state, GP_EXIT);
rcu_sync_call(rsp);
@@ -178,10 +174,10 @@ void rcu_sync_dtor(struct rcu_sync *rsp)
{
int gp_state;
- WARN_ON_ONCE(READ_ONCE(rsp->gp_count));
WARN_ON_ONCE(READ_ONCE(rsp->gp_state) == GP_PASSED);
spin_lock_irq(&rsp->rss_lock);
+ WARN_ON_ONCE(rsp->gp_count);
if (rsp->gp_state == GP_REPLAY)
WRITE_ONCE(rsp->gp_state, GP_EXIT);
gp_state = rsp->gp_state;
diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
index e1bf33018e6d..ba3440a45b6d 100644
--- a/kernel/rcu/tasks.h
+++ b/kernel/rcu/tasks.h
@@ -858,7 +858,7 @@ static void rcu_tasks_wait_gp(struct rcu_tasks *rtp)
// not know to synchronize with this RCU Tasks grace period) have
// completed exiting. The synchronize_rcu() in rcu_tasks_postgp()
// will take care of any tasks stuck in the non-preemptible region
-// of do_exit() following its call to exit_tasks_rcu_stop().
+// of do_exit() following its call to exit_tasks_rcu_finish().
// check_all_holdout_tasks(), repeatedly until holdout list is empty:
// Scans the holdout list, attempting to identify a quiescent state
// for each task on the list. If there is a quiescent state, the
@@ -1220,7 +1220,7 @@ void exit_tasks_rcu_start(void)
* Remove the task from the "yet another list" because do_exit() is now
* non-preemptible, allowing synchronize_rcu() to wait beyond this point.
*/
-void exit_tasks_rcu_stop(void)
+void exit_tasks_rcu_finish(void)
{
unsigned long flags;
struct rcu_tasks_percpu *rtpcp;
@@ -1231,22 +1231,12 @@ void exit_tasks_rcu_stop(void)
raw_spin_lock_irqsave_rcu_node(rtpcp, flags);
list_del_init(&t->rcu_tasks_exit_list);
raw_spin_unlock_irqrestore_rcu_node(rtpcp, flags);
-}
-/*
- * Contribute to protect against tasklist scan blind spot while the
- * task is exiting and may be removed from the tasklist. See
- * corresponding synchronize_srcu() for further details.
- */
-void exit_tasks_rcu_finish(void)
-{
- exit_tasks_rcu_stop();
- exit_tasks_rcu_finish_trace(current);
+ exit_tasks_rcu_finish_trace(t);
}
#else /* #ifdef CONFIG_TASKS_RCU */
void exit_tasks_rcu_start(void) { }
-void exit_tasks_rcu_stop(void) { }
void exit_tasks_rcu_finish(void) { exit_tasks_rcu_finish_trace(current); }
#endif /* #else #ifdef CONFIG_TASKS_RCU */
@@ -1757,6 +1747,16 @@ static void rcu_tasks_trace_pregp_step(struct list_head *hop)
// allow safe access to the hop list.
for_each_online_cpu(cpu) {
rcu_read_lock();
+ // Note that cpu_curr_snapshot() picks up the target
+ // CPU's current task while its runqueue is locked with
+ // an smp_mb__after_spinlock(). This ensures that either
+ // the grace-period kthread will see that task's read-side
+ // critical section or the task will see the updater's pre-GP
+ // accesses. The trailing smp_mb() in cpu_curr_snapshot()
+ // does not currently play a role other than simplify
+ // that function's ordering semantics. If these simplified
+ // ordering semantics continue to be redundant, that smp_mb()
+ // might be removed.
t = cpu_curr_snapshot(cpu);
if (rcu_tasks_trace_pertask_prep(t, true))
trc_add_holdout(t, hop);
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 28c7031711a3..e641cc681901 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -96,6 +96,7 @@ static struct rcu_state rcu_state = {
.ofl_lock = __ARCH_SPIN_LOCK_UNLOCKED,
.srs_cleanup_work = __WORK_INITIALIZER(rcu_state.srs_cleanup_work,
rcu_sr_normal_gp_cleanup_work),
+ .srs_cleanups_pending = ATOMIC_INIT(0),
};
/* Dump rcu_node combining tree at boot to verify correct setup. */
@@ -175,6 +176,9 @@ static int gp_init_delay;
module_param(gp_init_delay, int, 0444);
static int gp_cleanup_delay;
module_param(gp_cleanup_delay, int, 0444);
+static int nohz_full_patience_delay;
+module_param(nohz_full_patience_delay, int, 0444);
+static int nohz_full_patience_delay_jiffies;
// Add delay to rcu_read_unlock() for strict grace periods.
static int rcu_unlock_delay;
@@ -296,16 +300,6 @@ static void rcu_dynticks_eqs_online(void)
}
/*
- * Snapshot the ->dynticks counter with full ordering so as to allow
- * stable comparison of this counter with past and future snapshots.
- */
-static int rcu_dynticks_snap(int cpu)
-{
- smp_mb(); // Fundamental RCU ordering guarantee.
- return ct_dynticks_cpu_acquire(cpu);
-}
-
-/*
* Return true if the snapshot returned from rcu_dynticks_snap()
* indicates that RCU is in an extended quiescent state.
*/
@@ -321,7 +315,15 @@ static bool rcu_dynticks_in_eqs(int snap)
*/
static bool rcu_dynticks_in_eqs_since(struct rcu_data *rdp, int snap)
{
- return snap != rcu_dynticks_snap(rdp->cpu);
+ /*
+ * The first failing snapshot is already ordered against the accesses
+ * performed by the remote CPU after it exits idle.
+ *
+ * The second snapshot therefore only needs to order against accesses
+ * performed by the remote CPU prior to entering idle and therefore can
+ * rely solely on acquire semantics.
+ */
+ return snap != ct_dynticks_cpu_acquire(rdp->cpu);
}
/*
@@ -769,7 +771,18 @@ static void rcu_gpnum_ovf(struct rcu_node *rnp, struct rcu_data *rdp)
*/
static int dyntick_save_progress_counter(struct rcu_data *rdp)
{
- rdp->dynticks_snap = rcu_dynticks_snap(rdp->cpu);
+ /*
+ * Full ordering between remote CPU's post idle accesses and updater's
+ * accesses prior to current GP (and also the started GP sequence number)
+ * is enforced by rcu_seq_start() implicit barrier and even further by
+ * smp_mb__after_unlock_lock() barriers chained all the way throughout the
+ * rnp locking tree since rcu_gp_init() and up to the current leaf rnp
+ * locking.
+ *
+ * Ordering between remote CPU's pre idle accesses and post grace period
+ * updater's accesses is enforced by the below acquire semantic.
+ */
+ rdp->dynticks_snap = ct_dynticks_cpu_acquire(rdp->cpu);
if (rcu_dynticks_in_eqs(rdp->dynticks_snap)) {
trace_rcu_fqs(rcu_state.name, rdp->gp_seq, rdp->cpu, TPS("dti"));
rcu_gpnum_ovf(rdp->mynode, rdp);
@@ -1660,6 +1673,9 @@ static void rcu_sr_normal_gp_cleanup_work(struct work_struct *work)
rcu_sr_put_wait_head(rcu);
}
+
+ /* Order list manipulations with atomic access. */
+ atomic_dec_return_release(&rcu_state.srs_cleanups_pending);
}
/*
@@ -1667,7 +1683,7 @@ static void rcu_sr_normal_gp_cleanup_work(struct work_struct *work)
*/
static void rcu_sr_normal_gp_cleanup(void)
{
- struct llist_node *wait_tail, *next, *rcu;
+ struct llist_node *wait_tail, *next = NULL, *rcu = NULL;
int done = 0;
wait_tail = rcu_state.srs_wait_tail;
@@ -1693,16 +1709,34 @@ static void rcu_sr_normal_gp_cleanup(void)
break;
}
- // concurrent sr_normal_gp_cleanup work might observe this update.
- smp_store_release(&rcu_state.srs_done_tail, wait_tail);
+ /*
+ * Fast path, no more users to process except putting the second last
+ * wait head if no inflight-workers. If there are in-flight workers,
+ * they will remove the last wait head.
+ *
+ * Note that the ACQUIRE orders atomic access with list manipulation.
+ */
+ if (wait_tail->next && wait_tail->next->next == NULL &&
+ rcu_sr_is_wait_head(wait_tail->next) &&
+ !atomic_read_acquire(&rcu_state.srs_cleanups_pending)) {
+ rcu_sr_put_wait_head(wait_tail->next);
+ wait_tail->next = NULL;
+ }
+
+ /* Concurrent sr_normal_gp_cleanup work might observe this update. */
ASSERT_EXCLUSIVE_WRITER(rcu_state.srs_done_tail);
+ smp_store_release(&rcu_state.srs_done_tail, wait_tail);
/*
* We schedule a work in order to perform a final processing
* of outstanding users(if still left) and releasing wait-heads
* added by rcu_sr_normal_gp_init() call.
*/
- queue_work(sync_wq, &rcu_state.srs_cleanup_work);
+ if (wait_tail->next) {
+ atomic_inc(&rcu_state.srs_cleanups_pending);
+ if (!queue_work(sync_wq, &rcu_state.srs_cleanup_work))
+ atomic_dec(&rcu_state.srs_cleanups_pending);
+ }
}
/*
@@ -1810,7 +1844,7 @@ static noinline_for_stack bool rcu_gp_init(void)
WRITE_ONCE(rcu_state.gp_state, RCU_GP_ONOFF);
/* Exclude CPU hotplug operations. */
rcu_for_each_leaf_node(rnp) {
- local_irq_save(flags);
+ local_irq_disable();
arch_spin_lock(&rcu_state.ofl_lock);
raw_spin_lock_rcu_node(rnp);
if (rnp->qsmaskinit == rnp->qsmaskinitnext &&
@@ -1818,7 +1852,7 @@ static noinline_for_stack bool rcu_gp_init(void)
/* Nothing to do on this leaf rcu_node structure. */
raw_spin_unlock_rcu_node(rnp);
arch_spin_unlock(&rcu_state.ofl_lock);
- local_irq_restore(flags);
+ local_irq_enable();
continue;
}
@@ -1855,7 +1889,7 @@ static noinline_for_stack bool rcu_gp_init(void)
raw_spin_unlock_rcu_node(rnp);
arch_spin_unlock(&rcu_state.ofl_lock);
- local_irq_restore(flags);
+ local_irq_enable();
}
rcu_gp_slow(gp_preinit_delay); /* Races with CPU hotplug. */
@@ -4313,11 +4347,15 @@ static int rcu_pending(int user)
return 1;
/* Is this a nohz_full CPU in userspace or idle? (Ignore RCU if so.) */
- if ((user || rcu_is_cpu_rrupt_from_idle()) && rcu_nohz_full_cpu())
+ gp_in_progress = rcu_gp_in_progress();
+ if ((user || rcu_is_cpu_rrupt_from_idle() ||
+ (gp_in_progress &&
+ time_before(jiffies, READ_ONCE(rcu_state.gp_start) +
+ nohz_full_patience_delay_jiffies))) &&
+ rcu_nohz_full_cpu())
return 0;
/* Is the RCU core waiting for a quiescent state from this CPU? */
- gp_in_progress = rcu_gp_in_progress();
if (rdp->core_needs_qs && !rdp->cpu_no_qs.b.norm && gp_in_progress)
return 1;
@@ -4767,7 +4805,7 @@ rcu_boot_init_percpu_data(int cpu)
rdp->grpmask = leaf_node_cpu_bit(rdp->mynode, cpu);
INIT_WORK(&rdp->strict_work, strict_work_handler);
WARN_ON_ONCE(ct->dynticks_nesting != 1);
- WARN_ON_ONCE(rcu_dynticks_in_eqs(rcu_dynticks_snap(cpu)));
+ WARN_ON_ONCE(rcu_dynticks_in_eqs(ct_dynticks_cpu(cpu)));
rdp->barrier_seq_snap = rcu_state.barrier_sequence;
rdp->rcu_ofl_gp_seq = rcu_state.gp_seq;
rdp->rcu_ofl_gp_state = RCU_GP_CLEANED;
@@ -5110,11 +5148,15 @@ void rcutree_migrate_callbacks(int cpu)
struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
bool needwake;
- if (rcu_rdp_is_offloaded(rdp) ||
- rcu_segcblist_empty(&rdp->cblist))
- return; /* No callbacks to migrate. */
+ if (rcu_rdp_is_offloaded(rdp))
+ return;
raw_spin_lock_irqsave(&rcu_state.barrier_lock, flags);
+ if (rcu_segcblist_empty(&rdp->cblist)) {
+ raw_spin_unlock_irqrestore(&rcu_state.barrier_lock, flags);
+ return; /* No callbacks to migrate. */
+ }
+
WARN_ON_ONCE(rcu_rdp_cpu_online(rdp));
rcu_barrier_entrain(rdp);
my_rdp = this_cpu_ptr(&rcu_data);
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index bae7925c497f..fcf2b4aa3441 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -223,7 +223,6 @@ struct rcu_data {
struct swait_queue_head nocb_state_wq; /* For offloading state changes */
struct task_struct *nocb_gp_kthread;
raw_spinlock_t nocb_lock; /* Guard following pair of fields. */
- atomic_t nocb_lock_contended; /* Contention experienced. */
int nocb_defer_wakeup; /* Defer wakeup of nocb_kthread. */
struct timer_list nocb_timer; /* Enforce finite deferral. */
unsigned long nocb_gp_adv_time; /* Last call_rcu() CB adv (jiffies). */
@@ -420,6 +419,7 @@ struct rcu_state {
struct llist_node *srs_done_tail; /* ready for GP users. */
struct sr_wait_node srs_wait_nodes[SR_NORMAL_GP_WAIT_HEAD_MAX];
struct work_struct srs_cleanup_work;
+ atomic_t srs_cleanups_pending; /* srs inflight worker cleanups. */
};
/* Values for rcu_state structure's gp_flags field. */
diff --git a/kernel/rcu/tree_exp.h b/kernel/rcu/tree_exp.h
index 8a1d9c8bd9f7..4acd29d16fdb 100644
--- a/kernel/rcu/tree_exp.h
+++ b/kernel/rcu/tree_exp.h
@@ -265,7 +265,12 @@ static bool sync_exp_work_done(unsigned long s)
{
if (rcu_exp_gp_seq_done(s)) {
trace_rcu_exp_grace_period(rcu_state.name, s, TPS("done"));
- smp_mb(); /* Ensure test happens before caller kfree(). */
+ /*
+ * Order GP completion with preceding accesses. Order also GP
+ * completion with post GP update side accesses. Pairs with
+ * rcu_seq_end().
+ */
+ smp_mb();
return true;
}
return false;
@@ -357,7 +362,21 @@ static void __sync_rcu_exp_select_node_cpus(struct rcu_exp_work *rewp)
!(rnp->qsmaskinitnext & mask)) {
mask_ofl_test |= mask;
} else {
- snap = rcu_dynticks_snap(cpu);
+ /*
+ * Full ordering between remote CPU's post idle accesses
+ * and updater's accesses prior to current GP (and also
+ * the started GP sequence number) is enforced by
+ * rcu_seq_start() implicit barrier, relayed by kworkers
+ * locking and even further by smp_mb__after_unlock_lock()
+ * barriers chained all the way throughout the rnp locking
+ * tree since sync_exp_reset_tree() and up to the current
+ * leaf rnp locking.
+ *
+ * Ordering between remote CPU's pre idle accesses and
+ * post grace period updater's accesses is enforced by the
+ * below acquire semantic.
+ */
+ snap = ct_dynticks_cpu_acquire(cpu);
if (rcu_dynticks_in_eqs(snap))
mask_ofl_test |= mask;
else
@@ -953,7 +972,6 @@ void synchronize_rcu_expedited(void)
rnp = rcu_get_root();
wait_event(rnp->exp_wq[rcu_seq_ctr(s) & 0x3],
sync_exp_work_done(s));
- smp_mb(); /* Work actions happen before return. */
/* Let the next expedited grace period start. */
mutex_unlock(&rcu_state.exp_mutex);
diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h
index 3f85577bddd4..3ce30841119a 100644
--- a/kernel/rcu/tree_nocb.h
+++ b/kernel/rcu/tree_nocb.h
@@ -91,8 +91,7 @@ module_param(nocb_nobypass_lim_per_jiffy, int, 0);
/*
* Acquire the specified rcu_data structure's ->nocb_bypass_lock. If the
- * lock isn't immediately available, increment ->nocb_lock_contended to
- * flag the contention.
+ * lock isn't immediately available, perform minimal sanity check.
*/
static void rcu_nocb_bypass_lock(struct rcu_data *rdp)
__acquires(&rdp->nocb_bypass_lock)
@@ -100,29 +99,12 @@ static void rcu_nocb_bypass_lock(struct rcu_data *rdp)
lockdep_assert_irqs_disabled();
if (raw_spin_trylock(&rdp->nocb_bypass_lock))
return;
- atomic_inc(&rdp->nocb_lock_contended);
+ /*
+ * Contention expected only when local enqueue collide with
+ * remote flush from kthreads.
+ */
WARN_ON_ONCE(smp_processor_id() != rdp->cpu);
- smp_mb__after_atomic(); /* atomic_inc() before lock. */
raw_spin_lock(&rdp->nocb_bypass_lock);
- smp_mb__before_atomic(); /* atomic_dec() after lock. */
- atomic_dec(&rdp->nocb_lock_contended);
-}
-
-/*
- * Spinwait until the specified rcu_data structure's ->nocb_lock is
- * not contended. Please note that this is extremely special-purpose,
- * relying on the fact that at most two kthreads and one CPU contend for
- * this lock, and also that the two kthreads are guaranteed to have frequent
- * grace-period-duration time intervals between successive acquisitions
- * of the lock. This allows us to use an extremely simple throttling
- * mechanism, and further to apply it only to the CPU doing floods of
- * call_rcu() invocations. Don't try this at home!
- */
-static void rcu_nocb_wait_contended(struct rcu_data *rdp)
-{
- WARN_ON_ONCE(smp_processor_id() != rdp->cpu);
- while (WARN_ON_ONCE(atomic_read(&rdp->nocb_lock_contended)))
- cpu_relax();
}
/*
@@ -510,7 +492,6 @@ static bool rcu_nocb_try_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
}
// We need to use the bypass.
- rcu_nocb_wait_contended(rdp);
rcu_nocb_bypass_lock(rdp);
ncbs = rcu_cblist_n_cbs(&rdp->nocb_bypass);
rcu_segcblist_inc_len(&rdp->cblist); /* Must precede enqueue. */
@@ -635,8 +616,7 @@ static void call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *head,
}
}
-static int nocb_gp_toggle_rdp(struct rcu_data *rdp,
- bool *wake_state)
+static int nocb_gp_toggle_rdp(struct rcu_data *rdp)
{
struct rcu_segcblist *cblist = &rdp->cblist;
unsigned long flags;
@@ -650,8 +630,6 @@ static int nocb_gp_toggle_rdp(struct rcu_data *rdp,
* We will handle this rdp until it ever gets de-offloaded.
*/
rcu_segcblist_set_flags(cblist, SEGCBLIST_KTHREAD_GP);
- if (rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_CB))
- *wake_state = true;
ret = 1;
} else if (!rcu_segcblist_test_flags(cblist, SEGCBLIST_OFFLOADED) &&
rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_GP)) {
@@ -660,8 +638,6 @@ static int nocb_gp_toggle_rdp(struct rcu_data *rdp,
* We will ignore this rdp until it ever gets re-offloaded.
*/
rcu_segcblist_clear_flags(cblist, SEGCBLIST_KTHREAD_GP);
- if (!rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_CB))
- *wake_state = true;
ret = 0;
} else {
WARN_ON_ONCE(1);
@@ -877,16 +853,15 @@ static void nocb_gp_wait(struct rcu_data *my_rdp)
}
if (rdp_toggling) {
- bool wake_state = false;
int ret;
- ret = nocb_gp_toggle_rdp(rdp_toggling, &wake_state);
+ ret = nocb_gp_toggle_rdp(rdp_toggling);
if (ret == 1)
list_add_tail(&rdp_toggling->nocb_entry_rdp, &my_rdp->nocb_head_rdp);
else if (ret == 0)
list_del(&rdp_toggling->nocb_entry_rdp);
- if (wake_state)
- swake_up_one(&rdp_toggling->nocb_state_wq);
+
+ swake_up_one(&rdp_toggling->nocb_state_wq);
}
my_rdp->nocb_gp_seq = -1;
@@ -913,16 +888,9 @@ static int rcu_nocb_gp_kthread(void *arg)
return 0;
}
-static inline bool nocb_cb_can_run(struct rcu_data *rdp)
-{
- u8 flags = SEGCBLIST_OFFLOADED | SEGCBLIST_KTHREAD_CB;
-
- return rcu_segcblist_test_flags(&rdp->cblist, flags);
-}
-
static inline bool nocb_cb_wait_cond(struct rcu_data *rdp)
{
- return nocb_cb_can_run(rdp) && !READ_ONCE(rdp->nocb_cb_sleep);
+ return !READ_ONCE(rdp->nocb_cb_sleep) || kthread_should_park();
}
/*
@@ -934,21 +902,19 @@ static void nocb_cb_wait(struct rcu_data *rdp)
struct rcu_segcblist *cblist = &rdp->cblist;
unsigned long cur_gp_seq;
unsigned long flags;
- bool needwake_state = false;
bool needwake_gp = false;
- bool can_sleep = true;
struct rcu_node *rnp = rdp->mynode;
- do {
- swait_event_interruptible_exclusive(rdp->nocb_cb_wq,
- nocb_cb_wait_cond(rdp));
-
- if (READ_ONCE(rdp->nocb_cb_sleep)) {
- WARN_ON(signal_pending(current));
- trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("WokeEmpty"));
- }
- } while (!nocb_cb_can_run(rdp));
+ swait_event_interruptible_exclusive(rdp->nocb_cb_wq,
+ nocb_cb_wait_cond(rdp));
+ if (kthread_should_park()) {
+ kthread_parkme();
+ } else if (READ_ONCE(rdp->nocb_cb_sleep)) {
+ WARN_ON(signal_pending(current));
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("WokeEmpty"));
+ }
+ WARN_ON_ONCE(!rcu_rdp_is_offloaded(rdp));
local_irq_save(flags);
rcu_momentary_dyntick_idle();
@@ -971,37 +937,16 @@ static void nocb_cb_wait(struct rcu_data *rdp)
raw_spin_unlock_rcu_node(rnp); /* irqs remain disabled. */
}
- if (rcu_segcblist_test_flags(cblist, SEGCBLIST_OFFLOADED)) {
- if (!rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_CB)) {
- rcu_segcblist_set_flags(cblist, SEGCBLIST_KTHREAD_CB);
- if (rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_GP))
- needwake_state = true;
- }
- if (rcu_segcblist_ready_cbs(cblist))
- can_sleep = false;
+ if (!rcu_segcblist_ready_cbs(cblist)) {
+ WRITE_ONCE(rdp->nocb_cb_sleep, true);
+ trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("CBSleep"));
} else {
- /*
- * De-offloading. Clear our flag and notify the de-offload worker.
- * We won't touch the callbacks and keep sleeping until we ever
- * get re-offloaded.
- */
- WARN_ON_ONCE(!rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_CB));
- rcu_segcblist_clear_flags(cblist, SEGCBLIST_KTHREAD_CB);
- if (!rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_GP))
- needwake_state = true;
+ WRITE_ONCE(rdp->nocb_cb_sleep, false);
}
- WRITE_ONCE(rdp->nocb_cb_sleep, can_sleep);
-
- if (rdp->nocb_cb_sleep)
- trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("CBSleep"));
-
rcu_nocb_unlock_irqrestore(rdp, flags);
if (needwake_gp)
rcu_gp_kthread_wake();
-
- if (needwake_state)
- swake_up_one(&rdp->nocb_state_wq);
}
/*
@@ -1094,17 +1039,8 @@ static int rdp_offload_toggle(struct rcu_data *rdp,
bool wake_gp = false;
rcu_segcblist_offload(cblist, offload);
-
- if (rdp->nocb_cb_sleep)
- rdp->nocb_cb_sleep = false;
rcu_nocb_unlock_irqrestore(rdp, flags);
- /*
- * Ignore former value of nocb_cb_sleep and force wake up as it could
- * have been spuriously set to false already.
- */
- swake_up_one(&rdp->nocb_cb_wq);
-
raw_spin_lock_irqsave(&rdp_gp->nocb_gp_lock, flags);
// Queue this rdp for add/del to/from the list to iterate on rcuog
WRITE_ONCE(rdp_gp->nocb_toggling_rdp, rdp);
@@ -1161,19 +1097,11 @@ static long rcu_nocb_rdp_deoffload(void *arg)
if (wake_gp)
wake_up_process(rdp_gp->nocb_gp_kthread);
- /*
- * If rcuo[p] kthread spawn failed, directly remove SEGCBLIST_KTHREAD_CB.
- * Just wait SEGCBLIST_KTHREAD_GP to be cleared by rcuog.
- */
- if (!rdp->nocb_cb_kthread) {
- rcu_nocb_lock_irqsave(rdp, flags);
- rcu_segcblist_clear_flags(&rdp->cblist, SEGCBLIST_KTHREAD_CB);
- rcu_nocb_unlock_irqrestore(rdp, flags);
- }
-
swait_event_exclusive(rdp->nocb_state_wq,
- !rcu_segcblist_test_flags(cblist,
- SEGCBLIST_KTHREAD_CB | SEGCBLIST_KTHREAD_GP));
+ !rcu_segcblist_test_flags(cblist,
+ SEGCBLIST_KTHREAD_GP));
+ if (rdp->nocb_cb_kthread)
+ kthread_park(rdp->nocb_cb_kthread);
} else {
/*
* No kthread to clear the flags for us or remove the rdp from the nocb list
@@ -1181,8 +1109,7 @@ static long rcu_nocb_rdp_deoffload(void *arg)
* but we stick to paranoia in this rare path.
*/
rcu_nocb_lock_irqsave(rdp, flags);
- rcu_segcblist_clear_flags(&rdp->cblist,
- SEGCBLIST_KTHREAD_CB | SEGCBLIST_KTHREAD_GP);
+ rcu_segcblist_clear_flags(&rdp->cblist, SEGCBLIST_KTHREAD_GP);
rcu_nocb_unlock_irqrestore(rdp, flags);
list_del(&rdp->nocb_entry_rdp);
@@ -1282,8 +1209,10 @@ static long rcu_nocb_rdp_offload(void *arg)
wake_gp = rdp_offload_toggle(rdp, true, flags);
if (wake_gp)
wake_up_process(rdp_gp->nocb_gp_kthread);
+
+ kthread_unpark(rdp->nocb_cb_kthread);
+
swait_event_exclusive(rdp->nocb_state_wq,
- rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_CB) &&
rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_GP));
/*
@@ -1468,7 +1397,7 @@ void __init rcu_init_nohz(void)
if (rcu_segcblist_empty(&rdp->cblist))
rcu_segcblist_init(&rdp->cblist);
rcu_segcblist_offload(&rdp->cblist, true);
- rcu_segcblist_set_flags(&rdp->cblist, SEGCBLIST_KTHREAD_CB | SEGCBLIST_KTHREAD_GP);
+ rcu_segcblist_set_flags(&rdp->cblist, SEGCBLIST_KTHREAD_GP);
rcu_segcblist_clear_flags(&rdp->cblist, SEGCBLIST_RCU_CORE);
}
rcu_organize_nocb_kthreads();
@@ -1526,11 +1455,16 @@ static void rcu_spawn_cpu_nocb_kthread(int cpu)
mutex_unlock(&rdp_gp->nocb_gp_kthread_mutex);
/* Spawn the kthread for this CPU. */
- t = kthread_run(rcu_nocb_cb_kthread, rdp,
- "rcuo%c/%d", rcu_state.abbr, cpu);
+ t = kthread_create(rcu_nocb_cb_kthread, rdp,
+ "rcuo%c/%d", rcu_state.abbr, cpu);
if (WARN_ONCE(IS_ERR(t), "%s: Could not start rcuo CB kthread, OOM is now expected behavior\n", __func__))
goto end;
+ if (rcu_rdp_is_offloaded(rdp))
+ wake_up_process(t);
+ else
+ kthread_park(t);
+
if (IS_ENABLED(CONFIG_RCU_NOCB_CPU_CB_BOOST) && kthread_prio)
sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
@@ -1678,12 +1612,11 @@ static void show_rcu_nocb_state(struct rcu_data *rdp)
sprintf(bufw, "%ld", rsclp->gp_seq[RCU_WAIT_TAIL]);
sprintf(bufr, "%ld", rsclp->gp_seq[RCU_NEXT_READY_TAIL]);
- pr_info(" CB %d^%d->%d %c%c%c%c%c%c F%ld L%ld C%d %c%c%s%c%s%c%c q%ld %c CPU %d%s\n",
+ pr_info(" CB %d^%d->%d %c%c%c%c%c F%ld L%ld C%d %c%c%s%c%s%c%c q%ld %c CPU %d%s\n",
rdp->cpu, rdp->nocb_gp_rdp->cpu,
nocb_next_rdp ? nocb_next_rdp->cpu : -1,
"kK"[!!rdp->nocb_cb_kthread],
"bB"[raw_spin_is_locked(&rdp->nocb_bypass_lock)],
- "cC"[!!atomic_read(&rdp->nocb_lock_contended)],
"lL"[raw_spin_is_locked(&rdp->nocb_lock)],
"sS"[!!rdp->nocb_cb_sleep],
".W"[swait_active(&rdp->nocb_cb_wq)],
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 340bbefe5f65..c569da65b421 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -28,8 +28,8 @@ static bool rcu_rdp_is_offloaded(struct rcu_data *rdp)
!(lockdep_is_held(&rcu_state.barrier_mutex) ||
(IS_ENABLED(CONFIG_HOTPLUG_CPU) && lockdep_is_cpus_held()) ||
rcu_lockdep_is_held_nocb(rdp) ||
- (rdp == this_cpu_ptr(&rcu_data) &&
- !(IS_ENABLED(CONFIG_PREEMPT_COUNT) && preemptible())) ||
+ (!(IS_ENABLED(CONFIG_PREEMPT_COUNT) && preemptible()) &&
+ rdp == this_cpu_ptr(&rcu_data)) ||
rcu_current_is_nocb_kthread(rdp)),
"Unsafe read of RCU_NOCB offloaded state"
);
@@ -93,6 +93,16 @@ static void __init rcu_bootup_announce_oddness(void)
pr_info("\tRCU debug GP init slowdown %d jiffies.\n", gp_init_delay);
if (gp_cleanup_delay)
pr_info("\tRCU debug GP cleanup slowdown %d jiffies.\n", gp_cleanup_delay);
+ if (nohz_full_patience_delay < 0) {
+ pr_info("\tRCU NOCB CPU patience negative (%d), resetting to zero.\n", nohz_full_patience_delay);
+ nohz_full_patience_delay = 0;
+ } else if (nohz_full_patience_delay > 5 * MSEC_PER_SEC) {
+ pr_info("\tRCU NOCB CPU patience too large (%d), resetting to %ld.\n", nohz_full_patience_delay, 5 * MSEC_PER_SEC);
+ nohz_full_patience_delay = 5 * MSEC_PER_SEC;
+ } else if (nohz_full_patience_delay) {
+ pr_info("\tRCU NOCB CPU patience set to %d milliseconds.\n", nohz_full_patience_delay);
+ }
+ nohz_full_patience_delay_jiffies = msecs_to_jiffies(nohz_full_patience_delay);
if (!use_softirq)
pr_info("\tRCU_SOFTIRQ processing moved to rcuc kthreads.\n");
if (IS_ENABLED(CONFIG_RCU_EQS_DEBUG))
diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
index 460efecd077b..4b0e9d7c4c68 100644
--- a/kernel/rcu/tree_stall.h
+++ b/kernel/rcu/tree_stall.h
@@ -501,7 +501,7 @@ static void print_cpu_stall_info(int cpu)
}
delta = rcu_seq_ctr(rdp->mynode->gp_seq - rdp->rcu_iw_gp_seq);
falsepositive = rcu_is_gp_kthread_starving(NULL) &&
- rcu_dynticks_in_eqs(rcu_dynticks_snap(cpu));
+ rcu_dynticks_in_eqs(ct_dynticks_cpu(cpu));
rcuc_starved = rcu_is_rcuc_kthread_starving(rdp, &j);
if (rcuc_starved)
// Print signed value, as negative values indicate a probable bug.
@@ -515,7 +515,7 @@ static void print_cpu_stall_info(int cpu)
rdp->rcu_iw_pending ? (int)min(delta, 9UL) + '0' :
"!."[!delta],
ticks_value, ticks_title,
- rcu_dynticks_snap(cpu) & 0xffff,
+ ct_dynticks_cpu(cpu) & 0xffff,
ct_dynticks_nesting_cpu(cpu), ct_dynticks_nmi_nesting_cpu(cpu),
rdp->softirq_snap, kstat_softirqs_cpu(RCU_SOFTIRQ, cpu),
data_race(rcu_state.n_force_qs) - rcu_state.n_force_qs_gpstart,
diff --git a/kernel/scftorture.c b/kernel/scftorture.c
index 59032aaccd18..44e83a646264 100644
--- a/kernel/scftorture.c
+++ b/kernel/scftorture.c
@@ -43,6 +43,7 @@
#define SCFTORTOUT_ERRSTRING(s, x...) pr_alert(SCFTORT_FLAG "!!! " s "\n", ## x)
+MODULE_DESCRIPTION("Torture tests on the smp_call_function() family of primitives");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <[email protected]>");
@@ -67,7 +68,7 @@ torture_param(int, weight_many_wait, -1, "Testing weight for multi-CPU operation
torture_param(int, weight_all, -1, "Testing weight for all-CPU no-wait operations.");
torture_param(int, weight_all_wait, -1, "Testing weight for all-CPU operations.");
-char *torture_type = "";
+static char *torture_type = "";
#ifdef MODULE
# define SCFTORT_SHUTDOWN 0
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index bcf2c4cc0522..35a35e36024b 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -723,7 +723,6 @@ static void update_rq_clock_task(struct rq *rq, s64 delta)
rq->prev_irq_time += irq_delta;
delta -= irq_delta;
- psi_account_irqtime(rq->curr, irq_delta);
delayacct_irq(rq->curr, irq_delta);
#endif
#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
@@ -4467,12 +4466,7 @@ int task_call_func(struct task_struct *p, task_call_f func, void *arg)
* @cpu: The CPU on which to snapshot the task.
*
* Returns the task_struct pointer of the task "currently" running on
- * the specified CPU. If the same task is running on that CPU throughout,
- * the return value will be a pointer to that task's task_struct structure.
- * If the CPU did any context switches even vaguely concurrently with the
- * execution of this function, the return value will be a pointer to the
- * task_struct structure of a randomly chosen task that was running on
- * that CPU somewhere around the time that this function was executing.
+ * the specified CPU.
*
* If the specified CPU was offline, the return value is whatever it
* is, perhaps a pointer to the task_struct structure of that CPU's idle
@@ -4486,11 +4480,16 @@ int task_call_func(struct task_struct *p, task_call_f func, void *arg)
*/
struct task_struct *cpu_curr_snapshot(int cpu)
{
+ struct rq *rq = cpu_rq(cpu);
struct task_struct *t;
+ struct rq_flags rf;
- smp_mb(); /* Pairing determined by caller's synchronization design. */
+ rq_lock_irqsave(rq, &rf);
+ smp_mb__after_spinlock(); /* Pairing determined by caller's synchronization design. */
t = rcu_dereference(cpu_curr(cpu));
+ rq_unlock_irqrestore(rq, &rf);
smp_mb(); /* Pairing determined by caller's synchronization design. */
+
return t;
}
@@ -5665,7 +5664,7 @@ void sched_tick(void)
{
int cpu = smp_processor_id();
struct rq *rq = cpu_rq(cpu);
- struct task_struct *curr = rq->curr;
+ struct task_struct *curr;
struct rq_flags rf;
unsigned long hw_pressure;
u64 resched_latency;
@@ -5677,6 +5676,9 @@ void sched_tick(void)
rq_lock(rq, &rf);
+ curr = rq->curr;
+ psi_account_irqtime(rq, curr, NULL);
+
update_rq_clock(rq);
hw_pressure = arch_scale_hw_pressure(cpu_of(rq));
update_hw_load_avg(rq_clock_task(rq), rq, hw_pressure);
@@ -6737,6 +6739,7 @@ static void __sched notrace __schedule(unsigned int sched_mode)
++*switch_count;
migrate_disable_switch(rq, prev);
+ psi_account_irqtime(rq, prev, next);
psi_sched_switch(prev, next, !task_on_rq_queued(prev));
trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev, next, prev_state);
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index c75d1307d86d..9bedd148f007 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -1804,8 +1804,13 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
* The replenish timer needs to be canceled. No
* problem if it fires concurrently: boosted threads
* are ignored in dl_task_timer().
+ *
+ * If the timer callback was running (hrtimer_try_to_cancel == -1),
+ * it will eventually call put_task_struct().
*/
- hrtimer_try_to_cancel(&p->dl.dl_timer);
+ if (hrtimer_try_to_cancel(&p->dl.dl_timer) == 1 &&
+ !dl_server(&p->dl))
+ put_task_struct(p);
p->dl.dl_throttled = 0;
}
} else if (!dl_prio(p->normal_prio)) {
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 8a5b1ae0aa55..24dda708b699 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -9149,12 +9149,8 @@ static int detach_tasks(struct lb_env *env)
break;
env->loop++;
- /*
- * We've more or less seen every task there is, call it quits
- * unless we haven't found any movable task yet.
- */
- if (env->loop > env->loop_max &&
- !(env->flags & LBF_ALL_PINNED))
+ /* We've more or less seen every task there is, call it quits */
+ if (env->loop > env->loop_max)
break;
/* take a breather every nr_migrate tasks */
@@ -11393,9 +11389,7 @@ more_balance:
if (env.flags & LBF_NEED_BREAK) {
env.flags &= ~LBF_NEED_BREAK;
- /* Stop if we tried all running tasks */
- if (env.loop < busiest->nr_running)
- goto more_balance;
+ goto more_balance;
}
/*
diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c
index 7b4aa5809c0f..507d7b8d79af 100644
--- a/kernel/sched/psi.c
+++ b/kernel/sched/psi.c
@@ -773,6 +773,7 @@ static void psi_group_change(struct psi_group *group, int cpu,
enum psi_states s;
u32 state_mask;
+ lockdep_assert_rq_held(cpu_rq(cpu));
groupc = per_cpu_ptr(group->pcpu, cpu);
/*
@@ -991,22 +992,32 @@ void psi_task_switch(struct task_struct *prev, struct task_struct *next,
}
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
-void psi_account_irqtime(struct task_struct *task, u32 delta)
+void psi_account_irqtime(struct rq *rq, struct task_struct *curr, struct task_struct *prev)
{
- int cpu = task_cpu(task);
+ int cpu = task_cpu(curr);
struct psi_group *group;
struct psi_group_cpu *groupc;
- u64 now;
+ u64 now, irq;
+ s64 delta;
if (static_branch_likely(&psi_disabled))
return;
- if (!task->pid)
+ if (!curr->pid)
+ return;
+
+ lockdep_assert_rq_held(rq);
+ group = task_psi_group(curr);
+ if (prev && task_psi_group(prev) == group)
return;
now = cpu_clock(cpu);
+ irq = irq_time_read(cpu);
+ delta = (s64)(irq - rq->psi_irq_time);
+ if (delta < 0)
+ return;
+ rq->psi_irq_time = irq;
- group = task_psi_group(task);
do {
if (!group->enabled)
continue;
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index a831af102070..ef20c61004eb 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1126,6 +1126,7 @@ struct rq {
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
u64 prev_irq_time;
+ u64 psi_irq_time;
#endif
#ifdef CONFIG_PARAVIRT
u64 prev_steal_time;
diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h
index 38f3698f5e5b..b02dfc322951 100644
--- a/kernel/sched/stats.h
+++ b/kernel/sched/stats.h
@@ -110,8 +110,12 @@ __schedstats_from_se(struct sched_entity *se)
void psi_task_change(struct task_struct *task, int clear, int set);
void psi_task_switch(struct task_struct *prev, struct task_struct *next,
bool sleep);
-void psi_account_irqtime(struct task_struct *task, u32 delta);
-
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+void psi_account_irqtime(struct rq *rq, struct task_struct *curr, struct task_struct *prev);
+#else
+static inline void psi_account_irqtime(struct rq *rq, struct task_struct *curr,
+ struct task_struct *prev) {}
+#endif /*CONFIG_IRQ_TIME_ACCOUNTING */
/*
* PSI tracks state that persists across sleeps, such as iowaits and
* memory stalls. As a result, it has to distinguish between sleeps,
@@ -192,7 +196,8 @@ static inline void psi_ttwu_dequeue(struct task_struct *p) {}
static inline void psi_sched_switch(struct task_struct *prev,
struct task_struct *next,
bool sleep) {}
-static inline void psi_account_irqtime(struct task_struct *task, u32 delta) {}
+static inline void psi_account_irqtime(struct rq *rq, struct task_struct *curr,
+ struct task_struct *prev) {}
#endif /* CONFIG_PSI */
#ifdef CONFIG_SCHED_INFO
diff --git a/kernel/signal.c b/kernel/signal.c
index 1f9dd41c04be..60c737e423a1 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2600,6 +2600,14 @@ static void do_freezer_trap(void)
spin_unlock_irq(&current->sighand->siglock);
cgroup_enter_frozen();
schedule();
+
+ /*
+ * We could've been woken by task_work, run it to clear
+ * TIF_NOTIFY_SIGNAL. The caller will retry if necessary.
+ */
+ clear_notify_signal();
+ if (unlikely(task_work_pending(current)))
+ task_work_run();
}
static int ptrace_signal(int signr, kernel_siginfo_t *info, enum pid_type type)
diff --git a/kernel/smp.c b/kernel/smp.c
index f085ebcdf9e7..aaffecdad319 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -25,6 +25,7 @@
#include <linux/nmi.h>
#include <linux/sched/debug.h>
#include <linux/jump_label.h>
+#include <linux/string_choices.h>
#include <trace/events/ipi.h>
#define CREATE_TRACE_POINTS
@@ -982,8 +983,7 @@ void __init smp_init(void)
num_nodes = num_online_nodes();
num_cpus = num_online_cpus();
pr_info("Brought up %d node%s, %d CPU%s\n",
- num_nodes, (num_nodes > 1 ? "s" : ""),
- num_cpus, (num_cpus > 1 ? "s" : ""));
+ num_nodes, str_plural(num_nodes), num_cpus, str_plural(num_cpus));
/* Any cleanup work */
smp_cpus_done(setup_max_cpus);
@@ -1119,6 +1119,7 @@ int smp_call_on_cpu(unsigned int cpu, int (*func)(void *), void *par, bool phys)
queue_work_on(cpu, system_wq, &sscs.work);
wait_for_completion(&sscs.done);
+ destroy_work_on_stack(&sscs.work);
return sscs.ret;
}
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index b696b85ac63e..2ef820a2d067 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -76,8 +76,6 @@ COND_SYSCALL(timerfd_gettime32);
COND_SYSCALL(acct);
COND_SYSCALL(capget);
COND_SYSCALL(capset);
-/* __ARCH_WANT_SYS_CLONE3 */
-COND_SYSCALL(clone3);
COND_SYSCALL(futex);
COND_SYSCALL(futex_time32);
COND_SYSCALL(set_robust_list);
diff --git a/kernel/time/clocksource-wdtest.c b/kernel/time/clocksource-wdtest.c
index d06185e054ea..62e73444ffe4 100644
--- a/kernel/time/clocksource-wdtest.c
+++ b/kernel/time/clocksource-wdtest.c
@@ -22,6 +22,7 @@
#include "tick-internal.h"
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Clocksource watchdog unit test");
MODULE_AUTHOR("Paul E. McKenney <[email protected]>");
static int holdoff = IS_BUILTIN(CONFIG_TEST_CLOCKSOURCE_WATCHDOG) ? 10 : 0;
diff --git a/kernel/time/test_udelay.c b/kernel/time/test_udelay.c
index 20d5df631570..783f2297111b 100644
--- a/kernel/time/test_udelay.c
+++ b/kernel/time/test_udelay.c
@@ -155,5 +155,6 @@ static void __exit udelay_test_exit(void)
module_exit(udelay_test_exit);
+MODULE_DESCRIPTION("udelay test module");
MODULE_AUTHOR("David Riley <[email protected]>");
MODULE_LICENSE("GPL");
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 771d1e040303..b4843099a8da 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -1141,6 +1141,7 @@ void tick_broadcast_switch_to_oneshot(void)
#ifdef CONFIG_HOTPLUG_CPU
void hotplug_cpu__broadcast_tick_pull(int deadcpu)
{
+ struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
struct clock_event_device *bc;
unsigned long flags;
@@ -1148,6 +1149,28 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu)
bc = tick_broadcast_device.evtdev;
if (bc && broadcast_needs_cpu(bc, deadcpu)) {
+ /*
+ * If the broadcast force bit of the current CPU is set,
+ * then the current CPU has not yet reprogrammed the local
+ * timer device to avoid a ping-pong race. See
+ * ___tick_broadcast_oneshot_control().
+ *
+ * If the broadcast device is hrtimer based then
+ * programming the broadcast event below does not have any
+ * effect because the local clockevent device is not
+ * running and not programmed because the broadcast event
+ * is not earlier than the pending event of the local clock
+ * event device. As a consequence all CPUs waiting for a
+ * broadcast event are stuck forever.
+ *
+ * Detect this condition and reprogram the cpu local timer
+ * device to avoid the starvation.
+ */
+ if (tick_check_broadcast_expired()) {
+ cpumask_clear_cpu(smp_processor_id(), tick_broadcast_force_mask);
+ tick_program_event(td->evtdev->next_event, 1);
+ }
+
/* This moves the broadcast assignment to this CPU: */
clockevents_program_event(bc, bc->next_event, 1);
}
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 71a792cd8936..753a184c7090 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -1026,10 +1026,10 @@ static void tick_nohz_stop_tick(struct tick_sched *ts, int cpu)
if (expires == KTIME_MAX || ts->next_tick == hrtimer_get_expires(&ts->sched_timer))
return;
- WARN_ON_ONCE(1);
- printk_once("basemono: %llu ts->next_tick: %llu dev->next_event: %llu timer->active: %d timer->expires: %llu\n",
- basemono, ts->next_tick, dev->next_event,
- hrtimer_active(&ts->sched_timer), hrtimer_get_expires(&ts->sched_timer));
+ WARN_ONCE(1, "basemono: %llu ts->next_tick: %llu dev->next_event: %llu "
+ "timer->active: %d timer->expires: %llu\n", basemono, ts->next_tick,
+ dev->next_event, hrtimer_active(&ts->sched_timer),
+ hrtimer_get_expires(&ts->sched_timer));
}
/*
@@ -1385,20 +1385,6 @@ unsigned long tick_nohz_get_idle_calls_cpu(int cpu)
return ts->idle_calls;
}
-/**
- * tick_nohz_get_idle_calls - return the current idle calls counter value
- *
- * Called from the schedutil frequency scaling governor in scheduler context.
- *
- * Return: the current idle calls counter value for the current CPU
- */
-unsigned long tick_nohz_get_idle_calls(void)
-{
- struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
-
- return ts->idle_calls;
-}
-
static void tick_nohz_account_idle_time(struct tick_sched *ts,
ktime_t now)
{
diff --git a/kernel/time/time_test.c b/kernel/time/time_test.c
index 3e5d422dd15c..2889763165e5 100644
--- a/kernel/time/time_test.c
+++ b/kernel/time/time_test.c
@@ -96,4 +96,5 @@ static struct kunit_suite time_test_suite = {
};
kunit_test_suite(time_test_suite);
+MODULE_DESCRIPTION("time unit test suite");
MODULE_LICENSE("GPL");
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 4e18db1819f8..2fa87dcfeda9 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1195,6 +1195,108 @@ static bool timestamp_in_interval(u64 start, u64 end, u64 ts)
return false;
}
+static bool convert_clock(u64 *val, u32 numerator, u32 denominator)
+{
+ u64 rem, res;
+
+ if (!numerator || !denominator)
+ return false;
+
+ res = div64_u64_rem(*val, denominator, &rem) * numerator;
+ *val = res + div_u64(rem * numerator, denominator);
+ return true;
+}
+
+static bool convert_base_to_cs(struct system_counterval_t *scv)
+{
+ struct clocksource *cs = tk_core.timekeeper.tkr_mono.clock;
+ struct clocksource_base *base;
+ u32 num, den;
+
+ /* The timestamp was taken from the time keeper clock source */
+ if (cs->id == scv->cs_id)
+ return true;
+
+ /*
+ * Check whether cs_id matches the base clock. Prevent the compiler from
+ * re-evaluating @base as the clocksource might change concurrently.
+ */
+ base = READ_ONCE(cs->base);
+ if (!base || base->id != scv->cs_id)
+ return false;
+
+ num = scv->use_nsecs ? cs->freq_khz : base->numerator;
+ den = scv->use_nsecs ? USEC_PER_SEC : base->denominator;
+
+ if (!convert_clock(&scv->cycles, num, den))
+ return false;
+
+ scv->cycles += base->offset;
+ return true;
+}
+
+static bool convert_cs_to_base(u64 *cycles, enum clocksource_ids base_id)
+{
+ struct clocksource *cs = tk_core.timekeeper.tkr_mono.clock;
+ struct clocksource_base *base;
+
+ /*
+ * Check whether base_id matches the base clock. Prevent the compiler from
+ * re-evaluating @base as the clocksource might change concurrently.
+ */
+ base = READ_ONCE(cs->base);
+ if (!base || base->id != base_id)
+ return false;
+
+ *cycles -= base->offset;
+ if (!convert_clock(cycles, base->denominator, base->numerator))
+ return false;
+ return true;
+}
+
+static bool convert_ns_to_cs(u64 *delta)
+{
+ struct tk_read_base *tkr = &tk_core.timekeeper.tkr_mono;
+
+ if (BITS_TO_BYTES(fls64(*delta) + tkr->shift) >= sizeof(*delta))
+ return false;
+
+ *delta = div_u64((*delta << tkr->shift) - tkr->xtime_nsec, tkr->mult);
+ return true;
+}
+
+/**
+ * ktime_real_to_base_clock() - Convert CLOCK_REALTIME timestamp to a base clock timestamp
+ * @treal: CLOCK_REALTIME timestamp to convert
+ * @base_id: base clocksource id
+ * @cycles: pointer to store the converted base clock timestamp
+ *
+ * Converts a supplied, future realtime clock value to the corresponding base clock value.
+ *
+ * Return: true if the conversion is successful, false otherwise.
+ */
+bool ktime_real_to_base_clock(ktime_t treal, enum clocksource_ids base_id, u64 *cycles)
+{
+ struct timekeeper *tk = &tk_core.timekeeper;
+ unsigned int seq;
+ u64 delta;
+
+ do {
+ seq = read_seqcount_begin(&tk_core.seq);
+ if ((u64)treal < tk->tkr_mono.base_real)
+ return false;
+ delta = (u64)treal - tk->tkr_mono.base_real;
+ if (!convert_ns_to_cs(&delta))
+ return false;
+ *cycles = tk->tkr_mono.cycle_last + delta;
+ if (!convert_cs_to_base(cycles, base_id))
+ return false;
+ } while (read_seqcount_retry(&tk_core.seq, seq));
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(ktime_real_to_base_clock);
+
/**
* get_device_system_crosststamp - Synchronously capture system/device timestamp
* @get_time_fn: Callback to get simultaneous device time and
@@ -1241,7 +1343,7 @@ int get_device_system_crosststamp(int (*get_time_fn)
* installed timekeeper clocksource
*/
if (system_counterval.cs_id == CSID_GENERIC ||
- tk->tkr_mono.clock->id != system_counterval.cs_id)
+ !convert_base_to_cs(&system_counterval))
return -ENODEV;
cycles = system_counterval.cycles;
@@ -1307,6 +1409,30 @@ int get_device_system_crosststamp(int (*get_time_fn)
EXPORT_SYMBOL_GPL(get_device_system_crosststamp);
/**
+ * timekeeping_clocksource_has_base - Check whether the current clocksource
+ * is based on given a base clock
+ * @id: base clocksource ID
+ *
+ * Note: The return value is a snapshot which can become invalid right
+ * after the function returns.
+ *
+ * Return: true if the timekeeper clocksource has a base clock with @id,
+ * false otherwise
+ */
+bool timekeeping_clocksource_has_base(enum clocksource_ids id)
+{
+ /*
+ * This is a snapshot, so no point in using the sequence
+ * count. Just prevent the compiler from re-evaluating @base as the
+ * clocksource might change concurrently.
+ */
+ struct clocksource_base *base = READ_ONCE(tk_core.timekeeper.tkr_mono.clock->base);
+
+ return base ? base->id == id : false;
+}
+EXPORT_SYMBOL_GPL(timekeeping_clocksource_has_base);
+
+/**
* do_settimeofday64 - Sets the time of day.
* @ts: pointer to the timespec64 variable containing the new time
*
@@ -2421,6 +2547,7 @@ EXPORT_SYMBOL_GPL(random_get_entropy_fallback);
/**
* do_adjtimex() - Accessor function to NTP __do_adjtimex function
+ * @txc: Pointer to kernel_timex structure containing NTP parameters
*/
int do_adjtimex(struct __kernel_timex *txc)
{
@@ -2489,6 +2616,8 @@ int do_adjtimex(struct __kernel_timex *txc)
#ifdef CONFIG_NTP_PPS
/**
* hardpps() - Accessor function to NTP __hardpps function
+ * @phase_ts: Pointer to timespec64 structure representing phase timestamp
+ * @raw_ts: Pointer to timespec64 structure representing raw timestamp
*/
void hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
{
diff --git a/kernel/torture.c b/kernel/torture.c
index c72ab2d251f4..dede150aef01 100644
--- a/kernel/torture.c
+++ b/kernel/torture.c
@@ -40,6 +40,7 @@
#include <linux/sched/rt.h>
#include "rcu/rcu.h"
+MODULE_DESCRIPTION("Common functions for in-kernel torture tests");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <[email protected]>");
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 3fbaecfc88c2..1745ca788ede 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -216,8 +216,6 @@ struct worker_pool {
struct worker *manager; /* L: purely informational */
struct list_head workers; /* A: attached workers */
- struct list_head dying_workers; /* A: workers about to die */
- struct completion *detach_completion; /* all workers detached */
struct ida worker_ida; /* worker IDs for task name */
@@ -436,7 +434,7 @@ static struct wq_pod_type wq_pod_types[WQ_AFFN_NR_TYPES];
static enum wq_affn_scope wq_affn_dfl = WQ_AFFN_CACHE;
/* buf for wq_update_unbound_pod_attrs(), protected by CPU hotplug exclusion */
-static struct workqueue_attrs *wq_update_pod_attrs_buf;
+static struct workqueue_attrs *unbound_wq_update_pwq_attrs_buf;
static DEFINE_MUTEX(wq_pool_mutex); /* protects pools and workqueues list */
static DEFINE_MUTEX(wq_pool_attach_mutex); /* protects worker attach/detach */
@@ -447,6 +445,9 @@ static struct rcuwait manager_wait = __RCUWAIT_INITIALIZER(manager_wait);
static LIST_HEAD(workqueues); /* PR: list of all workqueues */
static bool workqueue_freezing; /* PL: have wqs started freezing? */
+/* PL: mirror the cpu_online_mask excluding the CPU in the midst of hotplugging */
+static cpumask_var_t wq_online_cpumask;
+
/* PL&A: allowable cpus for unbound wqs and work items */
static cpumask_var_t wq_unbound_cpumask;
@@ -1684,33 +1685,6 @@ static void __pwq_activate_work(struct pool_workqueue *pwq,
__clear_bit(WORK_STRUCT_INACTIVE_BIT, wdb);
}
-/**
- * pwq_activate_work - Activate a work item if inactive
- * @pwq: pool_workqueue @work belongs to
- * @work: work item to activate
- *
- * Returns %true if activated. %false if already active.
- */
-static bool pwq_activate_work(struct pool_workqueue *pwq,
- struct work_struct *work)
-{
- struct worker_pool *pool = pwq->pool;
- struct wq_node_nr_active *nna;
-
- lockdep_assert_held(&pool->lock);
-
- if (!(*work_data_bits(work) & WORK_STRUCT_INACTIVE))
- return false;
-
- nna = wq_node_nr_active(pwq->wq, pool->node);
- if (nna)
- atomic_inc(&nna->nr);
-
- pwq->nr_active++;
- __pwq_activate_work(pwq, work);
- return true;
-}
-
static bool tryinc_node_nr_active(struct wq_node_nr_active *nna)
{
int max = READ_ONCE(nna->max);
@@ -2117,7 +2091,7 @@ static int try_to_grab_pending(struct work_struct *work, u32 cflags,
*/
pwq = get_work_pwq(work);
if (pwq && pwq->pool == pool) {
- unsigned long work_data;
+ unsigned long work_data = *work_data_bits(work);
debug_work_deactivate(work);
@@ -2126,13 +2100,17 @@ static int try_to_grab_pending(struct work_struct *work, u32 cflags,
* pwq->inactive_works since a queued barrier can't be
* canceled (see the comments in insert_wq_barrier()).
*
- * An inactive work item cannot be grabbed directly because
+ * An inactive work item cannot be deleted directly because
* it might have linked barrier work items which, if left
* on the inactive_works list, will confuse pwq->nr_active
- * management later on and cause stall. Make sure the work
- * item is activated before grabbing.
+ * management later on and cause stall. Move the linked
+ * barrier work items to the worklist when deleting the grabbed
+ * item. Also keep WORK_STRUCT_INACTIVE in work_data, so that
+ * it doesn't participate in nr_active management in later
+ * pwq_dec_nr_in_flight().
*/
- pwq_activate_work(pwq, work);
+ if (work_data & WORK_STRUCT_INACTIVE)
+ move_linked_works(work, &pwq->pool->worklist, NULL);
list_del_init(&work->entry);
@@ -2140,7 +2118,6 @@ static int try_to_grab_pending(struct work_struct *work, u32 cflags,
* work->data points to pwq iff queued. Let's point to pool. As
* this destroys work->data needed by the next step, stash it.
*/
- work_data = *work_data_bits(work);
set_work_pool_and_keep_pending(work, pool->id,
pool_offq_flags(pool));
@@ -2298,9 +2275,13 @@ retry:
* If @work was previously on a different pool, it might still be
* running there, in which case the work needs to be queued on that
* pool to guarantee non-reentrancy.
+ *
+ * For ordered workqueue, work items must be queued on the newest pwq
+ * for accurate order management. Guaranteed order also guarantees
+ * non-reentrancy. See the comments above unplug_oldest_pwq().
*/
last_pool = get_work_pool(work);
- if (last_pool && last_pool != pool) {
+ if (last_pool && last_pool != pool && !(wq->flags & __WQ_ORDERED)) {
struct worker *worker;
raw_spin_lock(&last_pool->lock);
@@ -2710,6 +2691,27 @@ static void worker_attach_to_pool(struct worker *worker,
mutex_unlock(&wq_pool_attach_mutex);
}
+static void unbind_worker(struct worker *worker)
+{
+ lockdep_assert_held(&wq_pool_attach_mutex);
+
+ kthread_set_per_cpu(worker->task, -1);
+ if (cpumask_intersects(wq_unbound_cpumask, cpu_active_mask))
+ WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task, wq_unbound_cpumask) < 0);
+ else
+ WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task, cpu_possible_mask) < 0);
+}
+
+
+static void detach_worker(struct worker *worker)
+{
+ lockdep_assert_held(&wq_pool_attach_mutex);
+
+ unbind_worker(worker);
+ list_del(&worker->node);
+ worker->pool = NULL;
+}
+
/**
* worker_detach_from_pool() - detach a worker from its pool
* @worker: worker which is attached to its pool
@@ -2721,26 +2723,16 @@ static void worker_attach_to_pool(struct worker *worker,
static void worker_detach_from_pool(struct worker *worker)
{
struct worker_pool *pool = worker->pool;
- struct completion *detach_completion = NULL;
/* there is one permanent BH worker per CPU which should never detach */
WARN_ON_ONCE(pool->flags & POOL_BH);
mutex_lock(&wq_pool_attach_mutex);
-
- kthread_set_per_cpu(worker->task, -1);
- list_del(&worker->node);
- worker->pool = NULL;
-
- if (list_empty(&pool->workers) && list_empty(&pool->dying_workers))
- detach_completion = pool->detach_completion;
+ detach_worker(worker);
mutex_unlock(&wq_pool_attach_mutex);
/* clear leftover flags without pool->lock after it is detached */
worker->flags &= ~(WORKER_UNBOUND | WORKER_REBOUND);
-
- if (detach_completion)
- complete(detach_completion);
}
static int format_worker_id(char *buf, size_t size, struct worker *worker,
@@ -2844,35 +2836,22 @@ fail:
return NULL;
}
-static void unbind_worker(struct worker *worker)
+static void detach_dying_workers(struct list_head *cull_list)
{
- lockdep_assert_held(&wq_pool_attach_mutex);
+ struct worker *worker;
- kthread_set_per_cpu(worker->task, -1);
- if (cpumask_intersects(wq_unbound_cpumask, cpu_active_mask))
- WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task, wq_unbound_cpumask) < 0);
- else
- WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task, cpu_possible_mask) < 0);
+ list_for_each_entry(worker, cull_list, entry)
+ detach_worker(worker);
}
-static void wake_dying_workers(struct list_head *cull_list)
+static void reap_dying_workers(struct list_head *cull_list)
{
struct worker *worker, *tmp;
list_for_each_entry_safe(worker, tmp, cull_list, entry) {
list_del_init(&worker->entry);
- unbind_worker(worker);
- /*
- * If the worker was somehow already running, then it had to be
- * in pool->idle_list when set_worker_dying() happened or we
- * wouldn't have gotten here.
- *
- * Thus, the worker must either have observed the WORKER_DIE
- * flag, or have set its state to TASK_IDLE. Either way, the
- * below will be observed by the worker and is safe to do
- * outside of pool->lock.
- */
- wake_up_process(worker->task);
+ kthread_stop_put(worker->task);
+ kfree(worker);
}
}
@@ -2906,7 +2885,9 @@ static void set_worker_dying(struct worker *worker, struct list_head *list)
worker->flags |= WORKER_DIE;
list_move(&worker->entry, list);
- list_move(&worker->node, &pool->dying_workers);
+
+ /* get an extra task struct reference for later kthread_stop_put() */
+ get_task_struct(worker->task);
}
/**
@@ -2965,9 +2946,9 @@ static void idle_cull_fn(struct work_struct *work)
/*
* Grabbing wq_pool_attach_mutex here ensures an already-running worker
- * cannot proceed beyong worker_detach_from_pool() in its self-destruct
- * path. This is required as a previously-preempted worker could run after
- * set_worker_dying() has happened but before wake_dying_workers() did.
+ * cannot proceed beyong set_pf_worker() in its self-destruct path.
+ * This is required as a previously-preempted worker could run after
+ * set_worker_dying() has happened but before detach_dying_workers() did.
*/
mutex_lock(&wq_pool_attach_mutex);
raw_spin_lock_irq(&pool->lock);
@@ -2988,8 +2969,10 @@ static void idle_cull_fn(struct work_struct *work)
}
raw_spin_unlock_irq(&pool->lock);
- wake_dying_workers(&cull_list);
+ detach_dying_workers(&cull_list);
mutex_unlock(&wq_pool_attach_mutex);
+
+ reap_dying_workers(&cull_list);
}
static void send_mayday(struct work_struct *work)
@@ -3368,9 +3351,7 @@ woke_up:
set_pf_worker(false);
ida_free(&pool->worker_ida, worker->id);
- worker_detach_from_pool(worker);
WARN_ON_ONCE(!list_empty(&worker->entry));
- kfree(worker);
return 0;
}
@@ -4761,7 +4742,6 @@ static int init_worker_pool(struct worker_pool *pool)
timer_setup(&pool->mayday_timer, pool_mayday_timeout, 0);
INIT_LIST_HEAD(&pool->workers);
- INIT_LIST_HEAD(&pool->dying_workers);
ida_init(&pool->worker_ida);
INIT_HLIST_NODE(&pool->hash_node);
@@ -4903,7 +4883,6 @@ static void rcu_free_pool(struct rcu_head *rcu)
*/
static void put_unbound_pool(struct worker_pool *pool)
{
- DECLARE_COMPLETION_ONSTACK(detach_completion);
struct worker *worker;
LIST_HEAD(cull_list);
@@ -4955,14 +4934,11 @@ static void put_unbound_pool(struct worker_pool *pool)
WARN_ON(pool->nr_workers || pool->nr_idle);
raw_spin_unlock_irq(&pool->lock);
- wake_dying_workers(&cull_list);
+ detach_dying_workers(&cull_list);
- if (!list_empty(&pool->workers) || !list_empty(&pool->dying_workers))
- pool->detach_completion = &detach_completion;
mutex_unlock(&wq_pool_attach_mutex);
- if (pool->detach_completion)
- wait_for_completion(pool->detach_completion);
+ reap_dying_workers(&cull_list);
/* shut down the timers */
del_timer_sync(&pool->idle_timer);
@@ -5038,12 +5014,6 @@ fail:
return NULL;
}
-static void rcu_free_pwq(struct rcu_head *rcu)
-{
- kmem_cache_free(pwq_cache,
- container_of(rcu, struct pool_workqueue, rcu));
-}
-
/*
* Scheduled on pwq_release_worker by put_pwq() when an unbound pwq hits zero
* refcnt and needs to be destroyed.
@@ -5089,7 +5059,7 @@ static void pwq_release_workfn(struct kthread_work *work)
raw_spin_unlock_irq(&nna->lock);
}
- call_rcu(&pwq->rcu, rcu_free_pwq);
+ kfree_rcu(pwq, rcu);
/*
* If we're the last pwq going away, @wq is already dead and no one
@@ -5161,14 +5131,22 @@ static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq,
return pwq;
}
+static void apply_wqattrs_lock(void)
+{
+ mutex_lock(&wq_pool_mutex);
+}
+
+static void apply_wqattrs_unlock(void)
+{
+ mutex_unlock(&wq_pool_mutex);
+}
+
/**
* wq_calc_pod_cpumask - calculate a wq_attrs' cpumask for a pod
* @attrs: the wq_attrs of the default pwq of the target workqueue
* @cpu: the target CPU
- * @cpu_going_down: if >= 0, the CPU to consider as offline
*
- * Calculate the cpumask a workqueue with @attrs should use on @pod. If
- * @cpu_going_down is >= 0, that cpu is considered offline during calculation.
+ * Calculate the cpumask a workqueue with @attrs should use on @pod.
* The result is stored in @attrs->__pod_cpumask.
*
* If pod affinity is not enabled, @attrs->cpumask is always used. If enabled
@@ -5177,29 +5155,18 @@ static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq,
*
* The caller is responsible for ensuring that the cpumask of @pod stays stable.
*/
-static void wq_calc_pod_cpumask(struct workqueue_attrs *attrs, int cpu,
- int cpu_going_down)
+static void wq_calc_pod_cpumask(struct workqueue_attrs *attrs, int cpu)
{
const struct wq_pod_type *pt = wqattrs_pod_type(attrs);
int pod = pt->cpu_pod[cpu];
- /* does @pod have any online CPUs @attrs wants? */
+ /* calculate possible CPUs in @pod that @attrs wants */
cpumask_and(attrs->__pod_cpumask, pt->pod_cpus[pod], attrs->cpumask);
- cpumask_and(attrs->__pod_cpumask, attrs->__pod_cpumask, cpu_online_mask);
- if (cpu_going_down >= 0)
- cpumask_clear_cpu(cpu_going_down, attrs->__pod_cpumask);
-
- if (cpumask_empty(attrs->__pod_cpumask)) {
+ /* does @pod have any online CPUs @attrs wants? */
+ if (!cpumask_intersects(attrs->__pod_cpumask, wq_online_cpumask)) {
cpumask_copy(attrs->__pod_cpumask, attrs->cpumask);
return;
}
-
- /* yeap, return possible CPUs in @pod that @attrs wants */
- cpumask_and(attrs->__pod_cpumask, attrs->cpumask, pt->pod_cpus[pod]);
-
- if (cpumask_empty(attrs->__pod_cpumask))
- pr_warn_once("WARNING: workqueue cpumask: online intersect > "
- "possible intersect\n");
}
/* install @pwq into @wq and return the old pwq, @cpu < 0 for dfl_pwq */
@@ -5284,7 +5251,7 @@ apply_wqattrs_prepare(struct workqueue_struct *wq,
ctx->dfl_pwq->refcnt++;
ctx->pwq_tbl[cpu] = ctx->dfl_pwq;
} else {
- wq_calc_pod_cpumask(new_attrs, cpu, -1);
+ wq_calc_pod_cpumask(new_attrs, cpu);
ctx->pwq_tbl[cpu] = alloc_unbound_pwq(wq, new_attrs);
if (!ctx->pwq_tbl[cpu])
goto out_free;
@@ -5375,8 +5342,6 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq,
*
* Performs GFP_KERNEL allocations.
*
- * Assumes caller has CPU hotplug read exclusion, i.e. cpus_read_lock().
- *
* Return: 0 on success and -errno on failure.
*/
int apply_workqueue_attrs(struct workqueue_struct *wq,
@@ -5384,8 +5349,6 @@ int apply_workqueue_attrs(struct workqueue_struct *wq,
{
int ret;
- lockdep_assert_cpus_held();
-
mutex_lock(&wq_pool_mutex);
ret = apply_workqueue_attrs_locked(wq, attrs);
mutex_unlock(&wq_pool_mutex);
@@ -5394,15 +5357,12 @@ int apply_workqueue_attrs(struct workqueue_struct *wq,
}
/**
- * wq_update_pod - update pod affinity of a wq for CPU hot[un]plug
+ * unbound_wq_update_pwq - update a pwq slot for CPU hot[un]plug
* @wq: the target workqueue
- * @cpu: the CPU to update pool association for
- * @hotplug_cpu: the CPU coming up or going down
- * @online: whether @cpu is coming up or going down
+ * @cpu: the CPU to update the pwq slot for
*
* This function is to be called from %CPU_DOWN_PREPARE, %CPU_ONLINE and
- * %CPU_DOWN_FAILED. @cpu is being hot[un]plugged, update pod affinity of
- * @wq accordingly.
+ * %CPU_DOWN_FAILED. @cpu is in the same pod of the CPU being hot[un]plugged.
*
*
* If pod affinity can't be adjusted due to memory allocation failure, it falls
@@ -5415,10 +5375,8 @@ int apply_workqueue_attrs(struct workqueue_struct *wq,
* CPU_DOWN. If a workqueue user wants strict affinity, it's the user's
* responsibility to flush the work item from CPU_DOWN_PREPARE.
*/
-static void wq_update_pod(struct workqueue_struct *wq, int cpu,
- int hotplug_cpu, bool online)
+static void unbound_wq_update_pwq(struct workqueue_struct *wq, int cpu)
{
- int off_cpu = online ? -1 : hotplug_cpu;
struct pool_workqueue *old_pwq = NULL, *pwq;
struct workqueue_attrs *target_attrs;
@@ -5432,13 +5390,13 @@ static void wq_update_pod(struct workqueue_struct *wq, int cpu,
* Let's use a preallocated one. The following buf is protected by
* CPU hotplug exclusion.
*/
- target_attrs = wq_update_pod_attrs_buf;
+ target_attrs = unbound_wq_update_pwq_attrs_buf;
copy_workqueue_attrs(target_attrs, wq->unbound_attrs);
wqattrs_actualize_cpumask(target_attrs, wq_unbound_cpumask);
/* nothing to do if the target cpumask matches the current pwq */
- wq_calc_pod_cpumask(target_attrs, cpu, off_cpu);
+ wq_calc_pod_cpumask(target_attrs, cpu);
if (wqattrs_equal(target_attrs, unbound_pwq(wq, cpu)->pool->attrs))
return;
@@ -5472,21 +5430,24 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
bool highpri = wq->flags & WQ_HIGHPRI;
int cpu, ret;
+ lockdep_assert_held(&wq_pool_mutex);
+
wq->cpu_pwq = alloc_percpu(struct pool_workqueue *);
if (!wq->cpu_pwq)
goto enomem;
if (!(wq->flags & WQ_UNBOUND)) {
+ struct worker_pool __percpu *pools;
+
+ if (wq->flags & WQ_BH)
+ pools = bh_worker_pools;
+ else
+ pools = cpu_worker_pools;
+
for_each_possible_cpu(cpu) {
struct pool_workqueue **pwq_p;
- struct worker_pool __percpu *pools;
struct worker_pool *pool;
- if (wq->flags & WQ_BH)
- pools = bh_worker_pools;
- else
- pools = cpu_worker_pools;
-
pool = &(per_cpu_ptr(pools, cpu)[highpri]);
pwq_p = per_cpu_ptr(wq->cpu_pwq, cpu);
@@ -5504,26 +5465,18 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
return 0;
}
- cpus_read_lock();
if (wq->flags & __WQ_ORDERED) {
struct pool_workqueue *dfl_pwq;
- ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);
+ ret = apply_workqueue_attrs_locked(wq, ordered_wq_attrs[highpri]);
/* there should only be single pwq for ordering guarantee */
dfl_pwq = rcu_access_pointer(wq->dfl_pwq);
WARN(!ret && (wq->pwqs.next != &dfl_pwq->pwqs_node ||
wq->pwqs.prev != &dfl_pwq->pwqs_node),
"ordering guarantee broken for workqueue %s\n", wq->name);
} else {
- ret = apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);
+ ret = apply_workqueue_attrs_locked(wq, unbound_std_wq_attrs[highpri]);
}
- cpus_read_unlock();
-
- /* for unbound pwq, flush the pwq_release_worker ensures that the
- * pwq_release_workfn() completes before calling kfree(wq).
- */
- if (ret)
- kthread_flush_worker(pwq_release_worker);
return ret;
@@ -5561,6 +5514,8 @@ static int init_rescuer(struct workqueue_struct *wq)
char id_buf[WORKER_ID_LEN];
int ret;
+ lockdep_assert_held(&wq_pool_mutex);
+
if (!(wq->flags & WQ_MEM_RECLAIM))
return 0;
@@ -5585,7 +5540,7 @@ static int init_rescuer(struct workqueue_struct *wq)
wq->rescuer = rescuer;
if (wq->flags & WQ_UNBOUND)
- kthread_bind_mask(rescuer->task, wq_unbound_cpumask);
+ kthread_bind_mask(rescuer->task, unbound_effective_cpumask(wq));
else
kthread_bind_mask(rescuer->task, cpu_possible_mask);
wake_up_process(rescuer->task);
@@ -5733,21 +5688,14 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
goto err_unreg_lockdep;
}
- if (alloc_and_link_pwqs(wq) < 0)
- goto err_free_node_nr_active;
-
- if (wq_online && init_rescuer(wq) < 0)
- goto err_destroy;
-
- if ((wq->flags & WQ_SYSFS) && workqueue_sysfs_register(wq))
- goto err_destroy;
-
/*
- * wq_pool_mutex protects global freeze state and workqueues list.
- * Grab it, adjust max_active and add the new @wq to workqueues
- * list.
+ * wq_pool_mutex protects the workqueues list, allocations of PWQs,
+ * and the global freeze state.
*/
- mutex_lock(&wq_pool_mutex);
+ apply_wqattrs_lock();
+
+ if (alloc_and_link_pwqs(wq) < 0)
+ goto err_unlock_free_node_nr_active;
mutex_lock(&wq->mutex);
wq_adjust_max_active(wq);
@@ -5755,13 +5703,27 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
list_add_tail_rcu(&wq->list, &workqueues);
- mutex_unlock(&wq_pool_mutex);
+ if (wq_online && init_rescuer(wq) < 0)
+ goto err_unlock_destroy;
+
+ apply_wqattrs_unlock();
+
+ if ((wq->flags & WQ_SYSFS) && workqueue_sysfs_register(wq))
+ goto err_destroy;
return wq;
-err_free_node_nr_active:
- if (wq->flags & WQ_UNBOUND)
+err_unlock_free_node_nr_active:
+ apply_wqattrs_unlock();
+ /*
+ * Failed alloc_and_link_pwqs() may leave pending pwq->release_work,
+ * flushing the pwq_release_worker ensures that the pwq_release_workfn()
+ * completes before calling kfree(wq).
+ */
+ if (wq->flags & WQ_UNBOUND) {
+ kthread_flush_worker(pwq_release_worker);
free_node_nr_active(wq->node_nr_active);
+ }
err_unreg_lockdep:
wq_unregister_lockdep(wq);
wq_free_lockdep(wq);
@@ -5769,6 +5731,8 @@ err_free_wq:
free_workqueue_attrs(wq->unbound_attrs);
kfree(wq);
return NULL;
+err_unlock_destroy:
+ apply_wqattrs_unlock();
err_destroy:
destroy_workqueue(wq);
return NULL;
@@ -6607,6 +6571,8 @@ int workqueue_online_cpu(unsigned int cpu)
mutex_lock(&wq_pool_mutex);
+ cpumask_set_cpu(cpu, wq_online_cpumask);
+
for_each_pool(pool, pi) {
/* BH pools aren't affected by hotplug */
if (pool->flags & POOL_BH)
@@ -6629,7 +6595,7 @@ int workqueue_online_cpu(unsigned int cpu)
int tcpu;
for_each_cpu(tcpu, pt->pod_cpus[pt->cpu_pod[cpu]])
- wq_update_pod(wq, tcpu, cpu, true);
+ unbound_wq_update_pwq(wq, tcpu);
mutex_lock(&wq->mutex);
wq_update_node_max_active(wq, -1);
@@ -6653,6 +6619,9 @@ int workqueue_offline_cpu(unsigned int cpu)
/* update pod affinity of unbound workqueues */
mutex_lock(&wq_pool_mutex);
+
+ cpumask_clear_cpu(cpu, wq_online_cpumask);
+
list_for_each_entry(wq, &workqueues, list) {
struct workqueue_attrs *attrs = wq->unbound_attrs;
@@ -6661,7 +6630,7 @@ int workqueue_offline_cpu(unsigned int cpu)
int tcpu;
for_each_cpu(tcpu, pt->pod_cpus[pt->cpu_pod[cpu]])
- wq_update_pod(wq, tcpu, cpu, false);
+ unbound_wq_update_pwq(wq, tcpu);
mutex_lock(&wq->mutex);
wq_update_node_max_active(wq, cpu);
@@ -6887,8 +6856,7 @@ static int workqueue_apply_unbound_cpumask(const cpumask_var_t unbound_cpumask)
* @exclude_cpumask: the cpumask to be excluded from wq_unbound_cpumask
*
* This function can be called from cpuset code to provide a set of isolated
- * CPUs that should be excluded from wq_unbound_cpumask. The caller must hold
- * either cpus_read_lock or cpus_write_lock.
+ * CPUs that should be excluded from wq_unbound_cpumask.
*/
int workqueue_unbound_exclude_cpumask(cpumask_var_t exclude_cpumask)
{
@@ -6898,12 +6866,8 @@ int workqueue_unbound_exclude_cpumask(cpumask_var_t exclude_cpumask)
if (!zalloc_cpumask_var(&cpumask, GFP_KERNEL))
return -ENOMEM;
- lockdep_assert_cpus_held();
mutex_lock(&wq_pool_mutex);
- /* Save the current isolated cpumask & export it via sysfs */
- cpumask_copy(wq_isolated_cpumask, exclude_cpumask);
-
/*
* If the operation fails, it will fall back to
* wq_requested_unbound_cpumask which is initially set to
@@ -6915,6 +6879,10 @@ int workqueue_unbound_exclude_cpumask(cpumask_var_t exclude_cpumask)
if (!cpumask_equal(cpumask, wq_unbound_cpumask))
ret = workqueue_apply_unbound_cpumask(cpumask);
+ /* Save the current isolated cpumask & export it via sysfs */
+ if (!ret)
+ cpumask_copy(wq_isolated_cpumask, exclude_cpumask);
+
mutex_unlock(&wq_pool_mutex);
free_cpumask_var(cpumask);
return ret;
@@ -6948,9 +6916,8 @@ static int wq_affn_dfl_set(const char *val, const struct kernel_param *kp)
wq_affn_dfl = affn;
list_for_each_entry(wq, &workqueues, list) {
- for_each_online_cpu(cpu) {
- wq_update_pod(wq, cpu, cpu, true);
- }
+ for_each_online_cpu(cpu)
+ unbound_wq_update_pwq(wq, cpu);
}
mutex_unlock(&wq_pool_mutex);
@@ -7038,19 +7005,6 @@ static struct attribute *wq_sysfs_attrs[] = {
};
ATTRIBUTE_GROUPS(wq_sysfs);
-static void apply_wqattrs_lock(void)
-{
- /* CPUs should stay stable across pwq creations and installations */
- cpus_read_lock();
- mutex_lock(&wq_pool_mutex);
-}
-
-static void apply_wqattrs_unlock(void)
-{
- mutex_unlock(&wq_pool_mutex);
- cpus_read_unlock();
-}
-
static ssize_t wq_nice_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -7249,16 +7203,12 @@ static int workqueue_set_unbound_cpumask(cpumask_var_t cpumask)
*/
cpumask_and(cpumask, cpumask, cpu_possible_mask);
if (!cpumask_empty(cpumask)) {
+ ret = 0;
apply_wqattrs_lock();
- cpumask_copy(wq_requested_unbound_cpumask, cpumask);
- if (cpumask_equal(cpumask, wq_unbound_cpumask)) {
- ret = 0;
- goto out_unlock;
- }
-
- ret = workqueue_apply_unbound_cpumask(cpumask);
-
-out_unlock:
+ if (!cpumask_equal(cpumask, wq_unbound_cpumask))
+ ret = workqueue_apply_unbound_cpumask(cpumask);
+ if (!ret)
+ cpumask_copy(wq_requested_unbound_cpumask, cpumask);
apply_wqattrs_unlock();
}
@@ -7577,10 +7527,18 @@ static void wq_watchdog_timer_fn(struct timer_list *unused)
notrace void wq_watchdog_touch(int cpu)
{
+ unsigned long thresh = READ_ONCE(wq_watchdog_thresh) * HZ;
+ unsigned long touch_ts = READ_ONCE(wq_watchdog_touched);
+ unsigned long now = jiffies;
+
if (cpu >= 0)
- per_cpu(wq_watchdog_touched_cpu, cpu) = jiffies;
+ per_cpu(wq_watchdog_touched_cpu, cpu) = now;
+ else
+ WARN_ONCE(1, "%s should be called with valid CPU", __func__);
- wq_watchdog_touched = jiffies;
+ /* Don't unnecessarily store to global cacheline */
+ if (time_after(now, touch_ts + thresh / 4))
+ WRITE_ONCE(wq_watchdog_touched, jiffies);
}
static void wq_watchdog_set_thresh(unsigned long thresh)
@@ -7690,10 +7648,12 @@ void __init workqueue_init_early(void)
BUILD_BUG_ON(__alignof__(struct pool_workqueue) < __alignof__(long long));
+ BUG_ON(!alloc_cpumask_var(&wq_online_cpumask, GFP_KERNEL));
BUG_ON(!alloc_cpumask_var(&wq_unbound_cpumask, GFP_KERNEL));
BUG_ON(!alloc_cpumask_var(&wq_requested_unbound_cpumask, GFP_KERNEL));
BUG_ON(!zalloc_cpumask_var(&wq_isolated_cpumask, GFP_KERNEL));
+ cpumask_copy(wq_online_cpumask, cpu_online_mask);
cpumask_copy(wq_unbound_cpumask, cpu_possible_mask);
restrict_unbound_cpumask("HK_TYPE_WQ", housekeeping_cpumask(HK_TYPE_WQ));
restrict_unbound_cpumask("HK_TYPE_DOMAIN", housekeeping_cpumask(HK_TYPE_DOMAIN));
@@ -7704,8 +7664,8 @@ void __init workqueue_init_early(void)
pwq_cache = KMEM_CACHE(pool_workqueue, SLAB_PANIC);
- wq_update_pod_attrs_buf = alloc_workqueue_attrs();
- BUG_ON(!wq_update_pod_attrs_buf);
+ unbound_wq_update_pwq_attrs_buf = alloc_workqueue_attrs();
+ BUG_ON(!unbound_wq_update_pwq_attrs_buf);
/*
* If nohz_full is enabled, set power efficient workqueue as unbound.
@@ -7970,12 +7930,12 @@ void __init workqueue_init_topology(void)
/*
* Workqueues allocated earlier would have all CPUs sharing the default
- * worker pool. Explicitly call wq_update_pod() on all workqueue and CPU
- * combinations to apply per-pod sharing.
+ * worker pool. Explicitly call unbound_wq_update_pwq() on all workqueue
+ * and CPU combinations to apply per-pod sharing.
*/
list_for_each_entry(wq, &workqueues, list) {
for_each_online_cpu(cpu)
- wq_update_pod(wq, cpu, cpu, true);
+ unbound_wq_update_pwq(wq, cpu);
if (wq->flags & WQ_UNBOUND) {
mutex_lock(&wq->mutex);
wq_update_node_max_active(wq, -1);
diff --git a/lib/Makefile b/lib/Makefile
index 3b1769045651..30337431d10e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -426,3 +426,7 @@ $(obj)/$(TEST_FORTIFY_LOG): $(addprefix $(obj)/, $(TEST_FORTIFY_LOGS)) FORCE
ifeq ($(CONFIG_FORTIFY_SOURCE),y)
$(obj)/string.o: $(obj)/$(TEST_FORTIFY_LOG)
endif
+
+# Some architectures define __NO_FORTIFY if __SANITIZE_ADDRESS__ is undefined.
+# Pass CFLAGS_KASAN to avoid warnings.
+$(foreach x, $(patsubst %.log,%.o,$(TEST_FORTIFY_LOGS)), $(eval KASAN_SANITIZE_$(x) := y))
diff --git a/lib/build_OID_registry b/lib/build_OID_registry
index 56d8bafeb848..8267e8d71338 100755
--- a/lib/build_OID_registry
+++ b/lib/build_OID_registry
@@ -38,7 +38,9 @@ close IN_FILE || die;
#
open C_FILE, ">$ARGV[1]" or die;
print C_FILE "/*\n";
-print C_FILE " * Automatically generated by ", $0 =~ s#^\Q$abs_srctree/\E##r, ". Do not edit\n";
+my $scriptname = $0;
+$scriptname =~ s#^\Q$abs_srctree/\E##;
+print C_FILE " * Automatically generated by ", $scriptname, ". Do not edit\n";
print C_FILE " */\n";
#
diff --git a/lib/closure.c b/lib/closure.c
index c971216d9d77..116afae2eed9 100644
--- a/lib/closure.c
+++ b/lib/closure.c
@@ -244,6 +244,9 @@ void closure_debug_destroy(struct closure *cl)
{
unsigned long flags;
+ if (cl->magic == CLOSURE_MAGIC_STACK)
+ return;
+
BUG_ON(cl->magic != CLOSURE_MAGIC_ALIVE);
cl->magic = CLOSURE_MAGIC_DEAD;
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index fb12a9bacd2f..7cea91e193a8 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -78,16 +78,17 @@ static bool obj_freeing;
/* The number of objs on the global free list */
static int obj_nr_tofree;
-static int debug_objects_maxchain __read_mostly;
-static int __maybe_unused debug_objects_maxchecked __read_mostly;
-static int debug_objects_fixups __read_mostly;
-static int debug_objects_warnings __read_mostly;
-static int debug_objects_enabled __read_mostly
- = CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT;
-static int debug_objects_pool_size __read_mostly
- = ODEBUG_POOL_SIZE;
-static int debug_objects_pool_min_level __read_mostly
- = ODEBUG_POOL_MIN_LEVEL;
+static int __data_racy debug_objects_maxchain __read_mostly;
+static int __data_racy __maybe_unused debug_objects_maxchecked __read_mostly;
+static int __data_racy debug_objects_fixups __read_mostly;
+static int __data_racy debug_objects_warnings __read_mostly;
+static int __data_racy debug_objects_enabled __read_mostly
+ = CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT;
+static int __data_racy debug_objects_pool_size __read_mostly
+ = ODEBUG_POOL_SIZE;
+static int __data_racy debug_objects_pool_min_level __read_mostly
+ = ODEBUG_POOL_MIN_LEVEL;
+
static const struct debug_obj_descr *descr_test __read_mostly;
static struct kmem_cache *obj_cache __ro_after_init;
diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index 899850bd6f0b..c01eaafd8041 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -140,14 +140,14 @@ static __always_inline int do_hres(const struct vdso_data *vd, clockid_t clk,
do {
/*
- * Open coded to handle VDSO_CLOCKMODE_TIMENS. Time namespace
- * enabled tasks have a special VVAR page installed which
- * has vd->seq set to 1 and vd->clock_mode set to
- * VDSO_CLOCKMODE_TIMENS. For non time namespace affected tasks
- * this does not affect performance because if vd->seq is
- * odd, i.e. a concurrent update is in progress the extra
- * check for vd->clock_mode is just a few extra
- * instructions while spin waiting for vd->seq to become
+ * Open coded function vdso_read_begin() to handle
+ * VDSO_CLOCKMODE_TIMENS. Time namespace enabled tasks have a
+ * special VVAR page installed which has vd->seq set to 1 and
+ * vd->clock_mode set to VDSO_CLOCKMODE_TIMENS. For non time
+ * namespace affected tasks this does not affect performance
+ * because if vd->seq is odd, i.e. a concurrent update is in
+ * progress the extra check for vd->clock_mode is just a few
+ * extra instructions while spin waiting for vd->seq to become
* even again.
*/
while (unlikely((seq = READ_ONCE(vd->seq)) & 1)) {
@@ -223,8 +223,8 @@ static __always_inline int do_coarse(const struct vdso_data *vd, clockid_t clk,
do {
/*
- * Open coded to handle VDSO_CLOCK_TIMENS. See comment in
- * do_hres().
+ * Open coded function vdso_read_begin() to handle
+ * VDSO_CLOCK_TIMENS. See comment in do_hres().
*/
while ((seq = READ_ONCE(vd->seq)) & 1) {
if (IS_ENABLED(CONFIG_TIME_NS) &&
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 6392f1cc97a3..e66823d6b10b 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1358,14 +1358,31 @@ static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
* access frequencies are similar. This is for minimizing the monitoring
* overhead under the dynamically changeable access pattern. If a merge was
* unnecessarily made, later 'kdamond_split_regions()' will revert it.
+ *
+ * The total number of regions could be higher than the user-defined limit,
+ * max_nr_regions for some cases. For example, the user can update
+ * max_nr_regions to a number that lower than the current number of regions
+ * while DAMON is running. For such a case, repeat merging until the limit is
+ * met while increasing @threshold up to possible maximum level.
*/
static void kdamond_merge_regions(struct damon_ctx *c, unsigned int threshold,
unsigned long sz_limit)
{
struct damon_target *t;
-
- damon_for_each_target(t, c)
- damon_merge_regions_of(t, threshold, sz_limit);
+ unsigned int nr_regions;
+ unsigned int max_thres;
+
+ max_thres = c->attrs.aggr_interval /
+ (c->attrs.sample_interval ? c->attrs.sample_interval : 1);
+ do {
+ nr_regions = 0;
+ damon_for_each_target(t, c) {
+ damon_merge_regions_of(t, threshold, sz_limit);
+ nr_regions += damon_nr_regions(t);
+ }
+ threshold = max(1, threshold * 2);
+ } while (nr_regions > c->attrs.max_nr_regions &&
+ threshold / 2 < max_thres);
}
/*
diff --git a/mm/filemap.c b/mm/filemap.c
index 876cc64aadd7..657bcd887fdb 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1847,7 +1847,7 @@ repeat:
if (!folio || xa_is_value(folio))
goto out;
- if (!folio_try_get_rcu(folio))
+ if (!folio_try_get(folio))
goto repeat;
if (unlikely(folio != xas_reload(&xas))) {
@@ -2001,7 +2001,7 @@ retry:
if (!folio || xa_is_value(folio))
return folio;
- if (!folio_try_get_rcu(folio))
+ if (!folio_try_get(folio))
goto reset;
if (unlikely(folio != xas_reload(xas))) {
@@ -2181,7 +2181,7 @@ unsigned filemap_get_folios_contig(struct address_space *mapping,
if (xa_is_value(folio))
goto update_start;
- if (!folio_try_get_rcu(folio))
+ if (!folio_try_get(folio))
goto retry;
if (unlikely(folio != xas_reload(&xas)))
@@ -2313,7 +2313,7 @@ static void filemap_get_read_batch(struct address_space *mapping,
break;
if (xa_is_sibling(folio))
break;
- if (!folio_try_get_rcu(folio))
+ if (!folio_try_get(folio))
goto retry;
if (unlikely(folio != xas_reload(&xas)))
@@ -3124,7 +3124,7 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf)
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
/* Use the readahead code, even if readahead is disabled */
- if (vm_flags & VM_HUGEPAGE) {
+ if ((vm_flags & VM_HUGEPAGE) && HPAGE_PMD_ORDER <= MAX_PAGECACHE_ORDER) {
fpin = maybe_unlock_mmap_for_io(vmf, fpin);
ractl._index &= ~((unsigned long)HPAGE_PMD_NR - 1);
ra->size = HPAGE_PMD_NR;
@@ -3231,7 +3231,8 @@ static vm_fault_t filemap_fault_recheck_pte_none(struct vm_fault *vmf)
if (!(vmf->flags & FAULT_FLAG_ORIG_PTE_VALID))
return 0;
- ptep = pte_offset_map(vmf->pmd, vmf->address);
+ ptep = pte_offset_map_nolock(vma->vm_mm, vmf->pmd, vmf->address,
+ &vmf->ptl);
if (unlikely(!ptep))
return VM_FAULT_NOPAGE;
@@ -3472,7 +3473,7 @@ static struct folio *next_uptodate_folio(struct xa_state *xas,
continue;
if (folio_test_locked(folio))
continue;
- if (!folio_try_get_rcu(folio))
+ if (!folio_try_get(folio))
continue;
/* Has the page moved or been split? */
if (unlikely(folio != xas_reload(xas)))
@@ -4248,6 +4249,9 @@ static void filemap_cachestat(struct address_space *mapping,
XA_STATE(xas, &mapping->i_pages, first_index);
struct folio *folio;
+ /* Flush stats (and potentially sleep) outside the RCU read section. */
+ mem_cgroup_flush_stats_ratelimited(NULL);
+
rcu_read_lock();
xas_for_each(&xas, folio, last_index) {
int order;
@@ -4311,7 +4315,7 @@ static void filemap_cachestat(struct address_space *mapping,
goto resched;
}
#endif
- if (workingset_test_recent(shadow, true, &workingset))
+ if (workingset_test_recent(shadow, true, &workingset, false))
cs->nr_recently_evicted += nr_pages;
goto resched;
diff --git a/mm/gup.c b/mm/gup.c
index ca0f5cedce9b..f1d6bc06eb52 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -76,7 +76,7 @@ retry:
folio = page_folio(page);
if (WARN_ON_ONCE(folio_ref_count(folio) < 0))
return NULL;
- if (unlikely(!folio_ref_try_add_rcu(folio, refs)))
+ if (unlikely(!folio_ref_try_add(folio, refs)))
return NULL;
/*
@@ -97,95 +97,6 @@ retry:
return folio;
}
-/**
- * try_grab_folio() - Attempt to get or pin a folio.
- * @page: pointer to page to be grabbed
- * @refs: the value to (effectively) add to the folio's refcount
- * @flags: gup flags: these are the FOLL_* flag values.
- *
- * "grab" names in this file mean, "look at flags to decide whether to use
- * FOLL_PIN or FOLL_GET behavior, when incrementing the folio's refcount.
- *
- * Either FOLL_PIN or FOLL_GET (or neither) must be set, but not both at the
- * same time. (That's true throughout the get_user_pages*() and
- * pin_user_pages*() APIs.) Cases:
- *
- * FOLL_GET: folio's refcount will be incremented by @refs.
- *
- * FOLL_PIN on large folios: folio's refcount will be incremented by
- * @refs, and its pincount will be incremented by @refs.
- *
- * FOLL_PIN on single-page folios: folio's refcount will be incremented by
- * @refs * GUP_PIN_COUNTING_BIAS.
- *
- * Return: The folio containing @page (with refcount appropriately
- * incremented) for success, or NULL upon failure. If neither FOLL_GET
- * nor FOLL_PIN was set, that's considered failure, and furthermore,
- * a likely bug in the caller, so a warning is also emitted.
- */
-struct folio *try_grab_folio(struct page *page, int refs, unsigned int flags)
-{
- struct folio *folio;
-
- if (WARN_ON_ONCE((flags & (FOLL_GET | FOLL_PIN)) == 0))
- return NULL;
-
- if (unlikely(!(flags & FOLL_PCI_P2PDMA) && is_pci_p2pdma_page(page)))
- return NULL;
-
- if (flags & FOLL_GET)
- return try_get_folio(page, refs);
-
- /* FOLL_PIN is set */
-
- /*
- * Don't take a pin on the zero page - it's not going anywhere
- * and it is used in a *lot* of places.
- */
- if (is_zero_page(page))
- return page_folio(page);
-
- folio = try_get_folio(page, refs);
- if (!folio)
- return NULL;
-
- /*
- * Can't do FOLL_LONGTERM + FOLL_PIN gup fast path if not in a
- * right zone, so fail and let the caller fall back to the slow
- * path.
- */
- if (unlikely((flags & FOLL_LONGTERM) &&
- !folio_is_longterm_pinnable(folio))) {
- if (!put_devmap_managed_folio_refs(folio, refs))
- folio_put_refs(folio, refs);
- return NULL;
- }
-
- /*
- * When pinning a large folio, use an exact count to track it.
- *
- * However, be sure to *also* increment the normal folio
- * refcount field at least once, so that the folio really
- * is pinned. That's why the refcount from the earlier
- * try_get_folio() is left intact.
- */
- if (folio_test_large(folio))
- atomic_add(refs, &folio->_pincount);
- else
- folio_ref_add(folio,
- refs * (GUP_PIN_COUNTING_BIAS - 1));
- /*
- * Adjust the pincount before re-checking the PTE for changes.
- * This is essentially a smp_mb() and is paired with a memory
- * barrier in folio_try_share_anon_rmap_*().
- */
- smp_mb__after_atomic();
-
- node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, refs);
-
- return folio;
-}
-
static void gup_put_folio(struct folio *folio, int refs, unsigned int flags)
{
if (flags & FOLL_PIN) {
@@ -203,58 +114,59 @@ static void gup_put_folio(struct folio *folio, int refs, unsigned int flags)
}
/**
- * try_grab_page() - elevate a page's refcount by a flag-dependent amount
- * @page: pointer to page to be grabbed
- * @flags: gup flags: these are the FOLL_* flag values.
+ * try_grab_folio() - add a folio's refcount by a flag-dependent amount
+ * @folio: pointer to folio to be grabbed
+ * @refs: the value to (effectively) add to the folio's refcount
+ * @flags: gup flags: these are the FOLL_* flag values
*
* This might not do anything at all, depending on the flags argument.
*
* "grab" names in this file mean, "look at flags to decide whether to use
- * FOLL_PIN or FOLL_GET behavior, when incrementing the page's refcount.
+ * FOLL_PIN or FOLL_GET behavior, when incrementing the folio's refcount.
*
* Either FOLL_PIN or FOLL_GET (or neither) may be set, but not both at the same
- * time. Cases: please see the try_grab_folio() documentation, with
- * "refs=1".
+ * time.
*
* Return: 0 for success, or if no action was required (if neither FOLL_PIN
* nor FOLL_GET was set, nothing is done). A negative error code for failure:
*
- * -ENOMEM FOLL_GET or FOLL_PIN was set, but the page could not
+ * -ENOMEM FOLL_GET or FOLL_PIN was set, but the folio could not
* be grabbed.
+ *
+ * It is called when we have a stable reference for the folio, typically in
+ * GUP slow path.
*/
-int __must_check try_grab_page(struct page *page, unsigned int flags)
+int __must_check try_grab_folio(struct folio *folio, int refs,
+ unsigned int flags)
{
- struct folio *folio = page_folio(page);
-
if (WARN_ON_ONCE(folio_ref_count(folio) <= 0))
return -ENOMEM;
- if (unlikely(!(flags & FOLL_PCI_P2PDMA) && is_pci_p2pdma_page(page)))
+ if (unlikely(!(flags & FOLL_PCI_P2PDMA) && is_pci_p2pdma_page(&folio->page)))
return -EREMOTEIO;
if (flags & FOLL_GET)
- folio_ref_inc(folio);
+ folio_ref_add(folio, refs);
else if (flags & FOLL_PIN) {
/*
* Don't take a pin on the zero page - it's not going anywhere
* and it is used in a *lot* of places.
*/
- if (is_zero_page(page))
+ if (is_zero_folio(folio))
return 0;
/*
- * Similar to try_grab_folio(): be sure to *also*
- * increment the normal page refcount field at least once,
+ * Increment the normal page refcount field at least once,
* so that the page really is pinned.
*/
if (folio_test_large(folio)) {
- folio_ref_add(folio, 1);
- atomic_add(1, &folio->_pincount);
+ folio_ref_add(folio, refs);
+ atomic_add(refs, &folio->_pincount);
} else {
- folio_ref_add(folio, GUP_PIN_COUNTING_BIAS);
+ folio_ref_add(folio, refs * GUP_PIN_COUNTING_BIAS);
}
- node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, 1);
+ node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, refs);
}
return 0;
@@ -515,6 +427,102 @@ static int record_subpages(struct page *page, unsigned long sz,
return nr;
}
+
+/**
+ * try_grab_folio_fast() - Attempt to get or pin a folio in fast path.
+ * @page: pointer to page to be grabbed
+ * @refs: the value to (effectively) add to the folio's refcount
+ * @flags: gup flags: these are the FOLL_* flag values.
+ *
+ * "grab" names in this file mean, "look at flags to decide whether to use
+ * FOLL_PIN or FOLL_GET behavior, when incrementing the folio's refcount.
+ *
+ * Either FOLL_PIN or FOLL_GET (or neither) must be set, but not both at the
+ * same time. (That's true throughout the get_user_pages*() and
+ * pin_user_pages*() APIs.) Cases:
+ *
+ * FOLL_GET: folio's refcount will be incremented by @refs.
+ *
+ * FOLL_PIN on large folios: folio's refcount will be incremented by
+ * @refs, and its pincount will be incremented by @refs.
+ *
+ * FOLL_PIN on single-page folios: folio's refcount will be incremented by
+ * @refs * GUP_PIN_COUNTING_BIAS.
+ *
+ * Return: The folio containing @page (with refcount appropriately
+ * incremented) for success, or NULL upon failure. If neither FOLL_GET
+ * nor FOLL_PIN was set, that's considered failure, and furthermore,
+ * a likely bug in the caller, so a warning is also emitted.
+ *
+ * It uses add ref unless zero to elevate the folio refcount and must be called
+ * in fast path only.
+ */
+static struct folio *try_grab_folio_fast(struct page *page, int refs,
+ unsigned int flags)
+{
+ struct folio *folio;
+
+ /* Raise warn if it is not called in fast GUP */
+ VM_WARN_ON_ONCE(!irqs_disabled());
+
+ if (WARN_ON_ONCE((flags & (FOLL_GET | FOLL_PIN)) == 0))
+ return NULL;
+
+ if (unlikely(!(flags & FOLL_PCI_P2PDMA) && is_pci_p2pdma_page(page)))
+ return NULL;
+
+ if (flags & FOLL_GET)
+ return try_get_folio(page, refs);
+
+ /* FOLL_PIN is set */
+
+ /*
+ * Don't take a pin on the zero page - it's not going anywhere
+ * and it is used in a *lot* of places.
+ */
+ if (is_zero_page(page))
+ return page_folio(page);
+
+ folio = try_get_folio(page, refs);
+ if (!folio)
+ return NULL;
+
+ /*
+ * Can't do FOLL_LONGTERM + FOLL_PIN gup fast path if not in a
+ * right zone, so fail and let the caller fall back to the slow
+ * path.
+ */
+ if (unlikely((flags & FOLL_LONGTERM) &&
+ !folio_is_longterm_pinnable(folio))) {
+ if (!put_devmap_managed_folio_refs(folio, refs))
+ folio_put_refs(folio, refs);
+ return NULL;
+ }
+
+ /*
+ * When pinning a large folio, use an exact count to track it.
+ *
+ * However, be sure to *also* increment the normal folio
+ * refcount field at least once, so that the folio really
+ * is pinned. That's why the refcount from the earlier
+ * try_get_folio() is left intact.
+ */
+ if (folio_test_large(folio))
+ atomic_add(refs, &folio->_pincount);
+ else
+ folio_ref_add(folio,
+ refs * (GUP_PIN_COUNTING_BIAS - 1));
+ /*
+ * Adjust the pincount before re-checking the PTE for changes.
+ * This is essentially a smp_mb() and is paired with a memory
+ * barrier in folio_try_share_anon_rmap_*().
+ */
+ smp_mb__after_atomic();
+
+ node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, refs);
+
+ return folio;
+}
#endif /* CONFIG_ARCH_HAS_HUGEPD || CONFIG_HAVE_GUP_FAST */
#ifdef CONFIG_ARCH_HAS_HUGEPD
@@ -535,7 +543,7 @@ static unsigned long hugepte_addr_end(unsigned long addr, unsigned long end,
*/
static int gup_hugepte(struct vm_area_struct *vma, pte_t *ptep, unsigned long sz,
unsigned long addr, unsigned long end, unsigned int flags,
- struct page **pages, int *nr)
+ struct page **pages, int *nr, bool fast)
{
unsigned long pte_end;
struct page *page;
@@ -558,9 +566,15 @@ static int gup_hugepte(struct vm_area_struct *vma, pte_t *ptep, unsigned long sz
page = pte_page(pte);
refs = record_subpages(page, sz, addr, end, pages + *nr);
- folio = try_grab_folio(page, refs, flags);
- if (!folio)
- return 0;
+ if (fast) {
+ folio = try_grab_folio_fast(page, refs, flags);
+ if (!folio)
+ return 0;
+ } else {
+ folio = page_folio(page);
+ if (try_grab_folio(folio, refs, flags))
+ return 0;
+ }
if (unlikely(pte_val(pte) != pte_val(ptep_get(ptep)))) {
gup_put_folio(folio, refs, flags);
@@ -588,7 +602,7 @@ static int gup_hugepte(struct vm_area_struct *vma, pte_t *ptep, unsigned long sz
static int gup_hugepd(struct vm_area_struct *vma, hugepd_t hugepd,
unsigned long addr, unsigned int pdshift,
unsigned long end, unsigned int flags,
- struct page **pages, int *nr)
+ struct page **pages, int *nr, bool fast)
{
pte_t *ptep;
unsigned long sz = 1UL << hugepd_shift(hugepd);
@@ -598,7 +612,8 @@ static int gup_hugepd(struct vm_area_struct *vma, hugepd_t hugepd,
ptep = hugepte_offset(hugepd, addr, pdshift);
do {
next = hugepte_addr_end(addr, end, sz);
- ret = gup_hugepte(vma, ptep, sz, addr, end, flags, pages, nr);
+ ret = gup_hugepte(vma, ptep, sz, addr, end, flags, pages, nr,
+ fast);
if (ret != 1)
return ret;
} while (ptep++, addr = next, addr != end);
@@ -625,7 +640,7 @@ static struct page *follow_hugepd(struct vm_area_struct *vma, hugepd_t hugepd,
ptep = hugepte_offset(hugepd, addr, pdshift);
ptl = huge_pte_lock(h, vma->vm_mm, ptep);
ret = gup_hugepd(vma, hugepd, addr, pdshift, addr + PAGE_SIZE,
- flags, &page, &nr);
+ flags, &page, &nr, false);
spin_unlock(ptl);
if (ret == 1) {
@@ -642,7 +657,7 @@ static struct page *follow_hugepd(struct vm_area_struct *vma, hugepd_t hugepd,
static inline int gup_hugepd(struct vm_area_struct *vma, hugepd_t hugepd,
unsigned long addr, unsigned int pdshift,
unsigned long end, unsigned int flags,
- struct page **pages, int *nr)
+ struct page **pages, int *nr, bool fast)
{
return 0;
}
@@ -729,7 +744,7 @@ static struct page *follow_huge_pud(struct vm_area_struct *vma,
gup_must_unshare(vma, flags, page))
return ERR_PTR(-EMLINK);
- ret = try_grab_page(page, flags);
+ ret = try_grab_folio(page_folio(page), 1, flags);
if (ret)
page = ERR_PTR(ret);
else
@@ -806,7 +821,7 @@ static struct page *follow_huge_pmd(struct vm_area_struct *vma,
VM_BUG_ON_PAGE((flags & FOLL_PIN) && PageAnon(page) &&
!PageAnonExclusive(page), page);
- ret = try_grab_page(page, flags);
+ ret = try_grab_folio(page_folio(page), 1, flags);
if (ret)
return ERR_PTR(ret);
@@ -968,8 +983,8 @@ static struct page *follow_page_pte(struct vm_area_struct *vma,
VM_BUG_ON_PAGE((flags & FOLL_PIN) && PageAnon(page) &&
!PageAnonExclusive(page), page);
- /* try_grab_page() does nothing unless FOLL_GET or FOLL_PIN is set. */
- ret = try_grab_page(page, flags);
+ /* try_grab_folio() does nothing unless FOLL_GET or FOLL_PIN is set. */
+ ret = try_grab_folio(page_folio(page), 1, flags);
if (unlikely(ret)) {
page = ERR_PTR(ret);
goto out;
@@ -1233,7 +1248,7 @@ static int get_gate_page(struct mm_struct *mm, unsigned long address,
goto unmap;
*page = pte_page(entry);
}
- ret = try_grab_page(*page, gup_flags);
+ ret = try_grab_folio(page_folio(*page), 1, gup_flags);
if (unlikely(ret))
goto unmap;
out:
@@ -1636,20 +1651,19 @@ next_page:
* pages.
*/
if (page_increm > 1) {
- struct folio *folio;
+ struct folio *folio = page_folio(page);
/*
* Since we already hold refcount on the
* large folio, this should never fail.
*/
- folio = try_grab_folio(page, page_increm - 1,
- foll_flags);
- if (WARN_ON_ONCE(!folio)) {
+ if (try_grab_folio(folio, page_increm - 1,
+ foll_flags)) {
/*
* Release the 1st page ref if the
* folio is problematic, fail hard.
*/
- gup_put_folio(page_folio(page), 1,
+ gup_put_folio(folio, 1,
foll_flags);
ret = -EFAULT;
goto out;
@@ -2797,7 +2811,6 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
* This code is based heavily on the PowerPC implementation by Nick Piggin.
*/
#ifdef CONFIG_HAVE_GUP_FAST
-
/*
* Used in the GUP-fast path to determine whether GUP is permitted to work on
* a specific folio.
@@ -2962,7 +2975,7 @@ static int gup_fast_pte_range(pmd_t pmd, pmd_t *pmdp, unsigned long addr,
VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
page = pte_page(pte);
- folio = try_grab_folio(page, 1, flags);
+ folio = try_grab_folio_fast(page, 1, flags);
if (!folio)
goto pte_unmap;
@@ -3049,7 +3062,7 @@ static int gup_fast_devmap_leaf(unsigned long pfn, unsigned long addr,
break;
}
- folio = try_grab_folio(page, 1, flags);
+ folio = try_grab_folio_fast(page, 1, flags);
if (!folio) {
gup_fast_undo_dev_pagemap(nr, nr_start, flags, pages);
break;
@@ -3138,7 +3151,7 @@ static int gup_fast_pmd_leaf(pmd_t orig, pmd_t *pmdp, unsigned long addr,
page = pmd_page(orig);
refs = record_subpages(page, PMD_SIZE, addr, end, pages + *nr);
- folio = try_grab_folio(page, refs, flags);
+ folio = try_grab_folio_fast(page, refs, flags);
if (!folio)
return 0;
@@ -3182,7 +3195,7 @@ static int gup_fast_pud_leaf(pud_t orig, pud_t *pudp, unsigned long addr,
page = pud_page(orig);
refs = record_subpages(page, PUD_SIZE, addr, end, pages + *nr);
- folio = try_grab_folio(page, refs, flags);
+ folio = try_grab_folio_fast(page, refs, flags);
if (!folio)
return 0;
@@ -3222,7 +3235,7 @@ static int gup_fast_pgd_leaf(pgd_t orig, pgd_t *pgdp, unsigned long addr,
page = pgd_page(orig);
refs = record_subpages(page, PGDIR_SIZE, addr, end, pages + *nr);
- folio = try_grab_folio(page, refs, flags);
+ folio = try_grab_folio_fast(page, refs, flags);
if (!folio)
return 0;
@@ -3276,7 +3289,8 @@ static int gup_fast_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,
* pmd format and THP pmd format
*/
if (gup_hugepd(NULL, __hugepd(pmd_val(pmd)), addr,
- PMD_SHIFT, next, flags, pages, nr) != 1)
+ PMD_SHIFT, next, flags, pages, nr,
+ true) != 1)
return 0;
} else if (!gup_fast_pte_range(pmd, pmdp, addr, next, flags,
pages, nr))
@@ -3306,7 +3320,8 @@ static int gup_fast_pud_range(p4d_t *p4dp, p4d_t p4d, unsigned long addr,
return 0;
} else if (unlikely(is_hugepd(__hugepd(pud_val(pud))))) {
if (gup_hugepd(NULL, __hugepd(pud_val(pud)), addr,
- PUD_SHIFT, next, flags, pages, nr) != 1)
+ PUD_SHIFT, next, flags, pages, nr,
+ true) != 1)
return 0;
} else if (!gup_fast_pmd_range(pudp, pud, addr, next, flags,
pages, nr))
@@ -3333,7 +3348,8 @@ static int gup_fast_p4d_range(pgd_t *pgdp, pgd_t pgd, unsigned long addr,
BUILD_BUG_ON(p4d_leaf(p4d));
if (unlikely(is_hugepd(__hugepd(p4d_val(p4d))))) {
if (gup_hugepd(NULL, __hugepd(p4d_val(p4d)), addr,
- P4D_SHIFT, next, flags, pages, nr) != 1)
+ P4D_SHIFT, next, flags, pages, nr,
+ true) != 1)
return 0;
} else if (!gup_fast_pud_range(p4dp, p4d, addr, next, flags,
pages, nr))
@@ -3362,7 +3378,8 @@ static void gup_fast_pgd_range(unsigned long addr, unsigned long end,
return;
} else if (unlikely(is_hugepd(__hugepd(pgd_val(pgd))))) {
if (gup_hugepd(NULL, __hugepd(pgd_val(pgd)), addr,
- PGDIR_SHIFT, next, flags, pages, nr) != 1)
+ PGDIR_SHIFT, next, flags, pages, nr,
+ true) != 1)
return;
} else if (!gup_fast_p4d_range(pgdp, pgd, addr, next, flags,
pages, nr))
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index db7946a0a28c..2120f7478e55 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1331,7 +1331,7 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr,
if (!*pgmap)
return ERR_PTR(-EFAULT);
page = pfn_to_page(pfn);
- ret = try_grab_page(page, flags);
+ ret = try_grab_folio(page_folio(page), 1, flags);
if (ret)
page = ERR_PTR(ret);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index f35abff8be60..43e1af868cfd 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1625,13 +1625,10 @@ static inline void destroy_compound_gigantic_folio(struct folio *folio,
* folio appears as just a compound page. Otherwise, wait until after
* allocating vmemmap to clear the flag.
*
- * A reference is held on the folio, except in the case of demote.
- *
* Must be called with hugetlb lock held.
*/
-static void __remove_hugetlb_folio(struct hstate *h, struct folio *folio,
- bool adjust_surplus,
- bool demote)
+static void remove_hugetlb_folio(struct hstate *h, struct folio *folio,
+ bool adjust_surplus)
{
int nid = folio_nid(folio);
@@ -1645,6 +1642,7 @@ static void __remove_hugetlb_folio(struct hstate *h, struct folio *folio,
list_del(&folio->lru);
if (folio_test_hugetlb_freed(folio)) {
+ folio_clear_hugetlb_freed(folio);
h->free_huge_pages--;
h->free_huge_pages_node[nid]--;
}
@@ -1661,33 +1659,13 @@ static void __remove_hugetlb_folio(struct hstate *h, struct folio *folio,
if (!folio_test_hugetlb_vmemmap_optimized(folio))
__folio_clear_hugetlb(folio);
- /*
- * In the case of demote we do not ref count the page as it will soon
- * be turned into a page of smaller size.
- */
- if (!demote)
- folio_ref_unfreeze(folio, 1);
-
h->nr_huge_pages--;
h->nr_huge_pages_node[nid]--;
}
-static void remove_hugetlb_folio(struct hstate *h, struct folio *folio,
- bool adjust_surplus)
-{
- __remove_hugetlb_folio(h, folio, adjust_surplus, false);
-}
-
-static void remove_hugetlb_folio_for_demote(struct hstate *h, struct folio *folio,
- bool adjust_surplus)
-{
- __remove_hugetlb_folio(h, folio, adjust_surplus, true);
-}
-
static void add_hugetlb_folio(struct hstate *h, struct folio *folio,
bool adjust_surplus)
{
- int zeroed;
int nid = folio_nid(folio);
VM_BUG_ON_FOLIO(!folio_test_hugetlb_vmemmap_optimized(folio), folio);
@@ -1711,21 +1689,6 @@ static void add_hugetlb_folio(struct hstate *h, struct folio *folio,
*/
folio_set_hugetlb_vmemmap_optimized(folio);
- /*
- * This folio is about to be managed by the hugetlb allocator and
- * should have no users. Drop our reference, and check for others
- * just in case.
- */
- zeroed = folio_put_testzero(folio);
- if (unlikely(!zeroed))
- /*
- * It is VERY unlikely soneone else has taken a ref
- * on the folio. In this case, we simply return as
- * free_huge_folio() will be called when this other ref
- * is dropped.
- */
- return;
-
arch_clear_hugetlb_flags(folio);
enqueue_hugetlb_folio(h, folio);
}
@@ -1763,13 +1726,6 @@ static void __update_and_free_hugetlb_folio(struct hstate *h,
}
/*
- * Move PageHWPoison flag from head page to the raw error pages,
- * which makes any healthy subpages reusable.
- */
- if (unlikely(folio_test_hwpoison(folio)))
- folio_clear_hugetlb_hwpoison(folio);
-
- /*
* If vmemmap pages were allocated above, then we need to clear the
* hugetlb flag under the hugetlb lock.
*/
@@ -1780,6 +1736,15 @@ static void __update_and_free_hugetlb_folio(struct hstate *h,
}
/*
+ * Move PageHWPoison flag from head page to the raw error pages,
+ * which makes any healthy subpages reusable.
+ */
+ if (unlikely(folio_test_hwpoison(folio)))
+ folio_clear_hugetlb_hwpoison(folio);
+
+ folio_ref_unfreeze(folio, 1);
+
+ /*
* Non-gigantic pages demoted from CMA allocated gigantic pages
* need to be given back to CMA in free_gigantic_folio.
*/
@@ -2197,6 +2162,9 @@ static struct folio *alloc_buddy_hugetlb_folio(struct hstate *h,
nid = numa_mem_id();
retry:
folio = __folio_alloc(gfp_mask, order, nid, nmask);
+ /* Ensure hugetlb folio won't have large_rmappable flag set. */
+ if (folio)
+ folio_clear_large_rmappable(folio);
if (folio && !folio_ref_freeze(folio, 1)) {
folio_put(folio);
@@ -3079,11 +3047,8 @@ retry:
free_new:
spin_unlock_irq(&hugetlb_lock);
- if (new_folio) {
- /* Folio has a zero ref count, but needs a ref to be freed */
- folio_ref_unfreeze(new_folio, 1);
+ if (new_folio)
update_and_free_hugetlb_folio(h, new_folio, false);
- }
return ret;
}
@@ -3938,7 +3903,7 @@ static int demote_free_hugetlb_folio(struct hstate *h, struct folio *folio)
target_hstate = size_to_hstate(PAGE_SIZE << h->demote_order);
- remove_hugetlb_folio_for_demote(h, folio, false);
+ remove_hugetlb_folio(h, folio, false);
spin_unlock_irq(&hugetlb_lock);
/*
@@ -3952,7 +3917,6 @@ static int demote_free_hugetlb_folio(struct hstate *h, struct folio *folio)
if (rc) {
/* Allocation of vmemmmap failed, we can not demote folio */
spin_lock_irq(&hugetlb_lock);
- folio_ref_unfreeze(folio, 1);
add_hugetlb_folio(h, folio, false);
return rc;
}
diff --git a/mm/hugetlb_vmemmap.c b/mm/hugetlb_vmemmap.c
index b9a55322e52c..8193906515c6 100644
--- a/mm/hugetlb_vmemmap.c
+++ b/mm/hugetlb_vmemmap.c
@@ -446,6 +446,8 @@ static int __hugetlb_vmemmap_restore_folio(const struct hstate *h,
unsigned long vmemmap_reuse;
VM_WARN_ON_ONCE_FOLIO(!folio_test_hugetlb(folio), folio);
+ VM_WARN_ON_ONCE_FOLIO(folio_ref_count(folio), folio);
+
if (!folio_test_hugetlb_vmemmap_optimized(folio))
return 0;
@@ -481,6 +483,9 @@ static int __hugetlb_vmemmap_restore_folio(const struct hstate *h,
*/
int hugetlb_vmemmap_restore_folio(const struct hstate *h, struct folio *folio)
{
+ /* avoid writes from page_ref_add_unless() while unfolding vmemmap */
+ synchronize_rcu();
+
return __hugetlb_vmemmap_restore_folio(h, folio, 0);
}
@@ -505,6 +510,9 @@ long hugetlb_vmemmap_restore_folios(const struct hstate *h,
long restored = 0;
long ret = 0;
+ /* avoid writes from page_ref_add_unless() while unfolding vmemmap */
+ synchronize_rcu();
+
list_for_each_entry_safe(folio, t_folio, folio_list, lru) {
if (folio_test_hugetlb_vmemmap_optimized(folio)) {
ret = __hugetlb_vmemmap_restore_folio(h, folio,
@@ -550,6 +558,8 @@ static int __hugetlb_vmemmap_optimize_folio(const struct hstate *h,
unsigned long vmemmap_reuse;
VM_WARN_ON_ONCE_FOLIO(!folio_test_hugetlb(folio), folio);
+ VM_WARN_ON_ONCE_FOLIO(folio_ref_count(folio), folio);
+
if (!vmemmap_should_optimize_folio(h, folio))
return ret;
@@ -601,6 +611,9 @@ void hugetlb_vmemmap_optimize_folio(const struct hstate *h, struct folio *folio)
{
LIST_HEAD(vmemmap_pages);
+ /* avoid writes from page_ref_add_unless() while folding vmemmap */
+ synchronize_rcu();
+
__hugetlb_vmemmap_optimize_folio(h, folio, &vmemmap_pages, 0);
free_vmemmap_page_list(&vmemmap_pages);
}
@@ -644,6 +657,9 @@ void hugetlb_vmemmap_optimize_folios(struct hstate *h, struct list_head *folio_l
flush_tlb_all();
+ /* avoid writes from page_ref_add_unless() while folding vmemmap */
+ synchronize_rcu();
+
list_for_each_entry(folio, folio_list, lru) {
int ret;
diff --git a/mm/internal.h b/mm/internal.h
index 6902b7dd8509..cc2c5e07fad3 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1182,8 +1182,8 @@ int migrate_device_coherent_page(struct page *page);
/*
* mm/gup.c
*/
-struct folio *try_grab_folio(struct page *page, int refs, unsigned int flags);
-int __must_check try_grab_page(struct page *page, unsigned int flags);
+int __must_check try_grab_folio(struct folio *folio, int refs,
+ unsigned int flags);
/*
* mm/huge_memory.c
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 774a97e6e2da..aab471791bd9 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -2000,9 +2000,9 @@ out_unlock:
if (!is_shmem) {
filemap_nr_thps_inc(mapping);
/*
- * Paired with smp_mb() in do_dentry_open() to ensure
- * i_writecount is up to date and the update to nr_thps is
- * visible. Ensures the page cache will be truncated if the
+ * Paired with the fence in do_dentry_open() -> get_write_access()
+ * to ensure i_writecount is up to date and the update to nr_thps
+ * is visible. Ensures the page cache will be truncated if the
* file is opened writable.
*/
smp_mb();
@@ -2190,8 +2190,8 @@ rollback:
if (!is_shmem && result == SCAN_COPY_MC) {
filemap_nr_thps_dec(mapping);
/*
- * Paired with smp_mb() in do_dentry_open() to
- * ensure the update to nr_thps is visible.
+ * Paired with the fence in do_dentry_open() -> get_write_access()
+ * to ensure the update to nr_thps is visible.
*/
smp_mb();
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 71fe2a95b8bd..8f2f1bb18c9c 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -7823,17 +7823,6 @@ void mem_cgroup_migrate(struct folio *old, struct folio *new)
/* Transfer the charge and the css ref */
commit_charge(new, memcg);
- /*
- * If the old folio is a large folio and is in the split queue, it needs
- * to be removed from the split queue now, in case getting an incorrect
- * split queue in destroy_large_folio() after the memcg of the old folio
- * is cleared.
- *
- * In addition, the old folio is about to be freed after migration, so
- * removing from the split queue a bit earlier seems reasonable.
- */
- if (folio_test_large(old) && folio_test_large_rmappable(old))
- folio_undo_large_rmappable(old);
old->memcg_data = 0;
}
diff --git a/mm/migrate.c b/mm/migrate.c
index 20cb9f5f7446..a8c6f466e33a 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -415,6 +415,15 @@ int folio_migrate_mapping(struct address_space *mapping,
if (folio_ref_count(folio) != expected_count)
return -EAGAIN;
+ /* Take off deferred split queue while frozen and memcg set */
+ if (folio_test_large(folio) &&
+ folio_test_large_rmappable(folio)) {
+ if (!folio_ref_freeze(folio, expected_count))
+ return -EAGAIN;
+ folio_undo_large_rmappable(folio);
+ folio_ref_unfreeze(folio, expected_count);
+ }
+
/* No turning back from here */
newfolio->index = folio->index;
newfolio->mapping = folio->mapping;
@@ -433,6 +442,10 @@ int folio_migrate_mapping(struct address_space *mapping,
return -EAGAIN;
}
+ /* Take off deferred split queue while frozen and memcg set */
+ if (folio_test_large(folio) && folio_test_large_rmappable(folio))
+ folio_undo_large_rmappable(folio);
+
/*
* Now we know that no one else is looking at the folio:
* no turning back from here.
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 12c9297ed4a7..8a1c92090129 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -415,13 +415,20 @@ static void domain_dirty_limits(struct dirty_throttle_control *dtc)
else
bg_thresh = (bg_ratio * available_memory) / PAGE_SIZE;
- if (bg_thresh >= thresh)
- bg_thresh = thresh / 2;
tsk = current;
if (rt_task(tsk)) {
bg_thresh += bg_thresh / 4 + global_wb_domain.dirty_limit / 32;
thresh += thresh / 4 + global_wb_domain.dirty_limit / 32;
}
+ /*
+ * Dirty throttling logic assumes the limits in page units fit into
+ * 32-bits. This gives 16TB dirty limits max which is hopefully enough.
+ */
+ if (thresh > UINT_MAX)
+ thresh = UINT_MAX;
+ /* This makes sure bg_thresh is within 32-bits as well */
+ if (bg_thresh >= thresh)
+ bg_thresh = thresh / 2;
dtc->thresh = thresh;
dtc->bg_thresh = bg_thresh;
@@ -471,7 +478,11 @@ static unsigned long node_dirty_limit(struct pglist_data *pgdat)
if (rt_task(tsk))
dirty += dirty / 4;
- return dirty;
+ /*
+ * Dirty throttling logic assumes the limits in page units fit into
+ * 32-bits. This gives 16TB dirty limits max which is hopefully enough.
+ */
+ return min_t(unsigned long, dirty, UINT_MAX);
}
/**
@@ -508,10 +519,17 @@ static int dirty_background_bytes_handler(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
+ unsigned long old_bytes = dirty_background_bytes;
ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
- if (ret == 0 && write)
+ if (ret == 0 && write) {
+ if (DIV_ROUND_UP(dirty_background_bytes, PAGE_SIZE) >
+ UINT_MAX) {
+ dirty_background_bytes = old_bytes;
+ return -ERANGE;
+ }
dirty_background_ratio = 0;
+ }
return ret;
}
@@ -537,6 +555,10 @@ static int dirty_bytes_handler(struct ctl_table *table, int write,
ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
if (ret == 0 && write && vm_dirty_bytes != old_bytes) {
+ if (DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE) > UINT_MAX) {
+ vm_dirty_bytes = old_bytes;
+ return -ERANGE;
+ }
writeback_set_ratelimit();
vm_dirty_ratio = 0;
}
@@ -1660,7 +1682,7 @@ static inline void wb_dirty_limits(struct dirty_throttle_control *dtc)
*/
dtc->wb_thresh = __wb_calc_thresh(dtc, dtc->thresh);
dtc->wb_bg_thresh = dtc->thresh ?
- div64_u64(dtc->wb_thresh * dtc->bg_thresh, dtc->thresh) : 0;
+ div_u64((u64)dtc->wb_thresh * dtc->bg_thresh, dtc->thresh) : 0;
/*
* In order to avoid the stacked BDI deadlock we need
diff --git a/mm/readahead.c b/mm/readahead.c
index c1b23989d9ca..817b2a352d78 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -503,11 +503,11 @@ void page_cache_ra_order(struct readahead_control *ractl,
limit = min(limit, index + ra->size - 1);
- if (new_order < MAX_PAGECACHE_ORDER) {
+ if (new_order < MAX_PAGECACHE_ORDER)
new_order += 2;
- new_order = min_t(unsigned int, MAX_PAGECACHE_ORDER, new_order);
- new_order = min_t(unsigned int, new_order, ilog2(ra->size));
- }
+
+ new_order = min_t(unsigned int, MAX_PAGECACHE_ORDER, new_order);
+ new_order = min_t(unsigned int, new_order, ilog2(ra->size));
/* See comment in page_cache_ra_unbounded() */
nofs = memalloc_nofs_save();
diff --git a/mm/shmem.c b/mm/shmem.c
index a8b181a63402..831b52dfd56e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -541,8 +541,9 @@ static bool shmem_confirm_swap(struct address_space *mapping,
static int shmem_huge __read_mostly = SHMEM_HUGE_NEVER;
-bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
- struct mm_struct *mm, unsigned long vm_flags)
+static bool __shmem_is_huge(struct inode *inode, pgoff_t index,
+ bool shmem_huge_force, struct mm_struct *mm,
+ unsigned long vm_flags)
{
loff_t i_size;
@@ -573,6 +574,16 @@ bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
}
}
+bool shmem_is_huge(struct inode *inode, pgoff_t index,
+ bool shmem_huge_force, struct mm_struct *mm,
+ unsigned long vm_flags)
+{
+ if (HPAGE_PMD_ORDER > MAX_PAGECACHE_ORDER)
+ return false;
+
+ return __shmem_is_huge(inode, index, shmem_huge_force, mm, vm_flags);
+}
+
#if defined(CONFIG_SYSFS)
static int shmem_parse_huge(const char *str)
{
@@ -3166,10 +3177,13 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
struct folio *folio;
/*
- * Good, the fallocate(2) manpage permits EINTR: we may have
- * been interrupted because we are using up too much memory.
+ * Check for fatal signal so that we abort early in OOM
+ * situations. We don't want to abort in case of non-fatal
+ * signals as large fallocate can take noticeable time and
+ * e.g. periodic timers may result in fallocate constantly
+ * restarting.
*/
- if (signal_pending(current))
+ if (fatal_signal_pending(current))
error = -EINTR;
else if (shmem_falloc.nr_unswapped > shmem_falloc.nr_falloced)
error = -ENOMEM;
@@ -3903,14 +3917,14 @@ static const struct constant_table shmem_param_enums_huge[] = {
};
const struct fs_parameter_spec shmem_fs_parameters[] = {
- fsparam_u32 ("gid", Opt_gid),
+ fsparam_gid ("gid", Opt_gid),
fsparam_enum ("huge", Opt_huge, shmem_param_enums_huge),
fsparam_u32oct("mode", Opt_mode),
fsparam_string("mpol", Opt_mpol),
fsparam_string("nr_blocks", Opt_nr_blocks),
fsparam_string("nr_inodes", Opt_nr_inodes),
fsparam_string("size", Opt_size),
- fsparam_u32 ("uid", Opt_uid),
+ fsparam_uid ("uid", Opt_uid),
fsparam_flag ("inode32", Opt_inode32),
fsparam_flag ("inode64", Opt_inode64),
fsparam_flag ("noswap", Opt_noswap),
@@ -3970,9 +3984,7 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
ctx->mode = result.uint_32 & 07777;
break;
case Opt_uid:
- kuid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(kuid))
- goto bad_value;
+ kuid = result.uid;
/*
* The requested uid must be representable in the
@@ -3984,9 +3996,7 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
ctx->uid = kuid;
break;
case Opt_gid:
- kgid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(kgid))
- goto bad_value;
+ kgid = result.gid;
/*
* The requested gid must be representable in the
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index d0cbdd7c1e5b..e34ea860153f 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2543,7 +2543,15 @@ static DEFINE_PER_CPU(struct vmap_block_queue, vmap_block_queue);
static struct xarray *
addr_to_vb_xa(unsigned long addr)
{
- int index = (addr / VMAP_BLOCK_SIZE) % num_possible_cpus();
+ int index = (addr / VMAP_BLOCK_SIZE) % nr_cpu_ids;
+
+ /*
+ * Please note, nr_cpu_ids points on a highest set
+ * possible bit, i.e. we never invoke cpumask_next()
+ * if an index points on it which is nr_cpu_ids - 1.
+ */
+ if (!cpu_possible(index))
+ index = cpumask_next(index, cpu_possible_mask);
return &per_cpu(vmap_block_queue, index).vmap_blocks;
}
diff --git a/mm/workingset.c b/mm/workingset.c
index c22adb93622a..a2b28e356e68 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -412,10 +412,12 @@ void *workingset_eviction(struct folio *folio, struct mem_cgroup *target_memcg)
* @file: whether the corresponding folio is from the file lru.
* @workingset: where the workingset value unpacked from shadow should
* be stored.
+ * @flush: whether to flush cgroup rstat.
*
* Return: true if the shadow is for a recently evicted folio; false otherwise.
*/
-bool workingset_test_recent(void *shadow, bool file, bool *workingset)
+bool workingset_test_recent(void *shadow, bool file, bool *workingset,
+ bool flush)
{
struct mem_cgroup *eviction_memcg;
struct lruvec *eviction_lruvec;
@@ -467,10 +469,16 @@ bool workingset_test_recent(void *shadow, bool file, bool *workingset)
/*
* Flush stats (and potentially sleep) outside the RCU read section.
+ *
+ * Note that workingset_test_recent() itself might be called in RCU read
+ * section (for e.g, in cachestat) - these callers need to skip flushing
+ * stats (via the flush argument).
+ *
* XXX: With per-memcg flushing and thresholding, is ratelimiting
* still needed here?
*/
- mem_cgroup_flush_stats_ratelimited(eviction_memcg);
+ if (flush)
+ mem_cgroup_flush_stats_ratelimited(eviction_memcg);
eviction_lruvec = mem_cgroup_lruvec(eviction_memcg, pgdat);
refault = atomic_long_read(&eviction_lruvec->nonresident_age);
@@ -558,7 +566,7 @@ void workingset_refault(struct folio *folio, void *shadow)
mod_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + file, nr);
- if (!workingset_test_recent(shadow, file, &workingset))
+ if (!workingset_test_recent(shadow, file, &workingset, true))
return;
folio_set_active(folio);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 0c76dcde5361..080053a85b4d 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -899,8 +899,8 @@ static int hci_conn_hash_alloc_unset(struct hci_dev *hdev)
U16_MAX, GFP_ATOMIC);
}
-struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
- u8 role, u16 handle)
+static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ u8 role, u16 handle)
{
struct hci_conn *conn;
@@ -1041,7 +1041,16 @@ struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
if (unlikely(handle < 0))
return ERR_PTR(-ECONNREFUSED);
- return hci_conn_add(hdev, type, dst, role, handle);
+ return __hci_conn_add(hdev, type, dst, role, handle);
+}
+
+struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ u8 role, u16 handle)
+{
+ if (handle > HCI_CONN_HANDLE_MAX)
+ return ERR_PTR(-EINVAL);
+
+ return __hci_conn_add(hdev, type, dst, role, handle);
}
static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index dd3b0f501018..c644b30977bd 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -63,50 +63,6 @@ DEFINE_MUTEX(hci_cb_list_lock);
/* HCI ID Numbering */
static DEFINE_IDA(hci_index_ida);
-static int hci_scan_req(struct hci_request *req, unsigned long opt)
-{
- __u8 scan = opt;
-
- BT_DBG("%s %x", req->hdev->name, scan);
-
- /* Inquiry and Page scans */
- hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
- return 0;
-}
-
-static int hci_auth_req(struct hci_request *req, unsigned long opt)
-{
- __u8 auth = opt;
-
- BT_DBG("%s %x", req->hdev->name, auth);
-
- /* Authentication */
- hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth);
- return 0;
-}
-
-static int hci_encrypt_req(struct hci_request *req, unsigned long opt)
-{
- __u8 encrypt = opt;
-
- BT_DBG("%s %x", req->hdev->name, encrypt);
-
- /* Encryption */
- hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt);
- return 0;
-}
-
-static int hci_linkpol_req(struct hci_request *req, unsigned long opt)
-{
- __le16 policy = cpu_to_le16(opt);
-
- BT_DBG("%s %x", req->hdev->name, policy);
-
- /* Default link policy */
- hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy);
- return 0;
-}
-
/* Get HCI device by index.
* Device is held on return. */
struct hci_dev *hci_dev_get(int index)
@@ -735,6 +691,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
{
struct hci_dev *hdev;
struct hci_dev_req dr;
+ __le16 policy;
int err = 0;
if (copy_from_user(&dr, arg, sizeof(dr)))
@@ -761,8 +718,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
switch (cmd) {
case HCISETAUTH:
- err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
- HCI_INIT_TIMEOUT, NULL);
+ err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_AUTH_ENABLE,
+ 1, &dr.dev_opt, HCI_CMD_TIMEOUT);
break;
case HCISETENCRYPT:
@@ -773,19 +730,23 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
if (!test_bit(HCI_AUTH, &hdev->flags)) {
/* Auth must be enabled first */
- err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
- HCI_INIT_TIMEOUT, NULL);
+ err = __hci_cmd_sync_status(hdev,
+ HCI_OP_WRITE_AUTH_ENABLE,
+ 1, &dr.dev_opt,
+ HCI_CMD_TIMEOUT);
if (err)
break;
}
- err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt,
- HCI_INIT_TIMEOUT, NULL);
+ err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_ENCRYPT_MODE,
+ 1, &dr.dev_opt,
+ HCI_CMD_TIMEOUT);
break;
case HCISETSCAN:
- err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt,
- HCI_INIT_TIMEOUT, NULL);
+ err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_SCAN_ENABLE,
+ 1, &dr.dev_opt,
+ HCI_CMD_TIMEOUT);
/* Ensure that the connectable and discoverable states
* get correctly modified as this was a non-mgmt change.
@@ -795,8 +756,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
break;
case HCISETLINKPOL:
- err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt,
- HCI_INIT_TIMEOUT, NULL);
+ policy = cpu_to_le16(dr.dev_opt);
+
+ err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
+ 2, &policy,
+ HCI_CMD_TIMEOUT);
break;
case HCISETLINKMODE:
@@ -2751,7 +2715,11 @@ void hci_unregister_dev(struct hci_dev *hdev)
list_del(&hdev->list);
write_unlock(&hci_dev_list_lock);
+ cancel_work_sync(&hdev->rx_work);
+ cancel_work_sync(&hdev->cmd_work);
+ cancel_work_sync(&hdev->tx_work);
cancel_work_sync(&hdev->power_on);
+ cancel_work_sync(&hdev->error_reset);
hci_cmd_sync_clear(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index a487f9df8145..93f7ac905cec 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -6311,6 +6311,13 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data,
evt_type = __le16_to_cpu(info->type) & LE_EXT_ADV_EVT_TYPE_MASK;
legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type);
+
+ if (test_bit(HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY,
+ &hdev->quirks)) {
+ info->primary_phy &= 0x1f;
+ info->secondary_phy &= 0x1f;
+ }
+
if (legacy_evt_type != LE_ADV_INVALID) {
process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
info->bdaddr_type, NULL, 0,
@@ -6660,6 +6667,7 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
struct bt_iso_qos *qos;
bool pending = false;
u16 handle = __le16_to_cpu(ev->handle);
+ u32 c_sdu_interval, p_sdu_interval;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
@@ -6684,12 +6692,25 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
pending = test_and_clear_bit(HCI_CONN_CREATE_CIS, &conn->flags);
- /* Convert ISO Interval (1.25 ms slots) to SDU Interval (us) */
- qos->ucast.in.interval = le16_to_cpu(ev->interval) * 1250;
- qos->ucast.out.interval = qos->ucast.in.interval;
+ /* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 6, Part G
+ * page 3075:
+ * Transport_Latency_C_To_P = CIG_Sync_Delay + (FT_C_To_P) ×
+ * ISO_Interval + SDU_Interval_C_To_P
+ * ...
+ * SDU_Interval = (CIG_Sync_Delay + (FT) x ISO_Interval) -
+ * Transport_Latency
+ */
+ c_sdu_interval = (get_unaligned_le24(ev->cig_sync_delay) +
+ (ev->c_ft * le16_to_cpu(ev->interval) * 1250)) -
+ get_unaligned_le24(ev->c_latency);
+ p_sdu_interval = (get_unaligned_le24(ev->cig_sync_delay) +
+ (ev->p_ft * le16_to_cpu(ev->interval) * 1250)) -
+ get_unaligned_le24(ev->p_latency);
switch (conn->role) {
case HCI_ROLE_SLAVE:
+ qos->ucast.in.interval = c_sdu_interval;
+ qos->ucast.out.interval = p_sdu_interval;
/* Convert Transport Latency (us) to Latency (msec) */
qos->ucast.in.latency =
DIV_ROUND_CLOSEST(get_unaligned_le24(ev->c_latency),
@@ -6703,6 +6724,8 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data,
qos->ucast.out.phy = ev->p_phy;
break;
case HCI_ROLE_MASTER:
+ qos->ucast.in.interval = p_sdu_interval;
+ qos->ucast.out.interval = c_sdu_interval;
/* Convert Transport Latency (us) to Latency (msec) */
qos->ucast.out.latency =
DIV_ROUND_CLOSEST(get_unaligned_le24(ev->c_latency),
@@ -6893,6 +6916,10 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
bis = hci_conn_hash_lookup_handle(hdev, handle);
if (!bis) {
+ if (handle > HCI_CONN_HANDLE_MAX) {
+ bt_dev_dbg(hdev, "ignore too large handle %u", handle);
+ continue;
+ }
bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
HCI_ROLE_SLAVE, handle);
if (IS_ERR(bis))
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index a8a7d2b36870..eea34e6a236f 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -280,6 +280,19 @@ int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen,
}
EXPORT_SYMBOL(__hci_cmd_sync_status);
+int hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen,
+ const void *param, u32 timeout)
+{
+ int err;
+
+ hci_req_sync_lock(hdev);
+ err = __hci_cmd_sync_status(hdev, opcode, plen, param, timeout);
+ hci_req_sync_unlock(hdev);
+
+ return err;
+}
+EXPORT_SYMBOL(hci_cmd_sync_status);
+
static void hci_cmd_sync_work(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_sync_work);
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index cc055b952ce6..398fb81f7a13 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -1356,8 +1356,7 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
lock_sock(sk);
switch (sk->sk_state) {
case BT_CONNECT2:
- if (pi->conn->hcon &&
- test_bit(HCI_CONN_PA_SYNC, &pi->conn->hcon->flags)) {
+ if (test_bit(BT_SK_PA_SYNC, &pi->flags)) {
iso_conn_big_sync(sk);
sk->sk_state = BT_LISTEN;
} else {
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index aed025734d04..c3c26bbb5dda 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6761,6 +6761,8 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
BT_DBG("chan %p, len %d", chan, skb->len);
+ l2cap_chan_lock(chan);
+
if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
goto drop;
@@ -6777,6 +6779,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
}
drop:
+ l2cap_chan_unlock(chan);
l2cap_chan_put(chan);
free_skb:
kfree_skb(skb);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 6db60946c627..ba437c6f6ee5 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1239,6 +1239,10 @@ static void l2cap_sock_kill(struct sock *sk)
BT_DBG("sk %p state %s", sk, state_to_string(sk->sk_state));
+ /* Sock is dead, so set chan data to NULL, avoid other task use invalid
+ * sock pointer.
+ */
+ l2cap_pi(sk)->chan->data = NULL;
/* Kill poor orphan */
l2cap_chan_put(l2cap_pi(sk)->chan);
@@ -1481,12 +1485,16 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
{
- struct sock *sk = chan->data;
- struct l2cap_pinfo *pi = l2cap_pi(sk);
+ struct sock *sk;
+ struct l2cap_pinfo *pi;
int err;
- lock_sock(sk);
+ sk = chan->data;
+ if (!sk)
+ return -ENXIO;
+ pi = l2cap_pi(sk);
+ lock_sock(sk);
if (chan->mode == L2CAP_MODE_ERTM && !list_empty(&pi->rx_busy)) {
err = -ENOMEM;
goto done;
diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c
index 1daf95e17d67..3a5bd1cd1e99 100644
--- a/net/ceph/crush/mapper.c
+++ b/net/ceph/crush/mapper.c
@@ -429,7 +429,10 @@ static int is_out(const struct crush_map *map,
/**
* crush_choose_firstn - choose numrep distinct items of given type
* @map: the crush_map
+ * @work: working space initialized by crush_init_workspace()
* @bucket: the bucket we are choose an item from
+ * @weight: weight vector (for map leaves)
+ * @weight_max: size of weight vector
* @x: crush input value
* @numrep: the number of items to choose
* @type: the type of item to choose
@@ -445,6 +448,7 @@ static int is_out(const struct crush_map *map,
* @vary_r: pass r to recursive calls
* @out2: second output vector for leaf items (if @recurse_to_leaf)
* @parent_r: r value passed from the parent
+ * @choose_args: weights and ids for each known bucket
*/
static int crush_choose_firstn(const struct crush_map *map,
struct crush_work *work,
@@ -636,9 +640,8 @@ reject:
}
-/**
+/*
* crush_choose_indep: alternative breadth-first positionally stable mapping
- *
*/
static void crush_choose_indep(const struct crush_map *map,
struct crush_work *work,
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
index f263f7e91a21..ab66b599ac47 100644
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -1085,13 +1085,19 @@ static void delayed_work(struct work_struct *work)
struct ceph_mon_client *monc =
container_of(work, struct ceph_mon_client, delayed_work.work);
- dout("monc delayed_work\n");
mutex_lock(&monc->mutex);
+ dout("%s mon%d\n", __func__, monc->cur_mon);
+ if (monc->cur_mon < 0) {
+ goto out;
+ }
+
if (monc->hunting) {
dout("%s continuing hunt\n", __func__);
reopen_session(monc);
} else {
int is_auth = ceph_auth_is_authenticated(monc->auth);
+
+ dout("%s is_authed %d\n", __func__, is_auth);
if (ceph_con_keepalive_expired(&monc->con,
CEPH_MONC_PING_TIMEOUT)) {
dout("monc keepalive timeout\n");
@@ -1116,6 +1122,8 @@ static void delayed_work(struct work_struct *work)
}
}
__schedule_delayed(monc);
+
+out:
mutex_unlock(&monc->mutex);
}
@@ -1232,13 +1240,15 @@ EXPORT_SYMBOL(ceph_monc_init);
void ceph_monc_stop(struct ceph_mon_client *monc)
{
dout("stop\n");
- cancel_delayed_work_sync(&monc->delayed_work);
mutex_lock(&monc->mutex);
__close_session(monc);
+ monc->hunting = false;
monc->cur_mon = -1;
mutex_unlock(&monc->mutex);
+ cancel_delayed_work_sync(&monc->delayed_work);
+
/*
* flush msgr queue before we destroy ourselves to ensure that:
* - any work that references our embedded con is finished.
diff --git a/net/core/datagram.c b/net/core/datagram.c
index e614cfd8e14a..e72dd78471a6 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -416,15 +416,23 @@ static int __skb_datagram_iter(const struct sk_buff *skb, int offset,
end = start + skb_frag_size(frag);
if ((copy = end - offset) > 0) {
- struct page *page = skb_frag_page(frag);
- u8 *vaddr = kmap(page);
+ u32 p_off, p_len, copied;
+ struct page *p;
+ u8 *vaddr;
if (copy > len)
copy = len;
- n = INDIRECT_CALL_1(cb, simple_copy_to_iter,
- vaddr + skb_frag_off(frag) + offset - start,
- copy, data, to);
- kunmap(page);
+
+ n = 0;
+ skb_frag_foreach_page(frag,
+ skb_frag_off(frag) + offset - start,
+ copy, p, p_off, p_len, copied) {
+ vaddr = kmap_local_page(p);
+ n += INDIRECT_CALL_1(cb, simple_copy_to_iter,
+ vaddr + p_off, p_len, data, to);
+ kunmap_local(vaddr);
+ }
+
offset += n;
if (n != copy)
goto short_copy;
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
index fd20aae30be2..bbf40b999713 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
@@ -434,7 +434,8 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
page = sg_page(sge);
if (copied + copy > len)
copy = len - copied;
- copy = copy_page_to_iter(page, sge->offset, copy, iter);
+ if (copy)
+ copy = copy_page_to_iter(page, sge->offset, copy, iter);
if (!copy) {
copied = copied ? copied : -EFAULT;
goto out;
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index e645d751a5e8..223dcd25d88a 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -1306,7 +1306,8 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
if (rxfh.input_xfrm && rxfh.input_xfrm != RXH_XFRM_SYM_XOR &&
rxfh.input_xfrm != RXH_XFRM_NO_CHANGE)
return -EINVAL;
- if ((rxfh.input_xfrm & RXH_XFRM_SYM_XOR) &&
+ if (rxfh.input_xfrm != RXH_XFRM_NO_CHANGE &&
+ (rxfh.input_xfrm & RXH_XFRM_SYM_XOR) &&
!ops->cap_rss_sym_xor_supported)
return -EOPNOTSUPP;
diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c
index b2de2108b356..34d76e87847d 100644
--- a/net/ethtool/linkstate.c
+++ b/net/ethtool/linkstate.c
@@ -37,6 +37,8 @@ static int linkstate_get_sqi(struct net_device *dev)
mutex_lock(&phydev->lock);
if (!phydev->drv || !phydev->drv->get_sqi)
ret = -EOPNOTSUPP;
+ else if (!phydev->link)
+ ret = -ENETDOWN;
else
ret = phydev->drv->get_sqi(phydev);
mutex_unlock(&phydev->lock);
@@ -55,6 +57,8 @@ static int linkstate_get_sqi_max(struct net_device *dev)
mutex_lock(&phydev->lock);
if (!phydev->drv || !phydev->drv->get_sqi_max)
ret = -EOPNOTSUPP;
+ else if (!phydev->link)
+ ret = -ENETDOWN;
else
ret = phydev->drv->get_sqi_max(phydev);
mutex_unlock(&phydev->lock);
@@ -62,6 +66,17 @@ static int linkstate_get_sqi_max(struct net_device *dev)
return ret;
};
+static bool linkstate_sqi_critical_error(int sqi)
+{
+ return sqi < 0 && sqi != -EOPNOTSUPP && sqi != -ENETDOWN;
+}
+
+static bool linkstate_sqi_valid(struct linkstate_reply_data *data)
+{
+ return data->sqi >= 0 && data->sqi_max >= 0 &&
+ data->sqi <= data->sqi_max;
+}
+
static int linkstate_get_link_ext_state(struct net_device *dev,
struct linkstate_reply_data *data)
{
@@ -93,12 +108,12 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
data->link = __ethtool_get_link(dev);
ret = linkstate_get_sqi(dev);
- if (ret < 0 && ret != -EOPNOTSUPP)
+ if (linkstate_sqi_critical_error(ret))
goto out;
data->sqi = ret;
ret = linkstate_get_sqi_max(dev);
- if (ret < 0 && ret != -EOPNOTSUPP)
+ if (linkstate_sqi_critical_error(ret))
goto out;
data->sqi_max = ret;
@@ -136,11 +151,10 @@ static int linkstate_reply_size(const struct ethnl_req_info *req_base,
len = nla_total_size(sizeof(u8)) /* LINKSTATE_LINK */
+ 0;
- if (data->sqi != -EOPNOTSUPP)
- len += nla_total_size(sizeof(u32));
-
- if (data->sqi_max != -EOPNOTSUPP)
- len += nla_total_size(sizeof(u32));
+ if (linkstate_sqi_valid(data)) {
+ len += nla_total_size(sizeof(u32)); /* LINKSTATE_SQI */
+ len += nla_total_size(sizeof(u32)); /* LINKSTATE_SQI_MAX */
+ }
if (data->link_ext_state_provided)
len += nla_total_size(sizeof(u8)); /* LINKSTATE_EXT_STATE */
@@ -164,13 +178,14 @@ static int linkstate_fill_reply(struct sk_buff *skb,
nla_put_u8(skb, ETHTOOL_A_LINKSTATE_LINK, !!data->link))
return -EMSGSIZE;
- if (data->sqi != -EOPNOTSUPP &&
- nla_put_u32(skb, ETHTOOL_A_LINKSTATE_SQI, data->sqi))
- return -EMSGSIZE;
+ if (linkstate_sqi_valid(data)) {
+ if (nla_put_u32(skb, ETHTOOL_A_LINKSTATE_SQI, data->sqi))
+ return -EMSGSIZE;
- if (data->sqi_max != -EOPNOTSUPP &&
- nla_put_u32(skb, ETHTOOL_A_LINKSTATE_SQI_MAX, data->sqi_max))
- return -EMSGSIZE;
+ if (nla_put_u32(skb, ETHTOOL_A_LINKSTATE_SQI_MAX,
+ data->sqi_max))
+ return -EMSGSIZE;
+ }
if (data->link_ext_state_provided) {
if (nla_put_u8(skb, ETHTOOL_A_LINKSTATE_EXT_STATE,
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 7adace541fe2..9712cdb8087c 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -1383,6 +1383,7 @@ static int inet_diag_dump_compat(struct sk_buff *skb,
req.sdiag_family = AF_UNSPEC; /* compatibility */
req.sdiag_protocol = inet_diag_type2proto(cb->nlh->nlmsg_type);
req.idiag_ext = rc->idiag_ext;
+ req.pad = 0;
req.idiag_states = rc->idiag_states;
req.id = rc->id;
@@ -1398,6 +1399,7 @@ static int inet_diag_get_exact_compat(struct sk_buff *in_skb,
req.sdiag_family = rc->idiag_family;
req.sdiag_protocol = inet_diag_type2proto(nlh->nlmsg_type);
req.idiag_ext = rc->idiag_ext;
+ req.pad = 0;
req.idiag_states = rc->idiag_states;
req.id = rc->id;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 2e39cb881e20..38da23f991d6 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2129,8 +2129,16 @@ void tcp_clear_retrans(struct tcp_sock *tp)
static inline void tcp_init_undo(struct tcp_sock *tp)
{
tp->undo_marker = tp->snd_una;
+
/* Retransmission still in flight may cause DSACKs later. */
- tp->undo_retrans = tp->retrans_out ? : -1;
+ /* First, account for regular retransmits in flight: */
+ tp->undo_retrans = tp->retrans_out;
+ /* Next, account for TLP retransmits in flight: */
+ if (tp->tlp_high_seq && tp->tlp_retrans)
+ tp->undo_retrans++;
+ /* Finally, avoid 0, because undo_retrans==0 means "can undo now": */
+ if (!tp->undo_retrans)
+ tp->undo_retrans = -1;
}
static bool tcp_is_rack(const struct sock *sk)
@@ -2209,6 +2217,7 @@ void tcp_enter_loss(struct sock *sk)
tcp_set_ca_state(sk, TCP_CA_Loss);
tp->high_seq = tp->snd_nxt;
+ tp->tlp_high_seq = 0;
tcp_ecn_queue_cwr(tp);
/* F-RTO RFC5682 sec 3.1 step 1: retransmit SND.UNA if no previous
@@ -3077,7 +3086,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const u32 prior_snd_una,
return;
if (tcp_try_undo_dsack(sk))
- tcp_try_keep_open(sk);
+ tcp_try_to_open(sk, flag);
tcp_identify_packet_loss(sk, ack_flag);
if (icsk->icsk_ca_state != TCP_CA_Recovery) {
@@ -4224,6 +4233,13 @@ void tcp_parse_options(const struct net *net,
*/
break;
#endif
+#ifdef CONFIG_TCP_AO
+ case TCPOPT_AO:
+ /* TCP AO has already been checked
+ * (see tcp_inbound_ao_hash()).
+ */
+ break;
+#endif
case TCPOPT_FASTOPEN:
tcp_parse_fastopen_option(
opsize - TCPOLEN_FASTOPEN_BASE,
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
index e93df98de3f4..b01eb6d94413 100644
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@ -619,6 +619,7 @@ static const struct nla_policy tcp_metrics_nl_policy[TCP_METRICS_ATTR_MAX + 1] =
[TCP_METRICS_ATTR_ADDR_IPV4] = { .type = NLA_U32, },
[TCP_METRICS_ATTR_ADDR_IPV6] = { .type = NLA_BINARY,
.len = sizeof(struct in6_addr), },
+ [TCP_METRICS_ATTR_SADDR_IPV4] = { .type = NLA_U32, },
/* Following attributes are not received for GET/DEL,
* we keep them for reference
*/
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 5bfd76a31af6..892c86657fbc 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -483,15 +483,26 @@ static bool tcp_rtx_probe0_timed_out(const struct sock *sk,
const struct sk_buff *skb,
u32 rtx_delta)
{
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ u32 user_timeout = READ_ONCE(icsk->icsk_user_timeout);
const struct tcp_sock *tp = tcp_sk(sk);
- const int timeout = TCP_RTO_MAX * 2;
+ int timeout = TCP_RTO_MAX * 2;
s32 rcv_delta;
+ if (user_timeout) {
+ /* If user application specified a TCP_USER_TIMEOUT,
+ * it does not want win 0 packets to 'reset the timer'
+ * while retransmits are not making progress.
+ */
+ if (rtx_delta > user_timeout)
+ return true;
+ timeout = min_t(u32, timeout, msecs_to_jiffies(user_timeout));
+ }
/* Note: timer interrupt might have been delayed by at least one jiffy,
* and tp->rcv_tstamp might very well have been written recently.
* rcv_delta can thus be negative.
*/
- rcv_delta = inet_csk(sk)->icsk_timeout - tp->rcv_tstamp;
+ rcv_delta = icsk->icsk_timeout - tp->rcv_tstamp;
if (rcv_delta <= timeout)
return false;
@@ -536,8 +547,6 @@ void tcp_retransmit_timer(struct sock *sk)
if (WARN_ON_ONCE(!skb))
return;
- tp->tlp_high_seq = 0;
-
if (!tp->snd_wnd && !sock_flag(sk, SOCK_DEAD) &&
!((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))) {
/* Receiver dastardly shrinks window. Our retransmits
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 189c9113fe9a..578668878a85 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -326,6 +326,8 @@ found:
goto fail_unlock;
}
+ sock_set_flag(sk, SOCK_RCU_FREE);
+
sk_add_node_rcu(sk, &hslot->head);
hslot->count++;
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
@@ -342,7 +344,7 @@ found:
hslot2->count++;
spin_unlock(&hslot2->lock);
}
- sock_set_flag(sk, SOCK_RCU_FREE);
+
error = 0;
fail_unlock:
spin_unlock_bh(&hslot->lock);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1132dea0e290..0965ad11ec74 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -423,6 +423,7 @@ u64 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
BSS_CHANGED_ERP_SLOT;
}
+/* context: requires softirqs disabled */
void ieee80211_handle_queued_frames(struct ieee80211_local *local)
{
struct sk_buff *skb;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 963ed75deb76..771c05640aa3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1567,7 +1567,9 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
void ieee80211_stop_device(struct ieee80211_local *local)
{
+ local_bh_disable();
ieee80211_handle_queued_frames(local);
+ local_bh_enable();
ieee80211_led_radio(local, false);
ieee80211_mod_tpt_led_trig(local, 0, IEEE80211_TPT_LEDTRIG_FL_RADIO);
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 9ab7396668d2..21b7c3b280b4 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -161,8 +161,10 @@ void ieee802154_configure_durations(struct wpan_phy *phy,
}
phy->symbol_duration = duration;
- phy->lifs_period = (IEEE802154_LIFS_PERIOD * phy->symbol_duration) / NSEC_PER_SEC;
- phy->sifs_period = (IEEE802154_SIFS_PERIOD * phy->symbol_duration) / NSEC_PER_SEC;
+ phy->lifs_period =
+ (IEEE802154_LIFS_PERIOD * phy->symbol_duration) / NSEC_PER_USEC;
+ phy->sifs_period =
+ (IEEE802154_SIFS_PERIOD * phy->symbol_duration) / NSEC_PER_USEC;
}
EXPORT_SYMBOL(ieee802154_configure_durations);
@@ -184,10 +186,10 @@ static void ieee802154_setup_wpan_phy_pib(struct wpan_phy *wpan_phy)
* Should be done when all drivers sets this value.
*/
- wpan_phy->lifs_period =
- (IEEE802154_LIFS_PERIOD * wpan_phy->symbol_duration) / 1000;
- wpan_phy->sifs_period =
- (IEEE802154_SIFS_PERIOD * wpan_phy->symbol_duration) / 1000;
+ wpan_phy->lifs_period = (IEEE802154_LIFS_PERIOD *
+ wpan_phy->symbol_duration) / NSEC_PER_USEC;
+ wpan_phy->sifs_period = (IEEE802154_SIFS_PERIOD *
+ wpan_phy->symbol_duration) / NSEC_PER_USEC;
}
int ieee802154_register_hw(struct ieee802154_hw *hw)
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 2a6f1ed763c9..6fbed5bb5c3e 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -34,8 +34,8 @@ void ieee802154_xmit_sync_worker(struct work_struct *work)
if (res)
goto err_tx;
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
+ DEV_STATS_INC(dev, tx_packets);
+ DEV_STATS_ADD(dev, tx_bytes, skb->len);
ieee802154_xmit_complete(&local->hw, skb, false);
@@ -90,8 +90,8 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
if (ret)
goto err_wake_netif_queue;
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += len;
+ DEV_STATS_INC(dev, tx_packets);
+ DEV_STATS_ADD(dev, tx_bytes, len);
} else {
local->tx_skb = skb;
queue_work(local->workqueue, &local->sync_tx_work);
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index e8dcf41d360d..91cc3a81ba8f 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3823,6 +3823,15 @@ static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *r
nf_tables_rule_destroy(ctx, rule);
}
+/** nft_chain_validate - loop detection and hook validation
+ *
+ * @ctx: context containing call depth and base chain
+ * @chain: chain to validate
+ *
+ * Walk through the rules of the given chain and chase all jumps/gotos
+ * and set lookups until either the jump limit is hit or all reachable
+ * chains have been validated.
+ */
int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
{
struct nft_expr *expr, *last;
@@ -3844,6 +3853,9 @@ int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
if (!expr->ops->validate)
continue;
+ /* This may call nft_chain_validate() recursively,
+ * callers that do so must increment ctx->level.
+ */
err = expr->ops->validate(ctx, expr, &data);
if (err < 0)
return err;
@@ -10809,150 +10821,6 @@ int nft_chain_validate_hooks(const struct nft_chain *chain,
}
EXPORT_SYMBOL_GPL(nft_chain_validate_hooks);
-/*
- * Loop detection - walk through the ruleset beginning at the destination chain
- * of a new jump until either the source chain is reached (loop) or all
- * reachable chains have been traversed.
- *
- * The loop check is performed whenever a new jump verdict is added to an
- * expression or verdict map or a verdict map is bound to a new chain.
- */
-
-static int nf_tables_check_loops(const struct nft_ctx *ctx,
- const struct nft_chain *chain);
-
-static int nft_check_loops(const struct nft_ctx *ctx,
- const struct nft_set_ext *ext)
-{
- const struct nft_data *data;
- int ret;
-
- data = nft_set_ext_data(ext);
- switch (data->verdict.code) {
- case NFT_JUMP:
- case NFT_GOTO:
- ret = nf_tables_check_loops(ctx, data->verdict.chain);
- break;
- default:
- ret = 0;
- break;
- }
-
- return ret;
-}
-
-static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
- struct nft_set *set,
- const struct nft_set_iter *iter,
- struct nft_elem_priv *elem_priv)
-{
- const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
-
- if (!nft_set_elem_active(ext, iter->genmask))
- return 0;
-
- if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
- *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
- return 0;
-
- return nft_check_loops(ctx, ext);
-}
-
-static int nft_set_catchall_loops(const struct nft_ctx *ctx,
- struct nft_set *set)
-{
- u8 genmask = nft_genmask_next(ctx->net);
- struct nft_set_elem_catchall *catchall;
- struct nft_set_ext *ext;
- int ret = 0;
-
- list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
- ext = nft_set_elem_ext(set, catchall->elem);
- if (!nft_set_elem_active(ext, genmask))
- continue;
-
- ret = nft_check_loops(ctx, ext);
- if (ret < 0)
- return ret;
- }
-
- return ret;
-}
-
-static int nf_tables_check_loops(const struct nft_ctx *ctx,
- const struct nft_chain *chain)
-{
- const struct nft_rule *rule;
- const struct nft_expr *expr, *last;
- struct nft_set *set;
- struct nft_set_binding *binding;
- struct nft_set_iter iter;
-
- if (ctx->chain == chain)
- return -ELOOP;
-
- if (fatal_signal_pending(current))
- return -EINTR;
-
- list_for_each_entry(rule, &chain->rules, list) {
- nft_rule_for_each_expr(expr, last, rule) {
- struct nft_immediate_expr *priv;
- const struct nft_data *data;
- int err;
-
- if (strcmp(expr->ops->type->name, "immediate"))
- continue;
-
- priv = nft_expr_priv(expr);
- if (priv->dreg != NFT_REG_VERDICT)
- continue;
-
- data = &priv->data;
- switch (data->verdict.code) {
- case NFT_JUMP:
- case NFT_GOTO:
- err = nf_tables_check_loops(ctx,
- data->verdict.chain);
- if (err < 0)
- return err;
- break;
- default:
- break;
- }
- }
- }
-
- list_for_each_entry(set, &ctx->table->sets, list) {
- if (!nft_is_active_next(ctx->net, set))
- continue;
- if (!(set->flags & NFT_SET_MAP) ||
- set->dtype != NFT_DATA_VERDICT)
- continue;
-
- list_for_each_entry(binding, &set->bindings, list) {
- if (!(binding->flags & NFT_SET_MAP) ||
- binding->chain != chain)
- continue;
-
- iter.genmask = nft_genmask_next(ctx->net);
- iter.type = NFT_ITER_UPDATE;
- iter.skip = 0;
- iter.count = 0;
- iter.err = 0;
- iter.fn = nf_tables_loop_check_setelem;
-
- set->ops->walk(ctx, set, &iter);
- if (!iter.err)
- iter.err = nft_set_catchall_loops(ctx, set);
-
- if (iter.err < 0)
- return iter.err;
- }
- }
-
- return 0;
-}
-
/**
* nft_parse_u32_check - fetch u32 attribute and check for maximum value
*
@@ -11065,7 +10933,7 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
if (data != NULL &&
(data->verdict.code == NFT_GOTO ||
data->verdict.code == NFT_JUMP)) {
- err = nf_tables_check_loops(ctx, data->verdict.chain);
+ err = nft_chain_validate(ctx, data->verdict.chain);
if (err < 0)
return err;
}
@@ -11483,8 +11351,7 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
gc_seq = nft_gc_seq_begin(nft_net);
- if (!list_empty(&nf_tables_destroy_list))
- nf_tables_trans_destroy_flush_work();
+ nf_tables_trans_destroy_flush_work();
again:
list_for_each_entry(table, &nft_net->tables, list) {
if (nft_table_has_owner(table) &&
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index f1c31757e496..55e28e1da66e 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -325,7 +325,7 @@ static void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
hooks = nf_hook_entries_head(net, pf, entry->state.hook);
i = entry->hook_index;
- if (WARN_ON_ONCE(!hooks || i >= hooks->num_hook_entries)) {
+ if (!hooks || i >= hooks->num_hook_entries) {
kfree_skb_reason(skb, SKB_DROP_REASON_NETFILTER_DROP);
nf_queue_entry_free(entry);
return;
diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
index 2a96d9c1db65..6fa3cca87d34 100644
--- a/net/sched/act_ct.c
+++ b/net/sched/act_ct.c
@@ -1077,6 +1077,14 @@ do_nat:
*/
if (nf_conntrack_confirm(skb) != NF_ACCEPT)
goto drop;
+
+ /* The ct may be dropped if a clash has been resolved,
+ * so it's necessary to retrieve it from skb again to
+ * prevent UAF.
+ */
+ ct = nf_ct_get(skb, &ctinfo);
+ if (!ct)
+ skip_add = true;
}
if (!skip_add)
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index c2ef9dcf91d2..cc6051d4f2ef 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -91,7 +91,7 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt,
entry = tcx_entry_fetch_or_create(dev, true, &created);
if (!entry)
return -ENOMEM;
- tcx_miniq_set_active(entry, true);
+ tcx_miniq_inc(entry);
mini_qdisc_pair_init(&q->miniqp, sch, &tcx_entry(entry)->miniq);
if (created)
tcx_entry_update(dev, entry, true);
@@ -121,7 +121,7 @@ static void ingress_destroy(struct Qdisc *sch)
tcf_block_put_ext(q->block, sch, &q->block_info);
if (entry) {
- tcx_miniq_set_active(entry, false);
+ tcx_miniq_dec(entry);
if (!tcx_entry_is_active(entry)) {
tcx_entry_update(dev, NULL, true);
tcx_entry_free(entry);
@@ -257,7 +257,7 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt,
entry = tcx_entry_fetch_or_create(dev, true, &created);
if (!entry)
return -ENOMEM;
- tcx_miniq_set_active(entry, true);
+ tcx_miniq_inc(entry);
mini_qdisc_pair_init(&q->miniqp_ingress, sch, &tcx_entry(entry)->miniq);
if (created)
tcx_entry_update(dev, entry, true);
@@ -276,7 +276,7 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt,
entry = tcx_entry_fetch_or_create(dev, false, &created);
if (!entry)
return -ENOMEM;
- tcx_miniq_set_active(entry, true);
+ tcx_miniq_inc(entry);
mini_qdisc_pair_init(&q->miniqp_egress, sch, &tcx_entry(entry)->miniq);
if (created)
tcx_entry_update(dev, entry, false);
@@ -302,7 +302,7 @@ static void clsact_destroy(struct Qdisc *sch)
tcf_block_put_ext(q->egress_block, sch, &q->egress_block_info);
if (ingress_entry) {
- tcx_miniq_set_active(ingress_entry, false);
+ tcx_miniq_dec(ingress_entry);
if (!tcx_entry_is_active(ingress_entry)) {
tcx_entry_update(dev, NULL, true);
tcx_entry_free(ingress_entry);
@@ -310,7 +310,7 @@ static void clsact_destroy(struct Qdisc *sch)
}
if (egress_entry) {
- tcx_miniq_set_active(egress_entry, false);
+ tcx_miniq_dec(egress_entry);
if (!tcx_entry_is_active(egress_entry)) {
tcx_entry_update(dev, NULL, false);
tcx_entry_free(egress_entry);
diff --git a/net/socket.c b/net/socket.c
index e416920e9399..fcbdd5bc47ac 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1822,6 +1822,20 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
return __sys_socketpair(family, type, protocol, usockvec);
}
+int __sys_bind_socket(struct socket *sock, struct sockaddr_storage *address,
+ int addrlen)
+{
+ int err;
+
+ err = security_socket_bind(sock, (struct sockaddr *)address,
+ addrlen);
+ if (!err)
+ err = READ_ONCE(sock->ops)->bind(sock,
+ (struct sockaddr *)address,
+ addrlen);
+ return err;
+}
+
/*
* Bind a name to a socket. Nothing much to do here since it's
* the protocol's responsibility to handle the local address.
@@ -1839,15 +1853,8 @@ int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
err = move_addr_to_kernel(umyaddr, addrlen, &address);
- if (!err) {
- err = security_socket_bind(sock,
- (struct sockaddr *)&address,
- addrlen);
- if (!err)
- err = READ_ONCE(sock->ops)->bind(sock,
- (struct sockaddr *)
- &address, addrlen);
- }
+ if (!err)
+ err = __sys_bind_socket(sock, &address, addrlen);
fput_light(sock->file, fput_needed);
}
return err;
@@ -1863,23 +1870,28 @@ SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
* necessary for a listen, and if that works, we mark the socket as
* ready for listening.
*/
+int __sys_listen_socket(struct socket *sock, int backlog)
+{
+ int somaxconn, err;
+
+ somaxconn = READ_ONCE(sock_net(sock->sk)->core.sysctl_somaxconn);
+ if ((unsigned int)backlog > somaxconn)
+ backlog = somaxconn;
+
+ err = security_socket_listen(sock, backlog);
+ if (!err)
+ err = READ_ONCE(sock->ops)->listen(sock, backlog);
+ return err;
+}
int __sys_listen(int fd, int backlog)
{
struct socket *sock;
int err, fput_needed;
- int somaxconn;
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
- somaxconn = READ_ONCE(sock_net(sock->sk)->core.sysctl_somaxconn);
- if ((unsigned int)backlog > somaxconn)
- backlog = somaxconn;
-
- err = security_socket_listen(sock, backlog);
- if (!err)
- err = READ_ONCE(sock->ops)->listen(sock, backlog);
-
+ err = __sys_listen_socket(sock, backlog);
fput_light(sock->file, fput_needed);
}
return err;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index dfc353eea8ed..0e1691316f42 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -2441,6 +2441,13 @@ static void xs_tcp_setup_socket(struct work_struct *work)
transport->srcport = 0;
status = -EAGAIN;
break;
+ case -EPERM:
+ /* Happens, for instance, if a BPF program is preventing
+ * the connect. Remap the error so upper layers can better
+ * deal with it.
+ */
+ status = -ECONNREFUSED;
+ fallthrough;
case -EINVAL:
/* Happens, for instance, if the user specified a link
* local IPv6 address without a scope-id.
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index dfe94a90ece4..23efb78fe9ef 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -476,6 +476,7 @@ prev_vertex:
}
if (vertex->index == vertex->scc_index) {
+ struct unix_vertex *v;
struct list_head scc;
bool scc_dead = true;
@@ -486,15 +487,15 @@ prev_vertex:
*/
__list_cut_position(&scc, &vertex_stack, &vertex->scc_entry);
- list_for_each_entry_reverse(vertex, &scc, scc_entry) {
+ list_for_each_entry_reverse(v, &scc, scc_entry) {
/* Don't restart DFS from this vertex in unix_walk_scc(). */
- list_move_tail(&vertex->entry, &unix_visited_vertices);
+ list_move_tail(&v->entry, &unix_visited_vertices);
/* Mark vertex as off-stack. */
- vertex->index = unix_vertex_grouped_index;
+ v->index = unix_vertex_grouped_index;
if (scc_dead)
- scc_dead = unix_vertex_dead(vertex);
+ scc_dead = unix_vertex_dead(v);
}
if (scc_dead)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3c0bca4238d3..72c7bf558581 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -468,6 +468,10 @@ static const struct netlink_range_validation nl80211_punct_bitmap_range = {
.max = 0xffff,
};
+static const struct netlink_range_validation q_range = {
+ .max = INT_MAX,
+};
+
static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
@@ -754,7 +758,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
[NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
- [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
+ [NL80211_ATTR_TXQ_QUANTUM] = NLA_POLICY_FULL_RANGE(NLA_U32, &q_range),
[NL80211_ATTR_HE_CAPABILITY] =
NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_he_capa,
NL80211_HE_MAX_CAPABILITY_LEN),
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index ddb5644d4fd9..6deee85a29c8 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -7,6 +7,9 @@
*/
#include <kunit/test.h>
+#include <linux/blk_types.h>
+#include <linux/blk-mq.h>
+#include <linux/blkdev.h>
#include <linux/errname.h>
#include <linux/ethtool.h>
#include <linux/jiffies.h>
@@ -20,8 +23,10 @@
/* `bindgen` gets confused at certain things. */
const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
+const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE;
const gfp_t RUST_CONST_HELPER_GFP_ATOMIC = GFP_ATOMIC;
const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL;
const gfp_t RUST_CONST_HELPER_GFP_KERNEL_ACCOUNT = GFP_KERNEL_ACCOUNT;
const gfp_t RUST_CONST_HELPER_GFP_NOWAIT = GFP_NOWAIT;
const gfp_t RUST_CONST_HELPER___GFP_ZERO = __GFP_ZERO;
+const blk_features_t RUST_CONST_HELPER_BLK_FEAT_ROTATIONAL = BLK_FEAT_ROTATIONAL;
diff --git a/rust/helpers.c b/rust/helpers.c
index 2c37a0f5d7a8..3df5217fb2ff 100644
--- a/rust/helpers.c
+++ b/rust/helpers.c
@@ -186,3 +186,19 @@ static_assert(
__alignof__(size_t) == __alignof__(uintptr_t),
"Rust code expects C `size_t` to match Rust `usize`"
);
+
+// This will soon be moved to a separate file, so no need to merge with above.
+#include <linux/blk-mq.h>
+#include <linux/blkdev.h>
+
+void *rust_helper_blk_mq_rq_to_pdu(struct request *rq)
+{
+ return blk_mq_rq_to_pdu(rq);
+}
+EXPORT_SYMBOL_GPL(rust_helper_blk_mq_rq_to_pdu);
+
+struct request *rust_helper_blk_mq_rq_from_pdu(void *pdu)
+{
+ return blk_mq_rq_from_pdu(pdu);
+}
+EXPORT_SYMBOL_GPL(rust_helper_blk_mq_rq_from_pdu);
diff --git a/rust/kernel/block.rs b/rust/kernel/block.rs
new file mode 100644
index 000000000000..150f710efe5b
--- /dev/null
+++ b/rust/kernel/block.rs
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Types for working with the block layer.
+
+pub mod mq;
diff --git a/rust/kernel/block/mq.rs b/rust/kernel/block/mq.rs
new file mode 100644
index 000000000000..fb0f393c1cea
--- /dev/null
+++ b/rust/kernel/block/mq.rs
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! This module provides types for implementing block drivers that interface the
+//! blk-mq subsystem.
+//!
+//! To implement a block device driver, a Rust module must do the following:
+//!
+//! - Implement [`Operations`] for a type `T`.
+//! - Create a [`TagSet<T>`].
+//! - Create a [`GenDisk<T>`], via the [`GenDiskBuilder`].
+//! - Add the disk to the system by calling [`GenDiskBuilder::build`] passing in
+//! the `TagSet` reference.
+//!
+//! The types available in this module that have direct C counterparts are:
+//!
+//! - The [`TagSet`] type that abstracts the C type `struct tag_set`.
+//! - The [`GenDisk`] type that abstracts the C type `struct gendisk`.
+//! - The [`Request`] type that abstracts the C type `struct request`.
+//!
+//! The kernel will interface with the block device driver by calling the method
+//! implementations of the `Operations` trait.
+//!
+//! IO requests are passed to the driver as [`kernel::types::ARef<Request>`]
+//! instances. The `Request` type is a wrapper around the C `struct request`.
+//! The driver must mark end of processing by calling one of the
+//! `Request::end`, methods. Failure to do so can lead to deadlock or timeout
+//! errors. Please note that the C function `blk_mq_start_request` is implicitly
+//! called when the request is queued with the driver.
+//!
+//! The `TagSet` is responsible for creating and maintaining a mapping between
+//! `Request`s and integer ids as well as carrying a pointer to the vtable
+//! generated by `Operations`. This mapping is useful for associating
+//! completions from hardware with the correct `Request` instance. The `TagSet`
+//! determines the maximum queue depth by setting the number of `Request`
+//! instances available to the driver, and it determines the number of queues to
+//! instantiate for the driver. If possible, a driver should allocate one queue
+//! per core, to keep queue data local to a core.
+//!
+//! One `TagSet` instance can be shared between multiple `GenDisk` instances.
+//! This can be useful when implementing drivers where one piece of hardware
+//! with one set of IO resources are represented to the user as multiple disks.
+//!
+//! One significant difference between block device drivers implemented with
+//! these Rust abstractions and drivers implemented in C, is that the Rust
+//! drivers have to own a reference count on the `Request` type when the IO is
+//! in flight. This is to ensure that the C `struct request` instances backing
+//! the Rust `Request` instances are live while the Rust driver holds a
+//! reference to the `Request`. In addition, the conversion of an integer tag to
+//! a `Request` via the `TagSet` would not be sound without this bookkeeping.
+//!
+//! [`GenDisk`]: gen_disk::GenDisk
+//! [`GenDisk<T>`]: gen_disk::GenDisk
+//! [`GenDiskBuilder`]: gen_disk::GenDiskBuilder
+//! [`GenDiskBuilder::build`]: gen_disk::GenDiskBuilder::build
+//!
+//! # Example
+//!
+//! ```rust
+//! use kernel::{
+//! alloc::flags,
+//! block::mq::*,
+//! new_mutex,
+//! prelude::*,
+//! sync::{Arc, Mutex},
+//! types::{ARef, ForeignOwnable},
+//! };
+//!
+//! struct MyBlkDevice;
+//!
+//! #[vtable]
+//! impl Operations for MyBlkDevice {
+//!
+//! fn queue_rq(rq: ARef<Request<Self>>, _is_last: bool) -> Result {
+//! Request::end_ok(rq);
+//! Ok(())
+//! }
+//!
+//! fn commit_rqs() {}
+//! }
+//!
+//! let tagset: Arc<TagSet<MyBlkDevice>> =
+//! Arc::pin_init(TagSet::new(1, 256, 1), flags::GFP_KERNEL)?;
+//! let mut disk = gen_disk::GenDiskBuilder::new()
+//! .capacity_sectors(4096)
+//! .build(format_args!("myblk"), tagset)?;
+//!
+//! # Ok::<(), kernel::error::Error>(())
+//! ```
+
+pub mod gen_disk;
+mod operations;
+mod raw_writer;
+mod request;
+mod tag_set;
+
+pub use operations::Operations;
+pub use request::Request;
+pub use tag_set::TagSet;
diff --git a/rust/kernel/block/mq/gen_disk.rs b/rust/kernel/block/mq/gen_disk.rs
new file mode 100644
index 000000000000..f548a6199847
--- /dev/null
+++ b/rust/kernel/block/mq/gen_disk.rs
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Generic disk abstraction.
+//!
+//! C header: [`include/linux/blkdev.h`](srctree/include/linux/blkdev.h)
+//! C header: [`include/linux/blk_mq.h`](srctree/include/linux/blk_mq.h)
+
+use crate::block::mq::{raw_writer::RawWriter, Operations, TagSet};
+use crate::error;
+use crate::{bindings, error::from_err_ptr, error::Result, sync::Arc};
+use core::fmt::{self, Write};
+
+/// A builder for [`GenDisk`].
+///
+/// Use this struct to configure and add new [`GenDisk`] to the VFS.
+pub struct GenDiskBuilder {
+ rotational: bool,
+ logical_block_size: u32,
+ physical_block_size: u32,
+ capacity_sectors: u64,
+}
+
+impl Default for GenDiskBuilder {
+ fn default() -> Self {
+ Self {
+ rotational: false,
+ logical_block_size: bindings::PAGE_SIZE as u32,
+ physical_block_size: bindings::PAGE_SIZE as u32,
+ capacity_sectors: 0,
+ }
+ }
+}
+
+impl GenDiskBuilder {
+ /// Create a new instance.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Set the rotational media attribute for the device to be built.
+ pub fn rotational(mut self, rotational: bool) -> Self {
+ self.rotational = rotational;
+ self
+ }
+
+ /// Validate block size by verifying that it is between 512 and `PAGE_SIZE`,
+ /// and that it is a power of two.
+ fn validate_block_size(size: u32) -> Result<()> {
+ if !(512..=bindings::PAGE_SIZE as u32).contains(&size) || !size.is_power_of_two() {
+ Err(error::code::EINVAL)
+ } else {
+ Ok(())
+ }
+ }
+
+ /// Set the logical block size of the device to be built.
+ ///
+ /// This method will check that block size is a power of two and between 512
+ /// and 4096. If not, an error is returned and the block size is not set.
+ ///
+ /// This is the smallest unit the storage device can address. It is
+ /// typically 4096 bytes.
+ pub fn logical_block_size(mut self, block_size: u32) -> Result<Self> {
+ Self::validate_block_size(block_size)?;
+ self.logical_block_size = block_size;
+ Ok(self)
+ }
+
+ /// Set the physical block size of the device to be built.
+ ///
+ /// This method will check that block size is a power of two and between 512
+ /// and 4096. If not, an error is returned and the block size is not set.
+ ///
+ /// This is the smallest unit a physical storage device can write
+ /// atomically. It is usually the same as the logical block size but may be
+ /// bigger. One example is SATA drives with 4096 byte physical block size
+ /// that expose a 512 byte logical block size to the operating system.
+ pub fn physical_block_size(mut self, block_size: u32) -> Result<Self> {
+ Self::validate_block_size(block_size)?;
+ self.physical_block_size = block_size;
+ Ok(self)
+ }
+
+ /// Set the capacity of the device to be built, in sectors (512 bytes).
+ pub fn capacity_sectors(mut self, capacity: u64) -> Self {
+ self.capacity_sectors = capacity;
+ self
+ }
+
+ /// Build a new `GenDisk` and add it to the VFS.
+ pub fn build<T: Operations>(
+ self,
+ name: fmt::Arguments<'_>,
+ tagset: Arc<TagSet<T>>,
+ ) -> Result<GenDisk<T>> {
+ let lock_class_key = crate::sync::LockClassKey::new();
+
+ // SAFETY: `bindings::queue_limits` contain only fields that are valid when zeroed.
+ let mut lim: bindings::queue_limits = unsafe { core::mem::zeroed() };
+
+ lim.logical_block_size = self.logical_block_size;
+ lim.physical_block_size = self.physical_block_size;
+ if self.rotational {
+ lim.features = bindings::BLK_FEAT_ROTATIONAL;
+ }
+
+ // SAFETY: `tagset.raw_tag_set()` points to a valid and initialized tag set
+ let gendisk = from_err_ptr(unsafe {
+ bindings::__blk_mq_alloc_disk(
+ tagset.raw_tag_set(),
+ &mut lim,
+ core::ptr::null_mut(),
+ lock_class_key.as_ptr(),
+ )
+ })?;
+
+ const TABLE: bindings::block_device_operations = bindings::block_device_operations {
+ submit_bio: None,
+ open: None,
+ release: None,
+ ioctl: None,
+ compat_ioctl: None,
+ check_events: None,
+ unlock_native_capacity: None,
+ getgeo: None,
+ set_read_only: None,
+ swap_slot_free_notify: None,
+ report_zones: None,
+ devnode: None,
+ alternative_gpt_sector: None,
+ get_unique_id: None,
+ // TODO: Set to THIS_MODULE. Waiting for const_refs_to_static feature to
+ // be merged (unstable in rustc 1.78 which is staged for linux 6.10)
+ // https://github.com/rust-lang/rust/issues/119618
+ owner: core::ptr::null_mut(),
+ pr_ops: core::ptr::null_mut(),
+ free_disk: None,
+ poll_bio: None,
+ };
+
+ // SAFETY: `gendisk` is a valid pointer as we initialized it above
+ unsafe { (*gendisk).fops = &TABLE };
+
+ let mut raw_writer = RawWriter::from_array(
+ // SAFETY: `gendisk` points to a valid and initialized instance. We
+ // have exclusive access, since the disk is not added to the VFS
+ // yet.
+ unsafe { &mut (*gendisk).disk_name },
+ )?;
+ raw_writer.write_fmt(name)?;
+ raw_writer.write_char('\0')?;
+
+ // SAFETY: `gendisk` points to a valid and initialized instance of
+ // `struct gendisk`. `set_capacity` takes a lock to synchronize this
+ // operation, so we will not race.
+ unsafe { bindings::set_capacity(gendisk, self.capacity_sectors) };
+
+ crate::error::to_result(
+ // SAFETY: `gendisk` points to a valid and initialized instance of
+ // `struct gendisk`.
+ unsafe {
+ bindings::device_add_disk(core::ptr::null_mut(), gendisk, core::ptr::null_mut())
+ },
+ )?;
+
+ // INVARIANT: `gendisk` was initialized above.
+ // INVARIANT: `gendisk` was added to the VFS via `device_add_disk` above.
+ Ok(GenDisk {
+ _tagset: tagset,
+ gendisk,
+ })
+ }
+}
+
+/// A generic block device.
+///
+/// # Invariants
+///
+/// - `gendisk` must always point to an initialized and valid `struct gendisk`.
+/// - `gendisk` was added to the VFS through a call to
+/// `bindings::device_add_disk`.
+pub struct GenDisk<T: Operations> {
+ _tagset: Arc<TagSet<T>>,
+ gendisk: *mut bindings::gendisk,
+}
+
+// SAFETY: `GenDisk` is an owned pointer to a `struct gendisk` and an `Arc` to a
+// `TagSet` It is safe to send this to other threads as long as T is Send.
+unsafe impl<T: Operations + Send> Send for GenDisk<T> {}
+
+impl<T: Operations> Drop for GenDisk<T> {
+ fn drop(&mut self) {
+ // SAFETY: By type invariant, `self.gendisk` points to a valid and
+ // initialized instance of `struct gendisk`, and it was previously added
+ // to the VFS.
+ unsafe { bindings::del_gendisk(self.gendisk) };
+ }
+}
diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
new file mode 100644
index 000000000000..9ba7fdfeb4b2
--- /dev/null
+++ b/rust/kernel/block/mq/operations.rs
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! This module provides an interface for blk-mq drivers to implement.
+//!
+//! C header: [`include/linux/blk-mq.h`](srctree/include/linux/blk-mq.h)
+
+use crate::{
+ bindings,
+ block::mq::request::RequestDataWrapper,
+ block::mq::Request,
+ error::{from_result, Result},
+ types::ARef,
+};
+use core::{marker::PhantomData, sync::atomic::AtomicU64, sync::atomic::Ordering};
+
+/// Implement this trait to interface blk-mq as block devices.
+///
+/// To implement a block device driver, implement this trait as described in the
+/// [module level documentation]. The kernel will use the implementation of the
+/// functions defined in this trait to interface a block device driver. Note:
+/// There is no need for an exit_request() implementation, because the `drop`
+/// implementation of the [`Request`] type will be invoked by automatically by
+/// the C/Rust glue logic.
+///
+/// [module level documentation]: kernel::block::mq
+#[macros::vtable]
+pub trait Operations: Sized {
+ /// Called by the kernel to queue a request with the driver. If `is_last` is
+ /// `false`, the driver is allowed to defer committing the request.
+ fn queue_rq(rq: ARef<Request<Self>>, is_last: bool) -> Result;
+
+ /// Called by the kernel to indicate that queued requests should be submitted.
+ fn commit_rqs();
+
+ /// Called by the kernel to poll the device for completed requests. Only
+ /// used for poll queues.
+ fn poll() -> bool {
+ crate::build_error(crate::error::VTABLE_DEFAULT_ERROR)
+ }
+}
+
+/// A vtable for blk-mq to interact with a block device driver.
+///
+/// A `bindings::blk_mq_ops` vtable is constructed from pointers to the `extern
+/// "C"` functions of this struct, exposed through the `OperationsVTable::VTABLE`.
+///
+/// For general documentation of these methods, see the kernel source
+/// documentation related to `struct blk_mq_operations` in
+/// [`include/linux/blk-mq.h`].
+///
+/// [`include/linux/blk-mq.h`]: srctree/include/linux/blk-mq.h
+pub(crate) struct OperationsVTable<T: Operations>(PhantomData<T>);
+
+impl<T: Operations> OperationsVTable<T> {
+ /// This function is called by the C kernel. A pointer to this function is
+ /// installed in the `blk_mq_ops` vtable for the driver.
+ ///
+ /// # Safety
+ ///
+ /// - The caller of this function must ensure that the pointee of `bd` is
+ /// valid for reads for the duration of this function.
+ /// - This function must be called for an initialized and live `hctx`. That
+ /// is, `Self::init_hctx_callback` was called and
+ /// `Self::exit_hctx_callback()` was not yet called.
+ /// - `(*bd).rq` must point to an initialized and live `bindings:request`.
+ /// That is, `Self::init_request_callback` was called but
+ /// `Self::exit_request_callback` was not yet called for the request.
+ /// - `(*bd).rq` must be owned by the driver. That is, the block layer must
+ /// promise to not access the request until the driver calls
+ /// `bindings::blk_mq_end_request` for the request.
+ unsafe extern "C" fn queue_rq_callback(
+ _hctx: *mut bindings::blk_mq_hw_ctx,
+ bd: *const bindings::blk_mq_queue_data,
+ ) -> bindings::blk_status_t {
+ // SAFETY: `bd.rq` is valid as required by the safety requirement for
+ // this function.
+ let request = unsafe { &*(*bd).rq.cast::<Request<T>>() };
+
+ // One refcount for the ARef, one for being in flight
+ request.wrapper_ref().refcount().store(2, Ordering::Relaxed);
+
+ // SAFETY:
+ // - We own a refcount that we took above. We pass that to `ARef`.
+ // - By the safety requirements of this function, `request` is a valid
+ // `struct request` and the private data is properly initialized.
+ // - `rq` will be alive until `blk_mq_end_request` is called and is
+ // reference counted by `ARef` until then.
+ let rq = unsafe { Request::aref_from_raw((*bd).rq) };
+
+ // SAFETY: We have exclusive access and we just set the refcount above.
+ unsafe { Request::start_unchecked(&rq) };
+
+ let ret = T::queue_rq(
+ rq,
+ // SAFETY: `bd` is valid as required by the safety requirement for
+ // this function.
+ unsafe { (*bd).last },
+ );
+
+ if let Err(e) = ret {
+ e.to_blk_status()
+ } else {
+ bindings::BLK_STS_OK as _
+ }
+ }
+
+ /// This function is called by the C kernel. A pointer to this function is
+ /// installed in the `blk_mq_ops` vtable for the driver.
+ ///
+ /// # Safety
+ ///
+ /// This function may only be called by blk-mq C infrastructure.
+ unsafe extern "C" fn commit_rqs_callback(_hctx: *mut bindings::blk_mq_hw_ctx) {
+ T::commit_rqs()
+ }
+
+ /// This function is called by the C kernel. It is not currently
+ /// implemented, and there is no way to exercise this code path.
+ ///
+ /// # Safety
+ ///
+ /// This function may only be called by blk-mq C infrastructure.
+ unsafe extern "C" fn complete_callback(_rq: *mut bindings::request) {}
+
+ /// This function is called by the C kernel. A pointer to this function is
+ /// installed in the `blk_mq_ops` vtable for the driver.
+ ///
+ /// # Safety
+ ///
+ /// This function may only be called by blk-mq C infrastructure.
+ unsafe extern "C" fn poll_callback(
+ _hctx: *mut bindings::blk_mq_hw_ctx,
+ _iob: *mut bindings::io_comp_batch,
+ ) -> core::ffi::c_int {
+ T::poll().into()
+ }
+
+ /// This function is called by the C kernel. A pointer to this function is
+ /// installed in the `blk_mq_ops` vtable for the driver.
+ ///
+ /// # Safety
+ ///
+ /// This function may only be called by blk-mq C infrastructure. This
+ /// function may only be called once before `exit_hctx_callback` is called
+ /// for the same context.
+ unsafe extern "C" fn init_hctx_callback(
+ _hctx: *mut bindings::blk_mq_hw_ctx,
+ _tagset_data: *mut core::ffi::c_void,
+ _hctx_idx: core::ffi::c_uint,
+ ) -> core::ffi::c_int {
+ from_result(|| Ok(0))
+ }
+
+ /// This function is called by the C kernel. A pointer to this function is
+ /// installed in the `blk_mq_ops` vtable for the driver.
+ ///
+ /// # Safety
+ ///
+ /// This function may only be called by blk-mq C infrastructure.
+ unsafe extern "C" fn exit_hctx_callback(
+ _hctx: *mut bindings::blk_mq_hw_ctx,
+ _hctx_idx: core::ffi::c_uint,
+ ) {
+ }
+
+ /// This function is called by the C kernel. A pointer to this function is
+ /// installed in the `blk_mq_ops` vtable for the driver.
+ ///
+ /// # Safety
+ ///
+ /// - This function may only be called by blk-mq C infrastructure.
+ /// - `_set` must point to an initialized `TagSet<T>`.
+ /// - `rq` must point to an initialized `bindings::request`.
+ /// - The allocation pointed to by `rq` must be at the size of `Request`
+ /// plus the size of `RequestDataWrapper`.
+ unsafe extern "C" fn init_request_callback(
+ _set: *mut bindings::blk_mq_tag_set,
+ rq: *mut bindings::request,
+ _hctx_idx: core::ffi::c_uint,
+ _numa_node: core::ffi::c_uint,
+ ) -> core::ffi::c_int {
+ from_result(|| {
+ // SAFETY: By the safety requirements of this function, `rq` points
+ // to a valid allocation.
+ let pdu = unsafe { Request::wrapper_ptr(rq.cast::<Request<T>>()) };
+
+ // SAFETY: The refcount field is allocated but not initialized, so
+ // it is valid for writes.
+ unsafe { RequestDataWrapper::refcount_ptr(pdu.as_ptr()).write(AtomicU64::new(0)) };
+
+ Ok(0)
+ })
+ }
+
+ /// This function is called by the C kernel. A pointer to this function is
+ /// installed in the `blk_mq_ops` vtable for the driver.
+ ///
+ /// # Safety
+ ///
+ /// - This function may only be called by blk-mq C infrastructure.
+ /// - `_set` must point to an initialized `TagSet<T>`.
+ /// - `rq` must point to an initialized and valid `Request`.
+ unsafe extern "C" fn exit_request_callback(
+ _set: *mut bindings::blk_mq_tag_set,
+ rq: *mut bindings::request,
+ _hctx_idx: core::ffi::c_uint,
+ ) {
+ // SAFETY: The tagset invariants guarantee that all requests are allocated with extra memory
+ // for the request data.
+ let pdu = unsafe { bindings::blk_mq_rq_to_pdu(rq) }.cast::<RequestDataWrapper>();
+
+ // SAFETY: `pdu` is valid for read and write and is properly initialised.
+ unsafe { core::ptr::drop_in_place(pdu) };
+ }
+
+ const VTABLE: bindings::blk_mq_ops = bindings::blk_mq_ops {
+ queue_rq: Some(Self::queue_rq_callback),
+ queue_rqs: None,
+ commit_rqs: Some(Self::commit_rqs_callback),
+ get_budget: None,
+ put_budget: None,
+ set_rq_budget_token: None,
+ get_rq_budget_token: None,
+ timeout: None,
+ poll: if T::HAS_POLL {
+ Some(Self::poll_callback)
+ } else {
+ None
+ },
+ complete: Some(Self::complete_callback),
+ init_hctx: Some(Self::init_hctx_callback),
+ exit_hctx: Some(Self::exit_hctx_callback),
+ init_request: Some(Self::init_request_callback),
+ exit_request: Some(Self::exit_request_callback),
+ cleanup_rq: None,
+ busy: None,
+ map_queues: None,
+ #[cfg(CONFIG_BLK_DEBUG_FS)]
+ show_rq: None,
+ };
+
+ pub(crate) const fn build() -> &'static bindings::blk_mq_ops {
+ &Self::VTABLE
+ }
+}
diff --git a/rust/kernel/block/mq/raw_writer.rs b/rust/kernel/block/mq/raw_writer.rs
new file mode 100644
index 000000000000..9222465d670b
--- /dev/null
+++ b/rust/kernel/block/mq/raw_writer.rs
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use core::fmt::{self, Write};
+
+use crate::error::Result;
+use crate::prelude::EINVAL;
+
+/// A mutable reference to a byte buffer where a string can be written into.
+///
+/// # Invariants
+///
+/// `buffer` is always null terminated.
+pub(crate) struct RawWriter<'a> {
+ buffer: &'a mut [u8],
+ pos: usize,
+}
+
+impl<'a> RawWriter<'a> {
+ /// Create a new `RawWriter` instance.
+ fn new(buffer: &'a mut [u8]) -> Result<RawWriter<'a>> {
+ *(buffer.last_mut().ok_or(EINVAL)?) = 0;
+
+ // INVARIANT: We null terminated the buffer above.
+ Ok(Self { buffer, pos: 0 })
+ }
+
+ pub(crate) fn from_array<const N: usize>(
+ a: &'a mut [core::ffi::c_char; N],
+ ) -> Result<RawWriter<'a>> {
+ Self::new(
+ // SAFETY: the buffer of `a` is valid for read and write as `u8` for
+ // at least `N` bytes.
+ unsafe { core::slice::from_raw_parts_mut(a.as_mut_ptr().cast::<u8>(), N) },
+ )
+ }
+}
+
+impl Write for RawWriter<'_> {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ let bytes = s.as_bytes();
+ let len = bytes.len();
+
+ // We do not want to overwrite our null terminator
+ if self.pos + len > self.buffer.len() - 1 {
+ return Err(fmt::Error);
+ }
+
+ // INVARIANT: We are not overwriting the last byte
+ self.buffer[self.pos..self.pos + len].copy_from_slice(bytes);
+
+ self.pos += len;
+
+ Ok(())
+ }
+}
diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
new file mode 100644
index 000000000000..a0e22827f3f4
--- /dev/null
+++ b/rust/kernel/block/mq/request.rs
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! This module provides a wrapper for the C `struct request` type.
+//!
+//! C header: [`include/linux/blk-mq.h`](srctree/include/linux/blk-mq.h)
+
+use crate::{
+ bindings,
+ block::mq::Operations,
+ error::Result,
+ types::{ARef, AlwaysRefCounted, Opaque},
+};
+use core::{
+ marker::PhantomData,
+ ptr::{addr_of_mut, NonNull},
+ sync::atomic::{AtomicU64, Ordering},
+};
+
+/// A wrapper around a blk-mq `struct request`. This represents an IO request.
+///
+/// # Implementation details
+///
+/// There are four states for a request that the Rust bindings care about:
+///
+/// A) Request is owned by block layer (refcount 0)
+/// B) Request is owned by driver but with zero `ARef`s in existence
+/// (refcount 1)
+/// C) Request is owned by driver with exactly one `ARef` in existence
+/// (refcount 2)
+/// D) Request is owned by driver with more than one `ARef` in existence
+/// (refcount > 2)
+///
+///
+/// We need to track A and B to ensure we fail tag to request conversions for
+/// requests that are not owned by the driver.
+///
+/// We need to track C and D to ensure that it is safe to end the request and hand
+/// back ownership to the block layer.
+///
+/// The states are tracked through the private `refcount` field of
+/// `RequestDataWrapper`. This structure lives in the private data area of the C
+/// `struct request`.
+///
+/// # Invariants
+///
+/// * `self.0` is a valid `struct request` created by the C portion of the kernel.
+/// * The private data area associated with this request must be an initialized
+/// and valid `RequestDataWrapper<T>`.
+/// * `self` is reference counted by atomic modification of
+/// self.wrapper_ref().refcount().
+///
+#[repr(transparent)]
+pub struct Request<T: Operations>(Opaque<bindings::request>, PhantomData<T>);
+
+impl<T: Operations> Request<T> {
+ /// Create an `ARef<Request>` from a `struct request` pointer.
+ ///
+ /// # Safety
+ ///
+ /// * The caller must own a refcount on `ptr` that is transferred to the
+ /// returned `ARef`.
+ /// * The type invariants for `Request` must hold for the pointee of `ptr`.
+ pub(crate) unsafe fn aref_from_raw(ptr: *mut bindings::request) -> ARef<Self> {
+ // INVARIANT: By the safety requirements of this function, invariants are upheld.
+ // SAFETY: By the safety requirement of this function, we own a
+ // reference count that we can pass to `ARef`.
+ unsafe { ARef::from_raw(NonNull::new_unchecked(ptr as *const Self as *mut Self)) }
+ }
+
+ /// Notify the block layer that a request is going to be processed now.
+ ///
+ /// The block layer uses this hook to do proper initializations such as
+ /// starting the timeout timer. It is a requirement that block device
+ /// drivers call this function when starting to process a request.
+ ///
+ /// # Safety
+ ///
+ /// The caller must have exclusive ownership of `self`, that is
+ /// `self.wrapper_ref().refcount() == 2`.
+ pub(crate) unsafe fn start_unchecked(this: &ARef<Self>) {
+ // SAFETY: By type invariant, `self.0` is a valid `struct request` and
+ // we have exclusive access.
+ unsafe { bindings::blk_mq_start_request(this.0.get()) };
+ }
+
+ /// Try to take exclusive ownership of `this` by dropping the refcount to 0.
+ /// This fails if `this` is not the only `ARef` pointing to the underlying
+ /// `Request`.
+ ///
+ /// If the operation is successful, `Ok` is returned with a pointer to the
+ /// C `struct request`. If the operation fails, `this` is returned in the
+ /// `Err` variant.
+ fn try_set_end(this: ARef<Self>) -> Result<*mut bindings::request, ARef<Self>> {
+ // We can race with `TagSet::tag_to_rq`
+ if let Err(_old) = this.wrapper_ref().refcount().compare_exchange(
+ 2,
+ 0,
+ Ordering::Relaxed,
+ Ordering::Relaxed,
+ ) {
+ return Err(this);
+ }
+
+ let request_ptr = this.0.get();
+ core::mem::forget(this);
+
+ Ok(request_ptr)
+ }
+
+ /// Notify the block layer that the request has been completed without errors.
+ ///
+ /// This function will return `Err` if `this` is not the only `ARef`
+ /// referencing the request.
+ pub fn end_ok(this: ARef<Self>) -> Result<(), ARef<Self>> {
+ let request_ptr = Self::try_set_end(this)?;
+
+ // SAFETY: By type invariant, `this.0` was a valid `struct request`. The
+ // success of the call to `try_set_end` guarantees that there are no
+ // `ARef`s pointing to this request. Therefore it is safe to hand it
+ // back to the block layer.
+ unsafe { bindings::blk_mq_end_request(request_ptr, bindings::BLK_STS_OK as _) };
+
+ Ok(())
+ }
+
+ /// Return a pointer to the `RequestDataWrapper` stored in the private area
+ /// of the request structure.
+ ///
+ /// # Safety
+ ///
+ /// - `this` must point to a valid allocation of size at least size of
+ /// `Self` plus size of `RequestDataWrapper`.
+ pub(crate) unsafe fn wrapper_ptr(this: *mut Self) -> NonNull<RequestDataWrapper> {
+ let request_ptr = this.cast::<bindings::request>();
+ // SAFETY: By safety requirements for this function, `this` is a
+ // valid allocation.
+ let wrapper_ptr =
+ unsafe { bindings::blk_mq_rq_to_pdu(request_ptr).cast::<RequestDataWrapper>() };
+ // SAFETY: By C API contract, wrapper_ptr points to a valid allocation
+ // and is not null.
+ unsafe { NonNull::new_unchecked(wrapper_ptr) }
+ }
+
+ /// Return a reference to the `RequestDataWrapper` stored in the private
+ /// area of the request structure.
+ pub(crate) fn wrapper_ref(&self) -> &RequestDataWrapper {
+ // SAFETY: By type invariant, `self.0` is a valid allocation. Further,
+ // the private data associated with this request is initialized and
+ // valid. The existence of `&self` guarantees that the private data is
+ // valid as a shared reference.
+ unsafe { Self::wrapper_ptr(self as *const Self as *mut Self).as_ref() }
+ }
+}
+
+/// A wrapper around data stored in the private area of the C `struct request`.
+pub(crate) struct RequestDataWrapper {
+ /// The Rust request refcount has the following states:
+ ///
+ /// - 0: The request is owned by C block layer.
+ /// - 1: The request is owned by Rust abstractions but there are no ARef references to it.
+ /// - 2+: There are `ARef` references to the request.
+ refcount: AtomicU64,
+}
+
+impl RequestDataWrapper {
+ /// Return a reference to the refcount of the request that is embedding
+ /// `self`.
+ pub(crate) fn refcount(&self) -> &AtomicU64 {
+ &self.refcount
+ }
+
+ /// Return a pointer to the refcount of the request that is embedding the
+ /// pointee of `this`.
+ ///
+ /// # Safety
+ ///
+ /// - `this` must point to a live allocation of at least the size of `Self`.
+ pub(crate) unsafe fn refcount_ptr(this: *mut Self) -> *mut AtomicU64 {
+ // SAFETY: Because of the safety requirements of this function, the
+ // field projection is safe.
+ unsafe { addr_of_mut!((*this).refcount) }
+ }
+}
+
+// SAFETY: Exclusive access is thread-safe for `Request`. `Request` has no `&mut
+// self` methods and `&self` methods that mutate `self` are internally
+// synchronized.
+unsafe impl<T: Operations> Send for Request<T> {}
+
+// SAFETY: Shared access is thread-safe for `Request`. `&self` methods that
+// mutate `self` are internally synchronized`
+unsafe impl<T: Operations> Sync for Request<T> {}
+
+/// Store the result of `op(target.load())` in target, returning new value of
+/// target.
+fn atomic_relaxed_op_return(target: &AtomicU64, op: impl Fn(u64) -> u64) -> u64 {
+ let old = target.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |x| Some(op(x)));
+
+ // SAFETY: Because the operation passed to `fetch_update` above always
+ // return `Some`, `old` will always be `Ok`.
+ let old = unsafe { old.unwrap_unchecked() };
+
+ op(old)
+}
+
+/// Store the result of `op(target.load)` in `target` if `target.load() !=
+/// pred`, returning true if the target was updated.
+fn atomic_relaxed_op_unless(target: &AtomicU64, op: impl Fn(u64) -> u64, pred: u64) -> bool {
+ target
+ .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |x| {
+ if x == pred {
+ None
+ } else {
+ Some(op(x))
+ }
+ })
+ .is_ok()
+}
+
+// SAFETY: All instances of `Request<T>` are reference counted. This
+// implementation of `AlwaysRefCounted` ensure that increments to the ref count
+// keeps the object alive in memory at least until a matching reference count
+// decrement is executed.
+unsafe impl<T: Operations> AlwaysRefCounted for Request<T> {
+ fn inc_ref(&self) {
+ let refcount = &self.wrapper_ref().refcount();
+
+ #[cfg_attr(not(CONFIG_DEBUG_MISC), allow(unused_variables))]
+ let updated = atomic_relaxed_op_unless(refcount, |x| x + 1, 0);
+
+ #[cfg(CONFIG_DEBUG_MISC)]
+ if !updated {
+ panic!("Request refcount zero on clone")
+ }
+ }
+
+ unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
+ // SAFETY: The type invariants of `ARef` guarantee that `obj` is valid
+ // for read.
+ let wrapper_ptr = unsafe { Self::wrapper_ptr(obj.as_ptr()).as_ptr() };
+ // SAFETY: The type invariant of `Request` guarantees that the private
+ // data area is initialized and valid.
+ let refcount = unsafe { &*RequestDataWrapper::refcount_ptr(wrapper_ptr) };
+
+ #[cfg_attr(not(CONFIG_DEBUG_MISC), allow(unused_variables))]
+ let new_refcount = atomic_relaxed_op_return(refcount, |x| x - 1);
+
+ #[cfg(CONFIG_DEBUG_MISC)]
+ if new_refcount == 0 {
+ panic!("Request reached refcount zero in Rust abstractions");
+ }
+ }
+}
diff --git a/rust/kernel/block/mq/tag_set.rs b/rust/kernel/block/mq/tag_set.rs
new file mode 100644
index 000000000000..f9a1ca655a35
--- /dev/null
+++ b/rust/kernel/block/mq/tag_set.rs
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! This module provides the `TagSet` struct to wrap the C `struct blk_mq_tag_set`.
+//!
+//! C header: [`include/linux/blk-mq.h`](srctree/include/linux/blk-mq.h)
+
+use core::pin::Pin;
+
+use crate::{
+ bindings,
+ block::mq::{operations::OperationsVTable, request::RequestDataWrapper, Operations},
+ error,
+ prelude::PinInit,
+ try_pin_init,
+ types::Opaque,
+};
+use core::{convert::TryInto, marker::PhantomData};
+use macros::{pin_data, pinned_drop};
+
+/// A wrapper for the C `struct blk_mq_tag_set`.
+///
+/// `struct blk_mq_tag_set` contains a `struct list_head` and so must be pinned.
+///
+/// # Invariants
+///
+/// - `inner` is initialized and valid.
+#[pin_data(PinnedDrop)]
+#[repr(transparent)]
+pub struct TagSet<T: Operations> {
+ #[pin]
+ inner: Opaque<bindings::blk_mq_tag_set>,
+ _p: PhantomData<T>,
+}
+
+impl<T: Operations> TagSet<T> {
+ /// Try to create a new tag set
+ pub fn new(
+ nr_hw_queues: u32,
+ num_tags: u32,
+ num_maps: u32,
+ ) -> impl PinInit<Self, error::Error> {
+ // SAFETY: `blk_mq_tag_set` only contains integers and pointers, which
+ // all are allowed to be 0.
+ let tag_set: bindings::blk_mq_tag_set = unsafe { core::mem::zeroed() };
+ let tag_set = core::mem::size_of::<RequestDataWrapper>()
+ .try_into()
+ .map(|cmd_size| {
+ bindings::blk_mq_tag_set {
+ ops: OperationsVTable::<T>::build(),
+ nr_hw_queues,
+ timeout: 0, // 0 means default which is 30Hz in C
+ numa_node: bindings::NUMA_NO_NODE,
+ queue_depth: num_tags,
+ cmd_size,
+ flags: bindings::BLK_MQ_F_SHOULD_MERGE,
+ driver_data: core::ptr::null_mut::<core::ffi::c_void>(),
+ nr_maps: num_maps,
+ ..tag_set
+ }
+ });
+
+ try_pin_init!(TagSet {
+ inner <- PinInit::<_, error::Error>::pin_chain(Opaque::new(tag_set?), |tag_set| {
+ // SAFETY: we do not move out of `tag_set`.
+ let tag_set = unsafe { Pin::get_unchecked_mut(tag_set) };
+ // SAFETY: `tag_set` is a reference to an initialized `blk_mq_tag_set`.
+ error::to_result( unsafe { bindings::blk_mq_alloc_tag_set(tag_set.get())})
+ }),
+ _p: PhantomData,
+ })
+ }
+
+ /// Return the pointer to the wrapped `struct blk_mq_tag_set`
+ pub(crate) fn raw_tag_set(&self) -> *mut bindings::blk_mq_tag_set {
+ self.inner.get()
+ }
+}
+
+#[pinned_drop]
+impl<T: Operations> PinnedDrop for TagSet<T> {
+ fn drop(self: Pin<&mut Self>) {
+ // SAFETY: By type invariant `inner` is valid and has been properly
+ // initialized during construction.
+ unsafe { bindings::blk_mq_free_tag_set(self.inner.get()) };
+ }
+}
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index 55280ae9fe40..145f5c397009 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -126,6 +126,12 @@ impl Error {
self.0
}
+ #[cfg(CONFIG_BLOCK)]
+ pub(crate) fn to_blk_status(self) -> bindings::blk_status_t {
+ // SAFETY: `self.0` is a valid error due to its invariant.
+ unsafe { bindings::errno_to_blk_status(self.0) }
+ }
+
/// Returns the error encoded as a pointer.
#[allow(dead_code)]
pub(crate) fn to_ptr<T>(self) -> *mut T {
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index fbd91a48ff8b..2cf7c6b6f66b 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -27,6 +27,8 @@ compile_error!("Missing kernel configuration for conditional compilation");
extern crate self as kernel;
pub mod alloc;
+#[cfg(CONFIG_BLOCK)]
+pub mod block;
mod build_assert;
pub mod error;
pub mod init;
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
index 3ee8ecfb8c04..3500a3d62f0d 100644
--- a/scripts/Kconfig.include
+++ b/scripts/Kconfig.include
@@ -33,7 +33,8 @@ ld-option = $(success,$(LD) -v $(1))
# $(as-instr,<instr>)
# Return y if the assembler supports <instr>, n otherwise
-as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -Wa$(comma)--fatal-warnings -c -x assembler-with-cpp -o /dev/null -)
+as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) $(2) -Wa$(comma)--fatal-warnings -c -x assembler-with-cpp -o /dev/null -)
+as-instr64 = $(as-instr,$(1),$(m64-flag))
# check if $(CC) and $(LD) exist
$(error-if,$(failure,command -v $(CC)),C compiler '$(CC)' not found)
diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic
deleted file mode 100644
index 1486abf34c7c..000000000000
--- a/scripts/Makefile.asm-generic
+++ /dev/null
@@ -1,58 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# include/asm-generic contains a lot of files that are used
-# verbatim by several architectures.
-#
-# This Makefile reads the file arch/$(SRCARCH)/include/(uapi/)/asm/Kbuild
-# and for each file listed in this file with generic-y creates
-# a small wrapper file in arch/$(SRCARCH)/include/generated/(uapi/)/asm.
-
-PHONY := all
-all:
-
-src := $(srctree)/$(subst /generated,,$(obj))
-
-include $(srctree)/scripts/Kbuild.include
--include $(kbuild-file)
-
-# $(generic)/Kbuild lists mandatory-y. Exclude um since it is a special case.
-ifneq ($(SRCARCH),um)
-include $(srctree)/$(generic)/Kbuild
-endif
-
-redundant := $(filter $(mandatory-y) $(generated-y), $(generic-y))
-redundant += $(foreach f, $(generic-y), $(if $(wildcard $(src)/$(f)),$(f)))
-redundant := $(sort $(redundant))
-$(if $(redundant),\
- $(warning redundant generic-y found in $(src)/Kbuild: $(redundant)))
-
-# If arch does not implement mandatory headers, fallback to asm-generic ones.
-mandatory-y := $(filter-out $(generated-y), $(mandatory-y))
-generic-y += $(foreach f, $(mandatory-y), $(if $(wildcard $(src)/$(f)),,$(f)))
-
-generic-y := $(addprefix $(obj)/, $(generic-y))
-generated-y := $(addprefix $(obj)/, $(generated-y))
-
-# Remove stale wrappers when the corresponding files are removed from generic-y
-old-headers := $(wildcard $(obj)/*.h)
-unwanted := $(filter-out $(generic-y) $(generated-y),$(old-headers))
-
-quiet_cmd_wrap = WRAP $@
- cmd_wrap = echo "\#include <asm-generic/$*.h>" > $@
-
-quiet_cmd_remove = REMOVE $(unwanted)
- cmd_remove = rm -f $(unwanted)
-
-all: $(generic-y)
- $(if $(unwanted),$(call cmd,remove))
- @:
-
-$(obj)/%.h:
- $(call cmd,wrap)
-
-# Create output directory. Skip it if at least one old header exists
-# since we know the output directory already exists.
-ifeq ($(old-headers),)
-$(shell mkdir -p $(obj))
-endif
-
-.PHONY: $(PHONY)
diff --git a/scripts/Makefile.asm-headers b/scripts/Makefile.asm-headers
new file mode 100644
index 000000000000..6b8e8318e810
--- /dev/null
+++ b/scripts/Makefile.asm-headers
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: GPL-2.0
+# include/asm-generic contains a lot of files that are used
+# verbatim by several architectures.
+#
+# This Makefile generates arch/$(SRCARCH)/include/generated/(uapi/)/asm
+# headers from multiple sources:
+# - a small wrapper to include the corresponding asm-generic/*.h
+# is generated for each file listed as generic-y
+# - uapi/asm/unistd_*.h files listed as syscalls-y are generated from
+# syscall.tbl with the __NR_* macros
+# - Corresponding asm/syscall_table_*.h are generated from the same input
+
+PHONY := all
+all:
+
+src := $(srctree)/$(subst /generated,,$(obj))
+
+syscall_abis_32 += common,32
+syscall_abis_64 += common,64
+syscalltbl := $(srctree)/scripts/syscall.tbl
+syshdr-args := --emit-nr
+
+# let architectures override $(syscall_abis_%) and $(syscalltbl)
+-include $(srctree)/arch/$(SRCARCH)/kernel/Makefile.syscalls
+include $(srctree)/scripts/Kbuild.include
+-include $(kbuild-file)
+
+syshdr := $(srctree)/scripts/syscallhdr.sh
+systbl := $(srctree)/scripts/syscalltbl.sh
+
+# $(generic)/Kbuild lists mandatory-y. Exclude um since it is a special case.
+ifneq ($(SRCARCH),um)
+include $(srctree)/$(generic)/Kbuild
+endif
+
+redundant := $(filter $(mandatory-y) $(generated-y), $(generic-y))
+redundant += $(foreach f, $(generic-y), $(if $(wildcard $(src)/$(f)),$(f)))
+redundant := $(sort $(redundant))
+$(if $(redundant),\
+ $(warning redundant generic-y found in $(src)/Kbuild: $(redundant)))
+
+# If arch does not implement mandatory headers, fallback to asm-generic ones.
+mandatory-y := $(filter-out $(generated-y), $(mandatory-y))
+generic-y += $(foreach f, $(mandatory-y), $(if $(wildcard $(src)/$(f)),,$(f)))
+
+generic-y := $(addprefix $(obj)/, $(generic-y))
+syscall-y := $(addprefix $(obj)/, $(syscall-y))
+generated-y := $(addprefix $(obj)/, $(generated-y))
+
+# Remove stale wrappers when the corresponding files are removed from generic-y
+old-headers := $(wildcard $(obj)/*.h)
+unwanted := $(filter-out $(generic-y) $(generated-y) $(syscall-y),$(old-headers))
+
+quiet_cmd_wrap = WRAP $@
+ cmd_wrap = echo "\#include <asm-generic/$*.h>" > $@
+
+quiet_cmd_remove = REMOVE $(unwanted)
+ cmd_remove = rm -f $(unwanted)
+
+quiet_cmd_syshdr = SYSHDR $@
+ cmd_syshdr = $(CONFIG_SHELL) $(syshdr) \
+ $(if $(syshdr-args-$*),$(syshdr-args-$*),$(syshdr-args)) \
+ $(if $(syscall_compat),--prefix "compat$*_") \
+ --abis $(subst $(space),$(comma),$(strip $(syscall_abis_$*))) \
+ $< $@
+
+quiet_cmd_systbl = SYSTBL $@
+ cmd_systbl = $(CONFIG_SHELL) $(systbl) \
+ $(if $(systbl-args-$*),$(systbl-args-$*),$(systbl-args)) \
+ --abis $(subst $(space),$(comma),$(strip $(syscall_abis_$*))) \
+ $< $@
+
+all: $(generic-y) $(syscall-y)
+ $(if $(unwanted),$(call cmd,remove))
+ @:
+
+$(obj)/%.h: $(srctree)/$(generic)/%.h
+ $(call cmd,wrap)
+
+$(obj)/unistd_%.h: $(syscalltbl) $(syshdr) FORCE
+ $(call if_changed,syshdr)
+
+$(obj)/unistd_compat_%.h: syscall_compat:=1
+$(obj)/unistd_compat_%.h: $(syscalltbl) $(syshdr) FORCE
+ $(call if_changed,syshdr)
+
+$(obj)/syscall_table_%.h: $(syscalltbl) $(systbl) FORCE
+ $(call if_changed,systbl)
+
+# Create output directory. Skip it if at least one old header exists
+# since we know the output directory already exists.
+ifeq ($(old-headers),)
+$(shell mkdir -p $(obj))
+endif
+
+FORCE:
+
+.PHONY: $(PHONY)
diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch
index 52e5bfb61fd0..cc62980cfa6e 100644
--- a/scripts/const_structs.checkpatch
+++ b/scripts/const_structs.checkpatch
@@ -64,7 +64,17 @@ platform_suspend_ops
proc_ops
proto_ops
pwm_ops
+reg_default
+reg_field
+reg_sequence
regmap_access_table
+regmap_bus
+regmap_config
+regmap_irq
+regmap_irq_chip
+regmap_irq_sub_irq_map
+regmap_range
+regmap_range_cfg
regulator_ops
reset_control_ops
rpc_pipe_ops
diff --git a/scripts/ld-version.sh b/scripts/ld-version.sh
index a78b804b680c..b9513d224476 100755
--- a/scripts/ld-version.sh
+++ b/scripts/ld-version.sh
@@ -57,9 +57,11 @@ else
fi
fi
-# Some distributions append a package release number, as in 2.34-4.fc32
-# Trim the hyphen and any characters that follow.
-version=${version%-*}
+# There may be something after the version, such as a distribution's package
+# release number (like Fedora's "2.34-4.fc32") or punctuation (like LLD briefly
+# added before the "compatible with GNU linkers" string), so remove everything
+# after just numbers and periods.
+version=${version%%[!0-9.]*}
cversion=$(get_canonical_version $version)
min_cversion=$(get_canonical_version $min_version)
diff --git a/scripts/package/kernel.spec b/scripts/package/kernel.spec
index fffc8af8deb1..c52d517b9364 100644
--- a/scripts/package/kernel.spec
+++ b/scripts/package/kernel.spec
@@ -83,7 +83,6 @@ ln -fns /usr/src/kernels/%{KERNELRELEASE} %{buildroot}/lib/modules/%{KERNELRELEA
done
if [ -d "%{buildroot}/lib/modules/%{KERNELRELEASE}/dtb" ];then
- echo "/lib/modules/%{KERNELRELEASE}/dtb"
find "%{buildroot}/lib/modules/%{KERNELRELEASE}/dtb" -printf "%%%ghost /boot/dtb-%{KERNELRELEASE}/%%P\n"
fi
diff --git a/scripts/syscall.tbl b/scripts/syscall.tbl
new file mode 100644
index 000000000000..797e20ea99a2
--- /dev/null
+++ b/scripts/syscall.tbl
@@ -0,0 +1,404 @@
+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+#
+# This file contains the system call numbers for all of the
+# more recently added architectures.
+#
+# As a basic principle, no duplication of functionality
+# should be added, e.g. we don't use lseek when llseek
+# is present. New architectures should use this file
+# and implement the less feature-full calls in user space.
+#
+0 common io_setup sys_io_setup compat_sys_io_setup
+1 common io_destroy sys_io_destroy
+2 common io_submit sys_io_submit compat_sys_io_submit
+3 common io_cancel sys_io_cancel
+4 time32 io_getevents sys_io_getevents_time32
+4 64 io_getevents sys_io_getevents
+5 common setxattr sys_setxattr
+6 common lsetxattr sys_lsetxattr
+7 common fsetxattr sys_fsetxattr
+8 common getxattr sys_getxattr
+9 common lgetxattr sys_lgetxattr
+10 common fgetxattr sys_fgetxattr
+11 common listxattr sys_listxattr
+12 common llistxattr sys_llistxattr
+13 common flistxattr sys_flistxattr
+14 common removexattr sys_removexattr
+15 common lremovexattr sys_lremovexattr
+16 common fremovexattr sys_fremovexattr
+17 common getcwd sys_getcwd
+18 common lookup_dcookie sys_ni_syscall
+19 common eventfd2 sys_eventfd2
+20 common epoll_create1 sys_epoll_create1
+21 common epoll_ctl sys_epoll_ctl
+22 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
+23 common dup sys_dup
+24 common dup3 sys_dup3
+25 32 fcntl64 sys_fcntl64 compat_sys_fcntl64
+25 64 fcntl sys_fcntl
+26 common inotify_init1 sys_inotify_init1
+27 common inotify_add_watch sys_inotify_add_watch
+28 common inotify_rm_watch sys_inotify_rm_watch
+29 common ioctl sys_ioctl compat_sys_ioctl
+30 common ioprio_set sys_ioprio_set
+31 common ioprio_get sys_ioprio_get
+32 common flock sys_flock
+33 common mknodat sys_mknodat
+34 common mkdirat sys_mkdirat
+35 common unlinkat sys_unlinkat
+36 common symlinkat sys_symlinkat
+37 common linkat sys_linkat
+# renameat is superseded with flags by renameat2
+38 renameat renameat sys_renameat
+39 common umount2 sys_umount
+40 common mount sys_mount
+41 common pivot_root sys_pivot_root
+43 32 statfs64 sys_statfs64 compat_sys_statfs64
+43 64 statfs sys_statfs
+44 32 fstatfs64 sys_fstatfs64 compat_sys_fstatfs64
+44 64 fstatfs sys_fstatfs
+45 32 truncate64 sys_truncate64 compat_sys_truncate64
+45 64 truncate sys_truncate
+46 32 ftruncate64 sys_ftruncate64 compat_sys_ftruncate64
+46 64 ftruncate sys_ftruncate
+47 common fallocate sys_fallocate compat_sys_fallocate
+48 common faccessat sys_faccessat
+49 common chdir sys_chdir
+50 common fchdir sys_fchdir
+51 common chroot sys_chroot
+52 common fchmod sys_fchmod
+53 common fchmodat sys_fchmodat
+54 common fchownat sys_fchownat
+55 common fchown sys_fchown
+56 common openat sys_openat
+57 common close sys_close
+58 common vhangup sys_vhangup
+59 common pipe2 sys_pipe2
+60 common quotactl sys_quotactl
+61 common getdents64 sys_getdents64
+62 32 llseek sys_llseek
+62 64 lseek sys_lseek
+63 common read sys_read
+64 common write sys_write
+65 common readv sys_readv sys_readv
+66 common writev sys_writev sys_writev
+67 common pread64 sys_pread64 compat_sys_pread64
+68 common pwrite64 sys_pwrite64 compat_sys_pwrite64
+69 common preadv sys_preadv compat_sys_preadv
+70 common pwritev sys_pwritev compat_sys_pwritev
+71 32 sendfile64 sys_sendfile64
+71 64 sendfile sys_sendfile64
+72 time32 pselect6 sys_pselect6_time32 compat_sys_pselect6_time32
+72 64 pselect6 sys_pselect6
+73 time32 ppoll sys_ppoll_time32 compat_sys_ppoll_time32
+73 64 ppoll sys_ppoll
+74 common signalfd4 sys_signalfd4 compat_sys_signalfd4
+75 common vmsplice sys_vmsplice
+76 common splice sys_splice
+77 common tee sys_tee
+78 common readlinkat sys_readlinkat
+79 stat64 fstatat64 sys_fstatat64
+79 newstat fstatat sys_newfstatat
+80 stat64 fstat64 sys_fstat64
+80 newstat fstat sys_newfstat
+81 common sync sys_sync
+82 common fsync sys_fsync
+83 common fdatasync sys_fdatasync
+84 common sync_file_range sys_sync_file_range compat_sys_sync_file_range
+85 common timerfd_create sys_timerfd_create
+86 time32 timerfd_settime sys_timerfd_settime32
+86 64 timerfd_settime sys_timerfd_settime
+87 time32 timerfd_gettime sys_timerfd_gettime32
+87 64 timerfd_gettime sys_timerfd_gettime
+88 time32 utimensat sys_utimensat_time32
+88 64 utimensat sys_utimensat
+89 common acct sys_acct
+90 common capget sys_capget
+91 common capset sys_capset
+92 common personality sys_personality
+93 common exit sys_exit
+94 common exit_group sys_exit_group
+95 common waitid sys_waitid compat_sys_waitid
+96 common set_tid_address sys_set_tid_address
+97 common unshare sys_unshare
+98 time32 futex sys_futex_time32
+98 64 futex sys_futex
+99 common set_robust_list sys_set_robust_list compat_sys_set_robust_list
+100 common get_robust_list sys_get_robust_list compat_sys_get_robust_list
+101 time32 nanosleep sys_nanosleep_time32
+101 64 nanosleep sys_nanosleep
+102 common getitimer sys_getitimer compat_sys_getitimer
+103 common setitimer sys_setitimer compat_sys_setitimer
+104 common kexec_load sys_kexec_load compat_sys_kexec_load
+105 common init_module sys_init_module
+106 common delete_module sys_delete_module
+107 common timer_create sys_timer_create compat_sys_timer_create
+108 time32 timer_gettime sys_timer_gettime32
+108 64 timer_gettime sys_timer_gettime
+109 common timer_getoverrun sys_timer_getoverrun
+110 time32 timer_settime sys_timer_settime32
+110 64 timer_settime sys_timer_settime
+111 common timer_delete sys_timer_delete
+112 time32 clock_settime sys_clock_settime32
+112 64 clock_settime sys_clock_settime
+113 time32 clock_gettime sys_clock_gettime32
+113 64 clock_gettime sys_clock_gettime
+114 time32 clock_getres sys_clock_getres_time32
+114 64 clock_getres sys_clock_getres
+115 time32 clock_nanosleep sys_clock_nanosleep_time32
+115 64 clock_nanosleep sys_clock_nanosleep
+116 common syslog sys_syslog
+117 common ptrace sys_ptrace compat_sys_ptrace
+118 common sched_setparam sys_sched_setparam
+119 common sched_setscheduler sys_sched_setscheduler
+120 common sched_getscheduler sys_sched_getscheduler
+121 common sched_getparam sys_sched_getparam
+122 common sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity
+123 common sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity
+124 common sched_yield sys_sched_yield
+125 common sched_get_priority_max sys_sched_get_priority_max
+126 common sched_get_priority_min sys_sched_get_priority_min
+127 time32 sched_rr_get_interval sys_sched_rr_get_interval_time32
+127 64 sched_rr_get_interval sys_sched_rr_get_interval
+128 common restart_syscall sys_restart_syscall
+129 common kill sys_kill
+130 common tkill sys_tkill
+131 common tgkill sys_tgkill
+132 common sigaltstack sys_sigaltstack compat_sys_sigaltstack
+133 common rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend
+134 common rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction
+135 common rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask
+136 common rt_sigpending sys_rt_sigpending compat_sys_rt_sigpending
+137 time32 rt_sigtimedwait sys_rt_sigtimedwait_time32 compat_sys_rt_sigtimedwait_time32
+137 64 rt_sigtimedwait sys_rt_sigtimedwait
+138 common rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo
+139 common rt_sigreturn sys_rt_sigreturn compat_sys_rt_sigreturn
+140 common setpriority sys_setpriority
+141 common getpriority sys_getpriority
+142 common reboot sys_reboot
+143 common setregid sys_setregid
+144 common setgid sys_setgid
+145 common setreuid sys_setreuid
+146 common setuid sys_setuid
+147 common setresuid sys_setresuid
+148 common getresuid sys_getresuid
+149 common setresgid sys_setresgid
+150 common getresgid sys_getresgid
+151 common setfsuid sys_setfsuid
+152 common setfsgid sys_setfsgid
+153 common times sys_times compat_sys_times
+154 common setpgid sys_setpgid
+155 common getpgid sys_getpgid
+156 common getsid sys_getsid
+157 common setsid sys_setsid
+158 common getgroups sys_getgroups
+159 common setgroups sys_setgroups
+160 common uname sys_newuname
+161 common sethostname sys_sethostname
+162 common setdomainname sys_setdomainname
+# getrlimit and setrlimit are superseded with prlimit64
+163 rlimit getrlimit sys_getrlimit compat_sys_getrlimit
+164 rlimit setrlimit sys_setrlimit compat_sys_setrlimit
+165 common getrusage sys_getrusage compat_sys_getrusage
+166 common umask sys_umask
+167 common prctl sys_prctl
+168 common getcpu sys_getcpu
+169 time32 gettimeofday sys_gettimeofday compat_sys_gettimeofday
+169 64 gettimeofday sys_gettimeofday
+170 time32 settimeofday sys_settimeofday compat_sys_settimeofday
+170 64 settimeofday sys_settimeofday
+171 time32 adjtimex sys_adjtimex_time32
+171 64 adjtimex sys_adjtimex
+172 common getpid sys_getpid
+173 common getppid sys_getppid
+174 common getuid sys_getuid
+175 common geteuid sys_geteuid
+176 common getgid sys_getgid
+177 common getegid sys_getegid
+178 common gettid sys_gettid
+179 common sysinfo sys_sysinfo compat_sys_sysinfo
+180 common mq_open sys_mq_open compat_sys_mq_open
+181 common mq_unlink sys_mq_unlink
+182 time32 mq_timedsend sys_mq_timedsend_time32
+182 64 mq_timedsend sys_mq_timedsend
+183 time32 mq_timedreceive sys_mq_timedreceive_time32
+183 64 mq_timedreceive sys_mq_timedreceive
+184 common mq_notify sys_mq_notify compat_sys_mq_notify
+185 common mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr
+186 common msgget sys_msgget
+187 common msgctl sys_msgctl compat_sys_msgctl
+188 common msgrcv sys_msgrcv compat_sys_msgrcv
+189 common msgsnd sys_msgsnd compat_sys_msgsnd
+190 common semget sys_semget
+191 common semctl sys_semctl compat_sys_semctl
+192 time32 semtimedop sys_semtimedop_time32
+192 64 semtimedop sys_semtimedop
+193 common semop sys_semop
+194 common shmget sys_shmget
+195 common shmctl sys_shmctl compat_sys_shmctl
+196 common shmat sys_shmat compat_sys_shmat
+197 common shmdt sys_shmdt
+198 common socket sys_socket
+199 common socketpair sys_socketpair
+200 common bind sys_bind
+201 common listen sys_listen
+202 common accept sys_accept
+203 common connect sys_connect
+204 common getsockname sys_getsockname
+205 common getpeername sys_getpeername
+206 common sendto sys_sendto
+207 common recvfrom sys_recvfrom compat_sys_recvfrom
+208 common setsockopt sys_setsockopt sys_setsockopt
+209 common getsockopt sys_getsockopt sys_getsockopt
+210 common shutdown sys_shutdown
+211 common sendmsg sys_sendmsg compat_sys_sendmsg
+212 common recvmsg sys_recvmsg compat_sys_recvmsg
+213 common readahead sys_readahead compat_sys_readahead
+214 common brk sys_brk
+215 common munmap sys_munmap
+216 common mremap sys_mremap
+217 common add_key sys_add_key
+218 common request_key sys_request_key
+219 common keyctl sys_keyctl compat_sys_keyctl
+220 common clone sys_clone
+221 common execve sys_execve compat_sys_execve
+222 32 mmap2 sys_mmap2
+222 64 mmap sys_mmap
+223 32 fadvise64_64 sys_fadvise64_64 compat_sys_fadvise64_64
+223 64 fadvise64 sys_fadvise64_64
+224 common swapon sys_swapon
+225 common swapoff sys_swapoff
+226 common mprotect sys_mprotect
+227 common msync sys_msync
+228 common mlock sys_mlock
+229 common munlock sys_munlock
+230 common mlockall sys_mlockall
+231 common munlockall sys_munlockall
+232 common mincore sys_mincore
+233 common madvise sys_madvise
+234 common remap_file_pages sys_remap_file_pages
+235 common mbind sys_mbind
+236 common get_mempolicy sys_get_mempolicy
+237 common set_mempolicy sys_set_mempolicy
+238 common migrate_pages sys_migrate_pages
+239 common move_pages sys_move_pages
+240 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
+241 common perf_event_open sys_perf_event_open
+242 common accept4 sys_accept4
+243 time32 recvmmsg sys_recvmmsg_time32 compat_sys_recvmmsg_time32
+243 64 recvmmsg sys_recvmmsg
+# Architectures may provide up to 16 syscalls of their own between 244 and 259
+244 arc cacheflush sys_cacheflush
+245 arc arc_settls sys_arc_settls
+246 arc arc_gettls sys_arc_gettls
+247 arc sysfs sys_sysfs
+248 arc arc_usr_cmpxchg sys_arc_usr_cmpxchg
+
+244 csky set_thread_area sys_set_thread_area
+245 csky cacheflush sys_cacheflush
+
+244 nios2 cacheflush sys_cacheflush
+
+244 or1k or1k_atomic sys_or1k_atomic
+
+258 riscv riscv_hwprobe sys_riscv_hwprobe
+259 riscv riscv_flush_icache sys_riscv_flush_icache
+
+260 time32 wait4 sys_wait4 compat_sys_wait4
+260 64 wait4 sys_wait4
+261 common prlimit64 sys_prlimit64
+262 common fanotify_init sys_fanotify_init
+263 common fanotify_mark sys_fanotify_mark
+264 common name_to_handle_at sys_name_to_handle_at
+265 common open_by_handle_at sys_open_by_handle_at
+266 time32 clock_adjtime sys_clock_adjtime32
+266 64 clock_adjtime sys_clock_adjtime
+267 common syncfs sys_syncfs
+268 common setns sys_setns
+269 common sendmmsg sys_sendmmsg compat_sys_sendmmsg
+270 common process_vm_readv sys_process_vm_readv
+271 common process_vm_writev sys_process_vm_writev
+272 common kcmp sys_kcmp
+273 common finit_module sys_finit_module
+274 common sched_setattr sys_sched_setattr
+275 common sched_getattr sys_sched_getattr
+276 common renameat2 sys_renameat2
+277 common seccomp sys_seccomp
+278 common getrandom sys_getrandom
+279 common memfd_create sys_memfd_create
+280 common bpf sys_bpf
+281 common execveat sys_execveat compat_sys_execveat
+282 common userfaultfd sys_userfaultfd
+283 common membarrier sys_membarrier
+284 common mlock2 sys_mlock2
+285 common copy_file_range sys_copy_file_range
+286 common preadv2 sys_preadv2 compat_sys_preadv2
+287 common pwritev2 sys_pwritev2 compat_sys_pwritev2
+288 common pkey_mprotect sys_pkey_mprotect
+289 common pkey_alloc sys_pkey_alloc
+290 common pkey_free sys_pkey_free
+291 common statx sys_statx
+292 time32 io_pgetevents sys_io_pgetevents_time32 compat_sys_io_pgetevents
+292 64 io_pgetevents sys_io_pgetevents
+293 common rseq sys_rseq
+294 common kexec_file_load sys_kexec_file_load
+# 295 through 402 are unassigned to sync up with generic numbers don't use
+403 32 clock_gettime64 sys_clock_gettime
+404 32 clock_settime64 sys_clock_settime
+405 32 clock_adjtime64 sys_clock_adjtime
+406 32 clock_getres_time64 sys_clock_getres
+407 32 clock_nanosleep_time64 sys_clock_nanosleep
+408 32 timer_gettime64 sys_timer_gettime
+409 32 timer_settime64 sys_timer_settime
+410 32 timerfd_gettime64 sys_timerfd_gettime
+411 32 timerfd_settime64 sys_timerfd_settime
+412 32 utimensat_time64 sys_utimensat
+413 32 pselect6_time64 sys_pselect6 compat_sys_pselect6_time64
+414 32 ppoll_time64 sys_ppoll compat_sys_ppoll_time64
+416 32 io_pgetevents_time64 sys_io_pgetevents compat_sys_io_pgetevents_time64
+417 32 recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64
+418 32 mq_timedsend_time64 sys_mq_timedsend
+419 32 mq_timedreceive_time64 sys_mq_timedreceive
+420 32 semtimedop_time64 sys_semtimedop
+421 32 rt_sigtimedwait_time64 sys_rt_sigtimedwait compat_sys_rt_sigtimedwait_time64
+422 32 futex_time64 sys_futex
+423 32 sched_rr_get_interval_time64 sys_sched_rr_get_interval
+424 common pidfd_send_signal sys_pidfd_send_signal
+425 common io_uring_setup sys_io_uring_setup
+426 common io_uring_enter sys_io_uring_enter
+427 common io_uring_register sys_io_uring_register
+428 common open_tree sys_open_tree
+429 common move_mount sys_move_mount
+430 common fsopen sys_fsopen
+431 common fsconfig sys_fsconfig
+432 common fsmount sys_fsmount
+433 common fspick sys_fspick
+434 common pidfd_open sys_pidfd_open
+435 common clone3 sys_clone3
+436 common close_range sys_close_range
+437 common openat2 sys_openat2
+438 common pidfd_getfd sys_pidfd_getfd
+439 common faccessat2 sys_faccessat2
+440 common process_madvise sys_process_madvise
+441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2
+442 common mount_setattr sys_mount_setattr
+443 common quotactl_fd sys_quotactl_fd
+444 common landlock_create_ruleset sys_landlock_create_ruleset
+445 common landlock_add_rule sys_landlock_add_rule
+446 common landlock_restrict_self sys_landlock_restrict_self
+447 memfd_secret memfd_secret sys_memfd_secret
+448 common process_mrelease sys_process_mrelease
+449 common futex_waitv sys_futex_waitv
+450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+451 common cachestat sys_cachestat
+452 common fchmodat2 sys_fchmodat2
+453 common map_shadow_stack sys_map_shadow_stack
+454 common futex_wake sys_futex_wake
+455 common futex_wait sys_futex_wait
+456 common futex_requeue sys_futex_requeue
+457 common statmount sys_statmount
+458 common listmount sys_listmount
+459 common lsm_get_self_attr sys_lsm_get_self_attr
+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
diff --git a/scripts/syscalltbl.sh b/scripts/syscalltbl.sh
index 6abe143889ef..6a903b87a7c2 100755
--- a/scripts/syscalltbl.sh
+++ b/scripts/syscalltbl.sh
@@ -54,7 +54,7 @@ nxt=0
grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | {
- while read nr abi name native compat ; do
+ while read nr abi name native compat noreturn; do
if [ $nxt -gt $nr ]; then
echo "error: $infile: syscall table is not sorted or duplicates the same syscall number" >&2
@@ -66,7 +66,21 @@ grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | {
nxt=$((nxt + 1))
done
- if [ -n "$compat" ]; then
+ if [ "$compat" = "-" ]; then
+ unset compat
+ fi
+
+ if [ -n "$noreturn" ]; then
+ if [ "$noreturn" != "noreturn" ]; then
+ echo "error: $infile: invalid string \"$noreturn\" in 'noreturn' column"
+ exit 1
+ fi
+ if [ -n "$compat" ]; then
+ echo "__SYSCALL_COMPAT_NORETURN($nr, $native, $compat)"
+ else
+ echo "__SYSCALL_NORETURN($nr, $native)"
+ fi
+ elif [ -n "$compat" ]; then
echo "__SYSCALL_WITH_COMPAT($nr, $native, $compat)"
elif [ -n "$native" ]; then
echo "__SYSCALL($nr, $native)"
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index abdd22007ed8..e4a79a9b2d58 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -427,8 +427,6 @@ static void __init remove_securityfs_measurement_lists(struct dentry **lists)
kfree(lists);
}
-
- securityfs_measurement_list_count = 0;
}
static int __init create_securityfs_measurement_lists(void)
@@ -625,6 +623,7 @@ out:
securityfs_remove(binary_runtime_measurements);
remove_securityfs_measurement_lists(ascii_securityfs_measurement_lists);
remove_securityfs_measurement_lists(binary_securityfs_measurement_lists);
+ securityfs_measurement_list_count = 0;
securityfs_remove(ima_symlink);
securityfs_remove(ima_dir);
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 8af2136069d2..831cb84fd75a 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -1040,4 +1040,5 @@ static void __exit cleanup_encrypted(void)
late_initcall(init_encrypted);
module_exit(cleanup_encrypted);
+MODULE_DESCRIPTION("Encrypted key type");
MODULE_LICENSE("GPL");
diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c
index 5113aeae5628..e2d9644efde1 100644
--- a/security/keys/trusted-keys/trusted_core.c
+++ b/security/keys/trusted-keys/trusted_core.c
@@ -395,4 +395,5 @@ static void __exit cleanup_trusted(void)
late_initcall(init_trusted);
module_exit(cleanup_trusted);
+MODULE_DESCRIPTION("Trusted Key type");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
index 51998d1c72ff..80c816922f78 100644
--- a/sound/pci/hda/cs35l41_hda_property.c
+++ b/sound/pci/hda/cs35l41_hda_property.c
@@ -128,8 +128,8 @@ static const struct cs35l41_config cs35l41_config_table[] = {
{ "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
{ "17AA38B6", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
{ "17AA38B7", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
- { "17AA38C7", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 2, -1, 1000, 4500, 24 },
- { "17AA38C8", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 2, -1, 1000, 4500, 24 },
+ { "17AA38C7", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 },
+ { "17AA38C8", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 },
{ "17AA38F9", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
{ "17AA38FA", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
{}
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 766734dc5be2..5d86e5a9c814 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -463,7 +463,8 @@ static int azx_get_sync_time(ktime_t *device,
*device = ktime_add_ns(*device, (wallclk_cycles * NSEC_PER_SEC) /
((HDA_MAX_CYCLE_VALUE + 1) * runtime->rate));
- *system = convert_art_to_tsc(tsc_counter);
+ system->cycles = tsc_counter;
+ system->cs_id = CSID_X86_ART;
return 0;
}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 811e82474200..766f0b1d3e9d 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -10053,6 +10053,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x84a6, "HP 250 G7 Notebook PC", ALC269_FIXUP_HP_LINE1_MIC1_LED),
SND_PCI_QUIRK(0x103c, 0x84ae, "HP 15-db0403ng", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
@@ -10383,6 +10384,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE),
SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
+ SND_PCI_QUIRK(0x10ec, 0x11bc, "VAIO VJFE-IL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
@@ -10480,6 +10482,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL50NU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0xa650, "Clevo NP[567]0SN[CD]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0xa671, "Clevo NP70SN[CDE]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0xa763, "Clevo V54x_6x_TU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0xb022, "Clevo NH77D[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -10655,6 +10658,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
+ SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c
index 8ca8bcd177ab..dfda6bb5c6f8 100644
--- a/sound/soc/codecs/rt711-sdw.c
+++ b/sound/soc/codecs/rt711-sdw.c
@@ -38,7 +38,9 @@ static bool rt711_readable_register(struct device *dev, unsigned int reg)
case 0x8300 ... 0x83ff:
case 0x9c00 ... 0x9cff:
case 0xb900 ... 0xb9ff:
+ case 0x752008:
case 0x752009:
+ case 0x75200b:
case 0x752011:
case 0x75201a:
case 0x752045:
diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
index c61d298ea6b3..1c823f9eea57 100644
--- a/sound/soc/sof/intel/hda-dai.c
+++ b/sound/soc/sof/intel/hda-dai.c
@@ -617,12 +617,6 @@ static int hda_dai_suspend(struct hdac_bus *bus)
sdai = swidget->private;
ops = sdai->platform_private;
- ret = hda_link_dma_cleanup(hext_stream->link_substream,
- hext_stream,
- cpu_dai);
- if (ret < 0)
- return ret;
-
/* for consistency with TRIGGER_SUSPEND */
if (ops->post_trigger) {
ret = ops->post_trigger(sdev, cpu_dai,
@@ -631,6 +625,12 @@ static int hda_dai_suspend(struct hdac_bus *bus)
if (ret < 0)
return ret;
}
+
+ ret = hda_link_dma_cleanup(hext_stream->link_substream,
+ hext_stream,
+ cpu_dai);
+ if (ret < 0)
+ return ret;
}
}
diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
index 9fb8521b896b..f6e24edd7adb 100644
--- a/sound/soc/sof/intel/hda-pcm.c
+++ b/sound/soc/sof/intel/hda-pcm.c
@@ -258,6 +258,12 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
snd_pcm_hw_constraint_integer(substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
+ /* Limit the maximum number of periods to not exceed the BDL entries count */
+ if (runtime->hw.periods_max > HDA_DSP_MAX_BDL_ENTRIES)
+ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
+ runtime->hw.periods_min,
+ HDA_DSP_MAX_BDL_ENTRIES);
+
/* Only S16 and S32 supported by HDA hardware when used without DSP */
if (sdev->dspless_mode_selected)
snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT,
diff --git a/tools/arch/arm64/include/uapi/asm/unistd.h b/tools/arch/arm64/include/uapi/asm/unistd.h
index ce2ee8f1e361..9306726337fe 100644
--- a/tools/arch/arm64/include/uapi/asm/unistd.h
+++ b/tools/arch/arm64/include/uapi/asm/unistd.h
@@ -19,7 +19,6 @@
#define __ARCH_WANT_NEW_STAT
#define __ARCH_WANT_SET_GET_RLIMIT
#define __ARCH_WANT_TIME32_SYSCALLS
-#define __ARCH_WANT_SYS_CLONE3
#define __ARCH_WANT_MEMFD_SECRET
#include <asm-generic/unistd.h>
diff --git a/tools/arch/loongarch/include/uapi/asm/unistd.h b/tools/arch/loongarch/include/uapi/asm/unistd.h
index 0c743344e92d..8eeaac0087c3 100644
--- a/tools/arch/loongarch/include/uapi/asm/unistd.h
+++ b/tools/arch/loongarch/include/uapi/asm/unistd.h
@@ -4,6 +4,5 @@
*/
#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
#include <asm-generic/unistd.h>
diff --git a/tools/arch/x86/kcpuid/Makefile b/tools/arch/x86/kcpuid/Makefile
index 87b554fab14b..d0b4b0ed10ff 100644
--- a/tools/arch/x86/kcpuid/Makefile
+++ b/tools/arch/x86/kcpuid/Makefile
@@ -19,6 +19,6 @@ clean :
@rm -f kcpuid
install : kcpuid
- install -d $(DESTDIR)$(BINDIR)
+ install -d $(DESTDIR)$(BINDIR) $(DESTDIR)$(HWDATADIR)
install -m 755 -p kcpuid $(DESTDIR)$(BINDIR)/kcpuid
- install -m 444 -p cpuid.csv $(HWDATADIR)/cpuid.csv
+ install -m 444 -p cpuid.csv $(DESTDIR)$(HWDATADIR)/cpuid.csv
diff --git a/tools/gpio/gpio-sloppy-logic-analyzer.sh b/tools/gpio/gpio-sloppy-logic-analyzer.sh
new file mode 100755
index 000000000000..ed21a110df5e
--- /dev/null
+++ b/tools/gpio/gpio-sloppy-logic-analyzer.sh
@@ -0,0 +1,246 @@
+#!/bin/sh -eu
+# SPDX-License-Identifier: GPL-2.0
+#
+# Helper script for the Linux Kernel GPIO sloppy logic analyzer
+#
+# Copyright (C) Wolfram Sang <[email protected]>
+# Copyright (C) Renesas Electronics Corporation
+
+samplefreq=1000000
+numsamples=250000
+cpusetdefaultdir='/sys/fs/cgroup'
+cpusetprefix='cpuset.'
+debugdir='/sys/kernel/debug'
+ladirname='gpio-sloppy-logic-analyzer'
+outputdir="$PWD"
+neededcmds='taskset zip'
+max_chans=8
+duration=
+initcpu=
+listinstances=0
+lainstance=
+lasysfsdir=
+triggerdat=
+trigger_bindat=
+progname="${0##*/}"
+print_help()
+{
+ cat << EOF
+$progname - helper script for the Linux Kernel Sloppy GPIO Logic Analyzer
+Available options:
+ -c|--cpu <n>: which CPU to isolate for sampling. Only needed once. Default <1>.
+ Remember that a more powerful CPU gives you higher sampling speeds.
+ Also CPU0 is not recommended as it usually does extra bookkeeping.
+ -d|--duration-us <SI-n>: number of microseconds to sample. Overrides -n, no default value.
+ -h|--help: print this help
+ -i|--instance <str>: name of the logic analyzer in case you have multiple instances. Default
+ to first instance found
+ -k|--kernel-debug-dir <str>: path to the kernel debugfs mountpoint. Default: <$debugdir>
+ -l|--list-instances: list all available instances
+ -n|--num_samples <SI-n>: number of samples to acquire. Default <$numsamples>
+ -o|--output-dir <str>: directory to put the result files. Default: current dir
+ -s|--sample_freq <SI-n>: desired sampling frequency. Might be capped if too large.
+ Default: <1000000>
+ -t|--trigger <str>: pattern to use as trigger. <str> consists of two-char pairs. First
+ char is channel number starting at "1". Second char is trigger level:
+ "L" - low; "H" - high; "R" - rising; "F" - falling
+ These pairs can be combined with "+", so "1H+2F" triggers when probe 1
+ is high while probe 2 has a falling edge. You can have multiple triggers
+ combined with ",". So, "1H+2F,1H+2R" is like the example before but it
+ waits for a rising edge on probe 2 while probe 1 is still high after the
+ first trigger has been met.
+ Trigger data will only be used for the next capture and then be erased.
+
+<SI-n> is an integer value where SI units "T", "G", "M", "K" are recognized, e.g. '1M500K' is 1500000.
+
+Examples:
+Samples $numsamples values at 1MHz with an already prepared CPU or automatically prepares CPU1 if needed,
+use the first logic analyzer instance found:
+ '$progname'
+Samples 50us at 2MHz waiting for a falling edge on channel 2. CPU and instance as above:
+ '$progname -d 50 -s 2M -t "2F"'
+
+Note that the process exits after checking all parameters but a sub-process still works in
+the background. The result is only available once the sub-process finishes.
+
+Result is a .sr file to be consumed with PulseView from the free Sigrok project. It is
+a zip file which also contains the binary sample data which may be consumed by others.
+The filename is the logic analyzer instance name plus a since-epoch timestamp.
+EOF
+}
+
+fail()
+{
+ echo "$1"
+ exit 1
+}
+
+parse_si()
+{
+ conv_si="$(printf $1 | sed 's/[tT]+\?/*1000G+/g; s/[gG]+\?/*1000M+/g; s/[mM]+\?/*1000K+/g; s/[kK]+\?/*1000+/g; s/+$//')"
+ si_val="$((conv_si))"
+}
+set_newmask()
+{
+ for f in $(find "$1" -iname "$2"); do echo "$newmask" > "$f" 2>/dev/null || true; done
+}
+
+init_cpu()
+{
+ isol_cpu="$1"
+
+ [ -d "$lacpusetdir" ] || mkdir "$lacpusetdir"
+
+ cur_cpu=$(cat "${lacpusetfile}cpus")
+ [ "$cur_cpu" = "$isol_cpu" ] && return
+ [ -z "$cur_cpu" ] || fail "CPU$isol_cpu requested but CPU$cur_cpu already isolated"
+
+ echo "$isol_cpu" > "${lacpusetfile}cpus" || fail "Could not isolate CPU$isol_cpu. Does it exist?"
+ echo 1 > "${lacpusetfile}cpu_exclusive"
+ echo 0 > "${lacpusetfile}mems"
+
+ oldmask=$(cat /proc/irq/default_smp_affinity)
+ newmask=$(printf "%x" $((0x$oldmask & ~(1 << isol_cpu))))
+
+ set_newmask '/proc/irq' '*smp_affinity'
+ set_newmask '/sys/devices/virtual/workqueue/' 'cpumask'
+
+ # Move tasks away from isolated CPU
+ for p in $(ps -o pid | tail -n +2); do
+ mask=$(taskset -p "$p") || continue
+ # Ignore tasks with a custom mask, i.e. not equal $oldmask
+ [ "${mask##*: }" = "$oldmask" ] || continue
+ taskset -p "$newmask" "$p" || continue
+ done 2>/dev/null >/dev/null
+
+ # Big hammer! Working with 'rcu_momentary_dyntick_idle()' for a more fine-grained solution
+ # still printed warnings. Same for re-enabling the stall detector after sampling.
+ echo 1 > /sys/module/rcupdate/parameters/rcu_cpu_stall_suppress
+
+ cpufreqgov="/sys/devices/system/cpu/cpu$isol_cpu/cpufreq/scaling_governor"
+ [ -w "$cpufreqgov" ] && echo 'performance' > "$cpufreqgov" || true
+}
+
+parse_triggerdat()
+{
+ oldifs="$IFS"
+ IFS=','; for trig in $1; do
+ mask=0; val1=0; val2=0
+ IFS='+'; for elem in $trig; do
+ chan=${elem%[lhfrLHFR]}
+ mode=${elem#$chan}
+ # Check if we could parse something and the channel number fits
+ [ "$chan" != "$elem" ] && [ "$chan" -le $max_chans ] || fail "Trigger syntax error: $elem"
+ bit=$((1 << (chan - 1)))
+ mask=$((mask | bit))
+ case $mode in
+ [hH]) val1=$((val1 | bit)); val2=$((val2 | bit));;
+ [fF]) val1=$((val1 | bit));;
+ [rR]) val2=$((val2 | bit));;
+ esac
+ done
+ trigger_bindat="$trigger_bindat$(printf '\\%o\\%o' $mask $val1)"
+ [ $val1 -ne $val2 ] && trigger_bindat="$trigger_bindat$(printf '\\%o\\%o' $mask $val2)"
+ done
+ IFS="$oldifs"
+}
+
+do_capture()
+{
+ taskset "$1" echo 1 > "$lasysfsdir"/capture || fail "Capture error! Check kernel log"
+
+ srtmp=$(mktemp -d)
+ echo 1 > "$srtmp"/version
+ cp "$lasysfsdir"/sample_data "$srtmp"/logic-1-1
+ cat > "$srtmp"/metadata << EOF
+[global]
+sigrok version=0.2.0
+
+[device 1]
+capturefile=logic-1
+total probes=$(wc -l < "$lasysfsdir"/meta_data)
+samplerate=${samplefreq}Hz
+unitsize=1
+EOF
+ cat "$lasysfsdir"/meta_data >> "$srtmp"/metadata
+
+ zipname="$outputdir/${lasysfsdir##*/}-$(date +%s).sr"
+ zip -jq "$zipname" "$srtmp"/*
+ rm -rf "$srtmp"
+ delay_ack=$(cat "$lasysfsdir"/delay_ns_acquisition)
+ [ "$delay_ack" -eq 0 ] && delay_ack=1
+ echo "Logic analyzer done. Saved '$zipname'"
+ echo "Max sample frequency this time: $((1000000000 / delay_ack))Hz."
+}
+
+rep=$(getopt -a -l cpu:,duration-us:,help,instance:,list-instances,kernel-debug-dir:,num_samples:,output-dir:,sample_freq:,trigger: -o c:d:hi:k:ln:o:s:t: -- "$@") || exit 1
+eval set -- "$rep"
+while true; do
+ case "$1" in
+ -c|--cpu) initcpu="$2"; shift;;
+ -d|--duration-us) parse_si $2; duration=$si_val; shift;;
+ -h|--help) print_help; exit 0;;
+ -i|--instance) lainstance="$2"; shift;;
+ -k|--kernel-debug-dir) debugdir="$2"; shift;;
+ -l|--list-instances) listinstances=1;;
+ -n|--num_samples) parse_si $2; numsamples=$si_val; shift;;
+ -o|--output-dir) outputdir="$2"; shift;;
+ -s|--sample_freq) parse_si $2; samplefreq=$si_val; shift;;
+ -t|--trigger) triggerdat="$2"; shift;;
+ --) break;;
+ *) fail "error parsing command line: $*";;
+ esac
+ shift
+done
+
+for f in $neededcmds; do
+ command -v "$f" >/dev/null || fail "Command '$f' not found"
+done
+
+# print cpuset mountpoint if any, errorcode > 0 if noprefix option was found
+cpusetdir=$(awk '$3 == "cgroup" && $4 ~ /cpuset/ { print $2; exit (match($4, /noprefix/) > 0) }' /proc/self/mounts) || cpusetprefix=''
+if [ -z "$cpusetdir" ]; then
+ cpusetdir="$cpusetdefaultdir"
+ [ -d $cpusetdir ] || mkdir $cpusetdir
+ mount -t cgroup -o cpuset none $cpusetdir || fail "Couldn't mount cpusets. Not in kernel or already in use?"
+fi
+
+lacpusetdir="$cpusetdir/$ladirname"
+lacpusetfile="$lacpusetdir/$cpusetprefix"
+sysfsdir="$debugdir/$ladirname"
+
+[ "$samplefreq" -ne 0 ] || fail "Invalid sample frequency"
+
+[ -d "$sysfsdir" ] || fail "Could not find logic analyzer root dir '$sysfsdir'. Module loaded?"
+[ -x "$sysfsdir" ] || fail "Could not access logic analyzer root dir '$sysfsdir'. Need root?"
+
+[ $listinstances -gt 0 ] && find "$sysfsdir" -mindepth 1 -type d | sed 's|.*/||' && exit 0
+
+if [ -n "$lainstance" ]; then
+ lasysfsdir="$sysfsdir/$lainstance"
+else
+ lasysfsdir=$(find "$sysfsdir" -mindepth 1 -type d -print -quit)
+fi
+[ -d "$lasysfsdir" ] || fail "Logic analyzer directory '$lasysfsdir' not found!"
+[ -d "$outputdir" ] || fail "Output directory '$outputdir' not found!"
+
+[ -n "$initcpu" ] && init_cpu "$initcpu"
+[ -d "$lacpusetdir" ] || { echo "Auto-Isolating CPU1"; init_cpu 1; }
+
+ndelay=$((1000000000 / samplefreq))
+echo "$ndelay" > "$lasysfsdir"/delay_ns
+
+[ -n "$duration" ] && numsamples=$((samplefreq * duration / 1000000))
+echo $numsamples > "$lasysfsdir"/buf_size
+
+if [ -n "$triggerdat" ]; then
+ parse_triggerdat "$triggerdat"
+ printf "$trigger_bindat" > "$lasysfsdir"/trigger 2>/dev/null || fail "Trigger data '$triggerdat' rejected"
+fi
+
+workcpu=$(cat "${lacpusetfile}effective_cpus")
+[ -n "$workcpu" ] || fail "No isolated CPU found"
+cpumask=$(printf '%x' $((1 << workcpu)))
+instance=${lasysfsdir##*/}
+echo "Setting up '$instance': $numsamples samples at ${samplefreq}Hz with ${triggerdat:-no} trigger using CPU$workcpu"
+do_capture "$cpumask" &
diff --git a/tools/include/nolibc/stdint.h b/tools/include/nolibc/stdint.h
index 6665e272e213..cd79ddd6170e 100644
--- a/tools/include/nolibc/stdint.h
+++ b/tools/include/nolibc/stdint.h
@@ -96,6 +96,10 @@ typedef uint64_t uintmax_t;
#define UINT_FAST32_MAX SIZE_MAX
#define UINT_FAST64_MAX UINT64_MAX
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
#ifndef INT_MIN
#define INT_MIN (-__INT_MAX__ - 1)
#endif
@@ -110,4 +114,19 @@ typedef uint64_t uintmax_t;
#define LONG_MAX __LONG_MAX__
#endif
+#ifndef ULONG_MAX
+#define ULONG_MAX ((unsigned long)(__LONG_MAX__) * 2 + 1)
+#endif
+
+#ifndef LLONG_MIN
+#define LLONG_MIN (-__LONG_LONG_MAX__ - 1)
+#endif
+#ifndef LLONG_MAX
+#define LLONG_MAX __LONG_LONG_MAX__
+#endif
+
+#ifndef ULLONG_MAX
+#define ULLONG_MAX ((unsigned long long)(__LONG_LONG_MAX__) * 2 + 1)
+#endif
+
#endif /* _NOLIBC_STDINT_H */
diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
index 16cd4d807251..c968dbbc4ef8 100644
--- a/tools/include/nolibc/stdio.h
+++ b/tools/include/nolibc/stdio.h
@@ -376,6 +376,16 @@ int setvbuf(FILE *stream __attribute__((unused)),
return 0;
}
+static __attribute__((unused))
+const char *strerror(int errno)
+{
+ static char buf[18] = "errno=";
+
+ i64toa_r(errno, &buf[6]);
+
+ return buf;
+}
+
/* make sure to include all global symbols */
#include "nolibc.h"
diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h
index 5be9d3c7435a..75aa273c23a6 100644
--- a/tools/include/nolibc/stdlib.h
+++ b/tools/include/nolibc/stdlib.h
@@ -438,6 +438,115 @@ char *u64toa(uint64_t in)
return itoa_buffer;
}
+static __attribute__((unused))
+uintmax_t __strtox(const char *nptr, char **endptr, int base, intmax_t lower_limit, uintmax_t upper_limit)
+{
+ const char signed_ = lower_limit != 0;
+ unsigned char neg = 0, overflow = 0;
+ uintmax_t val = 0, limit, old_val;
+ char c;
+
+ if (base < 0 || base > 36) {
+ SET_ERRNO(EINVAL);
+ goto out;
+ }
+
+ while (isspace(*nptr))
+ nptr++;
+
+ if (*nptr == '+') {
+ nptr++;
+ } else if (*nptr == '-') {
+ neg = 1;
+ nptr++;
+ }
+
+ if (signed_ && neg)
+ limit = -(uintmax_t)lower_limit;
+ else
+ limit = upper_limit;
+
+ if ((base == 0 || base == 16) &&
+ (strncmp(nptr, "0x", 2) == 0 || strncmp(nptr, "0X", 2) == 0)) {
+ base = 16;
+ nptr += 2;
+ } else if (base == 0 && strncmp(nptr, "0", 1) == 0) {
+ base = 8;
+ nptr += 1;
+ } else if (base == 0) {
+ base = 10;
+ }
+
+ while (*nptr) {
+ c = *nptr;
+
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'z')
+ c = c - 'a' + 10;
+ else if (c >= 'A' && c <= 'Z')
+ c = c - 'A' + 10;
+ else
+ goto out;
+
+ if (c >= base)
+ goto out;
+
+ nptr++;
+ old_val = val;
+ val *= base;
+ val += c;
+
+ if (val > limit || val < old_val)
+ overflow = 1;
+ }
+
+out:
+ if (overflow) {
+ SET_ERRNO(ERANGE);
+ val = limit;
+ }
+ if (endptr)
+ *endptr = (char *)nptr;
+ return neg ? -val : val;
+}
+
+static __attribute__((unused))
+long strtol(const char *nptr, char **endptr, int base)
+{
+ return __strtox(nptr, endptr, base, LONG_MIN, LONG_MAX);
+}
+
+static __attribute__((unused))
+unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+ return __strtox(nptr, endptr, base, 0, ULONG_MAX);
+}
+
+static __attribute__((unused))
+long long strtoll(const char *nptr, char **endptr, int base)
+{
+ return __strtox(nptr, endptr, base, LLONG_MIN, LLONG_MAX);
+}
+
+static __attribute__((unused))
+unsigned long long strtoull(const char *nptr, char **endptr, int base)
+{
+ return __strtox(nptr, endptr, base, 0, ULLONG_MAX);
+}
+
+static __attribute__((unused))
+intmax_t strtoimax(const char *nptr, char **endptr, int base)
+{
+ return __strtox(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX);
+}
+
+static __attribute__((unused))
+uintmax_t strtoumax(const char *nptr, char **endptr, int base)
+{
+ return __strtox(nptr, endptr, base, 0, UINTMAX_MAX);
+}
+
/* make sure to include all global symbols */
#include "nolibc.h"
diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/asm-generic/unistd.h
index d983c48a3b6a..a00d53d02723 100644
--- a/tools/include/uapi/asm-generic/unistd.h
+++ b/tools/include/uapi/asm-generic/unistd.h
@@ -776,12 +776,8 @@ __SYSCALL(__NR_fsmount, sys_fsmount)
__SYSCALL(__NR_fspick, sys_fspick)
#define __NR_pidfd_open 434
__SYSCALL(__NR_pidfd_open, sys_pidfd_open)
-
-#ifdef __ARCH_WANT_SYS_CLONE3
#define __NR_clone3 435
__SYSCALL(__NR_clone3, sys_clone3)
-#endif
-
#define __NR_close_range 436
__SYSCALL(__NR_close_range, sys_close_range)
#define __NR_openat2 437
diff --git a/tools/memory-model/Documentation/README b/tools/memory-model/Documentation/README
index db90a26dbdf4..304162743a5b 100644
--- a/tools/memory-model/Documentation/README
+++ b/tools/memory-model/Documentation/README
@@ -47,6 +47,10 @@ DESCRIPTION OF FILES
README
This file.
+access-marking.txt
+ Guidelines for marking intentionally concurrent accesses to
+ shared memory.
+
cheatsheet.txt
Quick-reference guide to the Linux-kernel memory model.
diff --git a/tools/memory-model/Documentation/access-marking.txt b/tools/memory-model/Documentation/access-marking.txt
index 65778222183e..3fbe77fd564a 100644
--- a/tools/memory-model/Documentation/access-marking.txt
+++ b/tools/memory-model/Documentation/access-marking.txt
@@ -6,7 +6,8 @@ normal accesses to shared memory, that is "normal" as in accesses that do
not use read-modify-write atomic operations. It also describes how to
document these accesses, both with comments and with special assertions
processed by the Kernel Concurrency Sanitizer (KCSAN). This discussion
-builds on an earlier LWN article [1].
+builds on an earlier LWN article [1] and Linux Foundation mentorship
+session [2].
ACCESS-MARKING OPTIONS
@@ -24,6 +25,11 @@ The Linux kernel provides the following access-marking options:
4. WRITE_ONCE(), for example, "WRITE_ONCE(a, b);"
The various forms of atomic_set() also fit in here.
+5. __data_racy, for example "int __data_racy a;"
+
+6. KCSAN's negative-marking assertions, ASSERT_EXCLUSIVE_ACCESS()
+ and ASSERT_EXCLUSIVE_WRITER(), are described in the
+ "ACCESS-DOCUMENTATION OPTIONS" section below.
These may be used in combination, as shown in this admittedly improbable
example:
@@ -31,7 +37,7 @@ example:
WRITE_ONCE(a, b + data_race(c + d) + READ_ONCE(e));
Neither plain C-language accesses nor data_race() (#1 and #2 above) place
-any sort of constraint on the compiler's choice of optimizations [2].
+any sort of constraint on the compiler's choice of optimizations [3].
In contrast, READ_ONCE() and WRITE_ONCE() (#3 and #4 above) restrict the
compiler's use of code-motion and common-subexpression optimizations.
Therefore, if a given access is involved in an intentional data race,
@@ -205,6 +211,23 @@ because doing otherwise prevents KCSAN from detecting violations of your
code's synchronization rules.
+Use of __data_racy
+------------------
+
+Adding the __data_racy type qualifier to the declaration of a variable
+causes KCSAN to treat all accesses to that variable as if they were
+enclosed by data_race(). However, __data_racy does not affect the
+compiler, though one could imagine hardened kernel builds treating the
+__data_racy type qualifier as if it was the volatile keyword.
+
+Note well that __data_racy is subject to the same pointer-declaration
+rules as are other type qualifiers such as const and volatile.
+For example:
+
+ int __data_racy *p; // Pointer to data-racy data.
+ int *__data_racy p; // Data-racy pointer to non-data-racy data.
+
+
ACCESS-DOCUMENTATION OPTIONS
============================
@@ -342,7 +365,7 @@ as follows:
Because foo is read locklessly, all accesses are marked. The purpose
of the ASSERT_EXCLUSIVE_WRITER() is to allow KCSAN to check for a buggy
-concurrent lockless write.
+concurrent write, whether marked or not.
Lock-Protected Writes With Heuristic Lockless Reads
@@ -594,5 +617,8 @@ REFERENCES
[1] "Concurrency bugs should fear the big bad data-race detector (part 2)"
https://lwn.net/Articles/816854/
-[2] "Who's afraid of a big bad optimizing compiler?"
+[2] "The Kernel Concurrency Sanitizer"
+ https://www.linuxfoundation.org/webinars/the-kernel-concurrency-sanitizer
+
+[3] "Who's afraid of a big bad optimizing compiler?"
https://lwn.net/Articles/793253/
diff --git a/tools/memory-model/lock.cat b/tools/memory-model/lock.cat
index 53b5a492739d..03c12efed66a 100644
--- a/tools/memory-model/lock.cat
+++ b/tools/memory-model/lock.cat
@@ -54,6 +54,12 @@ flag ~empty LKR \ domain(lk-rmw) as unpaired-LKR
*)
empty ([LKW] ; po-loc ; [LKR]) \ (po-loc ; [UL] ; po-loc) as lock-nest
+(*
+ * In the same way, spin_is_locked() inside a critical section must always
+ * return True (no RU events can be in a critical section for the same lock).
+ *)
+empty ([LKW] ; po-loc ; [RU]) \ (po-loc ; [UL] ; po-loc) as nested-is-locked
+
(* The final value of a spinlock should not be tested *)
flag ~empty [FW] ; loc ; [ALL-LOCKS] as lock-final
@@ -79,42 +85,50 @@ empty ([UNMATCHED-LKW] ; loc ; [UNMATCHED-LKW]) \ id as unmatched-locks
(* rfi for LF events: link each LKW to the LF events in its critical section *)
let rfi-lf = ([LKW] ; po-loc ; [LF]) \ ([LKW] ; po-loc ; [UL] ; po-loc)
-(* rfe for LF events *)
+(* Utility macro to convert a single pair to a single-edge relation *)
+let pair-to-relation p = p ++ 0
+
+(*
+ * If a given LF event e is outside a critical section, it cannot read
+ * internally but it may read from an LKW event in another thread.
+ * Compute the relation containing these possible edges.
+ *)
+let possible-rfe-noncrit-lf e = (LKW * {e}) & loc & ext
+
+(* Compute set of sets of possible rfe edges for LF events *)
let all-possible-rfe-lf =
(*
- * Given an LF event r, compute the possible rfe edges for that event
- * (all those starting from LKW events in other threads),
- * and then convert that relation to a set of single-edge relations.
+ * Convert the possible-rfe-noncrit-lf relation for e
+ * to a set of single edges
*)
- let possible-rfe-lf r =
- let pair-to-relation p = p ++ 0
- in map pair-to-relation ((LKW * {r}) & loc & ext)
- (* Do this for each LF event r that isn't in rfi-lf *)
- in map possible-rfe-lf (LF \ range(rfi-lf))
+ let set-of-singleton-rfe-lf e =
+ map pair-to-relation (possible-rfe-noncrit-lf e)
+ (* Do this for each LF event e that isn't in rfi-lf *)
+ in map set-of-singleton-rfe-lf (LF \ range(rfi-lf))
(* Generate all rf relations for LF events *)
with rfe-lf from cross(all-possible-rfe-lf)
let rf-lf = rfe-lf | rfi-lf
(*
- * RU, i.e., spin_is_locked() returning False, is slightly different.
- * We rely on the memory model to rule out cases where spin_is_locked()
- * within one of the lock's critical sections returns False.
+ * A given RU event e may read internally from the last po-previous UL,
+ * or it may read from a UL event in another thread or the initial write.
+ * Compute the relation containing these possible edges.
*)
-
-(* rfi for RU events: an RU may read from the last po-previous UL *)
-let rfi-ru = ([UL] ; po-loc ; [RU]) \ ([UL] ; po-loc ; [LKW] ; po-loc)
-
-(* rfe for RU events: an RU may read from an external UL or the initial write *)
-let all-possible-rfe-ru =
- let possible-rfe-ru r =
- let pair-to-relation p = p ++ 0
- in map pair-to-relation (((UL | IW) * {r}) & loc & ext)
- in map possible-rfe-ru RU
+let possible-rf-ru e = (((UL * {e}) & po-loc) \
+ ([UL] ; po-loc ; [UL] ; po-loc)) |
+ (((UL | IW) * {e}) & loc & ext)
+
+(* Compute set of sets of possible rf edges for RU events *)
+let all-possible-rf-ru =
+ (* Convert the possible-rf-ru relation for e to a set of single edges *)
+ let set-of-singleton-rf-ru e =
+ map pair-to-relation (possible-rf-ru e)
+ (* Do this for each RU event e *)
+ in map set-of-singleton-rf-ru RU
(* Generate all rf relations for RU events *)
-with rfe-ru from cross(all-possible-rfe-ru)
-let rf-ru = rfe-ru | rfi-ru
+with rf-ru from cross(all-possible-rf-ru)
(* Final rf relation *)
let rf = rf | rf-lf | rf-ru
diff --git a/tools/objtool/Documentation/objtool.txt b/tools/objtool/Documentation/objtool.txt
index fe39c2a8ef0d..7c3ee959b63c 100644
--- a/tools/objtool/Documentation/objtool.txt
+++ b/tools/objtool/Documentation/objtool.txt
@@ -284,6 +284,25 @@ the objtool maintainers.
Otherwise the stack frame may not get created before the call.
+ objtool can help with pinpointing the exact function where it happens:
+
+ $ OBJTOOL_ARGS="--verbose" make arch/x86/kvm/
+
+ arch/x86/kvm/kvm.o: warning: objtool: .altinstr_replacement+0xc5: call without frame pointer save/setup
+ arch/x86/kvm/kvm.o: warning: objtool: em_loop.part.0+0x29: (alt)
+ arch/x86/kvm/kvm.o: warning: objtool: em_loop.part.0+0x0: <=== (sym)
+ LD [M] arch/x86/kvm/kvm-intel.o
+ 0000 0000000000028220 <em_loop.part.0>:
+ 0000 28220: 0f b6 47 61 movzbl 0x61(%rdi),%eax
+ 0004 28224: 3c e2 cmp $0xe2,%al
+ 0006 28226: 74 2c je 28254 <em_loop.part.0+0x34>
+ 0008 28228: 48 8b 57 10 mov 0x10(%rdi),%rdx
+ 000c 2822c: 83 f0 05 xor $0x5,%eax
+ 000f 2822f: 48 c1 e0 04 shl $0x4,%rax
+ 0013 28233: 25 f0 00 00 00 and $0xf0,%eax
+ 0018 28238: 81 e2 d5 08 00 00 and $0x8d5,%edx
+ 001e 2823e: 80 ce 02 or $0x2,%dh
+ ...
2. file.o: warning: objtool: .text+0x53: unreachable instruction
diff --git a/tools/objtool/arch/x86/special.c b/tools/objtool/arch/x86/special.c
index 4134d27c696b..4ea0f9815fda 100644
--- a/tools/objtool/arch/x86/special.c
+++ b/tools/objtool/arch/x86/special.c
@@ -9,6 +9,29 @@
void arch_handle_alternative(unsigned short feature, struct special_alt *alt)
{
+ static struct special_alt *group, *prev;
+
+ /*
+ * Recompute orig_len for nested ALTERNATIVE()s.
+ */
+ if (group && group->orig_sec == alt->orig_sec &&
+ group->orig_off == alt->orig_off) {
+
+ struct special_alt *iter = group;
+ for (;;) {
+ unsigned int len = max(iter->orig_len, alt->orig_len);
+ iter->orig_len = alt->orig_len = len;
+
+ if (iter == prev)
+ break;
+
+ iter = list_next_entry(iter, list);
+ }
+
+ } else group = alt;
+
+ prev = alt;
+
switch (feature) {
case X86_FEATURE_SMAP:
/*
diff --git a/tools/objtool/noreturns.h b/tools/objtool/noreturns.h
index 7ebf29c91184..1e8141ef1b15 100644
--- a/tools/objtool/noreturns.h
+++ b/tools/objtool/noreturns.h
@@ -7,12 +7,16 @@
* Yes, this is unfortunate. A better solution is in the works.
*/
NORETURN(__fortify_panic)
+NORETURN(__ia32_sys_exit)
+NORETURN(__ia32_sys_exit_group)
NORETURN(__kunit_abort)
NORETURN(__module_put_and_kthread_exit)
NORETURN(__reiserfs_panic)
NORETURN(__stack_chk_fail)
NORETURN(__tdx_hypercall_failed)
NORETURN(__ubsan_handle_builtin_unreachable)
+NORETURN(__x64_sys_exit)
+NORETURN(__x64_sys_exit_group)
NORETURN(arch_cpu_idle_dead)
NORETURN(bch2_trans_in_restart_error)
NORETURN(bch2_trans_restart_error)
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index 91b1950f5bd8..097a69db82a0 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -84,6 +84,14 @@ static int get_alt_entry(struct elf *elf, const struct special_entry *entry,
entry->new_len);
}
+ orig_reloc = find_reloc_by_dest(elf, sec, offset + entry->orig);
+ if (!orig_reloc) {
+ WARN_FUNC("can't find orig reloc", sec, offset + entry->orig);
+ return -1;
+ }
+
+ reloc_to_sec_off(orig_reloc, &alt->orig_sec, &alt->orig_off);
+
if (entry->feature) {
unsigned short feature;
@@ -94,14 +102,6 @@ static int get_alt_entry(struct elf *elf, const struct special_entry *entry,
arch_handle_alternative(feature, alt);
}
- orig_reloc = find_reloc_by_dest(elf, sec, offset + entry->orig);
- if (!orig_reloc) {
- WARN_FUNC("can't find orig reloc", sec, offset + entry->orig);
- return -1;
- }
-
- reloc_to_sec_off(orig_reloc, &alt->orig_sec, &alt->orig_off);
-
if (!entry->group || alt->new_len) {
new_reloc = find_reloc_by_dest(elf, sec, offset + entry->new);
if (!new_reloc) {
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index 233f2b6edf52..49b79cf0c5cc 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -86,14 +86,6 @@ static struct comm_str *comm_str__new(const char *str)
return result;
}
-static int comm_str__cmp(const void *_lhs, const void *_rhs)
-{
- const struct comm_str *lhs = *(const struct comm_str * const *)_lhs;
- const struct comm_str *rhs = *(const struct comm_str * const *)_rhs;
-
- return strcmp(comm_str__str(lhs), comm_str__str(rhs));
-}
-
static int comm_str__search(const void *_key, const void *_member)
{
const char *key = _key;
@@ -169,9 +161,24 @@ static struct comm_str *comm_strs__findnew(const char *str)
}
result = comm_str__new(str);
if (result) {
- comm_strs->strs[comm_strs->num_strs++] = result;
- qsort(comm_strs->strs, comm_strs->num_strs, sizeof(struct comm_str *),
- comm_str__cmp);
+ int low = 0, high = comm_strs->num_strs - 1;
+ int insert = comm_strs->num_strs; /* Default to inserting at the end. */
+
+ while (low <= high) {
+ int mid = low + (high - low) / 2;
+ int cmp = strcmp(comm_str__str(comm_strs->strs[mid]), str);
+
+ if (cmp < 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ insert = mid;
+ }
+ }
+ memmove(&comm_strs->strs[insert + 1], &comm_strs->strs[insert],
+ (comm_strs->num_strs - insert) * sizeof(struct comm_str *));
+ comm_strs->num_strs++;
+ comm_strs->strs[insert] = result;
}
}
up_write(&comm_strs->lock);
diff --git a/tools/perf/util/dsos.c b/tools/perf/util/dsos.c
index ab3d0c01dd63..a69a9c661200 100644
--- a/tools/perf/util/dsos.c
+++ b/tools/perf/util/dsos.c
@@ -203,11 +203,27 @@ int __dsos__add(struct dsos *dsos, struct dso *dso)
dsos->dsos = temp;
dsos->allocated = to_allocate;
}
- dsos->dsos[dsos->cnt++] = dso__get(dso);
- if (dsos->cnt >= 2 && dsos->sorted) {
- dsos->sorted = dsos__cmp_long_name_id_short_name(&dsos->dsos[dsos->cnt - 2],
- &dsos->dsos[dsos->cnt - 1])
- <= 0;
+ if (!dsos->sorted) {
+ dsos->dsos[dsos->cnt++] = dso__get(dso);
+ } else {
+ int low = 0, high = dsos->cnt - 1;
+ int insert = dsos->cnt; /* Default to inserting at the end. */
+
+ while (low <= high) {
+ int mid = low + (high - low) / 2;
+ int cmp = dsos__cmp_long_name_id_short_name(&dsos->dsos[mid], &dso);
+
+ if (cmp < 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ insert = mid;
+ }
+ }
+ memmove(&dsos->dsos[insert + 1], &dsos->dsos[insert],
+ (dsos->cnt - insert) * sizeof(struct dso *));
+ dsos->cnt++;
+ dsos->dsos[insert] = dso__get(dso);
}
dso__set_dsos(dso, dsos);
return 0;
diff --git a/tools/rcu/rcu-updaters.sh b/tools/rcu/rcu-updaters.sh
new file mode 100755
index 000000000000..4ef1397927bb
--- /dev/null
+++ b/tools/rcu/rcu-updaters.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Run bpftrace to obtain a histogram of the types of primitives used to
+# initiate RCU grace periods. The count associated with rcu_gp_init()
+# is the number of normal (non-expedited) grace periods.
+#
+# Usage: rcu-updaters.sh [ duration-in-seconds ]
+#
+# Note that not all kernel builds have all of these functions. In those
+# that do not, this script will issue a diagnostic for each that is not
+# found, but continue normally for the rest of the functions.
+
+duration=${1}
+if test -n "${duration}"
+then
+ exitclause='interval:s:'"${duration}"' { exit(); }'
+else
+ echo 'Hit control-C to end sample and print results.'
+fi
+bpftrace -e 'kprobe:kvfree_call_rcu,
+ kprobe:call_rcu,
+ kprobe:call_rcu_tasks,
+ kprobe:call_rcu_tasks_rude,
+ kprobe:call_rcu_tasks_trace,
+ kprobe:call_srcu,
+ kprobe:rcu_barrier,
+ kprobe:rcu_barrier_tasks,
+ kprobe:rcu_barrier_tasks_rude,
+ kprobe:rcu_barrier_tasks_trace,
+ kprobe:srcu_barrier,
+ kprobe:synchronize_rcu,
+ kprobe:synchronize_rcu_expedited,
+ kprobe:synchronize_rcu_tasks,
+ kprobe:synchronize_rcu_tasks_rude,
+ kprobe:synchronize_rcu_tasks_trace,
+ kprobe:synchronize_srcu,
+ kprobe:synchronize_srcu_expedited,
+ kprobe:get_state_synchronize_rcu,
+ kprobe:get_state_synchronize_rcu_full,
+ kprobe:start_poll_synchronize_rcu,
+ kprobe:start_poll_synchronize_rcu_expedited,
+ kprobe:start_poll_synchronize_rcu_full,
+ kprobe:start_poll_synchronize_rcu_expedited_full,
+ kprobe:poll_state_synchronize_rcu,
+ kprobe:poll_state_synchronize_rcu_full,
+ kprobe:cond_synchronize_rcu,
+ kprobe:cond_synchronize_rcu_full,
+ kprobe:start_poll_synchronize_srcu,
+ kprobe:poll_state_synchronize_srcu,
+ kprobe:rcu_gp_init
+ { @counts[func] = count(); } '"${exitclause}"
diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
index 3482248aa344..90d5afd52dd0 100644
--- a/tools/testing/cxl/test/cxl.c
+++ b/tools/testing/cxl/test/cxl.c
@@ -630,11 +630,15 @@ static struct cxl_hdm *mock_cxl_setup_hdm(struct cxl_port *port,
struct cxl_endpoint_dvsec_info *info)
{
struct cxl_hdm *cxlhdm = devm_kzalloc(&port->dev, sizeof(*cxlhdm), GFP_KERNEL);
+ struct device *dev = &port->dev;
if (!cxlhdm)
return ERR_PTR(-ENOMEM);
cxlhdm->port = port;
+ cxlhdm->interleave_mask = ~0U;
+ cxlhdm->iw_cap_mask = ~0UL;
+ dev_set_drvdata(dev, cxlhdm);
return cxlhdm;
}
diff --git a/tools/testing/selftests/arm64/abi/ptrace.c b/tools/testing/selftests/arm64/abi/ptrace.c
index abe4d58d731d..4c941270d8de 100644
--- a/tools/testing/selftests/arm64/abi/ptrace.c
+++ b/tools/testing/selftests/arm64/abi/ptrace.c
@@ -47,7 +47,7 @@ static void test_tpidr(pid_t child)
/* ...write a new value.. */
write_iov.iov_len = sizeof(uint64_t);
- write_val[0] = read_val[0]++;
+ write_val[0] = read_val[0] + 1;
ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_TLS, &write_iov);
ksft_test_result(ret == 0, "write_tpidr_one\n");
diff --git a/tools/testing/selftests/arm64/fp/.gitignore b/tools/testing/selftests/arm64/fp/.gitignore
index 00e52c966281..8362e7ec35ad 100644
--- a/tools/testing/selftests/arm64/fp/.gitignore
+++ b/tools/testing/selftests/arm64/fp/.gitignore
@@ -2,6 +2,7 @@ fp-pidbench
fp-ptrace
fp-stress
fpsimd-test
+kernel-test
rdvl-sme
rdvl-sve
sve-probe-vls
diff --git a/tools/testing/selftests/arm64/fp/Makefile b/tools/testing/selftests/arm64/fp/Makefile
index 55d4f00d9e8e..d171021e4cdd 100644
--- a/tools/testing/selftests/arm64/fp/Makefile
+++ b/tools/testing/selftests/arm64/fp/Makefile
@@ -12,6 +12,7 @@ TEST_GEN_PROGS := \
vec-syscfg \
za-fork za-ptrace
TEST_GEN_PROGS_EXTENDED := fp-pidbench fpsimd-test \
+ kernel-test \
rdvl-sme rdvl-sve \
sve-test \
ssve-test \
diff --git a/tools/testing/selftests/arm64/fp/fp-stress.c b/tools/testing/selftests/arm64/fp/fp-stress.c
index dd31647b00a2..faac24bdefeb 100644
--- a/tools/testing/selftests/arm64/fp/fp-stress.c
+++ b/tools/testing/selftests/arm64/fp/fp-stress.c
@@ -319,6 +319,19 @@ static void start_fpsimd(struct child_data *child, int cpu, int copy)
ksft_print_msg("Started %s\n", child->name);
}
+static void start_kernel(struct child_data *child, int cpu, int copy)
+{
+ int ret;
+
+ ret = asprintf(&child->name, "KERNEL-%d-%d", cpu, copy);
+ if (ret == -1)
+ ksft_exit_fail_msg("asprintf() failed\n");
+
+ child_start(child, "./kernel-test");
+
+ ksft_print_msg("Started %s\n", child->name);
+}
+
static void start_sve(struct child_data *child, int vl, int cpu)
{
int ret;
@@ -438,7 +451,7 @@ int main(int argc, char **argv)
int ret;
int timeout = 10;
int cpus, i, j, c;
- int sve_vl_count, sme_vl_count, fpsimd_per_cpu;
+ int sve_vl_count, sme_vl_count;
bool all_children_started = false;
int seen_children;
int sve_vls[MAX_VLS], sme_vls[MAX_VLS];
@@ -482,12 +495,7 @@ int main(int argc, char **argv)
have_sme2 = false;
}
- /* Force context switching if we only have FPSIMD */
- if (!sve_vl_count && !sme_vl_count)
- fpsimd_per_cpu = 2;
- else
- fpsimd_per_cpu = 1;
- tests += cpus * fpsimd_per_cpu;
+ tests += cpus * 2;
ksft_print_header();
ksft_set_plan(tests);
@@ -542,8 +550,8 @@ int main(int argc, char **argv)
tests);
for (i = 0; i < cpus; i++) {
- for (j = 0; j < fpsimd_per_cpu; j++)
- start_fpsimd(&children[num_children++], i, j);
+ start_fpsimd(&children[num_children++], i, 0);
+ start_kernel(&children[num_children++], i, 0);
for (j = 0; j < sve_vl_count; j++)
start_sve(&children[num_children++], sve_vls[j], i);
diff --git a/tools/testing/selftests/arm64/fp/kernel-test.c b/tools/testing/selftests/arm64/fp/kernel-test.c
new file mode 100644
index 000000000000..e8da3b4cbd23
--- /dev/null
+++ b/tools/testing/selftests/arm64/fp/kernel-test.c
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 ARM Limited.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+
+#include <linux/kernel.h>
+#include <linux/if_alg.h>
+
+#define DATA_SIZE (16 * 4096)
+
+static int base, sock;
+
+static int digest_len;
+static char *ref;
+static char *digest;
+static char *alg_name;
+
+static struct iovec data_iov;
+static int zerocopy[2];
+static int sigs;
+static int iter;
+
+static void handle_exit_signal(int sig, siginfo_t *info, void *context)
+{
+ printf("Terminated by signal %d, iterations=%d, signals=%d\n",
+ sig, iter, sigs);
+ exit(0);
+}
+
+static void handle_kick_signal(int sig, siginfo_t *info, void *context)
+{
+ sigs++;
+}
+
+static char *drivers[] = {
+ "crct10dif-arm64-ce",
+ /* "crct10dif-arm64-neon", - Same priority as generic */
+ "sha1-ce",
+ "sha224-arm64",
+ "sha224-arm64-neon",
+ "sha224-ce",
+ "sha256-arm64",
+ "sha256-arm64-neon",
+ "sha256-ce",
+ "sha384-ce",
+ "sha512-ce",
+ "sha3-224-ce",
+ "sha3-256-ce",
+ "sha3-384-ce",
+ "sha3-512-ce",
+ "sm3-ce",
+ "sm3-neon",
+};
+
+static bool create_socket(void)
+{
+ FILE *proc;
+ struct sockaddr_alg addr;
+ char buf[1024];
+ char *c, *driver_name;
+ bool is_shash, match;
+ int ret, i;
+
+ ret = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ if (ret < 0) {
+ if (errno == EAFNOSUPPORT) {
+ printf("AF_ALG not supported\n");
+ return false;
+ }
+
+ printf("Failed to create AF_ALG socket: %s (%d)\n",
+ strerror(errno), errno);
+ return false;
+ }
+ base = ret;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.salg_family = AF_ALG;
+ strncpy((char *)addr.salg_type, "hash", sizeof(addr.salg_type));
+
+ proc = fopen("/proc/crypto", "r");
+ if (!proc) {
+ printf("Unable to open /proc/crypto\n");
+ return false;
+ }
+
+ driver_name = NULL;
+ is_shash = false;
+ match = false;
+
+ /* Look through /proc/crypto for a driver with kernel mode FP usage */
+ while (!match) {
+ c = fgets(buf, sizeof(buf), proc);
+ if (!c) {
+ if (feof(proc)) {
+ printf("Nothing found in /proc/crypto\n");
+ return false;
+ }
+ continue;
+ }
+
+ /* Algorithm descriptions are separated by a blank line */
+ if (*c == '\n') {
+ if (is_shash && driver_name) {
+ for (i = 0; i < ARRAY_SIZE(drivers); i++) {
+ if (strcmp(drivers[i],
+ driver_name) == 0) {
+ match = true;
+ }
+ }
+ }
+
+ if (!match) {
+ digest_len = 0;
+
+ free(driver_name);
+ driver_name = NULL;
+
+ free(alg_name);
+ alg_name = NULL;
+
+ is_shash = false;
+ }
+ continue;
+ }
+
+ /* Remove trailing newline */
+ c = strchr(buf, '\n');
+ if (c)
+ *c = '\0';
+
+ /* Find the field/value separator and start of the value */
+ c = strchr(buf, ':');
+ if (!c)
+ continue;
+ c += 2;
+
+ if (strncmp(buf, "digestsize", strlen("digestsize")) == 0)
+ sscanf(c, "%d", &digest_len);
+
+ if (strncmp(buf, "name", strlen("name")) == 0)
+ alg_name = strdup(c);
+
+ if (strncmp(buf, "driver", strlen("driver")) == 0)
+ driver_name = strdup(c);
+
+ if (strncmp(buf, "type", strlen("type")) == 0)
+ if (strncmp(c, "shash", strlen("shash")) == 0)
+ is_shash = true;
+ }
+
+ strncpy((char *)addr.salg_name, alg_name,
+ sizeof(addr.salg_name) - 1);
+
+ ret = bind(base, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret < 0) {
+ printf("Failed to bind %s: %s (%d)\n",
+ addr.salg_name, strerror(errno), errno);
+ return false;
+ }
+
+ ret = accept(base, NULL, 0);
+ if (ret < 0) {
+ printf("Failed to accept %s: %s (%d)\n",
+ addr.salg_name, strerror(errno), errno);
+ return false;
+ }
+
+ sock = ret;
+
+ ret = pipe(zerocopy);
+ if (ret != 0) {
+ printf("Failed to create zerocopy pipe: %s (%d)\n",
+ strerror(errno), errno);
+ return false;
+ }
+
+ ref = malloc(digest_len);
+ if (!ref) {
+ printf("Failed to allocated %d byte reference\n", digest_len);
+ return false;
+ }
+
+ digest = malloc(digest_len);
+ if (!digest) {
+ printf("Failed to allocated %d byte digest\n", digest_len);
+ return false;
+ }
+
+ return true;
+}
+
+static bool compute_digest(void *buf)
+{
+ struct iovec iov;
+ int ret, wrote;
+
+ iov = data_iov;
+ while (iov.iov_len) {
+ ret = vmsplice(zerocopy[1], &iov, 1, SPLICE_F_GIFT);
+ if (ret < 0) {
+ printf("Failed to send buffer: %s (%d)\n",
+ strerror(errno), errno);
+ return false;
+ }
+
+ wrote = ret;
+ ret = splice(zerocopy[0], NULL, sock, NULL, wrote, 0);
+ if (ret < 0) {
+ printf("Failed to splice buffer: %s (%d)\n",
+ strerror(errno), errno);
+ } else if (ret != wrote) {
+ printf("Short splice: %d < %d\n", ret, wrote);
+ }
+
+ iov.iov_len -= wrote;
+ iov.iov_base += wrote;
+ }
+
+reread:
+ ret = recv(sock, buf, digest_len, 0);
+ if (ret == 0) {
+ printf("No digest returned\n");
+ return false;
+ }
+ if (ret != digest_len) {
+ if (errno == -EAGAIN)
+ goto reread;
+ printf("Failed to get digest: %s (%d)\n",
+ strerror(errno), errno);
+ return false;
+ }
+
+ return true;
+}
+
+int main(void)
+{
+ char *data;
+ struct sigaction sa;
+ int ret;
+
+ /* Ensure we have unbuffered output */
+ setvbuf(stdout, NULL, _IOLBF, 0);
+
+ /* The parent will communicate with us via signals */
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = handle_exit_signal;
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ ret = sigaction(SIGTERM, &sa, NULL);
+ if (ret < 0)
+ printf("Failed to install SIGTERM handler: %s (%d)\n",
+ strerror(errno), errno);
+
+ sa.sa_sigaction = handle_kick_signal;
+ ret = sigaction(SIGUSR2, &sa, NULL);
+ if (ret < 0)
+ printf("Failed to install SIGUSR2 handler: %s (%d)\n",
+ strerror(errno), errno);
+
+ data = malloc(DATA_SIZE);
+ if (!data) {
+ printf("Failed to allocate data buffer\n");
+ return EXIT_FAILURE;
+ }
+ memset(data, 0, DATA_SIZE);
+
+ data_iov.iov_base = data;
+ data_iov.iov_len = DATA_SIZE;
+
+ /*
+ * If we can't create a socket assume it's a lack of system
+ * support and fall back to a basic FPSIMD test for the
+ * benefit of fp-stress.
+ */
+ if (!create_socket()) {
+ execl("./fpsimd-test", "./fpsimd-test", NULL);
+ printf("Failed to fall back to fspimd-test: %d (%s)\n",
+ errno, strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ /*
+ * Compute a reference digest we hope is repeatable, we do
+ * this at runtime partly to make it easier to play with
+ * parameters.
+ */
+ if (!compute_digest(ref)) {
+ printf("Failed to compute reference digest\n");
+ return EXIT_FAILURE;
+ }
+
+ printf("AF_ALG using %s\n", alg_name);
+
+ while (true) {
+ if (!compute_digest(digest)) {
+ printf("Failed to compute digest, iter=%d\n", iter);
+ return EXIT_FAILURE;
+ }
+
+ if (memcmp(ref, digest, digest_len) != 0) {
+ printf("Digest mismatch, iter=%d\n", iter);
+ return EXIT_FAILURE;
+ }
+
+ iter++;
+ }
+
+ return EXIT_FAILURE;
+}
diff --git a/tools/testing/selftests/arm64/tags/Makefile b/tools/testing/selftests/arm64/tags/Makefile
index 6d29cfde43a2..0a77f35295fb 100644
--- a/tools/testing/selftests/arm64/tags/Makefile
+++ b/tools/testing/selftests/arm64/tags/Makefile
@@ -2,6 +2,5 @@
CFLAGS += $(KHDR_INCLUDES)
TEST_GEN_PROGS := tags_test
-TEST_PROGS := run_tags_test.sh
include ../../lib.mk
diff --git a/tools/testing/selftests/arm64/tags/run_tags_test.sh b/tools/testing/selftests/arm64/tags/run_tags_test.sh
deleted file mode 100755
index 745f11379930..000000000000
--- a/tools/testing/selftests/arm64/tags/run_tags_test.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-
-echo "--------------------"
-echo "running tags test"
-echo "--------------------"
-./tags_test
-if [ $? -ne 0 ]; then
- echo "[FAIL]"
-else
- echo "[PASS]"
-fi
diff --git a/tools/testing/selftests/arm64/tags/tags_test.c b/tools/testing/selftests/arm64/tags/tags_test.c
index 955f87c1170d..8ae26e496c89 100644
--- a/tools/testing/selftests/arm64/tags/tags_test.c
+++ b/tools/testing/selftests/arm64/tags/tags_test.c
@@ -17,19 +17,21 @@ int main(void)
static int tbi_enabled = 0;
unsigned long tag = 0;
struct utsname *ptr;
- int err;
+
+ ksft_print_header();
+ ksft_set_plan(1);
if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0)
tbi_enabled = 1;
ptr = (struct utsname *)malloc(sizeof(*ptr));
if (!ptr)
- ksft_exit_fail_msg("Failed to allocate utsname buffer\n");
+ ksft_exit_fail_perror("Failed to allocate utsname buffer");
if (tbi_enabled)
tag = 0x42;
ptr = (struct utsname *)SET_TAG(ptr, tag);
- err = uname(ptr);
+ ksft_test_result(!uname(ptr), "Syscall successful with tagged address\n");
free(ptr);
- return err;
+ ksft_finished();
}
diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
index eeabd798bc3a..98b6b6a886ce 100644
--- a/tools/testing/selftests/bpf/config
+++ b/tools/testing/selftests/bpf/config
@@ -58,9 +58,12 @@ CONFIG_MPLS=y
CONFIG_MPLS_IPTUNNEL=y
CONFIG_MPLS_ROUTING=y
CONFIG_MPTCP=y
+CONFIG_NET_ACT_SKBMOD=y
+CONFIG_NET_CLS=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_CLS_BPF=y
CONFIG_NET_CLS_FLOWER=y
+CONFIG_NET_CLS_MATCHALL=y
CONFIG_NET_FOU=y
CONFIG_NET_FOU_IP_TUNNELS=y
CONFIG_NET_IPGRE=y
diff --git a/tools/testing/selftests/bpf/prog_tests/tc_links.c b/tools/testing/selftests/bpf/prog_tests/tc_links.c
index bc9841144685..1af9ec1149aa 100644
--- a/tools/testing/selftests/bpf/prog_tests/tc_links.c
+++ b/tools/testing/selftests/bpf/prog_tests/tc_links.c
@@ -9,6 +9,8 @@
#define ping_cmd "ping -q -c1 -w1 127.0.0.1 > /dev/null"
#include "test_tc_link.skel.h"
+
+#include "netlink_helpers.h"
#include "tc_helpers.h"
void serial_test_tc_links_basic(void)
@@ -1787,6 +1789,65 @@ void serial_test_tc_links_ingress(void)
test_tc_links_ingress(BPF_TCX_INGRESS, false, false);
}
+struct qdisc_req {
+ struct nlmsghdr n;
+ struct tcmsg t;
+ char buf[1024];
+};
+
+static int qdisc_replace(int ifindex, const char *kind, bool block)
+{
+ struct rtnl_handle rth = { .fd = -1 };
+ struct qdisc_req req;
+ int err;
+
+ err = rtnl_open(&rth, 0);
+ if (!ASSERT_OK(err, "open_rtnetlink"))
+ return err;
+
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
+ req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE | NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_NEWQDISC;
+ req.t.tcm_family = AF_UNSPEC;
+ req.t.tcm_ifindex = ifindex;
+ req.t.tcm_parent = 0xfffffff1;
+
+ addattr_l(&req.n, sizeof(req), TCA_KIND, kind, strlen(kind) + 1);
+ if (block)
+ addattr32(&req.n, sizeof(req), TCA_INGRESS_BLOCK, 1);
+
+ err = rtnl_talk(&rth, &req.n, NULL);
+ ASSERT_OK(err, "talk_rtnetlink");
+ rtnl_close(&rth);
+ return err;
+}
+
+void serial_test_tc_links_dev_chain0(void)
+{
+ int err, ifindex;
+
+ ASSERT_OK(system("ip link add dev foo type veth peer name bar"), "add veth");
+ ifindex = if_nametoindex("foo");
+ ASSERT_NEQ(ifindex, 0, "non_zero_ifindex");
+ err = qdisc_replace(ifindex, "ingress", true);
+ if (!ASSERT_OK(err, "attaching ingress"))
+ goto cleanup;
+ ASSERT_OK(system("tc filter add block 1 matchall action skbmod swap mac"), "add block");
+ err = qdisc_replace(ifindex, "clsact", false);
+ if (!ASSERT_OK(err, "attaching clsact"))
+ goto cleanup;
+ /* Heuristic: kern_sync_rcu() alone does not work; a wait-time of ~5s
+ * triggered the issue without the fix reliably 100% of the time.
+ */
+ sleep(5);
+ ASSERT_OK(system("tc filter add dev foo ingress matchall action skbmod swap mac"), "add filter");
+cleanup:
+ ASSERT_OK(system("ip link del dev foo"), "del veth");
+ ASSERT_EQ(if_nametoindex("foo"), 0, "foo removed");
+ ASSERT_EQ(if_nametoindex("bar"), 0, "bar removed");
+}
+
static void test_tc_links_dev_mixed(int target)
{
LIBBPF_OPTS(bpf_tc_opts, tc_opts, .handle = 1, .priority = 1);
diff --git a/tools/testing/selftests/bpf/prog_tests/timer_lockup.c b/tools/testing/selftests/bpf/prog_tests/timer_lockup.c
new file mode 100644
index 000000000000..871d16cb95cf
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/timer_lockup.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+#include <sched.h>
+#include <test_progs.h>
+#include <pthread.h>
+#include <network_helpers.h>
+
+#include "timer_lockup.skel.h"
+
+static long cpu;
+static int *timer1_err;
+static int *timer2_err;
+static bool skip;
+
+volatile int k = 0;
+
+static void *timer_lockup_thread(void *arg)
+{
+ LIBBPF_OPTS(bpf_test_run_opts, opts,
+ .data_in = &pkt_v4,
+ .data_size_in = sizeof(pkt_v4),
+ .repeat = 1000,
+ );
+ int i, prog_fd = *(int *)arg;
+ cpu_set_t cpuset;
+
+ CPU_ZERO(&cpuset);
+ CPU_SET(__sync_fetch_and_add(&cpu, 1), &cpuset);
+ ASSERT_OK(pthread_setaffinity_np(pthread_self(), sizeof(cpuset),
+ &cpuset),
+ "cpu affinity");
+
+ for (i = 0; !READ_ONCE(*timer1_err) && !READ_ONCE(*timer2_err); i++) {
+ bpf_prog_test_run_opts(prog_fd, &opts);
+ /* Skip the test if we can't reproduce the race in a reasonable
+ * amount of time.
+ */
+ if (i > 50) {
+ WRITE_ONCE(skip, true);
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+void test_timer_lockup(void)
+{
+ int timer1_prog, timer2_prog;
+ struct timer_lockup *skel;
+ pthread_t thrds[2];
+ void *ret;
+
+ skel = timer_lockup__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "timer_lockup__open_and_load"))
+ return;
+
+ timer1_prog = bpf_program__fd(skel->progs.timer1_prog);
+ timer2_prog = bpf_program__fd(skel->progs.timer2_prog);
+
+ timer1_err = &skel->bss->timer1_err;
+ timer2_err = &skel->bss->timer2_err;
+
+ if (!ASSERT_OK(pthread_create(&thrds[0], NULL, timer_lockup_thread,
+ &timer1_prog),
+ "pthread_create thread1"))
+ goto out;
+ if (!ASSERT_OK(pthread_create(&thrds[1], NULL, timer_lockup_thread,
+ &timer2_prog),
+ "pthread_create thread2")) {
+ pthread_exit(&thrds[0]);
+ goto out;
+ }
+
+ pthread_join(thrds[1], &ret);
+ pthread_join(thrds[0], &ret);
+
+ if (skip) {
+ test__skip();
+ goto out;
+ }
+
+ if (*timer1_err != -EDEADLK && *timer1_err != 0)
+ ASSERT_FAIL("timer1_err bad value");
+ if (*timer2_err != -EDEADLK && *timer2_err != 0)
+ ASSERT_FAIL("timer2_err bad value");
+out:
+ timer_lockup__destroy(skel);
+ return;
+}
diff --git a/tools/testing/selftests/bpf/progs/timer_lockup.c b/tools/testing/selftests/bpf/progs/timer_lockup.c
new file mode 100644
index 000000000000..3e520133281e
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/timer_lockup.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <time.h>
+#include <errno.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include "bpf_misc.h"
+
+char _license[] SEC("license") = "GPL";
+
+struct elem {
+ struct bpf_timer t;
+};
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, 1);
+ __type(key, int);
+ __type(value, struct elem);
+} timer1_map SEC(".maps");
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, 1);
+ __type(key, int);
+ __type(value, struct elem);
+} timer2_map SEC(".maps");
+
+int timer1_err;
+int timer2_err;
+
+static int timer_cb1(void *map, int *k, struct elem *v)
+{
+ struct bpf_timer *timer;
+ int key = 0;
+
+ timer = bpf_map_lookup_elem(&timer2_map, &key);
+ if (timer)
+ timer2_err = bpf_timer_cancel(timer);
+
+ return 0;
+}
+
+static int timer_cb2(void *map, int *k, struct elem *v)
+{
+ struct bpf_timer *timer;
+ int key = 0;
+
+ timer = bpf_map_lookup_elem(&timer1_map, &key);
+ if (timer)
+ timer1_err = bpf_timer_cancel(timer);
+
+ return 0;
+}
+
+SEC("tc")
+int timer1_prog(void *ctx)
+{
+ struct bpf_timer *timer;
+ int key = 0;
+
+ timer = bpf_map_lookup_elem(&timer1_map, &key);
+ if (timer) {
+ bpf_timer_init(timer, &timer1_map, CLOCK_BOOTTIME);
+ bpf_timer_set_callback(timer, timer_cb1);
+ bpf_timer_start(timer, 1, BPF_F_TIMER_CPU_PIN);
+ }
+
+ return 0;
+}
+
+SEC("tc")
+int timer2_prog(void *ctx)
+{
+ struct bpf_timer *timer;
+ int key = 0;
+
+ timer = bpf_map_lookup_elem(&timer2_map, &key);
+ if (timer) {
+ bpf_timer_init(timer, &timer2_map, CLOCK_BOOTTIME);
+ bpf_timer_set_callback(timer, timer_cb2);
+ bpf_timer_start(timer, 1, BPF_F_TIMER_CPU_PIN);
+ }
+
+ return 0;
+}
diff --git a/tools/testing/selftests/cgroup/.gitignore b/tools/testing/selftests/cgroup/.gitignore
index 2732e0b29271..952e4448bf07 100644
--- a/tools/testing/selftests/cgroup/.gitignore
+++ b/tools/testing/selftests/cgroup/.gitignore
@@ -1,11 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-only
-test_memcontrol
test_core
-test_freezer
-test_kmem
-test_kill
test_cpu
test_cpuset
-test_zswap
+test_freezer
test_hugetlb_memcg
+test_kill
+test_kmem
+test_memcontrol
+test_pids
+test_zswap
wait_inotify
diff --git a/tools/testing/selftests/cgroup/Makefile b/tools/testing/selftests/cgroup/Makefile
index 16461dc0ffdf..1b897152bab6 100644
--- a/tools/testing/selftests/cgroup/Makefile
+++ b/tools/testing/selftests/cgroup/Makefile
@@ -6,26 +6,29 @@ all: ${HELPER_PROGS}
TEST_FILES := with_stress.sh
TEST_PROGS := test_stress.sh test_cpuset_prs.sh test_cpuset_v1_hp.sh
TEST_GEN_FILES := wait_inotify
-TEST_GEN_PROGS = test_memcontrol
-TEST_GEN_PROGS += test_kmem
-TEST_GEN_PROGS += test_core
-TEST_GEN_PROGS += test_freezer
-TEST_GEN_PROGS += test_kill
+# Keep the lists lexicographically sorted
+TEST_GEN_PROGS = test_core
TEST_GEN_PROGS += test_cpu
TEST_GEN_PROGS += test_cpuset
-TEST_GEN_PROGS += test_zswap
+TEST_GEN_PROGS += test_freezer
TEST_GEN_PROGS += test_hugetlb_memcg
+TEST_GEN_PROGS += test_kill
+TEST_GEN_PROGS += test_kmem
+TEST_GEN_PROGS += test_memcontrol
+TEST_GEN_PROGS += test_pids
+TEST_GEN_PROGS += test_zswap
LOCAL_HDRS += $(selfdir)/clone3/clone3_selftests.h $(selfdir)/pidfd/pidfd.h
include ../lib.mk
-$(OUTPUT)/test_memcontrol: cgroup_util.c
-$(OUTPUT)/test_kmem: cgroup_util.c
$(OUTPUT)/test_core: cgroup_util.c
-$(OUTPUT)/test_freezer: cgroup_util.c
-$(OUTPUT)/test_kill: cgroup_util.c
$(OUTPUT)/test_cpu: cgroup_util.c
$(OUTPUT)/test_cpuset: cgroup_util.c
-$(OUTPUT)/test_zswap: cgroup_util.c
+$(OUTPUT)/test_freezer: cgroup_util.c
$(OUTPUT)/test_hugetlb_memcg: cgroup_util.c
+$(OUTPUT)/test_kill: cgroup_util.c
+$(OUTPUT)/test_kmem: cgroup_util.c
+$(OUTPUT)/test_memcontrol: cgroup_util.c
+$(OUTPUT)/test_pids: cgroup_util.c
+$(OUTPUT)/test_zswap: cgroup_util.c
diff --git a/tools/testing/selftests/cgroup/test_cpuset_prs.sh b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
index b5eb1be2248c..7c08cc153367 100755
--- a/tools/testing/selftests/cgroup/test_cpuset_prs.sh
+++ b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
@@ -28,6 +28,14 @@ CPULIST=$(cat $CGROUP2/cpuset.cpus.effective)
NR_CPUS=$(lscpu | grep "^CPU(s):" | sed -e "s/.*:[[:space:]]*//")
[[ $NR_CPUS -lt 8 ]] && skip_test "Test needs at least 8 cpus available!"
+# Check to see if /dev/console exists and is writable
+if [[ -c /dev/console && -w /dev/console ]]
+then
+ CONSOLE=/dev/console
+else
+ CONSOLE=/dev/null
+fi
+
# Set verbose flag and delay factor
PROG=$1
VERBOSE=0
@@ -103,8 +111,8 @@ console_msg()
{
MSG=$1
echo "$MSG"
- echo "" > /dev/console
- echo "$MSG" > /dev/console
+ echo "" > $CONSOLE
+ echo "$MSG" > $CONSOLE
pause 0.01
}
@@ -161,6 +169,14 @@ test_add_proc()
# T = put a task into cgroup
# O<c>=<v> = Write <v> to CPU online file of <c>
#
+# ECPUs - effective CPUs of cpusets
+# Pstate - partition root state
+# ISOLCPUS - isolated CPUs (<icpus>[,<icpus2>])
+#
+# Note that if there are 2 fields in ISOLCPUS, the first one is for
+# sched-debug matching which includes offline CPUs and single-CPU partitions
+# while the second one is for matching cpuset.cpus.isolated.
+#
SETUP_A123_PARTITIONS="C1-3:P1:S+ C2-3:P1:S+ C3:P1"
TEST_MATRIX=(
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
@@ -220,23 +236,29 @@ TEST_MATRIX=(
" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3:P2 . . 0 A1:0-1,A2:2-3,A3:2-3 A1:P0,A2:P2 2-3"
" C0-3:S+ C1-3:S+ C2-3 . X2-3 X3:P2 . . 0 A1:0-2,A2:3,A3:3 A1:P0,A2:P2 3"
" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2 . 0 A1:0-1,A2:1,A3:2-3 A1:P0,A3:P2 2-3"
- " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:C3 . 0 A1:0-2,A2:1-2,A3:3 A1:P0,A3:P2 3"
+ " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:C3 . 0 A1:0-1,A2:1,A3:2-3 A1:P0,A3:P2 2-3"
" C0-3:S+ C1-3:S+ C2-3 C2-3 . . . P2 0 A1:0-3,A2:1-3,A3:2-3,B1:2-3 A1:P0,A3:P0,B1:P-2"
" C0-3:S+ C1-3:S+ C2-3 C4-5 . . . P2 0 B1:4-5 B1:P2 4-5"
" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2 0 A3:2-3,B1:4 A3:P2,B1:P2 2-4"
" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2:C1-3 P2 0 A3:2-3,B1:4 A3:P2,B1:P2 2-4"
" C0-3:S+ C1-3:S+ C2-3 C4 X1-3 X1-3:P2 P2 . 0 A2:1,A3:2-3 A2:P2,A3:P2 1-3"
" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2:C4-5 0 A3:2-3,B1:4-5 A3:P2,B1:P2 2-5"
+ " C4:X0-3:S+ X1-3:S+ X2-3 . . P2 . . 0 A1:4,A2:1-3,A3:1-3 A2:P2 1-3"
+ " C4:X0-3:S+ X1-3:S+ X2-3 . . . P2 . 0 A1:4,A2:4,A3:2-3 A3:P2 2-3"
# Nested remote/local partition tests
" C0-3:S+ C1-3:S+ C2-3 C4-5 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:,A3:2-3,B1:4-5 \
A1:P0,A2:P1,A3:P2,B1:P1 2-3"
" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:,A3:2-3,B1:4 \
A1:P0,A2:P1,A3:P2,B1:P1 2-4,2-3"
+ " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 . P1 0 A1:0-1,A2:2-3,A3:2-3,B1:4 \
+ A1:P0,A2:P1,A3:P0,B1:P1"
" C0-3:S+ C1-3:S+ C3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:2,A3:3,B1:4 \
A1:P0,A2:P1,A3:P2,B1:P1 2-4,3"
" C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X4:P1 . 0 A1:0-1,A2:2-3,A3:4 \
A1:P0,A2:P2,A3:P1 2-4,2-3"
+ " C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X3-4:P1 . 0 A1:0-1,A2:2,A3:3-4 \
+ A1:P0,A2:P2,A3:P1 2"
" C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \
. . X5 . . 0 A1:0-4,A2:1-4,A3:2-4 \
A1:P0,A2:P-2,A3:P-1"
@@ -262,8 +284,8 @@ TEST_MATRIX=(
. . X2-3 P2 . . 0 A1:0-2,A2:3,XA2:3 A2:P2 3"
# Invalid to valid local partition direct transition tests
- " C1-3:S+:P2 C2-3:X1:P2 . . . . . . 0 A1:1-3,XA1:1-3,A2:2-3:XA2: A1:P2,A2:P-2 1-3"
- " C1-3:S+:P2 C2-3:X1:P2 . . . X3:P2 . . 0 A1:1-2,XA1:1-3,A2:3:XA2:3 A1:P2,A2:P2 1-3"
+ " C1-3:S+:P2 X4:P2 . . . . . . 0 A1:1-3,XA1:1-3,A2:1-3:XA2: A1:P2,A2:P-2 1-3"
+ " C1-3:S+:P2 X4:P2 . . . X3:P2 . . 0 A1:1-2,XA1:1-3,A2:3:XA2:3 A1:P2,A2:P2 1-3"
" C0-3:P2 . . C4-6 C0-4 . . . 0 A1:0-4,B1:4-6 A1:P-2,B1:P0"
" C0-3:P2 . . C4-6 C0-4:C0-3 . . . 0 A1:0-3,B1:4-6 A1:P2,B1:P0 0-3"
" C0-3:P2 . . C3-5:C4-5 . . . . 0 A1:0-3,B1:4-5 A1:P2,B1:P0 0-3"
@@ -274,32 +296,26 @@ TEST_MATRIX=(
" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
. . X4 . . 0 A1:1-3,A2:1-3,A3:2-3,XA2:,XA3: A1:P2,A2:P-2,A3:P-2 1-3"
" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
- . . C4 . . 0 A1:1-3,A2:1-3,A3:2-3,XA2:,XA3: A1:P2,A2:P-2,A3:P-2 1-3"
+ . . C4:X . . 0 A1:1-3,A2:1-3,A3:2-3,XA2:,XA3: A1:P2,A2:P-2,A3:P-2 1-3"
# Local partition CPU change tests
" C0-5:S+:P2 C4-5:S+:P1 . . . C3-5 . . 0 A1:0-2,A2:3-5 A1:P2,A2:P1 0-2"
" C0-5:S+:P2 C4-5:S+:P1 . . C1-5 . . . 0 A1:1-3,A2:4-5 A1:P2,A2:P1 1-3"
# cpus_allowed/exclusive_cpus update tests
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
- . C4 . P2 . 0 A1:4,A2:4,XA2:,XA3:,A3:4 \
+ . X:C4 . P2 . 0 A1:4,A2:4,XA2:,XA3:,A3:4 \
A1:P0,A3:P-2"
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
. X1 . P2 . 0 A1:0-3,A2:1-3,XA1:1,XA2:,XA3:,A3:2-3 \
A1:P0,A3:P-2"
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
- . . C3 P2 . 0 A1:0-2,A2:0-2,XA2:3,XA3:3,A3:3 \
- A1:P0,A3:P2 3"
- " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
. . X3 P2 . 0 A1:0-2,A2:1-2,XA2:3,XA3:3,A3:3 \
A1:P0,A3:P2 3"
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
. . X3 . . 0 A1:0-3,A2:1-3,XA2:3,XA3:3,A3:2-3 \
A1:P0,A3:P-2"
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
- . . C3 . . 0 A1:0-3,A2:3,XA2:3,XA3:3,A3:3 \
- A1:P0,A3:P-2"
- " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
- . C4 . . . 0 A1:4,A2:4,A3:4,XA1:,XA2:,XA3 \
+ . X4 . . . 0 A1:0-3,A2:1-3,A3:2-3,XA1:4,XA2:,XA3 \
A1:P0,A3:P-2"
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
@@ -346,6 +362,9 @@ TEST_MATRIX=(
" C0-1:P1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P-1"
" C0-1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P0,B1:P-1"
+ # cpuset.cpus can overlap with sibling cpuset.cpus.exclusive but not subsumed by it
+ " C0-3 . . C4-5 X5 . . . 0 A1:0-3,B1:4-5"
+
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
# Failure cases:
@@ -355,6 +374,9 @@ TEST_MATRIX=(
# Changes to cpuset.cpus.exclusive that violate exclusivity rule is rejected
" C0-3 . . C4-5 X0-3 . . X3-5 1 A1:0-3,B1:4-5"
+
+ # cpuset.cpus cannot be a subset of sibling cpuset.cpus.exclusive
+ " C0-3 . . C4-5 X3-5 . . . 1 A1:0-3,B1:4-5"
)
#
@@ -556,14 +578,15 @@ check_cgroup_states()
do
set -- $(echo $CHK | sed -e "s/:/ /g")
CGRP=$1
+ CGRP_DIR=$CGRP
STATE=$2
FILE=
EVAL=$(expr substr $STATE 2 2)
- [[ $CGRP = A2 ]] && CGRP=A1/A2
- [[ $CGRP = A3 ]] && CGRP=A1/A2/A3
+ [[ $CGRP = A2 ]] && CGRP_DIR=A1/A2
+ [[ $CGRP = A3 ]] && CGRP_DIR=A1/A2/A3
case $STATE in
- P*) FILE=$CGRP/cpuset.cpus.partition
+ P*) FILE=$CGRP_DIR/cpuset.cpus.partition
;;
*) echo "Unknown state: $STATE!"
exit 1
@@ -587,6 +610,16 @@ check_cgroup_states()
;;
esac
[[ $EVAL != $VAL ]] && return 1
+
+ #
+ # For root partition, dump sched-domains info to console if
+ # verbose mode set for manual comparison with sched debug info.
+ #
+ [[ $VAL -eq 1 && $VERBOSE -gt 0 ]] && {
+ DOMS=$(cat $CGRP_DIR/cpuset.cpus.effective)
+ [[ -n "$DOMS" ]] &&
+ echo " [$CGRP] sched-domain: $DOMS" > $CONSOLE
+ }
done
return 0
}
@@ -694,9 +727,9 @@ null_isolcpus_check()
[[ $VERBOSE -gt 0 ]] || return 0
# Retry a few times before printing error
RETRY=0
- while [[ $RETRY -lt 5 ]]
+ while [[ $RETRY -lt 8 ]]
do
- pause 0.01
+ pause 0.02
check_isolcpus "."
[[ $? -eq 0 ]] && return 0
((RETRY++))
@@ -726,7 +759,7 @@ run_state_test()
while [[ $I -lt $CNT ]]
do
- echo "Running test $I ..." > /dev/console
+ echo "Running test $I ..." > $CONSOLE
[[ $VERBOSE -gt 1 ]] && {
echo ""
eval echo \${$TEST[$I]}
@@ -783,7 +816,7 @@ run_state_test()
while [[ $NEWLIST != $CPULIST && $RETRY -lt 8 ]]
do
# Wait a bit longer & recheck a few times
- pause 0.01
+ pause 0.02
((RETRY++))
NEWLIST=$(cat cpuset.cpus.effective)
done
diff --git a/tools/testing/selftests/cgroup/test_pids.c b/tools/testing/selftests/cgroup/test_pids.c
new file mode 100644
index 000000000000..9ecb83c6cc5c
--- /dev/null
+++ b/tools/testing/selftests/cgroup/test_pids.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <linux/limits.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "../kselftest.h"
+#include "cgroup_util.h"
+
+static int run_success(const char *cgroup, void *arg)
+{
+ return 0;
+}
+
+static int run_pause(const char *cgroup, void *arg)
+{
+ return pause();
+}
+
+/*
+ * This test checks that pids.max prevents forking new children above the
+ * specified limit in the cgroup.
+ */
+static int test_pids_max(const char *root)
+{
+ int ret = KSFT_FAIL;
+ char *cg_pids;
+ int pid;
+
+ cg_pids = cg_name(root, "pids_test");
+ if (!cg_pids)
+ goto cleanup;
+
+ if (cg_create(cg_pids))
+ goto cleanup;
+
+ if (cg_read_strcmp(cg_pids, "pids.max", "max\n"))
+ goto cleanup;
+
+ if (cg_write(cg_pids, "pids.max", "2"))
+ goto cleanup;
+
+ if (cg_enter_current(cg_pids))
+ goto cleanup;
+
+ pid = cg_run_nowait(cg_pids, run_pause, NULL);
+ if (pid < 0)
+ goto cleanup;
+
+ if (cg_run_nowait(cg_pids, run_success, NULL) != -1 || errno != EAGAIN)
+ goto cleanup;
+
+ if (kill(pid, SIGINT))
+ goto cleanup;
+
+ ret = KSFT_PASS;
+
+cleanup:
+ cg_enter_current(root);
+ cg_destroy(cg_pids);
+ free(cg_pids);
+
+ return ret;
+}
+
+/*
+ * This test checks that pids.events are counted in cgroup associated with pids.max
+ */
+static int test_pids_events(const char *root)
+{
+ int ret = KSFT_FAIL;
+ char *cg_parent = NULL, *cg_child = NULL;
+ int pid;
+
+ cg_parent = cg_name(root, "pids_parent");
+ cg_child = cg_name(cg_parent, "pids_child");
+ if (!cg_parent || !cg_child)
+ goto cleanup;
+
+ if (cg_create(cg_parent))
+ goto cleanup;
+ if (cg_write(cg_parent, "cgroup.subtree_control", "+pids"))
+ goto cleanup;
+ if (cg_create(cg_child))
+ goto cleanup;
+
+ if (cg_write(cg_parent, "pids.max", "2"))
+ goto cleanup;
+
+ if (cg_read_strcmp(cg_child, "pids.max", "max\n"))
+ goto cleanup;
+
+ if (cg_enter_current(cg_child))
+ goto cleanup;
+
+ pid = cg_run_nowait(cg_child, run_pause, NULL);
+ if (pid < 0)
+ goto cleanup;
+
+ if (cg_run_nowait(cg_child, run_success, NULL) != -1 || errno != EAGAIN)
+ goto cleanup;
+
+ if (kill(pid, SIGINT))
+ goto cleanup;
+
+ if (cg_read_key_long(cg_child, "pids.events", "max ") != 0)
+ goto cleanup;
+ if (cg_read_key_long(cg_parent, "pids.events", "max ") != 1)
+ goto cleanup;
+
+
+ ret = KSFT_PASS;
+
+cleanup:
+ cg_enter_current(root);
+ if (cg_child)
+ cg_destroy(cg_child);
+ if (cg_parent)
+ cg_destroy(cg_parent);
+ free(cg_child);
+ free(cg_parent);
+
+ return ret;
+}
+
+
+
+#define T(x) { x, #x }
+struct pids_test {
+ int (*fn)(const char *root);
+ const char *name;
+} tests[] = {
+ T(test_pids_max),
+ T(test_pids_events),
+};
+#undef T
+
+int main(int argc, char **argv)
+{
+ char root[PATH_MAX];
+
+ ksft_print_header();
+ ksft_set_plan(ARRAY_SIZE(tests));
+ if (cg_find_unified_root(root, sizeof(root), NULL))
+ ksft_exit_skip("cgroup v2 isn't mounted\n");
+
+ /*
+ * Check that pids controller is available:
+ * pids is listed in cgroup.controllers
+ */
+ if (cg_read_strstr(root, "cgroup.controllers", "pids"))
+ ksft_exit_skip("pids controller isn't available\n");
+
+ if (cg_read_strstr(root, "cgroup.subtree_control", "pids"))
+ if (cg_write(root, "cgroup.subtree_control", "+pids"))
+ ksft_exit_skip("Failed to set pids controller\n");
+
+ for (int i = 0; i < ARRAY_SIZE(tests); i++) {
+ switch (tests[i].fn(root)) {
+ case KSFT_PASS:
+ ksft_test_result_pass("%s\n", tests[i].name);
+ break;
+ case KSFT_SKIP:
+ ksft_test_result_skip("%s\n", tests[i].name);
+ break;
+ default:
+ ksft_test_result_fail("%s\n", tests[i].name);
+ break;
+ }
+ }
+
+ ksft_finished();
+}
diff --git a/tools/testing/selftests/filesystems/statmount/Makefile b/tools/testing/selftests/filesystems/statmount/Makefile
index 07a0d5b545ca..3af3136e35a4 100644
--- a/tools/testing/selftests/filesystems/statmount/Makefile
+++ b/tools/testing/selftests/filesystems/statmount/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES)
-TEST_GEN_PROGS := statmount_test
+TEST_GEN_PROGS := statmount_test statmount_test_ns
include ../../lib.mk
diff --git a/tools/testing/selftests/filesystems/statmount/statmount.h b/tools/testing/selftests/filesystems/statmount/statmount.h
new file mode 100644
index 000000000000..f4294bab9d73
--- /dev/null
+++ b/tools/testing/selftests/filesystems/statmount/statmount.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __STATMOUNT_H
+#define __STATMOUNT_H
+
+#include <stdint.h>
+#include <linux/mount.h>
+#include <asm/unistd.h>
+
+static inline int statmount(uint64_t mnt_id, uint64_t mnt_ns_id, uint64_t mask,
+ struct statmount *buf, size_t bufsize,
+ unsigned int flags)
+{
+ struct mnt_id_req req = {
+ .size = MNT_ID_REQ_SIZE_VER0,
+ .mnt_id = mnt_id,
+ .param = mask,
+ };
+
+ if (mnt_ns_id) {
+ req.size = MNT_ID_REQ_SIZE_VER1;
+ req.mnt_ns_id = mnt_ns_id;
+ }
+
+ return syscall(__NR_statmount, &req, buf, bufsize, flags);
+}
+
+static ssize_t listmount(uint64_t mnt_id, uint64_t mnt_ns_id,
+ uint64_t last_mnt_id, uint64_t list[], size_t num,
+ unsigned int flags)
+{
+ struct mnt_id_req req = {
+ .size = MNT_ID_REQ_SIZE_VER0,
+ .mnt_id = mnt_id,
+ .param = last_mnt_id,
+ };
+
+ if (mnt_ns_id) {
+ req.size = MNT_ID_REQ_SIZE_VER1;
+ req.mnt_ns_id = mnt_ns_id;
+ }
+
+ return syscall(__NR_listmount, &req, list, num, flags);
+}
+
+#endif /* __STATMOUNT_H */
diff --git a/tools/testing/selftests/filesystems/statmount/statmount_test.c b/tools/testing/selftests/filesystems/statmount/statmount_test.c
index e8c019d72cbf..c773334bbcc9 100644
--- a/tools/testing/selftests/filesystems/statmount/statmount_test.c
+++ b/tools/testing/selftests/filesystems/statmount/statmount_test.c
@@ -4,17 +4,15 @@
#include <assert.h>
#include <stddef.h>
-#include <stdint.h>
#include <sched.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/statfs.h>
-#include <linux/mount.h>
#include <linux/stat.h>
-#include <asm/unistd.h>
+#include "statmount.h"
#include "../../kselftest.h"
static const char *const known_fs[] = {
@@ -36,18 +34,6 @@ static const char *const known_fs[] = {
"ufs", "v7", "vboxsf", "vfat", "virtiofs", "vxfs", "xenfs", "xfs",
"zonefs", NULL };
-static int statmount(uint64_t mnt_id, uint64_t mask, struct statmount *buf,
- size_t bufsize, unsigned int flags)
-{
- struct mnt_id_req req = {
- .size = MNT_ID_REQ_SIZE_VER0,
- .mnt_id = mnt_id,
- .param = mask,
- };
-
- return syscall(__NR_statmount, &req, buf, bufsize, flags);
-}
-
static struct statmount *statmount_alloc(uint64_t mnt_id, uint64_t mask, unsigned int flags)
{
size_t bufsize = 1 << 15;
@@ -56,7 +42,7 @@ static struct statmount *statmount_alloc(uint64_t mnt_id, uint64_t mask, unsigne
int ret;
for (;;) {
- ret = statmount(mnt_id, mask, tmp, bufsize, flags);
+ ret = statmount(mnt_id, 0, mask, tmp, bufsize, flags);
if (ret != -1)
break;
if (tofree)
@@ -121,7 +107,7 @@ static char root_mntpoint[] = "/tmp/statmount_test_root.XXXXXX";
static int orig_root;
static uint64_t root_id, parent_id;
static uint32_t old_root_id, old_parent_id;
-
+static FILE *f_mountinfo;
static void cleanup_namespace(void)
{
@@ -146,7 +132,7 @@ static void setup_namespace(void)
uid_t uid = getuid();
gid_t gid = getgid();
- ret = unshare(CLONE_NEWNS|CLONE_NEWUSER);
+ ret = unshare(CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWPID);
if (ret == -1)
ksft_exit_fail_msg("unsharing mountns and userns: %s\n",
strerror(errno));
@@ -157,6 +143,11 @@ static void setup_namespace(void)
sprintf(buf, "0 %d 1", gid);
write_file("/proc/self/gid_map", buf);
+ f_mountinfo = fopen("/proc/self/mountinfo", "re");
+ if (!f_mountinfo)
+ ksft_exit_fail_msg("failed to open mountinfo: %s\n",
+ strerror(errno));
+
ret = mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL);
if (ret == -1)
ksft_exit_fail_msg("making mount tree private: %s\n",
@@ -216,25 +207,13 @@ static int setup_mount_tree(int log2_num)
return 0;
}
-static ssize_t listmount(uint64_t mnt_id, uint64_t last_mnt_id,
- uint64_t list[], size_t num, unsigned int flags)
-{
- struct mnt_id_req req = {
- .size = MNT_ID_REQ_SIZE_VER0,
- .mnt_id = mnt_id,
- .param = last_mnt_id,
- };
-
- return syscall(__NR_listmount, &req, list, num, flags);
-}
-
static void test_listmount_empty_root(void)
{
ssize_t res;
const unsigned int size = 32;
uint64_t list[size];
- res = listmount(LSMT_ROOT, 0, list, size, 0);
+ res = listmount(LSMT_ROOT, 0, 0, list, size, 0);
if (res == -1) {
ksft_test_result_fail("listmount: %s\n", strerror(errno));
return;
@@ -259,7 +238,7 @@ static void test_statmount_zero_mask(void)
struct statmount sm;
int ret;
- ret = statmount(root_id, 0, &sm, sizeof(sm), 0);
+ ret = statmount(root_id, 0, 0, &sm, sizeof(sm), 0);
if (ret == -1) {
ksft_test_result_fail("statmount zero mask: %s\n",
strerror(errno));
@@ -285,7 +264,7 @@ static void test_statmount_mnt_basic(void)
int ret;
uint64_t mask = STATMOUNT_MNT_BASIC;
- ret = statmount(root_id, mask, &sm, sizeof(sm), 0);
+ ret = statmount(root_id, 0, mask, &sm, sizeof(sm), 0);
if (ret == -1) {
ksft_test_result_fail("statmount mnt basic: %s\n",
strerror(errno));
@@ -345,7 +324,7 @@ static void test_statmount_sb_basic(void)
struct statx sx;
struct statfs sf;
- ret = statmount(root_id, mask, &sm, sizeof(sm), 0);
+ ret = statmount(root_id, 0, mask, &sm, sizeof(sm), 0);
if (ret == -1) {
ksft_test_result_fail("statmount sb basic: %s\n",
strerror(errno));
@@ -470,6 +449,88 @@ static void test_statmount_fs_type(void)
free(sm);
}
+static void test_statmount_mnt_opts(void)
+{
+ struct statmount *sm;
+ const char *statmount_opts;
+ char *line = NULL;
+ size_t len = 0;
+
+ sm = statmount_alloc(root_id, STATMOUNT_MNT_BASIC | STATMOUNT_MNT_OPTS,
+ 0);
+ if (!sm) {
+ ksft_test_result_fail("statmount mnt opts: %s\n",
+ strerror(errno));
+ return;
+ }
+
+ while (getline(&line, &len, f_mountinfo) != -1) {
+ int i;
+ char *p, *p2;
+ unsigned int old_mnt_id;
+
+ old_mnt_id = atoi(line);
+ if (old_mnt_id != sm->mnt_id_old)
+ continue;
+
+ for (p = line, i = 0; p && i < 5; i++)
+ p = strchr(p + 1, ' ');
+ if (!p)
+ continue;
+
+ p2 = strchr(p + 1, ' ');
+ if (!p2)
+ continue;
+ *p2 = '\0';
+ p = strchr(p2 + 1, '-');
+ if (!p)
+ continue;
+ for (p++, i = 0; p && i < 2; i++)
+ p = strchr(p + 1, ' ');
+ if (!p)
+ continue;
+ p++;
+
+ /* skip generic superblock options */
+ if (strncmp(p, "ro", 2) == 0)
+ p += 2;
+ else if (strncmp(p, "rw", 2) == 0)
+ p += 2;
+ if (*p == ',')
+ p++;
+ if (strncmp(p, "sync", 4) == 0)
+ p += 4;
+ if (*p == ',')
+ p++;
+ if (strncmp(p, "dirsync", 7) == 0)
+ p += 7;
+ if (*p == ',')
+ p++;
+ if (strncmp(p, "lazytime", 8) == 0)
+ p += 8;
+ if (*p == ',')
+ p++;
+ p2 = strrchr(p, '\n');
+ if (p2)
+ *p2 = '\0';
+
+ statmount_opts = sm->str + sm->mnt_opts;
+ if (strcmp(statmount_opts, p) != 0)
+ ksft_test_result_fail(
+ "unexpected mount options: '%s' != '%s'\n",
+ statmount_opts, p);
+ else
+ ksft_test_result_pass("statmount mount options\n");
+ free(sm);
+ free(line);
+ return;
+ }
+
+ ksft_test_result_fail("didnt't find mount entry\n");
+ free(sm);
+ free(line);
+}
+
static void test_statmount_string(uint64_t mask, size_t off, const char *name)
{
struct statmount *sm;
@@ -506,14 +567,14 @@ static void test_statmount_string(uint64_t mask, size_t off, const char *name)
exactsize = sm->size;
shortsize = sizeof(*sm) + i;
- ret = statmount(root_id, mask, sm, exactsize, 0);
+ ret = statmount(root_id, 0, mask, sm, exactsize, 0);
if (ret == -1) {
ksft_test_result_fail("statmount exact size: %s\n",
strerror(errno));
goto out;
}
errno = 0;
- ret = statmount(root_id, mask, sm, shortsize, 0);
+ ret = statmount(root_id, 0, mask, sm, shortsize, 0);
if (ret != -1 || errno != EOVERFLOW) {
ksft_test_result_fail("should have failed with EOVERFLOW: %s\n",
strerror(errno));
@@ -541,7 +602,7 @@ static void test_listmount_tree(void)
if (res == -1)
return;
- num = res = listmount(LSMT_ROOT, 0, list, size, 0);
+ num = res = listmount(LSMT_ROOT, 0, 0, list, size, 0);
if (res == -1) {
ksft_test_result_fail("listmount: %s\n", strerror(errno));
return;
@@ -553,7 +614,7 @@ static void test_listmount_tree(void)
}
for (i = 0; i < size - step;) {
- res = listmount(LSMT_ROOT, i ? list2[i - 1] : 0, list2 + i, step, 0);
+ res = listmount(LSMT_ROOT, 0, i ? list2[i - 1] : 0, list2 + i, step, 0);
if (res == -1)
ksft_test_result_fail("short listmount: %s\n",
strerror(errno));
@@ -585,18 +646,18 @@ int main(void)
int ret;
uint64_t all_mask = STATMOUNT_SB_BASIC | STATMOUNT_MNT_BASIC |
STATMOUNT_PROPAGATE_FROM | STATMOUNT_MNT_ROOT |
- STATMOUNT_MNT_POINT | STATMOUNT_FS_TYPE;
+ STATMOUNT_MNT_POINT | STATMOUNT_FS_TYPE | STATMOUNT_MNT_NS_ID;
ksft_print_header();
- ret = statmount(0, 0, NULL, 0, 0);
+ ret = statmount(0, 0, 0, NULL, 0, 0);
assert(ret == -1);
if (errno == ENOSYS)
ksft_exit_skip("statmount() syscall not supported\n");
setup_namespace();
- ksft_set_plan(14);
+ ksft_set_plan(15);
test_listmount_empty_root();
test_statmount_zero_mask();
test_statmount_mnt_basic();
@@ -604,6 +665,7 @@ int main(void)
test_statmount_mnt_root();
test_statmount_mnt_point();
test_statmount_fs_type();
+ test_statmount_mnt_opts();
test_statmount_string(STATMOUNT_MNT_ROOT, str_off(mnt_root), "mount root");
test_statmount_string(STATMOUNT_MNT_POINT, str_off(mnt_point), "mount point");
test_statmount_string(STATMOUNT_FS_TYPE, str_off(fs_type), "fs type");
diff --git a/tools/testing/selftests/filesystems/statmount/statmount_test_ns.c b/tools/testing/selftests/filesystems/statmount/statmount_test_ns.c
new file mode 100644
index 000000000000..e044f5fc57fd
--- /dev/null
+++ b/tools/testing/selftests/filesystems/statmount/statmount_test_ns.c
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <linux/nsfs.h>
+#include <linux/stat.h>
+
+#include "statmount.h"
+#include "../../kselftest.h"
+
+#define NSID_PASS 0
+#define NSID_FAIL 1
+#define NSID_SKIP 2
+#define NSID_ERROR 3
+
+static void handle_result(int ret, const char *testname)
+{
+ if (ret == NSID_PASS)
+ ksft_test_result_pass("%s\n", testname);
+ else if (ret == NSID_FAIL)
+ ksft_test_result_fail("%s\n", testname);
+ else if (ret == NSID_ERROR)
+ ksft_exit_fail_msg("%s\n", testname);
+ else
+ ksft_test_result_skip("%s\n", testname);
+}
+
+static inline int wait_for_pid(pid_t pid)
+{
+ int status, ret;
+
+again:
+ ret = waitpid(pid, &status, 0);
+ if (ret == -1) {
+ if (errno == EINTR)
+ goto again;
+
+ ksft_print_msg("waitpid returned -1, errno=%d\n", errno);
+ return -1;
+ }
+
+ if (!WIFEXITED(status)) {
+ ksft_print_msg(
+ "waitpid !WIFEXITED, WIFSIGNALED=%d, WTERMSIG=%d\n",
+ WIFSIGNALED(status), WTERMSIG(status));
+ return -1;
+ }
+
+ ret = WEXITSTATUS(status);
+ return ret;
+}
+
+static int get_mnt_ns_id(const char *mnt_ns, uint64_t *mnt_ns_id)
+{
+ int fd = open(mnt_ns, O_RDONLY);
+
+ if (fd < 0) {
+ ksft_print_msg("failed to open for ns %s: %s\n",
+ mnt_ns, strerror(errno));
+ sleep(60);
+ return NSID_ERROR;
+ }
+
+ if (ioctl(fd, NS_GET_MNTNS_ID, mnt_ns_id) < 0) {
+ ksft_print_msg("failed to get the nsid for ns %s: %s\n",
+ mnt_ns, strerror(errno));
+ return NSID_ERROR;
+ }
+ close(fd);
+ return NSID_PASS;
+}
+
+static int get_mnt_id(const char *path, uint64_t *mnt_id)
+{
+ struct statx sx;
+ int ret;
+
+ ret = statx(AT_FDCWD, path, 0, STATX_MNT_ID_UNIQUE, &sx);
+ if (ret == -1) {
+ ksft_print_msg("retrieving unique mount ID for %s: %s\n", path,
+ strerror(errno));
+ return NSID_ERROR;
+ }
+
+ if (!(sx.stx_mask & STATX_MNT_ID_UNIQUE)) {
+ ksft_print_msg("no unique mount ID available for %s\n", path);
+ return NSID_ERROR;
+ }
+
+ *mnt_id = sx.stx_mnt_id;
+ return NSID_PASS;
+}
+
+static int write_file(const char *path, const char *val)
+{
+ int fd = open(path, O_WRONLY);
+ size_t len = strlen(val);
+ int ret;
+
+ if (fd == -1) {
+ ksft_print_msg("opening %s for write: %s\n", path, strerror(errno));
+ return NSID_ERROR;
+ }
+
+ ret = write(fd, val, len);
+ if (ret == -1) {
+ ksft_print_msg("writing to %s: %s\n", path, strerror(errno));
+ return NSID_ERROR;
+ }
+ if (ret != len) {
+ ksft_print_msg("short write to %s\n", path);
+ return NSID_ERROR;
+ }
+
+ ret = close(fd);
+ if (ret == -1) {
+ ksft_print_msg("closing %s\n", path);
+ return NSID_ERROR;
+ }
+
+ return NSID_PASS;
+}
+
+static int setup_namespace(void)
+{
+ int ret;
+ char buf[32];
+ uid_t uid = getuid();
+ gid_t gid = getgid();
+
+ ret = unshare(CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWPID);
+ if (ret == -1)
+ ksft_exit_fail_msg("unsharing mountns and userns: %s\n",
+ strerror(errno));
+
+ sprintf(buf, "0 %d 1", uid);
+ ret = write_file("/proc/self/uid_map", buf);
+ if (ret != NSID_PASS)
+ return ret;
+ ret = write_file("/proc/self/setgroups", "deny");
+ if (ret != NSID_PASS)
+ return ret;
+ sprintf(buf, "0 %d 1", gid);
+ ret = write_file("/proc/self/gid_map", buf);
+ if (ret != NSID_PASS)
+ return ret;
+
+ ret = mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL);
+ if (ret == -1) {
+ ksft_print_msg("making mount tree private: %s\n",
+ strerror(errno));
+ return NSID_ERROR;
+ }
+
+ return NSID_PASS;
+}
+
+static int _test_statmount_mnt_ns_id(void)
+{
+ struct statmount sm;
+ uint64_t mnt_ns_id;
+ uint64_t root_id;
+ int ret;
+
+ ret = get_mnt_ns_id("/proc/self/ns/mnt", &mnt_ns_id);
+ if (ret != NSID_PASS)
+ return ret;
+
+ ret = get_mnt_id("/", &root_id);
+ if (ret != NSID_PASS)
+ return ret;
+
+ ret = statmount(root_id, 0, STATMOUNT_MNT_NS_ID, &sm, sizeof(sm), 0);
+ if (ret == -1) {
+ ksft_print_msg("statmount mnt ns id: %s\n", strerror(errno));
+ return NSID_ERROR;
+ }
+
+ if (sm.size != sizeof(sm)) {
+ ksft_print_msg("unexpected size: %u != %u\n", sm.size,
+ (uint32_t)sizeof(sm));
+ return NSID_FAIL;
+ }
+ if (sm.mask != STATMOUNT_MNT_NS_ID) {
+ ksft_print_msg("statmount mnt ns id unavailable\n");
+ return NSID_SKIP;
+ }
+
+ if (sm.mnt_ns_id != mnt_ns_id) {
+ ksft_print_msg("unexpected mnt ns ID: 0x%llx != 0x%llx\n",
+ (unsigned long long)sm.mnt_ns_id,
+ (unsigned long long)mnt_ns_id);
+ return NSID_FAIL;
+ }
+
+ return NSID_PASS;
+}
+
+static void test_statmount_mnt_ns_id(void)
+{
+ pid_t pid;
+ int ret;
+
+ pid = fork();
+ if (pid < 0)
+ ksft_exit_fail_msg("failed to fork: %s\n", strerror(errno));
+
+ /* We're the original pid, wait for the result. */
+ if (pid != 0) {
+ ret = wait_for_pid(pid);
+ handle_result(ret, "test statmount ns id");
+ return;
+ }
+
+ ret = setup_namespace();
+ if (ret != NSID_PASS)
+ exit(ret);
+ ret = _test_statmount_mnt_ns_id();
+ exit(ret);
+}
+
+static int validate_external_listmount(pid_t pid, uint64_t child_nr_mounts)
+{
+ uint64_t list[256];
+ uint64_t mnt_ns_id;
+ uint64_t nr_mounts;
+ char buf[256];
+ int ret;
+
+ /* Get the mount ns id for our child. */
+ snprintf(buf, sizeof(buf), "/proc/%lu/ns/mnt", (unsigned long)pid);
+ ret = get_mnt_ns_id(buf, &mnt_ns_id);
+
+ nr_mounts = listmount(LSMT_ROOT, mnt_ns_id, 0, list, 256, 0);
+ if (nr_mounts == (uint64_t)-1) {
+ ksft_print_msg("listmount: %s\n", strerror(errno));
+ return NSID_ERROR;
+ }
+
+ if (nr_mounts != child_nr_mounts) {
+ ksft_print_msg("listmount results is %zi != %zi\n", nr_mounts,
+ child_nr_mounts);
+ return NSID_FAIL;
+ }
+
+ /* Validate that all of our entries match our mnt_ns_id. */
+ for (int i = 0; i < nr_mounts; i++) {
+ struct statmount sm;
+
+ ret = statmount(list[i], mnt_ns_id, STATMOUNT_MNT_NS_ID, &sm,
+ sizeof(sm), 0);
+ if (ret < 0) {
+ ksft_print_msg("statmount mnt ns id: %s\n", strerror(errno));
+ return NSID_ERROR;
+ }
+
+ if (sm.mask != STATMOUNT_MNT_NS_ID) {
+ ksft_print_msg("statmount mnt ns id unavailable\n");
+ return NSID_SKIP;
+ }
+
+ if (sm.mnt_ns_id != mnt_ns_id) {
+ ksft_print_msg("listmount gave us the wrong ns id: 0x%llx != 0x%llx\n",
+ (unsigned long long)sm.mnt_ns_id,
+ (unsigned long long)mnt_ns_id);
+ return NSID_FAIL;
+ }
+ }
+
+ return NSID_PASS;
+}
+
+static void test_listmount_ns(void)
+{
+ uint64_t nr_mounts;
+ char pval;
+ int child_ready_pipe[2];
+ int parent_ready_pipe[2];
+ pid_t pid;
+ int ret, child_ret;
+
+ if (pipe(child_ready_pipe) < 0)
+ ksft_exit_fail_msg("failed to create the child pipe: %s\n",
+ strerror(errno));
+ if (pipe(parent_ready_pipe) < 0)
+ ksft_exit_fail_msg("failed to create the parent pipe: %s\n",
+ strerror(errno));
+
+ pid = fork();
+ if (pid < 0)
+ ksft_exit_fail_msg("failed to fork: %s\n", strerror(errno));
+
+ if (pid == 0) {
+ char cval;
+ uint64_t list[256];
+
+ close(child_ready_pipe[0]);
+ close(parent_ready_pipe[1]);
+
+ ret = setup_namespace();
+ if (ret != NSID_PASS)
+ exit(ret);
+
+ nr_mounts = listmount(LSMT_ROOT, 0, 0, list, 256, 0);
+ if (nr_mounts == (uint64_t)-1) {
+ ksft_print_msg("listmount: %s\n", strerror(errno));
+ exit(NSID_FAIL);
+ }
+
+ /*
+ * Tell our parent how many mounts we have, and then wait for it
+ * to tell us we're done.
+ */
+ write(child_ready_pipe[1], &nr_mounts, sizeof(nr_mounts));
+ read(parent_ready_pipe[0], &cval, sizeof(cval));
+ exit(NSID_PASS);
+ }
+
+ close(child_ready_pipe[1]);
+ close(parent_ready_pipe[0]);
+
+ /* Wait until the child has created everything. */
+ if (read(child_ready_pipe[0], &nr_mounts, sizeof(nr_mounts)) !=
+ sizeof(nr_mounts))
+ ret = NSID_ERROR;
+
+ ret = validate_external_listmount(pid, nr_mounts);
+
+ if (write(parent_ready_pipe[1], &pval, sizeof(pval)) != sizeof(pval))
+ ret = NSID_ERROR;
+
+ child_ret = wait_for_pid(pid);
+ if (child_ret != NSID_PASS)
+ ret = child_ret;
+ handle_result(ret, "test listmount ns id");
+}
+
+int main(void)
+{
+ int ret;
+
+ ksft_print_header();
+ ret = statmount(0, 0, 0, NULL, 0, 0);
+ assert(ret == -1);
+ if (errno == ENOSYS)
+ ksft_exit_skip("statmount() syscall not supported\n");
+
+ ksft_set_plan(2);
+ test_statmount_mnt_ns_id();
+ test_listmount_ns();
+
+ if (ksft_get_fail_cnt() + ksft_get_error_cnt() > 0)
+ ksft_exit_fail();
+ else
+ ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
index 76c2a6945d3e..b8967b6e29d5 100644
--- a/tools/testing/selftests/kselftest.h
+++ b/tools/testing/selftests/kselftest.h
@@ -168,15 +168,7 @@ static inline __printf(1, 2) void ksft_print_msg(const char *msg, ...)
static inline void ksft_perror(const char *msg)
{
-#ifndef NOLIBC
ksft_print_msg("%s: %s (%d)\n", msg, strerror(errno), errno);
-#else
- /*
- * nolibc doesn't provide strerror() and it seems
- * inappropriate to add one, just print the errno.
- */
- ksft_print_msg("%s: %d)\n", msg, errno);
-#endif
}
static inline __printf(1, 2) void ksft_test_result_pass(const char *msg, ...)
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h
index b634969cbb6f..40723a6a083f 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -66,8 +66,6 @@
#include <sys/wait.h>
#include <unistd.h>
#include <setjmp.h>
-#include <syscall.h>
-#include <linux/sched.h>
#include "kselftest.h"
@@ -82,17 +80,6 @@
# define TH_LOG_ENABLED 1
#endif
-/* Wait for the child process to end but without sharing memory mapping. */
-static inline pid_t clone3_vfork(void)
-{
- struct clone_args args = {
- .flags = CLONE_VFORK,
- .exit_signal = SIGCHLD,
- };
-
- return syscall(__NR_clone3, &args, sizeof(args));
-}
-
/**
* TH_LOG()
*
@@ -437,7 +424,7 @@ static inline pid_t clone3_vfork(void)
} \
if (setjmp(_metadata->env) == 0) { \
/* _metadata and potentially self are shared with all forks. */ \
- child = clone3_vfork(); \
+ child = fork(); \
if (child == 0) { \
fixture_name##_setup(_metadata, self, variant->data); \
/* Let setup failure terminate early. */ \
@@ -1016,7 +1003,14 @@ void __wait_for_test(struct __test_metadata *t)
.sa_flags = SA_SIGINFO,
};
struct sigaction saved_action;
- int status;
+ /*
+ * Sets status so that WIFEXITED(status) returns true and
+ * WEXITSTATUS(status) returns KSFT_FAIL. This safe default value
+ * should never be evaluated because of the waitpid(2) check and
+ * SIGALRM handling.
+ */
+ int status = KSFT_FAIL << 8;
+ int child;
if (sigaction(SIGALRM, &action, &saved_action)) {
t->exit_code = KSFT_FAIL;
@@ -1028,7 +1022,15 @@ void __wait_for_test(struct __test_metadata *t)
__active_test = t;
t->timed_out = false;
alarm(t->timeout);
- waitpid(t->pid, &status, 0);
+ child = waitpid(t->pid, &status, 0);
+ if (child == -1 && errno != EINTR) {
+ t->exit_code = KSFT_FAIL;
+ fprintf(TH_LOG_STREAM,
+ "# %s: Failed to wait for PID %d (errno: %d)\n",
+ t->name, t->pid, errno);
+ return;
+ }
+
alarm(0);
if (sigaction(SIGALRM, &saved_action, NULL)) {
t->exit_code = KSFT_FAIL;
@@ -1083,6 +1085,7 @@ void __wait_for_test(struct __test_metadata *t)
WTERMSIG(status));
}
} else {
+ t->exit_code = KSFT_FAIL;
fprintf(TH_LOG_STREAM,
"# %s: Test ended in some other way [%u]\n",
t->name,
@@ -1218,6 +1221,7 @@ void __run_test(struct __fixture_metadata *f,
struct __test_xfail *xfail;
char test_name[1024];
const char *diagnostic;
+ int child;
/* reset test struct */
t->exit_code = KSFT_PASS;
@@ -1236,15 +1240,16 @@ void __run_test(struct __fixture_metadata *f,
fflush(stdout);
fflush(stderr);
- t->pid = clone3_vfork();
- if (t->pid < 0) {
+ child = fork();
+ if (child < 0) {
ksft_print_msg("ERROR SPAWNING TEST CHILD\n");
t->exit_code = KSFT_FAIL;
- } else if (t->pid == 0) {
+ } else if (child == 0) {
setpgrp();
t->fn(t, variant);
_exit(t->exit_code);
} else {
+ t->pid = child;
__wait_for_test(t);
}
ksft_print_msg(" %4s %s\n",
diff --git a/tools/testing/selftests/net/af_unix/scm_rights.c b/tools/testing/selftests/net/af_unix/scm_rights.c
index 2bfed46e0b19..d66336256580 100644
--- a/tools/testing/selftests/net/af_unix/scm_rights.c
+++ b/tools/testing/selftests/net/af_unix/scm_rights.c
@@ -14,12 +14,12 @@
FIXTURE(scm_rights)
{
- int fd[16];
+ int fd[32];
};
FIXTURE_VARIANT(scm_rights)
{
- char name[16];
+ char name[32];
int type;
int flags;
bool test_listener;
@@ -172,6 +172,8 @@ static void __create_sockets(struct __test_metadata *_metadata,
const FIXTURE_VARIANT(scm_rights) *variant,
int n)
{
+ ASSERT_LE(n * 2, sizeof(self->fd) / sizeof(self->fd[0]));
+
if (variant->test_listener)
create_listeners(_metadata, self, n);
else
@@ -283,4 +285,23 @@ TEST_F(scm_rights, cross_edge)
close_sockets(8);
}
+TEST_F(scm_rights, backtrack_from_scc)
+{
+ create_sockets(10);
+
+ send_fd(0, 1);
+ send_fd(0, 4);
+ send_fd(1, 2);
+ send_fd(2, 3);
+ send_fd(3, 1);
+
+ send_fd(5, 6);
+ send_fd(5, 9);
+ send_fd(6, 7);
+ send_fd(7, 8);
+ send_fd(8, 6);
+
+ close_sockets(10);
+}
+
TEST_HARNESS_MAIN
diff --git a/tools/testing/selftests/net/msg_zerocopy.c b/tools/testing/selftests/net/msg_zerocopy.c
index bdc03a2097e8..7ea5fb28c93d 100644
--- a/tools/testing/selftests/net/msg_zerocopy.c
+++ b/tools/testing/selftests/net/msg_zerocopy.c
@@ -85,6 +85,7 @@ static bool cfg_rx;
static int cfg_runtime_ms = 4200;
static int cfg_verbose;
static int cfg_waittime_ms = 500;
+static int cfg_notification_limit = 32;
static bool cfg_zerocopy;
static socklen_t cfg_alen;
@@ -95,6 +96,7 @@ static char payload[IP_MAXPACKET];
static long packets, bytes, completions, expected_completions;
static int zerocopied = -1;
static uint32_t next_completion;
+static uint32_t sends_since_notify;
static unsigned long gettimeofday_ms(void)
{
@@ -208,6 +210,7 @@ static bool do_sendmsg(int fd, struct msghdr *msg, bool do_zerocopy, int domain)
error(1, errno, "send");
if (cfg_verbose && ret != len)
fprintf(stderr, "send: ret=%u != %u\n", ret, len);
+ sends_since_notify++;
if (len) {
packets++;
@@ -435,7 +438,7 @@ static bool do_recv_completion(int fd, int domain)
/* Detect notification gaps. These should not happen often, if at all.
* Gaps can occur due to drops, reordering and retransmissions.
*/
- if (lo != next_completion)
+ if (cfg_verbose && lo != next_completion)
fprintf(stderr, "gap: %u..%u does not append to %u\n",
lo, hi, next_completion);
next_completion = hi + 1;
@@ -460,6 +463,7 @@ static bool do_recv_completion(int fd, int domain)
static void do_recv_completions(int fd, int domain)
{
while (do_recv_completion(fd, domain)) {}
+ sends_since_notify = 0;
}
/* Wait for all remaining completions on the errqueue */
@@ -549,6 +553,9 @@ static void do_tx(int domain, int type, int protocol)
else
do_sendmsg(fd, &msg, cfg_zerocopy, domain);
+ if (cfg_zerocopy && sends_since_notify >= cfg_notification_limit)
+ do_recv_completions(fd, domain);
+
while (!do_poll(fd, POLLOUT)) {
if (cfg_zerocopy)
do_recv_completions(fd, domain);
@@ -708,7 +715,7 @@ static void parse_opts(int argc, char **argv)
cfg_payload_len = max_payload_len;
- while ((c = getopt(argc, argv, "46c:C:D:i:mp:rs:S:t:vz")) != -1) {
+ while ((c = getopt(argc, argv, "46c:C:D:i:l:mp:rs:S:t:vz")) != -1) {
switch (c) {
case '4':
if (cfg_family != PF_UNSPEC)
@@ -736,6 +743,9 @@ static void parse_opts(int argc, char **argv)
if (cfg_ifindex == 0)
error(1, errno, "invalid iface: %s", optarg);
break;
+ case 'l':
+ cfg_notification_limit = strtoul(optarg, NULL, 0);
+ break;
case 'm':
cfg_cork_mixed = true;
break;
diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile
index 40dd95228051..3fbabab46958 100644
--- a/tools/testing/selftests/nolibc/Makefile
+++ b/tools/testing/selftests/nolibc/Makefile
@@ -152,7 +152,7 @@ CFLAGS_mips32be = -EB -mabi=32
CFLAGS_STACKPROTECTOR ?= $(call cc-option,-mstack-protector-guard=global $(call cc-option,-fstack-protector-all))
CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -W -Wall -Wextra \
$(call cc-option,-fno-stack-protector) \
- $(CFLAGS_$(XARCH)) $(CFLAGS_STACKPROTECTOR)
+ $(CFLAGS_$(XARCH)) $(CFLAGS_STACKPROTECTOR) $(CFLAGS_EXTRA)
LDFLAGS :=
REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
index 94bb6e11c16f..093d0512f4c5 100644
--- a/tools/testing/selftests/nolibc/nolibc-test.c
+++ b/tools/testing/selftests/nolibc/nolibc-test.c
@@ -64,6 +64,14 @@ static const char *argv0;
/* will be used by constructor tests */
static int constructor_test_value;
+static const int is_nolibc =
+#ifdef NOLIBC
+ 1
+#else
+ 0
+#endif
+;
+
/* definition of a series of tests */
struct test {
const char *name; /* test name */
@@ -607,7 +615,7 @@ int expect_strne(const char *expr, int llen, const char *cmp)
static __attribute__((unused))
int expect_str_buf_eq(size_t expr, const char *buf, size_t val, int llen, const char *cmp)
{
- llen += printf(" = %lu <%s> ", expr, buf);
+ llen += printf(" = %lu <%s> ", (unsigned long)expr, buf);
if (strcmp(buf, cmp) != 0) {
result(llen, FAIL);
return 1;
@@ -621,6 +629,51 @@ int expect_str_buf_eq(size_t expr, const char *buf, size_t val, int llen, const
return 0;
}
+#define EXPECT_STRTOX(cond, func, input, base, expected, chars, expected_errno) \
+ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_strtox(llen, func, input, base, expected, chars, expected_errno); } while (0)
+
+static __attribute__((unused))
+int expect_strtox(int llen, void *func, const char *input, int base, intmax_t expected, int expected_chars, int expected_errno)
+{
+ char *endptr;
+ int actual_errno, actual_chars;
+ intmax_t r;
+
+ errno = 0;
+ if (func == strtol) {
+ r = strtol(input, &endptr, base);
+ } else if (func == strtoul) {
+ r = strtoul(input, &endptr, base);
+ } else {
+ result(llen, FAIL);
+ return 1;
+ }
+ actual_errno = errno;
+ actual_chars = endptr - input;
+
+ llen += printf(" %lld = %lld", (long long)expected, (long long)r);
+ if (r != expected) {
+ result(llen, FAIL);
+ return 1;
+ }
+ if (expected_chars == -1) {
+ if (*endptr != '\0') {
+ result(llen, FAIL);
+ return 1;
+ }
+ } else if (expected_chars != actual_chars) {
+ result(llen, FAIL);
+ return 1;
+ }
+ if (actual_errno != expected_errno) {
+ result(llen, FAIL);
+ return 1;
+ }
+
+ result(llen, OK);
+ return 0;
+}
+
/* declare tests based on line numbers. There must be exactly one test per line. */
#define CASE_TEST(name) \
case __LINE__: llen += printf("%d %s", test, #name);
@@ -942,6 +995,7 @@ int run_syscall(int min, int max)
int ret = 0;
void *p1, *p2;
int has_gettid = 1;
+ int has_brk;
/* <proc> indicates whether or not /proc is mounted */
proc = stat("/proc", &stat_buf) == 0;
@@ -954,6 +1008,9 @@ int run_syscall(int min, int max)
has_gettid = __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 30);
#endif
+ /* on musl setting brk()/sbrk() always fails */
+ has_brk = brk(0) == 0;
+
for (test = min; test >= 0 && test <= max; test++) {
int llen = 0; /* line length */
@@ -969,9 +1026,9 @@ int run_syscall(int min, int max)
CASE_TEST(kill_0); EXPECT_SYSZR(1, kill(getpid(), 0)); break;
CASE_TEST(kill_CONT); EXPECT_SYSZR(1, kill(getpid(), 0)); break;
CASE_TEST(kill_BADPID); EXPECT_SYSER(1, kill(INT_MAX, 0), -1, ESRCH); break;
- CASE_TEST(sbrk_0); EXPECT_PTRNE(1, sbrk(0), (void *)-1); break;
- CASE_TEST(sbrk); if ((p1 = p2 = sbrk(4096)) != (void *)-1) p2 = sbrk(-4096); EXPECT_SYSZR(1, (p2 == (void *)-1) || p2 == p1); break;
- CASE_TEST(brk); EXPECT_SYSZR(1, brk(sbrk(0))); break;
+ CASE_TEST(sbrk_0); EXPECT_PTRNE(has_brk, sbrk(0), (void *)-1); break;
+ CASE_TEST(sbrk); if ((p1 = p2 = sbrk(4096)) != (void *)-1) p2 = sbrk(-4096); EXPECT_SYSZR(has_brk, (p2 == (void *)-1) || p2 == p1); break;
+ CASE_TEST(brk); EXPECT_SYSZR(has_brk, brk(sbrk(0))); break;
CASE_TEST(chdir_root); EXPECT_SYSZR(1, chdir("/")); chdir(getenv("PWD")); break;
CASE_TEST(chdir_dot); EXPECT_SYSZR(1, chdir(".")); break;
CASE_TEST(chdir_blah); EXPECT_SYSER(1, chdir("/blah"), -1, ENOENT); break;
@@ -1076,19 +1133,17 @@ int run_stdlib(int min, int max)
CASE_TEST(strchr_foobar_z); EXPECT_STRZR(1, strchr("foobar", 'z')); break;
CASE_TEST(strrchr_foobar_o); EXPECT_STREQ(1, strrchr("foobar", 'o'), "obar"); break;
CASE_TEST(strrchr_foobar_z); EXPECT_STRZR(1, strrchr("foobar", 'z')); break;
-#ifdef NOLIBC
- CASE_TEST(strlcat_0); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 0), buf, 3, "test"); break;
- CASE_TEST(strlcat_1); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 1), buf, 4, "test"); break;
- CASE_TEST(strlcat_5); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 5), buf, 7, "test"); break;
- CASE_TEST(strlcat_6); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 6), buf, 7, "testb"); break;
- CASE_TEST(strlcat_7); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 7), buf, 7, "testba"); break;
- CASE_TEST(strlcat_8); EXPECT_STRBUFEQ(1, strlcat(buf, "bar", 8), buf, 7, "testbar"); break;
- CASE_TEST(strlcpy_0); EXPECT_STRBUFEQ(1, strlcpy(buf, "bar", 0), buf, 3, "test"); break;
- CASE_TEST(strlcpy_1); EXPECT_STRBUFEQ(1, strlcpy(buf, "bar", 1), buf, 3, ""); break;
- CASE_TEST(strlcpy_2); EXPECT_STRBUFEQ(1, strlcpy(buf, "bar", 2), buf, 3, "b"); break;
- CASE_TEST(strlcpy_3); EXPECT_STRBUFEQ(1, strlcpy(buf, "bar", 3), buf, 3, "ba"); break;
- CASE_TEST(strlcpy_4); EXPECT_STRBUFEQ(1, strlcpy(buf, "bar", 4), buf, 3, "bar"); break;
-#endif
+ CASE_TEST(strlcat_0); EXPECT_STRBUFEQ(is_nolibc, strlcat(buf, "bar", 0), buf, 3, "test"); break;
+ CASE_TEST(strlcat_1); EXPECT_STRBUFEQ(is_nolibc, strlcat(buf, "bar", 1), buf, 4, "test"); break;
+ CASE_TEST(strlcat_5); EXPECT_STRBUFEQ(is_nolibc, strlcat(buf, "bar", 5), buf, 7, "test"); break;
+ CASE_TEST(strlcat_6); EXPECT_STRBUFEQ(is_nolibc, strlcat(buf, "bar", 6), buf, 7, "testb"); break;
+ CASE_TEST(strlcat_7); EXPECT_STRBUFEQ(is_nolibc, strlcat(buf, "bar", 7), buf, 7, "testba"); break;
+ CASE_TEST(strlcat_8); EXPECT_STRBUFEQ(is_nolibc, strlcat(buf, "bar", 8), buf, 7, "testbar"); break;
+ CASE_TEST(strlcpy_0); EXPECT_STRBUFEQ(is_nolibc, strlcpy(buf, "bar", 0), buf, 3, "test"); break;
+ CASE_TEST(strlcpy_1); EXPECT_STRBUFEQ(is_nolibc, strlcpy(buf, "bar", 1), buf, 3, ""); break;
+ CASE_TEST(strlcpy_2); EXPECT_STRBUFEQ(is_nolibc, strlcpy(buf, "bar", 2), buf, 3, "b"); break;
+ CASE_TEST(strlcpy_3); EXPECT_STRBUFEQ(is_nolibc, strlcpy(buf, "bar", 3), buf, 3, "ba"); break;
+ CASE_TEST(strlcpy_4); EXPECT_STRBUFEQ(is_nolibc, strlcpy(buf, "bar", 4), buf, 3, "bar"); break;
CASE_TEST(memcmp_20_20); EXPECT_EQ(1, memcmp("aaa\x20", "aaa\x20", 4), 0); break;
CASE_TEST(memcmp_20_60); EXPECT_LT(1, memcmp("aaa\x20", "aaa\x60", 4), 0); break;
CASE_TEST(memcmp_60_20); EXPECT_GT(1, memcmp("aaa\x60", "aaa\x20", 4), 0); break;
@@ -1139,6 +1194,26 @@ int run_stdlib(int min, int max)
CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, sizeof(long) == 8 ? (ptrdiff_t) 0x8000000000000000LL : (ptrdiff_t) 0x80000000); break;
CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, sizeof(long) == 8 ? (ptrdiff_t) 0x7fffffffffffffffLL : (ptrdiff_t) 0x7fffffff); break;
CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, sizeof(long) == 8 ? (size_t) 0xffffffffffffffffULL : (size_t) 0xffffffffU); break;
+ CASE_TEST(strtol_simple); EXPECT_STRTOX(1, strtol, "35", 10, 35, -1, 0); break;
+ CASE_TEST(strtol_positive); EXPECT_STRTOX(1, strtol, "+35", 10, 35, -1, 0); break;
+ CASE_TEST(strtol_negative); EXPECT_STRTOX(1, strtol, "-35", 10, -35, -1, 0); break;
+ CASE_TEST(strtol_hex_auto); EXPECT_STRTOX(1, strtol, "0xFF", 0, 255, -1, 0); break;
+ CASE_TEST(strtol_base36); EXPECT_STRTOX(1, strtol, "12yZ", 36, 50507, -1, 0); break;
+ CASE_TEST(strtol_cutoff); EXPECT_STRTOX(1, strtol, "1234567890", 8, 342391, 7, 0); break;
+ CASE_TEST(strtol_octal_auto); EXPECT_STRTOX(1, strtol, "011", 0, 9, -1, 0); break;
+ CASE_TEST(strtol_hex_00); EXPECT_STRTOX(1, strtol, "0x00", 16, 0, -1, 0); break;
+ CASE_TEST(strtol_hex_FF); EXPECT_STRTOX(1, strtol, "FF", 16, 255, -1, 0); break;
+ CASE_TEST(strtol_hex_ff); EXPECT_STRTOX(1, strtol, "ff", 16, 255, -1, 0); break;
+ CASE_TEST(strtol_hex_prefix); EXPECT_STRTOX(1, strtol, "0xFF", 16, 255, -1, 0); break;
+ CASE_TEST(strtol_trailer); EXPECT_STRTOX(1, strtol, "35foo", 10, 35, 2, 0); break;
+ CASE_TEST(strtol_overflow); EXPECT_STRTOX(1, strtol, "0x8000000000000000", 16, LONG_MAX, -1, ERANGE); break;
+ CASE_TEST(strtol_underflow); EXPECT_STRTOX(1, strtol, "-0x8000000000000001", 16, LONG_MIN, -1, ERANGE); break;
+ CASE_TEST(strtoul_negative); EXPECT_STRTOX(1, strtoul, "-0x1", 16, ULONG_MAX, 4, 0); break;
+ CASE_TEST(strtoul_overflow); EXPECT_STRTOX(1, strtoul, "0x10000000000000000", 16, ULONG_MAX, -1, ERANGE); break;
+ CASE_TEST(strerror_success); EXPECT_STREQ(is_nolibc, strerror(0), "errno=0"); break;
+ CASE_TEST(strerror_EINVAL); EXPECT_STREQ(is_nolibc, strerror(EINVAL), "errno=22"); break;
+ CASE_TEST(strerror_int_max); EXPECT_STREQ(is_nolibc, strerror(INT_MAX), "errno=2147483647"); break;
+ CASE_TEST(strerror_int_min); EXPECT_STREQ(is_nolibc, strerror(INT_MIN), "errno=-2147483648"); break;
case __LINE__:
return ret; /* must be last */
diff --git a/tools/testing/selftests/nolibc/run-tests.sh b/tools/testing/selftests/nolibc/run-tests.sh
index c0a5a7cea9fa..0446e6326a40 100755
--- a/tools/testing/selftests/nolibc/run-tests.sh
+++ b/tools/testing/selftests/nolibc/run-tests.sh
@@ -15,9 +15,10 @@ download_location="${cache_dir}/crosstools/"
build_location="$(realpath "${cache_dir}"/nolibc-tests/)"
perform_download=0
test_mode=system
+CFLAGS_EXTRA="-Werror"
archs="i386 x86_64 arm64 arm mips32le mips32be ppc ppc64 ppc64le riscv s390 loongarch"
-TEMP=$(getopt -o 'j:d:c:b:a:m:ph' -n "$0" -- "$@")
+TEMP=$(getopt -o 'j:d:c:b:a:m:peh' -n "$0" -- "$@")
eval set -- "$TEMP"
unset TEMP
@@ -40,6 +41,7 @@ Options:
-a [ARCH] Host architecture of toolchains to use (default: ${hostarch})
-b [DIR] Build location (default: ${build_location})
-m [MODE] Test mode user/system (default: ${test_mode})
+ -e Disable -Werror
EOF
}
@@ -66,6 +68,9 @@ while true; do
'-m')
test_mode="$2"
shift 2; continue ;;
+ '-e')
+ CFLAGS_EXTRA=""
+ shift; continue ;;
'-h')
print_usage
exit 0
@@ -153,7 +158,7 @@ test_arch() {
exit 1
esac
printf '%-15s' "$arch:"
- swallow_output "${MAKE[@]}" "$test_target" V=1
+ swallow_output "${MAKE[@]}" CFLAGS_EXTRA="$CFLAGS_EXTRA" "$test_target" V=1
cp run.out run.out."${arch}"
"${MAKE[@]}" report | grep passed
}
diff --git a/tools/testing/selftests/powerpc/flags.mk b/tools/testing/selftests/powerpc/flags.mk
index b909bee3cb2a..abb9e58d95c4 100644
--- a/tools/testing/selftests/powerpc/flags.mk
+++ b/tools/testing/selftests/powerpc/flags.mk
@@ -5,8 +5,5 @@ GIT_VERSION := $(shell git describe --always --long --dirty || echo "unknown")
export GIT_VERSION
endif
-ifeq ($(CFLAGS),)
-CFLAGS := -std=gnu99 -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(selfdir)/powerpc/include $(CFLAGS)
+CFLAGS := -std=gnu99 -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(selfdir)/powerpc/include $(USERCFLAGS)
export CFLAGS
-endif
-
diff --git a/tools/testing/selftests/resctrl/cat_test.c b/tools/testing/selftests/resctrl/cat_test.c
index c7686fb6641a..55315ed695f4 100644
--- a/tools/testing/selftests/resctrl/cat_test.c
+++ b/tools/testing/selftests/resctrl/cat_test.c
@@ -291,11 +291,30 @@ static int cat_run_test(const struct resctrl_test *test, const struct user_param
return ret;
}
+static bool arch_supports_noncont_cat(const struct resctrl_test *test)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ /* AMD always supports non-contiguous CBM. */
+ if (get_vendor() == ARCH_AMD)
+ return true;
+
+ /* Intel support for non-contiguous CBM needs to be discovered. */
+ if (!strcmp(test->resource, "L3"))
+ __cpuid_count(0x10, 1, eax, ebx, ecx, edx);
+ else if (!strcmp(test->resource, "L2"))
+ __cpuid_count(0x10, 2, eax, ebx, ecx, edx);
+ else
+ return false;
+
+ return ((ecx >> 3) & 1);
+}
+
static int noncont_cat_run_test(const struct resctrl_test *test,
const struct user_params *uparams)
{
unsigned long full_cache_mask, cont_mask, noncont_mask;
- unsigned int eax, ebx, ecx, edx, sparse_masks;
+ unsigned int sparse_masks;
int bit_center, ret;
char schemata[64];
@@ -304,15 +323,8 @@ static int noncont_cat_run_test(const struct resctrl_test *test,
if (ret)
return ret;
- if (!strcmp(test->resource, "L3"))
- __cpuid_count(0x10, 1, eax, ebx, ecx, edx);
- else if (!strcmp(test->resource, "L2"))
- __cpuid_count(0x10, 2, eax, ebx, ecx, edx);
- else
- return -EINVAL;
-
- if (sparse_masks != ((ecx >> 3) & 1)) {
- ksft_print_msg("CPUID output doesn't match 'sparse_masks' file content!\n");
+ if (arch_supports_noncont_cat(test) != sparse_masks) {
+ ksft_print_msg("Hardware and kernel differ on non-contiguous CBM support!\n");
return 1;
}
diff --git a/tools/testing/selftests/riscv/sigreturn/sigreturn.c b/tools/testing/selftests/riscv/sigreturn/sigreturn.c
index 62397d5934f1..ed351a1cb917 100644
--- a/tools/testing/selftests/riscv/sigreturn/sigreturn.c
+++ b/tools/testing/selftests/riscv/sigreturn/sigreturn.c
@@ -51,7 +51,7 @@ static int vector_sigreturn(int data, void (*handler)(int, siginfo_t *, void *))
asm(".option push \n\
.option arch, +v \n\
- vsetivli x0, 1, e32, ta, ma \n\
+ vsetivli x0, 1, e32, m1, ta, ma \n\
vmv.s.x v0, %1 \n\
# Generate SIGSEGV \n\
lw a0, 0(x0) \n\
diff --git a/tools/testing/selftests/timens/exec.c b/tools/testing/selftests/timens/exec.c
index e40dc5be2f66..d12ff955de0d 100644
--- a/tools/testing/selftests/timens/exec.c
+++ b/tools/testing/selftests/timens/exec.c
@@ -30,7 +30,7 @@ int main(int argc, char *argv[])
for (i = 0; i < 2; i++) {
_gettime(CLOCK_MONOTONIC, &tst, i);
- if (abs(tst.tv_sec - now.tv_sec) > 5)
+ if (labs(tst.tv_sec - now.tv_sec) > 5)
return pr_fail("%ld %ld\n", now.tv_sec, tst.tv_sec);
}
return 0;
@@ -50,7 +50,7 @@ int main(int argc, char *argv[])
for (i = 0; i < 2; i++) {
_gettime(CLOCK_MONOTONIC, &tst, i);
- if (abs(tst.tv_sec - now.tv_sec) > 5)
+ if (labs(tst.tv_sec - now.tv_sec) > 5)
return pr_fail("%ld %ld\n",
now.tv_sec, tst.tv_sec);
}
@@ -70,7 +70,7 @@ int main(int argc, char *argv[])
/* Check that a child process is in the new timens. */
for (i = 0; i < 2; i++) {
_gettime(CLOCK_MONOTONIC, &tst, i);
- if (abs(tst.tv_sec - now.tv_sec - OFFSET) > 5)
+ if (labs(tst.tv_sec - now.tv_sec - OFFSET) > 5)
return pr_fail("%ld %ld\n",
now.tv_sec + OFFSET, tst.tv_sec);
}
diff --git a/tools/testing/selftests/timens/timer.c b/tools/testing/selftests/timens/timer.c
index 5e7f0051bd7b..5b939f59dfa4 100644
--- a/tools/testing/selftests/timens/timer.c
+++ b/tools/testing/selftests/timens/timer.c
@@ -56,7 +56,7 @@ int run_test(int clockid, struct timespec now)
return pr_perror("timerfd_gettime");
elapsed = new_value.it_value.tv_sec;
- if (abs(elapsed - 3600) > 60) {
+ if (llabs(elapsed - 3600) > 60) {
ksft_test_result_fail("clockid: %d elapsed: %lld\n",
clockid, elapsed);
return 1;
diff --git a/tools/testing/selftests/timens/timerfd.c b/tools/testing/selftests/timens/timerfd.c
index 9edd43d6b2c1..a4196bbd6e33 100644
--- a/tools/testing/selftests/timens/timerfd.c
+++ b/tools/testing/selftests/timens/timerfd.c
@@ -61,7 +61,7 @@ int run_test(int clockid, struct timespec now)
return pr_perror("timerfd_gettime(%d)", clockid);
elapsed = new_value.it_value.tv_sec;
- if (abs(elapsed - 3600) > 60) {
+ if (llabs(elapsed - 3600) > 60) {
ksft_test_result_fail("clockid: %d elapsed: %lld\n",
clockid, elapsed);
return 1;
diff --git a/tools/testing/selftests/timens/vfork_exec.c b/tools/testing/selftests/timens/vfork_exec.c
index beb7614941fb..5b8907bf451d 100644
--- a/tools/testing/selftests/timens/vfork_exec.c
+++ b/tools/testing/selftests/timens/vfork_exec.c
@@ -32,7 +32,7 @@ static void *tcheck(void *_args)
for (i = 0; i < 2; i++) {
_gettime(CLOCK_MONOTONIC, &tst, i);
- if (abs(tst.tv_sec - now->tv_sec) > 5) {
+ if (labs(tst.tv_sec - now->tv_sec) > 5) {
pr_fail("%s: in-thread: unexpected value: %ld (%ld)\n",
args->tst_name, tst.tv_sec, now->tv_sec);
return (void *)1UL;
@@ -64,7 +64,7 @@ static int check(char *tst_name, struct timespec *now)
for (i = 0; i < 2; i++) {
_gettime(CLOCK_MONOTONIC, &tst, i);
- if (abs(tst.tv_sec - now->tv_sec) > 5)
+ if (labs(tst.tv_sec - now->tv_sec) > 5)
return pr_fail("%s: unexpected value: %ld (%ld)\n",
tst_name, tst.tv_sec, now->tv_sec);
}
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile
index d53a4d8008f9..98d8ba2afa00 100644
--- a/tools/testing/selftests/vDSO/Makefile
+++ b/tools/testing/selftests/vDSO/Makefile
@@ -1,35 +1,30 @@
# SPDX-License-Identifier: GPL-2.0
-include ../lib.mk
-
uname_M := $(shell uname -m 2>/dev/null || echo not)
ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
-TEST_GEN_PROGS := $(OUTPUT)/vdso_test_gettimeofday $(OUTPUT)/vdso_test_getcpu
-TEST_GEN_PROGS += $(OUTPUT)/vdso_test_abi
-TEST_GEN_PROGS += $(OUTPUT)/vdso_test_clock_getres
+TEST_GEN_PROGS := vdso_test_gettimeofday
+TEST_GEN_PROGS += vdso_test_getcpu
+TEST_GEN_PROGS += vdso_test_abi
+TEST_GEN_PROGS += vdso_test_clock_getres
ifeq ($(ARCH),$(filter $(ARCH),x86 x86_64))
-TEST_GEN_PROGS += $(OUTPUT)/vdso_standalone_test_x86
+TEST_GEN_PROGS += vdso_standalone_test_x86
endif
-TEST_GEN_PROGS += $(OUTPUT)/vdso_test_correctness
+TEST_GEN_PROGS += vdso_test_correctness
CFLAGS := -std=gnu99
-CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector
-LDFLAGS_vdso_test_correctness := -ldl
+
ifeq ($(CONFIG_X86_32),y)
LDLIBS += -lgcc_s
endif
-all: $(TEST_GEN_PROGS)
+include ../lib.mk
$(OUTPUT)/vdso_test_gettimeofday: parse_vdso.c vdso_test_gettimeofday.c
$(OUTPUT)/vdso_test_getcpu: parse_vdso.c vdso_test_getcpu.c
$(OUTPUT)/vdso_test_abi: parse_vdso.c vdso_test_abi.c
$(OUTPUT)/vdso_test_clock_getres: vdso_test_clock_getres.c
+
$(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c
- $(CC) $(CFLAGS) $(CFLAGS_vdso_standalone_test_x86) \
- vdso_standalone_test_x86.c parse_vdso.c \
- -o $@
+$(OUTPUT)/vdso_standalone_test_x86: CFLAGS +=-nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector
+
$(OUTPUT)/vdso_test_correctness: vdso_test_correctness.c
- $(CC) $(CFLAGS) \
- vdso_test_correctness.c \
- -o $@ \
- $(LDFLAGS_vdso_test_correctness)
+$(OUTPUT)/vdso_test_correctness: LDFLAGS += -ldl
diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c
index 413f75620a35..4ae417372e9e 100644
--- a/tools/testing/selftests/vDSO/parse_vdso.c
+++ b/tools/testing/selftests/vDSO/parse_vdso.c
@@ -55,14 +55,20 @@ static struct vdso_info
ELF(Verdef) *verdef;
} vdso_info;
-/* Straight from the ELF specification. */
-static unsigned long elf_hash(const unsigned char *name)
+/*
+ * Straight from the ELF specification...and then tweaked slightly, in order to
+ * avoid a few clang warnings.
+ */
+static unsigned long elf_hash(const char *name)
{
unsigned long h = 0, g;
- while (*name)
+ const unsigned char *uch_name = (const unsigned char *)name;
+
+ while (*uch_name)
{
- h = (h << 4) + *name++;
- if (g = h & 0xf0000000)
+ h = (h << 4) + *uch_name++;
+ g = h & 0xf0000000;
+ if (g)
h ^= g >> 24;
h &= ~g;
}
diff --git a/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c
index 8a44ff973ee1..27f6fdf11969 100644
--- a/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c
+++ b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c
@@ -18,7 +18,7 @@
#include "parse_vdso.h"
-/* We need a libc functions... */
+/* We need some libc functions... */
int strcmp(const char *a, const char *b)
{
/* This implementation is buggy: it never returns -1. */
@@ -34,6 +34,20 @@ int strcmp(const char *a, const char *b)
return 0;
}
+/*
+ * The clang build needs this, although gcc does not.
+ * Stolen from lib/string.c.
+ */
+void *memcpy(void *dest, const void *src, size_t count)
+{
+ char *tmp = dest;
+ const char *s = src;
+
+ while (count--)
+ *tmp++ = *s++;
+ return dest;
+}
+
/* ...and two syscalls. This is x86-specific. */
static inline long x86_syscall3(long nr, long a0, long a1, long a2)
{
@@ -70,7 +84,7 @@ void to_base10(char *lastdig, time_t n)
}
}
-__attribute__((externally_visible)) void c_main(void **stack)
+void c_main(void **stack)
{
/* Parse the stack */
long argc = (long)*stack;
diff --git a/tools/testing/selftests/wireguard/qemu/Makefile b/tools/testing/selftests/wireguard/qemu/Makefile
index e95bd56b332f..35856b11c143 100644
--- a/tools/testing/selftests/wireguard/qemu/Makefile
+++ b/tools/testing/selftests/wireguard/qemu/Makefile
@@ -109,9 +109,9 @@ KERNEL_ARCH := x86_64
KERNEL_BZIMAGE := $(KERNEL_BUILD_PATH)/arch/x86/boot/bzImage
QEMU_VPORT_RESULT := virtio-serial-device
ifeq ($(HOST_ARCH),$(ARCH))
-QEMU_MACHINE := -cpu host -machine microvm,accel=kvm,pit=off,pic=off,rtc=off -no-acpi
+QEMU_MACHINE := -cpu host -machine microvm,accel=kvm,pit=off,pic=off,rtc=off,acpi=off
else
-QEMU_MACHINE := -cpu max -machine microvm -no-acpi
+QEMU_MACHINE := -cpu max -machine microvm,acpi=off
endif
else ifeq ($(ARCH),i686)
CHOST := i686-linux-musl
@@ -120,9 +120,9 @@ KERNEL_ARCH := x86
KERNEL_BZIMAGE := $(KERNEL_BUILD_PATH)/arch/x86/boot/bzImage
QEMU_VPORT_RESULT := virtio-serial-device
ifeq ($(subst x86_64,i686,$(HOST_ARCH)),$(ARCH))
-QEMU_MACHINE := -cpu host -machine microvm,accel=kvm,pit=off,pic=off,rtc=off -no-acpi
+QEMU_MACHINE := -cpu host -machine microvm,accel=kvm,pit=off,pic=off,rtc=off,acpi=off
else
-QEMU_MACHINE := -cpu coreduo -machine microvm -no-acpi
+QEMU_MACHINE := -cpu coreduo -machine microvm,acpi=off
endif
else ifeq ($(ARCH),mips64)
CHOST := mips64-linux-musl